Copying formats only from separate Google Sheet - google-apps-script

I'm trying to copy formatting only from a source sheet that is in a different workbook than the current sheet. Essentially, the source sheet format changes and I'd like to pull updates to the formatting into my destination sheet (which is the current sheet I would be working in). I'm using the following code, but I get "Cannot convert Spreadsheet to (class)" error" on the last line. Any insights?
var ss = SpreadsheetApp.openById("Source ID")
var source = ss
var destination = SpreadsheetApp.openById("Destination ID");
var range = source.getRange("N3:AE50");
range.copyFormatToRange(destination, 10, 27, 4, 50);

You want to copy the format from Spreadsheet A to Spreadsheet B. If my understanding is correct, how about this workaround? I think that there are several answers for your situation, so please think of this as one of them.
As tehhowch pointed out, copyFormatToRange() can be used for the same sheets in a Spreadsheet. For this situation, I understood that you want to use for between 2 Spreadsheets. In my workaround, I used the following flow.
Copy the source sheet of Spreadsheet with "Source ID" to Spreadsheet with "Destination ID".
Retrieve the range from the copied sheet as the source range.
Copy the source range to the destination sheet using copyFormatToRange().
Delete the copied sheet.
Sample script :
var sourceA1Notation = "N3:AE50";
var destinationA1Notation = "D10"; // row=4, col=10 This is the cell of upper left for putting the source range.
var source = SpreadsheetApp.openById("Source ID");
var destination = SpreadsheetApp.openById("Destination ID");
var sourceSheet = source.getSheets()[0]; // You can also use source.getSheetByName(name)
var destinationSheet = destination.getSheets()[0]; // You can also use source.getSheetByName(name)
var copiedsheet = sourceSheet.copyTo(destination);
var sourceRange = copiedsheet.getRange(sourceA1Notation);
var destinationRange = destinationSheet.getRange(destinationA1Notation);
sourceRange.copyFormatToRange(
destinationSheet,
destinationRange.getColumn(),
destinationRange.getColumn() + sourceRange.getNumColumns() - 1,
destinationRange.getRow(),
destinationRange.getRow() + sourceRange.getNumRows() - 1
);
destination.deleteSheet(copiedsheet);
Note :
When you use this, please input and confirm sourceA1Notation, destinationA1Notation, "Source ID" and "Destination ID".
destinationA1Notation is the cell of upper left for putting the source range.
In this sample script, each first sheet of "Source ID" and "Destination ID" is used. If you want to use other sheet, please modify this script.
References :
copyFormatToRange()
getSheets()
getSheetByName()
If I misunderstand what you want, I'm sorry.

Related

Is possible to copy a data range from one spreadsheet to another?

