如何使用Google Apps脚本在复制的数据范围旁边添加公式?

时间:2019-03-15 14:10:29

标签: google-apps-script google-sheets

我在理解数组时遇到了麻烦,但是我知道这是解决我的问题所需要做的。目前,我正在将需要的数据从另一个工作表复制到选项卡上,然后复制该数据表,然后将其粘贴到该工作表的另一个选项卡中。现在,我需要在此最终产生的数据的末尾添加另一列,该列是相邻每个单元格中的公式,该列是从AP2开始的AP列。这是脚本:

function CopyDataToNewFile() {
  var sss = SpreadsheetApp.openById('some id');
  var ss = sss.getSheetByName('Outcome'); // ss = source sheet
  var destination = SpreadsheetApp.openById('other id');
  var target = destination.getSheetByName('Final');

  ss.copyTo(destination);

  var data = destination.getSheetByName('Copy of Outcome');
  var infoTable = data.getRange(2, 1, data.getLastRow(), data.getLastColumn());
  var lastRow = target.getLastRow();

  infoTable.copyTo(target.getRange(lastRow + 1, 1), {contentsOnly: true});

  destination.setActiveSheet(destination.getSheetByName('Copy of Outcome'));
  destination.deleteActiveSheet();
}

我要在每个复制行中附加以下公式:

'=vlookup($I2, IMPORTRANGE("https://docs.google.com/spreadsheets/d/<yet another id>/edit#gid=1203869430", "Source_Hours!A:B"), 2, false)'

这是我尝试执行的操作:

 function CopyDataToNewFile() {
      var sss = SpreadsheetApp.openById('some id');
      var ss = sss.getSheetByName('Outcome'); // ss = source sheet
      var destination = SpreadsheetApp.openById('other id');
      var target = destination.getSheetByName('Final');


  ss.copyTo(destination);

  var data = destination.getSheetByName('Copy of Outcome');
  var infoTable = data.getRange(2, 1, data.getLastRow(), data.getLastColumn());
  var lastRow = target.getLastRow();

  infoTable.copyTo(target.getRange(lastRow + 1, 1), {contentsOnly: true});


 target.getRange(2,infoTable.getLastColumn()+1,infoTable.getLastRow(),1).setFormula('=vlookup($I2,IMPORTRANGE("https://docs.google.com/spreadsheets/d/1f7_unFqRkI6O2EHBLsNGLRCH5j9rlEXBdVnRLTgS_lM/edit#gid=1203869430","Source_Hours!A:B"),2,false)');


  destination.setActiveSheet(destination.getSheetByName('Copy of Outcome'));
  destination.deleteActiveSheet();
}

它在我第一次运行脚本时有效,但是下次我运行它时,它不会在最后一栏中添加公式。我不是程序员,只是知道足够危险。 :)

1 个答案:

答案 0 :(得分:0)

您的解决方案即将结束。我推荐的方法是创建对脚本将复制到的第一行的引用-target.getLastRow() + 1-然后将该引用用于数据表副本和公式write。您的脚本还存在一个可能的问题,因为您假设工作表名称始终为"Copy of Outcome" -严格保证此名称不正确(考虑将工作表复制两次而不删除第一个副本)。而是绑定返回值Sheet#copyTo,因为它是新创建的工作表副本。这样,复制的工作表的名称就无关紧要了-脚本不需要它按预期的功能运行。

function CopyDataToNewFile() {
  const source = SpreadsheetApp.openById('some id').getSheetByName('Outcome');
  const destination = SpreadsheetApp.openById('other id');
  const target = destination.getSheetByName('Final');
  if (!source || !target)
    throw new Error("Missing required worksheets (sheet names not found)");

  // Copy the source sheet and get a reference to the copy.
  var datasheet = source.copyTo(destination);
  var infoTable = datasheet.getRange(2, 1, datasheet.getLastRow(), datasheet.getLastColumn());

  // Copy the table contents to the end of the target sheet.
  // Determine the first row we are writing data into.
  const startRow = target.getLastRow() + 1;
  infoTable.copyTo(target.getRange(startRow, 1), {contentsOnly: true});
  // Set a column formula in the adjacent column.
  target.getRange(startRow, 1 + infoTable.getNumColumns(), infoTable.getNumRows(), 1)
    .setFormula("some formula");

  // Remove the intermediate sheet.
  destination.deleteSheet(datasheet);
}

使用的新功能:

因为您似乎只希望传输值,所以可以使用JavaScript数组限制使用的Spreadsheet Service方法的数量的替代方法。这利用了链接的优势,因为Range#setValues返回对写入范围的引用。假定源工作表“结果”上的值不依赖于工作簿。如果“结果”中的公式引用了同一工作簿中的其他工作表,则自然不会起作用,因为这些值将参考原始工作簿,而不是目标工作簿。

  ...
  const dataToCopy = source.getDataRange().getValues();
  dataToCopy.shift(); // remove header row.
  const startRow = target.getLastRow() + 1;
  const numRows = dataToCopy.length;
  const numColumns = dataToCopy[0].length;
  target
    .getRange(startRow, 1, numRows, numColumns)
    .setValues(dataToCopy)
    .offset(0, numColumns, numRows, 1) // offset is from the top-right cell of the range
    .setFormula("some formula");
}