How to copy and paste as values Google Apps Script/Sheets from one spreadsheet to another? - google-apps-script

So I have a huge spreadsheet with 9k rows and more than 30 columns. I want to copy this spreadsheet to another spreadsheet (Values only).
Previously I was using this code successfully, but due to the increase in data, the script now times out (1800s +). Is there a way to optimize this script or maybe an alternative option altogether?
function temp() {
var sss = SpreadsheetApp.openById('XYZ'); // sss = source spreadsheet
//var ss = sss.getSheets()[4]; // ss = source sheet
var ss = sss.getSheets(); // ss = source sheet
var id=4; //default number
for(var i in ss)
{
var sheet = ss[i];
if(sheet.getName()== "ABC")
{ id=i;
break;
}
}
console.log(id);
ss=sss.getSheets()[id];
//Get full range of data
var SRange = ss.getDataRange();
//get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
//get the data values in range
var SData = SRange.getValues();
SpreadsheetApp.flush();
var tss = SpreadsheetApp.getActiveSpreadsheet(); // tss = target spreadsheet
var ts = tss.getSheetByName('ABC'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
}

I believe your goal is as follows.
You want to reduce the process cost of the script.
In this case, I would like to propose to use Sheets API. This has already been mentioned in the Yuri Khristich's comment. Also, when the benchmark is measured between Spreadsheet service (SpreadsheetApp) and Sheets API, when Sheets API is used for reading and writing the values for Spreadsheet, it was confirmed that the process cost could be reduced. Ref
When Sheets API is used for your script, it becomes as follows.
Modified script:
Before you use this script, please enable Sheets API at Advanced Google services. And please set the source Spreadsheet ID and the sheet names.
function temp() {
var sourceSpreadsheetId = "XYZ"; // Please set the source Spreadsheet ID.
var destinationSpreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var sourceValues = Sheets.Spreadsheets.Values.get(sourceSpreadsheetId, "ABC").values;
Sheets.Spreadsheets.Values.update({values: sourceValues}, destinationSpreadsheetId, "ABC", {valueInputOption: "USER_ENTERED"});
}
References:
Benchmark: Reading and Writing Spreadsheet using Google Apps Script
Method: spreadsheets.values.get
Method: spreadsheets.values.update

Copy from one spreadsheet to another
function copyfromonetoanother() {
const sss = SpreadsheetApp.getActive();
const dss = SpreadsheetApp.openById("dssid");
const ssh = sss.getSheetByName('Sheet1');
const vs = ssh.getDataRange().getValues();
const dsh = dss.getSheetByName('Sheet1');
dsh.getRange(dsh.getLastRow() + 1,1,vs.length,vs[0].length).setValues(vs);
}
If you wish to select the source range:
function copyfromonetoanother() {
const sss = SpreadsheetApp.getActive();
const dss = SpreadsheetApp.openById("dssid");
const ssh = sss.getSheetByName('Sheet1');
const vs = ssh.activeRange().getValues();
const dsh = dss.getSheetByName('Sheet1');
dsh.getRange(dsh.getLastRow() + 1,1,vs.length,vs[0].length).setValues(vs);
}
This function appends to the bottom of the destination sheet
function appenddatatobottomofdestination() {
const sssId = "source spreadsheet id";
const sss = SpreadsheetApp.openById(sssId);
const dss = SpreadsheetApp.getActive();
const dssId = dss.getId();
const ssh = sss.getSheetByName('Sheet1');//Source sheet
const srg = ssh.getRange(1,1,ssh.getLastRow(),ssh.getLastColumn());
const dsh = dss.getSheetByName("Sheet1");//Destination sheet
var vs = Sheets.Spreadsheets.Values.get(sssId, `${ssh.getName()}!${srg.getA1Notation()}`).values;
const drg = dsh.getRange(dsh.getLastRow() + 1, 1, vs.length,vs[0].length);//appends to bottom of spreadsheet
Sheets.Spreadsheets.Values.update({values: vs}, dssId, `${dsh.getName()}!${drg.getA1Notation()}`, {valueInputOption: "USER_ENTERED"});
}

Related

Copy from template to rangelist

function FunctionC12C31() {
var allSheetTabs,i,L,thisSheet,thisSheetName,sheetsToExclude,value;
sheetsToExclude = ['Template','Sheet1','Sheet2'];
var ss = SpreadsheetApp.getActiveSpreadsheet();
allSheetTabs = ss.getSheets();
L = allSheetTabs.length;
for (i=0;i<L;i++) {
thisSheet = allSheetTabs[i];
thisSheetName = thisSheet.getName();
//continue to loop if this sheet is one to exclude
if (sheetsToExclude.indexOf(thisSheetName) !== -1) {continue;}
value = thisSheet.getRangeList(['C12:C35','C5:C6','G16:G19','G4']).clearContent();
}}
Need help modifying this to instead of clearing contents
it will copy the formula from a RangeList(['C12:C35','C5:C6','G16:G19','G4'])
to be copied to from a Template Sheet too all sheet except to "sheetsToExclude" list.
or perhaps a different script?
copy from a template sheet RangeList(['C12:C35','C5:C6','G16:G19','G4'])
data will be formulas and need to be pasted on same RangeList
paste data to ALL sheets except from specified sheets. Like sheetsToExclude = ['Template','Sheet1','Sheet2'];
I believe your goal is as follows.
You want to retrieve the formulas from the cells 'C12:C35','C5:C6','G16:G19','G4' of a template sheet. And, you want to put the retrieved formulas to the same ranges in the sheets except for sheetsToExclude = ['Template','Sheet1','Sheet2'] in the active Spreadsheet.
The template sheet is included in the same active Spreadsheet. The sheet name is "Template".
In this case, how about the following modification?
Modified script 1:
Unfortunately, in the current stage, the values cannot be retrieved and put from the discrete cells using RangeList. So, in this case, it is required to use another method. In order to retrieve the formulas from the discrete cells and put the formulas to the discrete cells with the row process cost, I would like to propose using Sheets API. So, before you use this script, please enable Sheets API at Advanced Google services.
In this script, "Method: spreadsheets.batchUpdate" is used.
function myFunction() {
// These variables are from your showing script.
var templateSheetName = "Template";
var sheetsToExclude = [templateSheetName, 'Sheet1', 'Sheet2'];
var ranges = ['C12:C35', 'C5:C6', 'G16:G19', 'G4'];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssId = ss.getId();
var template = ss.getSheetByName(templateSheetName);
var sheetId = template.getSheetId();
var gridRanges = ranges.map(r => {
var range = template.getRange(r);
var row = range.getRow();
var col = range.getColumn();
return {
sheetId,
startRowIndex: row - 1,
endRowIndex: row - 1 + range.getNumRows(),
startColumnIndex: col - 1,
endColumnIndex: col - 1 + range.getNumColumns(),
};
});
var requests = ss.getSheets().reduce((ar, s) => {
if (!sheetsToExclude.includes(s.getSheetName())) {
gridRanges.forEach(source => {
var destination = JSON.parse(JSON.stringify(source));
destination.sheetId = s.getSheetId();
ar.push({ copyPaste: { source, destination, pasteType: "PASTE_FORMULA" } });
});
}
return ar;
}, []);
Sheets.Spreadsheets.batchUpdate({ requests }, ssId);
}
When this script is run, the formulas are retrieved from 'C12:C35', 'C5:C6', 'G16:G19', 'G4' of templateSheetName sheet, and the retrieved formulas are put into the same ranges in the sheets except for sheetsToExclude.
Modified script 2:
In this script, "Method: spreadsheets.values.batchGet" and "Method: spreadsheets.values.batchUpdate" are used.
function myFunction() {
// These variables are from your showing script.
var templateSheetName = "Template";
var sheetsToExclude = [templateSheetName, 'Sheet1', 'Sheet2'];
var ranges = ['C12:C35', 'C5:C6', 'G16:G19', 'G4'];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssId = ss.getId();
var sheets = ss.getSheets().filter(s => !sheetsToExclude.includes(s.getSheetName()));
var formulas = Sheets.Spreadsheets.Values.batchGet(ssId, { ranges: ranges.map(r => `'${templateSheetName}'!${r}`), valueRenderOption: "FORMULA" }).valueRanges;
var data = sheets.flatMap(s => formulas.slice().map(({ range, values }) => ({ range: range.replace(templateSheetName, s.getSheetName()), values })));
Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" }, ssId);
}
When this script is run, the formulas are retrieved from 'C12:C35', 'C5:C6', 'G16:G19', 'G4' of templateSheetName sheet, and the retrieved formulas are put into the same ranges in the sheets except for sheetsToExclude.
Note:
If you cannot use Sheets API, how about the following modified script? In this case, only the Spreadsheet service (SpreadsheetApp) is used.
function myFunction2() {
// These variables are from your showing script.
var templateSheetName = "Template";
var sheetsToExclude = [templateSheetName, 'Sheet1', 'Sheet2'];
var ranges = ['C12:C35', 'C5:C6', 'G16:G19', 'G4'];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssId = ss.getId();
var sheets = ss.getSheets().filter(s => !sheetsToExclude.includes(s.getSheetName()));
var formulas = ranges.map(r => ss.getSheetByName(templateSheetName).getRange(r).getFormulas());
sheets.forEach(s => ranges.forEach((r, i) => s.getRange(r).setFormulas(formulas[i])));
}
References:
Method: spreadsheets.batchUpdate
Method: spreadsheets.values.batchGet
Method: spreadsheets.values.batchUpdate

How do i paste into another file through app script

I am using this code:
function copyInfo() {  
var ss = SpreadsheetApp.getActiveSpreadsheet();  
var copySheet = ss.getSheetByName("Product-analyse");  
var pasteSheet = ss.getSheetByName("Blad18"); // get source range  
var source = copySheet.getRange(93,7,39,6);  // get destination range  
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,39,6); // copy values to destination range  
source.copyTo(destination);  // clear source values
source.clearContent();
} 
Now its pasting in "Blad18". Instead I want it to be pasted in another file.
I tried adding {contentOnly: TRUE}. Though this didnt seem to work
I cannot figure this out unfortunately. Everything else is correctly set already.
Any help is greatly appreciated.
Updated script I am using:
function copyInfo() {
var ssSource = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ssSource.getSheetByName("Product-analyse");
var ssPaste = SpreadsheetApp.openById("1qhnA8L3ZkU-iEyOJtszAC4OW58sg2TJZSa_rmN_EXBI"); // the id of the other spreadsheet
var pasteSheet = ssPaste.getSheetByName("Submitted Data"); // get source range
var source = copySheet.getRange(93,7,39,6); // get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,39,6); // copy values to destination range
source.copyTo(destination); // clear source values
source.clearContent();
}
Try this:
function copyInfo() {
var ss = SpreadsheetApp.getActive();
var csh = ss.getSheetByName("Sheet0");
var psh = ss.getSheetByName("Sheet1");
const cshsr = 2;
var crg = csh.getRange(cshsr, 1, csh.getLastRow() - cshsr + 1, csh.getLastColumn());
var prg = psh.getRange(psh.getLastRow() + 1, 1);
crg.copyTo(prg);
}
I believe what you want to do is copy from one spreadsheet file to another spreadsheet file. Here is an example
function copyInfo() {
var ssSource = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ssSource.getSheetByName("Product-analyse");
var ssPaste = SpreadsheetApp.openById("dfsfhsfhskfhaskjfhsjkfas"); // the id of the other spreadsheet
var pasteSheet = ssPaste.getSheetByName("Blad18"); // get source range
var source = copySheet.getRange(93,7,39,6); // get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,39,6); // copy values to destination range
source.copyTo(destination); // clear source values
source.clearContent();
}
Reference
SpreadsheetApp.openById()

My Google App Script is Duplicating a whole sheet

I am using the following app script to copy data from a certain range to another file. But for some reason this script is also copying and pasting the whole sheet. How to stop this?
function copyInfo() {
var destinationSpreadsheetUrl = "https://docs.google.com/spreadsheets/d/189hJTiUlwubZdeN1HZ9n98U-gdaGdFSAu1-ARvlGMKo/edit#gid=0"; // Please set your Spreadsheet URL.
var destinationSheetName = "RawDataCopyPaste"; // Please set the destination sheet name.
// Source sheet.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Product-analyse");
var temp1 = copySheet.copyTo(ss);
var r = temp1.getDataRange();
r.copyTo(r, { contentsOnly: true });
// Destination sheet.
var dstSS = SpreadsheetApp.openByUrl(destinationSpreadsheetUrl);
var dstSheet = dstSS.getSheetByName(destinationSheetName);
var temp2 = temp1.copyTo(dstSS);
temp2.getRange(93, 6, 40, ).copyTo(dstSheet.getRange(dstSheet.getLastRow() + 2, 1));
// clear source values
copySheet.getRange(1, 2, 300, 9)
}
Example Source Sheet: https://docs.google.com/spreadsheets/d/1EKvIACMU7DMfuK9SQk8o6mmTTQ8_8a1qPt2jWy_q2MU/edit#gid=495001425
Example Dest Sheet: https://docs.google.com/spreadsheets/d/1mSDRsHPiPUlqg94x1Ocdssxr7fMJhqztch7kd_Xh_cE/edit#gid=0
Try it this way:
function copyInfoToAnotherFile() {
const sss = SpreadsheetApp.getActive();
const dss = SpreadsheetApp.openById("dssid");
const ssh = sss.getSheet("Sheet0");
const svs = ssh.getDataRange().getValues();
const dsh = dss.getSheetByName("Sheet0");
dsh.getRange(dsh.getLastRow() + 1, 1, svs.length,svs[0].length).setValues(svs);
}