function transferDataToDataBase(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var DB = SpreadsheetApp.openById("SHEET ID");
var SCPM_Input = ss.getSheetByName("Report")[0];
var history_Input = DB.getSheetByName(Database);
var blankRow = history_Input.getLastRow();
SCPM_Input.getRange(("A2:T").copyTo(history_Input.getRange(blankRow+1,1,blankRow+1,20));
}
Question:
The last line has an error at ";", don't know how to fix it. It said the syntax error;
It seems copy To only works for transferring from one sheet to another in the same spreadsheet, but not in between spread sheet. Is there a way to copyTo between spreadsheets?
Many thanks.
If you want to copy the formatting as well then copy the entire sheet/tab and then use copyTo() to copy the range and then delete the copied sheet. Or if you just want the data use getValues() and setValues();
This is part of the problem:
var SCPM_Input = ss.getSheetByName("Report")[0]; because the index zero at the end should not be there and you cannot have sheet.getLastRow() + 1 number of rows in a sheet as shown in the next row.
SCPM_Input.getRange(("A2:T").copyTo(history_Input.getRange(blankRow+1,1,blankRow+1,20));
And copyTo doesn't work between spreadsheets.
There is an update:
Since the database will be used by multiple users. I set up a standalone database. I copied my "Report" sheet from spreadsheet 1 to spreadsheet 2. It will create a sheet "copy of Report".I rename, copied to Database sheet and delete it.
Feel free to discuss if there is an easier way to do it. Thanks.
// transfer the report to DataBase Spreadsheet
function transferDataToDataBase(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var db = SpreadsheetApp.openById('spreadsheet ID')
var scpm_Input = ss.getSheetByName("Report");
scpm_Input.copyTo(db);
Utilities.sleep(3000);
db.getSheetByName('copy of report').setName('Import')
var history_Input = db.getSheetByName('Database');
var blankRow = history_Input.getLastRow();
var target = db.getSheetByName('Import');
target.getRange("A2:T").copyTo(history_Input.getRange(blankRow+1,1,blankRow+1,20));
history_Input.getRange(blankRow+1,21).setValue(new Date()).setNumberFormat("yyyy-mm-dd h:mm") //update the date and time
db.deleteSheet(target);
}

Google app script to cut and paste a range from a google sheet to another google sheet

I'm trying to put together a script that cuts a range from a google spreadsheet and pastes it to another spreadsheet. The script works fine as long as the source sheet is the first sheet in my document. How can I fix it so that the script grabs the right sheet no matter where it is in my document?
I'm very very new at this and mostly used code I found online. Probably made a very obvious mistake..
function CopyRangeTo_OtherSheet() {
var sss = SpreadsheetApp.openById('1O1gML-IeOkx6n6RhCavay6Zg9zflalcVs0qkB2yu7bE');
var ss = sss.getSheetByName('Sheet1');
var range = ss.getRange(2,4,sss.getLastRow()-1,9);
var data = range.getValues();
var tss = SpreadsheetApp.openById('1WHoETM3QxV166ndnPW4Qv37Y6SBGPVw-CcEQxNpw0Co');
var ts = tss.getSheetByName('Sheet3');
ts.getRange(ts.getLastRow()+1, 1,50,9).setValues(data);
var spread = SpreadsheetApp.openById('1O1gML-IeOkx6n6RhCavay6Zg9zflalcVs0qkB2yu7bE');
var sheet = spread.getSheetByName("Sheet1");
sheet.getRange("D2:H").clearContent();
}
The number of rows will be different in each sheet. .getLastRow() on a spreadsheet class only returns the last row in first sheet. getLastRow of sheet instead
ss.getLastRow()
Your line var ss = sss.getSheetByName('Sheet1'); implies that you take the sheet with the name Sheet1.
This is the sheet you use to obtain your values from range and subsequently copy them.
If you want to copy / cut and paste values from a different sheet, simply paste the correct name of the sheet in var ss = sss.getSheetByName('PASTE HERE THE NAME OF THE SHEET');
Small annotation:
If the range you want to clear is the same from which you copied the
values, you do not need to define it again. You can simply replace the
lines
var spread = SpreadsheetApp.openById('1O1gML-IeOkx6n6RhCavay6Zg9zflalcVs0qkB2yu7bE');
var sheet = spread.getSheetByName("Sheet1");
sheet.getRange("D2:H").clearContent();
through
range.clearContents();
Also note:
setValues() only works if the range into which the values shall be set has the same dimension like the value range, i.e. the original range.
If your original range is 2,4,ss.getLastRow()-1,9, then the number of rows is ss.getLastRow()-1 and the number of columns 9.
Thus, you need to define
ts.getRange(ts.getLastRow()+1, 1,ss.getLastRow()-1,9).setValues(data);
to adapt the row number dynamically.

Copy a range in active sheet, create new spreadsheet with custom name, paste range

I recently wrote my first Google Apps script that makes a copy of a spreadsheet (including all tabs within that spreadsheet) and places it into a specific folder in the user's Drive. The copy is renamed based on a cell value in the original spreadsheet. Here is my script, for reference:
function copyDocument() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Get current active spreadsheet.
var id = ss.getId(); // Get current active spreadsheet ID.
var sstocopy = DriveApp.getFileById(id); // Get spreadsheet with DriveApp.
var sheet = ss.getActiveSheet(); // Get current active sheet.
var sheet_name = sheet.getRange("B1").getValue(); // Get the value of cell B1, used to name the new spreadsheet.
var folder_name = sheet.getRange("C23").getValue(); // Get the target folder ID.
var folder = DriveApp.getFolderById(folder_name); // Get the ID of the folder where you will place a copy of the spreadsheet.
sstocopy.makeCopy(sheet_name,folder); // Make a copy of the spreadsheet in the destination folder.
}
This script works, but I have been asked to modify it because the script I wrote is copying over unnecessary tabs and data that is causing confusion to users.
The new script should make a copy of a specific range in a specific sheet, create a new spreadsheet, and paste that range into it. It should also name itself after a cell value in the range.
However, the only method I have come across that specifically copies a sheet into a new spreadsheet is copyTo(spreadsheet). However, the Google Apps Script Guide specifies that "the copied sheet will be named 'Copy of [original name]'" by default.
I want to be able to rename the copied sheet after a specific cell. My question is, can I use copyTo(spreadsheet) and give the new spreadsheet a custom name, based on a cell?
Thanks!
You will need to get the data from the specific sheet to copy out to a variable of using:
var sourceSheet = ss.getSheetByName("Sheet1");
var sourceData = sourceSheet.getDataRange().getValues();
var originalRangeNotation = sourceSheet.getDataRange().getA1Notation();
Then you need to create a new, empty file and make a sheet with the same name
var ssNew = SpreadsheetApp.create("My New File Name");
ssNew.insertSheet('My New Sheet');
Then add the contents from the saved data to the new file. Since the insertSheet makes the new sheet the active one, we use:
var sheetNew = ssNew.getActiveSheet();
var rangeNew = sheet.getRange(originalRangeNotation);
range.setValues(sourceData);
Thanks. I ended up using this in place of sstocopy.makeCopy()
folder.addFile()
new_sheet.getActiveSheet().getRange("X:Y").setValues(sheet.getRange("X:Y").getValues())
DriveApp.getRootFolder().removeFile(temp)

Why can't I copy ranges between spreadsheets with copyValuesToRange()?

I am able to copy a range of values from one spreadsheet to another with Range.setValues(values) but not with Range.copyValuesToRange(sheet, column, columnEnd, row, rowEnd):
function test()
{
var sourceSheet = SpreadsheetApp.getActiveSheet();
var sourceCols = sourceSheet.getRange("A1:B10");
// Copying the first two columns this way works.
var sheet1 = SpreadsheetApp.create("New Spreadsheet 1").getActiveSheet();
sheet1.getRange("A1:B10").setValues(sourceCols.getValues());
// Copying the first two columns this way does not work.
var sheet2 = SpreadsheetApp.create("New Spreadsheet 2").getActiveSheet();
sourceCols.copyValuesToRange(sheet2, 1, 2, 1, 10);
}
Specifically, after running the code, New Spreadsheet 1 contains range A1:B10 of the source spreadsheet, while New Spreadsheet 2 is empty. Both have a single sheet named "Sheet1". The source spreadsheet is unmodified.
What am I doing wrong? I'm wondering if the failing method only works within a single spreadsheet, but I see nothing in the documentation about that.
The reason I want to use Range.copyValuesToRange() is so I can also copy the formatting with Range.copyFormatToRange().
The methods copyValuesToRange and copyFormatToRange, as well as Range.copyTo, are restricted to copying within the same spreadsheets, although documentation is not explicit about that. A workaround which allows you to copy between spreadsheets with formatting is to copy the entire sheet to the destination spreadsheet, using Sheet.copyTo method. Then copy the required range from there, and optionally, delete the sheet. Like this:
function cc() {
var ss1 = SpreadsheetApp.openByUrl('some url');
var ss2 = SpreadsheetApp.openByUrl('another url');
var sheet1 = ss1.getSheetByName('name');
var sheet2 = ss2.getSheetByName('another name');
// the above was the setup, main code begins here
var copySheet = sheet1.copyTo(ss2);
copySheet.getRange("A1:B2").copyTo(sh2.getRange("C1:D2"));
ss2.deleteSheet(copySheet);
}

copyTo using {contentsOnly:true} not working

As a caveat, I am very new to Google Apps scripting. I appreciate any assistance that can be provided.
I am trying to copy the contents of a sheet into a new document. This code works without any problem:
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
However, this copies over the formulas from the current sheet - I am trying to copy the values only, as the formulas reference data on other sheets in the original document.
My attempt to do this is as follows:
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet, {contentsOnly:true})
However, this generates the following error: Cannot find method (class)copyTo($Proxy914,object).
I am unsure what I am doing wrong. Any assistance would be appreciated. Thanks in advance!
There are actually 2 copyTo, one applies to sheet and the other applies to Range
According to the documentation (see links above), the second one has optional argument to copy values only while the first has not.
What I guess you could do is use the Range.copyTo() to copy the whole sheet range to a temporary sheet (in the same spreadsheet) and then copy that temporary sheet to the other spreadsheet and finally delete the temporary sheet from the source spreadsheet.
Hoping it is clear enough ;-)
In the script gallery there is a script called spreadsheetFrozenBackup, through which a copy of a spreadsheet can be made.
The range.copyTo that Serge alludes to is used.
It is not a long script, so I reproduce it here for information:
// Make copy of current spreadsheet with backup name.
function spreadsheetFrozenBackup() {
// Get current spreadsheet.
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Name the backup spreadsheet with date.
var bssName = ss.getName() + " frozen at " + Utilities.formatDate(new Date(), "GMT", "yyyyMMdd HHmmss");
var bs = SpreadsheetApp.openById((DocsList.copy(DocsList.getFileById(ss.getId()), bssName)).getId());
// Make sure all the formulae have been evaluated...
SpreadsheetApp.flush();
// Get all the sheets in the spreadsheet
var bsl = bs.getSheets();
var pl = "";
for (var i = 0; i < bsl.length; i++) {
bsl[i].getDataRange().copyTo(bsl[i].getDataRange(), {contentsOnly:true});
pl = pl + " " + bsl[i].getName();
SpreadsheetApp.getActiveSpreadsheet().toast(pl, "Processed Sheets");
}
SpreadsheetApp.getActiveSpreadsheet().toast(bssName, "Frozen Backup");
}