【问题标题】:Issue with 2D array - Google Apps Script二维数组的问题 - Google Apps 脚本
【发布时间】:2018-06-04 19:08:34
【问题描述】:

我正在尝试遍历大量单元格来测试 A 列中的值,如果返回 true,那么我想将相邻的 3 个单元格(B-D 列)存储在一个数组中,并最终将该数组粘贴到单独的工作表上.当前代码找到所有正确的值,但它将它们全部写入一行,而不是像原始数据源中的多行和 3 列。

var dataset = [],
    month,
    i,
    j,
    x = 0,
    targetmonth = ss.getSheetByName("BOH").getRange("B2").getValue(),
    location = ss.getSheetByName(output).getRange("D3").getValue();

for ( i = 7; i < 3000; i++){
  month = ss.getSheetByName(location).getRange(i,1).getValue();
  if (month == targetmonth){
    for (j = 2; j<5; j++){
      dataset [x] = [ss.getSheetByName(location).getRange(i,j).getValues()];
      x = x + 1;
    } 
  }
}

//I've changed the range size in line below to 360x3 which is what it should be 
//but this line currently only runs when set to 1x360

ss.getSheetByName(output).getRange(8,3,360,3).setValues([dataset]);

【问题讨论】:

  • 不喜欢只在 JavaScript 数组中工作?你的脚本会快很多。
  • 你能告诉我一些关于这方面的资源吗? JavaScript 相对较新。
  • 您选择的 JavaScript 参考和无数的网络教程都将包含大量关于 Array 对象的信息。我更喜欢 Mozilla 开发者网络,但更喜欢他们自己的。至于在 Apps 脚本中使用它们,请阅读 Apps 脚本文档以了解 Spreadsheet 类中的最佳实践。

标签: arrays for-loop google-apps-script google-sheets


【解决方案1】:

遵循最佳做法,您应尽量减少通过使用getValues() 重复调用电子表格服务。您当前的脚本循环访问 A7:A2999 的值,如果它可以在一次读取中完成:

// const x -> no reassignment / redeclaring x allowed. (You can still manipulate the object).
const startRow = 7, endRow = 2999,
    numRows = endRow - startRow + 1;
const months = ss.getSheetByName(location)
  .getRange(startRow, 1, numRows, 1).getValues();

然后您有条件地访问同一范围的 B:D 列。您会发现在开始时将所有内容全部读入内存会更快,并且仅在需要时访问所需的行和列:

const startCol = 2, endCol = 4,
    numCols = endCol - startCol + 1;
const targetValues = ss.getSheetByName(location)
  .getRange(startRow, startCol, numRows, numCols).getValues();

您还应该使用比 ij 更有意义的迭代索引名称,并且您没有在函数开头声明所有内容(阅读有关 JavaScript 和“提升”的信息),当点-使用更有意义。

你的函数的其余部分如下所示:

const output = [],
    targetMonth = /** set this */,
    destinationName = /** set this */;
for (var monthIndex = 0; monthIndex < months.length; ++monthIndex) {
  // Add the array of target column values to the output (by reference)
  if (months[monthIndex][0] === targetMonth) {
    output.push(targetValues[monthIndex]);
  }
}
// Write the output array.
ss.getSheetByName(destinationName).getRange(8, 3, output.length, output[0].length).setValues(output);

我们刚刚从 ~numRows x numColumns 电子表格访问次数增加到 ~4!鉴于单个小区访问调用大约需要 0.1 秒,这将是boatloads faster。是的,如果您读取大量单元格,可能需要一段时间(从 400k 单元格获取/设置值大约需要 30 秒),但只要 1-by-1 访问,它就远不及。

参考资料:

PS:如果在序列化数据之前更改targetValues 中的值,output 中引用的值也会更新,因为它们是同一个对象。 (阅读“按值”/深拷贝和“按引用”/浅拷贝以了解原因。对于编写的这个脚本,区别并不重要,因为它们没有被修改。)

【讨论】:

  • 谢谢!这很有帮助。
猜你喜欢
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多