简体   繁体   中英

Copy data from one Spreadsheet to another keeping format and without formulas

What I'm looking to do is to copy a data range from one Spreadsheet to another while preserving formats (colors, styling, etc.) and only taking the values without the formulas.

I already have this code (from a previous answer from @Tanaike), with a bit of modifications. It preserves the formatting but copies the formulas and I only need the values.

//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);

Modification points:

  • In your script, range of var destRange = destSheet.getRange(range);and var sourceRange = sourceSheet.getRange(range); is not declared.
  • Method of copyTo in Class Range cannot be used for other Google Spreadsheet. It seems that this is the current specification. I think that this might be the reason of your issue.
  • And, for example, when IMPORTRANGE is used in the source sheet as the formula, when sourceRange.getSheet().copyTo(destSS) is used, the values cannot be shown because of the authorization. Also I'm worry about this.

When above points are reflected to your script, it becomes as follows.

Modified script:

Before you use this script, please set the variables of sourceID , sheetName and newID . And, please set range as the 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);
  • I'm not sure your direction of DriveApp.getFolderById(destFolder).addFile(docFile);and DriveApp.getRootFolder().removeFile(docFile); in your script. So in this modification, I don't show it. When you are required to use it, please add it.

Note:

  • If you can copy only the row height except for the default height of 21 pixels, the cost of script might be reduced. If you use it, please modify as follows. In this modification, Sheets API is not used.

    • From

       for (var r = row; r <= row + destTempRange.getNumRows(); r++) { destSheet.setRowHeight(i++, destTempSheet.getRowHeight(r)); }
    • To

       for (var r = row; r <= row + destTempRange.getNumRows(); r++) { var rowHeight = destTempSheet.getRowHeight(r); if (rowHeight.= 21) destSheet,setRowHeight(i; rowHeight); i++; }
  • Or, when you use Sheets API, you can also use the following modification. In this case, please enable Sheets API at Advanced Google services.

    • From

       var i = 1; var row = destTempRange.getRow(); for (var r = row; r <= row + destTempRange.getNumRows(); r++) { destSheet.setRowHeight(i++, destTempSheet.getRowHeight(r)); }
    • To

       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);

References:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM