0

我正在尝试从以前的相关问题中调整示例脚本。对于列 K 中的单元格值为零的行,我想将该行设为黄色。

这是我目前改编的代码:

function colorAll() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 3;
  var endRow = sheet.getLastRow();

  for (var r = startRow; r <= endRow; r++) {
    colorRow(r);
  }
}

function colorRow(r){
  var sheet = SpreadsheetApp.getActiveSheet();
  var c = sheet.getLastColumn();
  var dataRange = sheet.getRange(r, 1, 1, c);

  var data = dataRange.getValue();
  var row = data[0];

  if(row[0] === "0"){
    dataRange.setBackground("white");
  }else{
    dataRange.setBackground("yellow");
  }

  SpreadsheetApp.flush(); 
}

function onEdit(event)
{
  var r = event.source.getActiveRange().getRowIndex();
  if (r >= 3) {
    colorRow(r);
  }
}

function onOpen(){
  colorAll();
}

我的问题是,我不知道如何引用 K 列。在上面的链接答案中,脚本的创建者声称,“ [h]ere 是一个 Google Apps 脚本示例,它根据A 列中的值。 “首先,最重要的是,我不知道他在哪里引用 A 列。我想更改“var dataRange = sheet.getRange(r, 1, 1, c);” 到“var dataRange = sheet.getRange(r, 11 , 1, c);” 会这样做,但这只是在我的工作表末尾添加了 10 个空白列,然后脚本崩溃了。我不懂为什么。

其次,但更重要的是,他声称脚本影响整个行的说法是不准确的,因为他原来的“var dataRange = sheet.getRange(r, 1, 1, 3);” 只为前三列着色 - 这就是我添加“var c”并将“3”更改为“c”的原因。

此外,当我播放/调试脚本,或从电子表格脚本管理器运行“onEdit”时,我得到“ TypeError: Cannot read property "source" from undefined ”。我可以看到“来源”是未定义的——一开始我错误地认为它是一种方法——但我也不确定如何解决这个问题。

最后,列 K 并不总是参考列,因为我的意思是在它的左侧添加更多列。我假设每次添加列时我都必须更新脚本,但是第 2 行中有一个列标题永远不会改变,所以如果有人可以帮助我设计一些代码来查找行中的特定字符串2,然后获取该列引用以在函数 colorRow() 中使用,我将不胜感激。

我不知道这个脚本的结构是否有效,但理想情况下,我希望我的电子表格具有反应性——我不想在编辑驱动单元后或打开时重新运行这个脚本;它看起来应该这样做(如果它不是错误的话),但这是我第一次尝试使用 Google Apps 脚本,我不确定任何事情。

