首页 > 解决方案 > 将数据从一个电子表格复制到另一种保留格式且不使用公式

问题描述

我要做的是将数据范围从一个电子表格复制到另一个电子表格,同时保留格式(颜色、样式等),并且只获取没有公式的值。

我已经有了这段代码(来自@Tanaike 的先前回答),并进行了一些修改。它保留格式但复制公式,我只需要值。

//Source
var sourceSheet = SpreadsheetApp.openById(sourceID).getSheetByName(sheetName);
var sourceRange = sourceSheet.getRange(range);

//Destination
var destSS = SpreadsheetApp.openById(newID);
var destSheet = destSS.getSheets()[0];
var destRange = destSheet.getRange(range);
destSheet.clear();

//var copiedsheet = sourceRange.getSheet().copyTo(destSS); // <-- This works, but copies formulas and get Ref errors
var copiedsheet = sourceRange.getSheet().copyTo(destRange, {contentsOnly: true}); //Doesn't work, I tried many variations of this

copiedsheet.getRange(sourceRange.getA1Notation()).copyTo(destRange, {contentsOnly: true});
copiedsheet.getRange(sourceRange.getA1Notation()).copyTo(destRange, SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS, false); // Will preserve formatting
destSS.deleteSheet(destSS.getSheets()[0]);

DriveApp.getFolderById(destFolder).addFile(docFile);
DriveApp.getRootFolder().removeFile(docFile);

标签: javascriptgoogle-apps-scriptgoogle-sheets

解决方案


修改点:

  • 在您的脚本中,rangeofvar destRange = destSheet.getRange(range);var sourceRange = sourceSheet.getRange(range);没有被声明。
  • 类范围内的方法copyTo不能用于其他 Google 电子表格。这似乎是当前的规范。我认为这可能是您的问题的原因。
  • 并且,例如,当源表中使用IMPORTRANGE作为公式时sourceRange.getSheet().copyTo(destSS),使用时,由于授权,无法显示值。我也很担心这个。

当以上几点反映到您的脚本时,它变成如下。

修改后的脚本:

在使用此脚本之前,请先设置sourceID,sheetName和的变量newID。并且,请设置range为 A1Notation。

//Source
var sourceSS = SpreadsheetApp.openById(sourceID);
var sourceSheet = sourceSS.getSheetByName(sheetName);
var tempSheet = sourceSheet.copyTo(sourceSS);
var temoSheetRange = tempSheet.getRange(range);
temoSheetRange.copyTo(temoSheetRange, {contentsOnly: true});
SpreadsheetApp.flush(); // This might not be required.

//Destination
var destSS = SpreadsheetApp.openById(newID);
var destSheet = destSS.getSheets()[0];
destSheet.clear();
var destTempSheet = tempSheet.copyTo(destSS);
var destTempRange = destTempSheet.getRange(range);
var dstRange = destSheet.getRange("A1");
destTempRange.copyTo(dstRange);
destTempRange.copyTo(dstRange, SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS, false);
var i = 1;
var row = destTempRange.getRow();
for (var r = row; r <= row + destTempRange.getNumRows(); r++) {
  destSheet.setRowHeight(i++, destTempSheet.getRowHeight(r));
}
destSS.deleteSheet(destTempSheet);
sourceSS.deleteSheet(tempSheet);
  • 我不确定你的剧本的方向DriveApp.getFolderById(destFolder).addFile(docFile);和方向。DriveApp.getRootFolder().removeFile(docFile);所以在这个修改中,我没有展示它。当您需要使用它时,请添加它。

笔记:

  • 如果您只能复制除默认像素高度之外的行高21,则脚本的成本可能会降低。如果您使用它,请进行如下修改。在此修改中,不使用 Sheets API。

    •   for (var r = row; r <= row + destTempRange.getNumRows(); r++) {
          destSheet.setRowHeight(i++, destTempSheet.getRowHeight(r));
        }
      
    •   for (var r = row; r <= row + destTempRange.getNumRows(); r++) {
          var rowHeight = destTempSheet.getRowHeight(r);
          if (rowHeight != 21) destSheet.setRowHeight(i, rowHeight);
          i++;
        }
      
  • 或者,当您使用 Sheets API 时,您也可以使用以下修改。在这种情况下,请在高级 Google 服务中启用 Sheets API。

    •   var i = 1;
        var row = destTempRange.getRow();
        for (var r = row; r <= row + destTempRange.getNumRows(); r++) {
          destSheet.setRowHeight(i++, destTempSheet.getRowHeight(r));
        }
      
    •   var reqs = [];
        var sheetId = destSheet.getSheetId();
        var reqs = Sheets.Spreadsheets.get(newID, {ranges: [destTempSheet.getSheetName()], fields: "sheets(data(rowMetadata))"}).sheets[0].data[0].rowMetadata.reduce((ar, {pixelSize}, r) => {
          if (pixelSize != 21) ar.push({updateDimensionProperties:{range:{sheetId:sheetId,dimension:"ROWS",startIndex:r,endIndex:r+1},properties:{pixelSize:pixelSize},fields:"pixelSize"}});
          return ar;
        }, []);
        if (reqs.length > 0) Sheets.Spreadsheets.batchUpdate({requests: reqs}, newID);
      

参考:


推荐阅读