Copy filter data from one spreadsheet file to another - Google Apps Script

I'm currently working on a project where I need to copy data to another google sheet.
let me explain:
I'd created a function where I applied filter by text and it works. But the issue is that I can't copy only the filtered data to another sheet. I'd seen many stack conversations but nothing fit.
here is the code
function copyWithValues() {
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = spreadSheet.getSheetByName('testo');
const sourceRange = sourceSheet.getDataRange();
const sourceValues = sourceRange.getValues();
const targetSpreadsheet = titleAsDate();
let rowCount = sourceValues.length;
let columnCount = sourceValues[0].length;
let targetSheet = targetSpreadsheet.getSheetByName('Sheet1').setName("Report");
let targetRange = targetSheet.getRange(1, 1, rowCount, columnCount);
targetRange.setValues(sourceValues);
}
Explanation:
The following solution is inspired by this answer.
The latter has one limitation though, it only works for transferring the filter data between sheets of the same spreadsheet.
We are going to use the exact same answer to copy the filter values from the source sheet and paste them to a temporary sheet temp_sheet of the source spreadsheet file.
Then we simply get the values of that temporary file and paste them to another spreadsheet file with the regular method of getting and setting the values as you have already implemented in your code.
Solution:
function copyWithValues() {
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = spreadSheet.getSheetByName('testo');
const temp_sheet = spreadSheet.insertSheet('temp_sheet');
const sourceRange = sourceSheet.getFilter().getRange();
sourceRange.copyTo(
temp_sheet.getRange('A1'),
SpreadsheetApp.CopyPasteType.PASTE_NORMAL,
false);
SpreadsheetApp.flush();
const sourceValues = temp_sheet.getDataRange().getValues();
const targetSpreadsheet = titleAsDate();
const rowCount = sourceValues.length;
const columnCount = sourceValues[0].length;
const targetSheet = targetSpreadsheet.getSheetByName('Sheet1').setName("Report");
const targetRange = targetSheet.getRange(1, 1, rowCount, columnCount);
targetRange.setValues(sourceValues);
spreadSheet.deleteSheet(temp_sheet);
}
where the helper function titleAsDate() is defined as:
function titleAsDate() {
const currentDate = Utilities.formatDate(new Date(), "GMT+8", "dd-MM-yyyy HH:mm:ss");
return SpreadsheetApp.create("Report of the " + currentDate);
}
based on your previous question.