我不擅长编写脚本,但我早在 2006 年就在研究生院上过编程基础/Python 课程,之后不久就使用 Excel 和 Access 工作了 4 年,经常创建和调整宏。我不能真正从头开始设计,但我了解基本原理和概念,即使我不能翻译所有内容(例如,我不明白“for”中第三个参数中的“++”是什么意思我正在使用的语句:“for (var r = startRow; r <= endRow; r++ )。”我认为我在寓言上相当于一个有文化的西班牙语使用者试图阅读意大利语。

帮助和教育解释/示例将不胜感激。感谢您阅读/略读/跳到这句话。

4

2 回答 2

3

我不会重写您已经获得一些帮助的代码,而是尝试为您解释您提出的具体问题。我看到您已经有了一些答案,但是我将其完全投入其中,因为它有助于理解。

My problem is, I can't figure out how to reference column K.

列 A = 1,B = 2,... K = 10。

I can't figure out where he's referencing column A.

当您更改 .getRange 时,您已经很接近了。.getRange 会根据 () 中的参数数量做不同的事情。有 4 个参数是 getRange(row, column, numRows, numColumns)。

sheet.getRange(r, 1, 1, c)  // the first '1' references column A

从 row(r) 开始,最初是 row(3) 和 column(1)。所以这是单元格(A3)。该范围扩展到 1 行和 (c) 列。由于 c = sheet.getLastColumn(),这意味着您已将范围设为 1 行和所有列。

当您将其更改为

var dataRange = sheet.getRange(r, 11, 1, c)  // the '11' references column L

您有一个从第(3)列(L)开始的范围为11 = L。这运行到第(3)列(getLastColumn())。如果您超出范围,这将做一些奇怪的事情。您可能已将其推入无限 for 循环,这会导致脚本崩溃

其次,但更重要的是,他声称脚本影响整个行的说法是不准确的,因为他原来的“var dataRange = sheet.getRange(r, 1, 1, 3);” 只为前三列着色 - 这就是我添加“var c”并将“3”更改为“c”的原因。

你是对的。(3) 表示范围扩展到 3 列。

"TypeError: Cannot read property "source" from undefined."

这里发生的事情并不直观。您不能从电子表格脚本管理器运行 onEdit(event) 函数,因为它需要一个“事件”。

  • onEdit 是一个特殊的谷歌触发器,只要编辑电子表格就会运行。
  • 它传递了激活它的(事件),并且
  • 事件源。指事件发生的工作表
  • var r = event.source.getActiveRange().getRowIndex(); 获取发生编辑的行号,即要改变颜色的行。

如果您在管理器中运行它,则没有事件可供读取,因此未定义。出于同样的原因,您也无法调试它。

最后,列 K 并不总是参考列,因为我的意思是在它的左侧添加更多列。我假设每次添加列时我都必须更新脚本,但是第 2 行中有一个永远不会改变的列标题,所以如果有人可以帮助我设计一些代码来查找行中的特定字符串2,然后获取该列引用以在函数 colorRow() 中使用,我将不胜感激。

在我给你代码帮助她之前,我有一个替代建议,因为你也在谈论效率,在电子表格中运行函数通常比使用脚本更快。您可以尝试将 A 列作为索引列,其中 ColumnA(Row#) = ColumnK(Row#)。如果将以下内容放入单元格(A1)中,则 ColumnA 将与 Column K 完全匹配。

=ArrayFormula(K:K) 

更好的是,如果您在 A 和 K 之间添加/删除列,公式将更改其引用而无需您执行任何操作。现在只需隐藏 columnA,您的工作表就会恢复其原始外观。

这是您的代码帮助,使用您自己的一些代码。

function findSearchColumn () {
  var colNo;  // This is what we are looking for.
  var sheet = SpreadsheetApp.getActiveSheet();
  var c = sheet.getLastColumn();

  // gets the values form the 2nd row in array format
  var values = sheet.getRange(2, 1, 1, c).getValues();
  // Returns a two-dimensional array of values, indexed by row, then by column.

  // we are going to search through values[0][col] as there is only one row
  for (var col = 0; col < data[0].length; col++) { // data[0].length should = c
    if (data[0][col] == value) {
      colNo = col;
      break; // we don't need to do any more here.
    }
  }
  return(colNo);
}

如果 break 给您带来问题,只需将其删除并让外观完整或将其替换为 col = data[0].length;

我不知道这个脚本的结构是否有效,但理想情况下,我希望我的电子表格具有反应性——我不想在编辑驱动单元后或打开时重新运行这个脚本;它看起来应该这样做(如果它不是错误的话),但这是我第一次尝试使用 Google Apps 脚本,我不确定任何事情。

没关系,效率的微调取决于电子表格。每次编辑工作表时都会运行 onEdit(event) 函数,对此您无能为力。然而,它应该做的第一件事是检查相关范围是否已被编辑。if (r >= 3) 行似乎正在这样做。您可以根据需要使其具体化。我对隐藏索引列的建议旨在提高效率并且更容易实现。

I'm not great with scripting,

你做得很好,但可以做一些背景阅读,只需查找 for 循环之类的东西。不幸的是,Python 在语法上与许多其他语言不同。google 脚本中的 for 循环与 VBA、C、JAVA 等相同。所以阅读这些基本操作实际上是在教你很多语言。

I don't understand what the "++" means in the third argument in the "for" statement 这就是为什么语言 C++ 得名的原因,就像一个程序员的笑话。

r++ 和 r = r+1 一样

r-- 表示 r = r-1

r+2 表示 r = r+2

所以

for (var r = startRow; r <= endRow; r++)
  • 表示 r 以 startRow 开头,在本例中为 3。
  • 循环将一直运行到 r <= endRow,在本例中为 sheet.getLastRow()
  • 每次循环运行后 r 递增 1,因此如果 endRow == 10,则循环将从 r = 3 运行到 r = 10 => 8 次
于 2014-08-10T15:59:08.723 回答
0

1.onEdit这是一个特殊的函数,当你编辑电子表格时会自动调用。如果您手动运行它,则所需的参数将不可用。

2.要在K列为0时改变整行的颜色,只需对脚本进行简单的修改即可。见下文

function colorRow(r){
  var sheet = SpreadsheetApp.getActiveSheet();
  var c = sheet.getLastColumn();
  var dataRange = sheet.getRange(r, 1, 1, c); 

  var data = dataRange.getValues(); 

  if(data[0][10].toString() == "0"){ //Important because based on the formatting in the spreadsheet, this can be a String or an integer 
    dataRange.setBackground("white");
  }else{
    dataRange.setBackground("yellow");
  }

  SpreadsheetApp.flush(); 
}
于 2013-06-14T10:30:02.357 回答