【问题标题】:Copy and Paste data into next empty row将数据复制并粘贴到下一个空行
【发布时间】:2020-11-06 16:58:54
【问题描述】:

我有一个系统生成的电子表格,当订单号中有多个商品时,它会输入空白单元格。例如,如果订单 1 有三个项目,我将有三行完全填满,但只有一个带有日期。表头是这样的:

Order Number | User | Date | Item

我附上了来自示例数据集的示例图像:

我尝试了以下代码,它可以很好地完成这项工作,但我无法完成任务,因为每次运行脚本时执行都会超时(它在行号 1,000 附近停止)。我的电子表格有大约 3,000 行并且增长缓慢。我阅读了一些有关尝试使代码更高效的说明,但对我来说它已经非常有效(至少将其与 VBA 进行比较)。 感谢您提供任何帮助!

function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var last = sheet.getLastRow();// get last row number
 
  for (i = 2; i < last; i++) { 
    var info = sheet.getRange(i, 3);
    Logger.log(info);
 
    if (info.isBlank()) {
      var data = sheet.getRange(i-1, 3).getValues(); //copy value from cell above with date
      sheet.getRange(i, 3).setValues(data); //paste value on empty cell
    } 
  }
}

【问题讨论】:

    标签: javascript loops google-apps-script optimization google-sheets


    【解决方案1】:

    我认为您的问题的原因是循环中使用了getValuessetValues。这样一来,处理成本会很高。 Rubén's answer 已经提到了这一点。那么为了降低成本,在你的情况下,如何修改如下流程?

    1. 使用getValues从“C”列检索值。
    2. 创建一个数组以将值放入电子表格。
    3. 使用setValues 将创建的数组放入电子表格。

    当上述流程反映到您的脚本时,它变成如下。

    修改脚本:

    function myFunction() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
      var last = sheet.getLastRow();// get last row number
    
      // I modified below script.
      var range = sheet.getRange("C2:C" + last);
    
      // 1. Retrieve values from the column "C".
      var values = range.getValues();
    
      // 2. Create an array for putting values to Spreadsheet.
      var temp = "";
      var v = values.map(([c]) => [c.toString() != "" ? temp = c : temp]);
    
      // 3. Put the created array to the Spreadsheet.
      range.setValues(v);
    }
    

    参考资料:

    【讨论】:

    • 效果很好!并感谢您提供参考材料。
    • @Haddocks 感谢您的回复。很高兴您的问题得到解决。
    【解决方案2】:

    问题在于getRange 和其他类似的电子表格服务 (Class SpreadsheetApp) “非常”慢。

    不是在每次 for 迭代时读取一个范围,而是使用 getDataRange() 然后 getValues() 一次读取整个数据范围,然后遍历具有所有数据范围值的数组。

    相关

    【讨论】:

    • 我认为,当提出针对 OP 情况的示例修改脚本时,可能有助于了解修改点。所以我提出了它作为几个修改之一。
    • 感谢您的评论@Tanaike。当已经有很多类似的问题并且 OP 没有包含他们的搜索/研究工作的简要描述时,我会犹豫是否这样做。无论如何,我很高兴你发布了一个答案:)
    • 感谢您的回复。我可以理解它。我认为当用户能够得到解决用户问题的方向时,它可能会导致作为用户的教育。所以我提出了它。但是,当然,当我找到解决问题的明确重复问题时,我想建议参考它。
    • 鲁本,谢谢你提供的材料。我将阅读您发布的文章。实际上我是 javascript 和 Google Sheets 的新手(通常会为小任务做一些 Python 或 VBA),我不知道getRange 和其他电子表格服务背后的缓慢过程。我试图搜索类似的问题,但发现自己正在阅读有关提高代码效率的文章,这对新用户来说是一大步。
    【解决方案3】:

    试试这个:

    function myFunction() {
      var ss=SpreadsheetApp.getActive();
      var sh=ss.getActiveSheet()
      var shsr=2;//data start row
      var vs=sh.getRange(shsr,3,sh.getLastRow()-shsr+1,1).getValues();
      vs.forEach(function(r,i){if(!r[0]){vs[i][0]=vs[i-1][0];}});
      sh.getRange(shsr,3,sh.getLastRow()-shsr+1,1).setValues(vs);
    }
    

    【讨论】:

    • 这也有效。感谢 Cooper 的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    相关资源
    最近更新 更多