Google script for google sheets - Range copy paste special 'add'

i'm really newbie at scripting, i used to do my work with microsoft office that have a special paste "add" feature and now for google sheet i can't really find it.
I will have a source range of C2:C102 and destination at same sheet D2:D102 i want the script (that i can run manually weekly) to copy all the range from source and sum it with the already existing data at D2:D102 (only values).
Here is a small example - Before after
I tried to use this code but ofc it just replaces the values.
function copyCells(){
var thisSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var SourceSheet = thisSpreadsheet.getSheetByName("test");
var SourceRange = thisSpreadsheet.getRange("C2:C102");
var destinationSheet = thisSpreadsheet.getSheetByName("test");
var destinationRange = destinationSheet.getRange("D2:D102");
SourceRange.copyTo(destinationRange, {contentsOnly: true});
}
Any help will be really appreciated :)
Haven't tested the code but try this.
grab values with getValues()
sum the values
copy back values with setValues()
function copyCells(){
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const SourceSheet = spreadsheet.getSheetByName("test");
const SourceRange = spreadsheet.getRange("C2:C102");
const SourceValues = SourceRange.getValues();
const destinationSheet = spreadsheet.getSheetByName("test");
const destinationRange = destinationSheet.getRange("D2:D102");
const destinationValues = destinationRange.getValues();
for (let i = 0; i < SourceValues.length; i++)
destinationValues[i][0] = parseFloat(destinationValues[i][0]) + parseFloat(SourceValues[i][0])
destinationRange.setValues(destinationValues);
}
REFERENCES
range.getValues()
range.setValues()