I have a dashboard on a gsheet spreadsheet, with one sheet being an overview. It has tables generated by various QUERY Functions. I want to create a script that would make a copy of this sheet only, and save it into a new Spreadsheet, stored on a Google Drive folder.
I managed to do this, but then the result does not display my queries, it just copies the formula.
Here is my code :
function CopyToSpreadSheet() {
//Source sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
//Name new sheet in target SpreadSheet
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = SpreadsheetApp.getActiveSpreadsheet().getName() + " Archive " + formattedDate;
//Create new spreadsheet
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
//open target SpreadSheet
var target = SpreadsheetApp.openById(newss_id);
//CopyTo...
var targetSheet = sourceSheet.copyTo(target);
targetSheet.setName(name);
return;
}
So, i've been trying the CopyTo parameters {contentsOnly:true} and SpreadsheetApp.CopyPasteType.PASTE_VALUES, which gives me The parameters (SpreadsheetApp.Spreadsheet,(class)) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the ContentsOnly parameter, and The parameters (SpreadsheetApp.Spreadsheet,SpreadsheetApp.CopyPasteType) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the CopypasteType.
At this point, I have no idea how to fix this, but it is clearly coming from me not knowing how to handle this. I've also tried to use .makeCopy, but there was no parameter to force the copy to use the Values and not the formula in itself.
Any ideas? I'm open to anything at this point!
Thanks in advance :)
I believe your goal is as follows.
From your title of Google App Script : Pasting Values only in new spreadsheet and I want to create a script that would make a copy of this sheet only, and save it into a new Spreadsheet, stored on a Google Drive folder., you want to copy only the values from the source sheet to the target sheet in a new Spreadsheet by using Google Apps Script.
Modification points:
First, about the reason for your issue of So, i've been trying the CopyTo parameters {contentsOnly:true} and SpreadsheetApp.CopyPasteType.PASTE_VALUES, which gives me The parameters (SpreadsheetApp.Spreadsheet,(class)) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the ContentsOnly parameter, and The parameters (SpreadsheetApp.Spreadsheet,SpreadsheetApp.CopyPasteType) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the CopypasteType., I thought that you might have used the method of copyTo(destination, options) of Class Range to Class Spreadsheet. If my understanding is correct, such an error occurs and the reason for this is due to it.
In order to copy only the values from a source sheet to a destination sheet, I thought that there might be the following 2 patterns.
Pattern 1:
In this pattern, getValues and setValues are used.
function CopyToSpreadSheet() {
// Source sheet side.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
var range = sourceSheet.getDataRange();
// This is from your script.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = ss.getName() + " Archive " + formattedDate;
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
// Destination sheet side.
var target = SpreadsheetApp.openById(newss_id);
var targetSheet = target.getSheets()[0];
targetSheet.setName(sourceSheet.getSheetName()); // If you don't want to rename sheet name, please remove this line.
targetSheet.getRange(range.getA1Notation()).setNumberFormats(range.getNumberFormats()).setValues(range.getValues());
}
When this script is run, only the values are copied from the source sheet to the destination sheet. In this sample, the number format is also copied.
Pattern 2:
In this pattern, copyTo methods of Class Sheet and Class Spreadsheet are used.
function CopyToSpreadSheet() {
// Source sheet side.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
var tempSheet1 = sourceSheet.copyTo(ss);
var tempRange1 = tempSheet1.getDataRange();
tempRange1.copyTo(tempRange1, { contentsOnly: true });
// This is from your script.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = ss.getName() + " Archive " + formattedDate;
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
// Destination sheet side.
var target = SpreadsheetApp.openById(newss_id);
var tempSheet2 = tempSheet1.copyTo(target);
var targetSheet = target.getSheets()[0];
targetSheet.setName(sourceSheet.getSheetName()); // If you don't want to rename sheet name, please remove this line.
const tempRange2 = tempSheet2.getDataRange();
tempRange2.copyTo(targetSheet.getRange("A1"));
// Remove temp sheets.
ss.deleteSheet(tempSheet1);
target.deleteSheet(tempSheet2);
}
When this script is run, not only the values but also background colors, font styles, and so on are copied from the source sheet to the destination sheet.
References:
getValues()
setValues(values)
copyTo(spreadsheet) of Class Sheet
copyTo(destination, options) of Class Range
Since no example given I'm assuming you are using the Query function without importrange which only works within the same spreadsheet.
Try:
=query(importrange("URL", "Dashboard!A1:A"), "select Col1", 0)
Replace the URL with your Source Spreadsheet URL and the Range to refer to.
Source Spreadsheet:
Result:
This is the result I got using your code, only the drive folder ID was changed. I am able to get the actual data/values not only the formula.
Explanation:
The reason is using the normal Query function it can only get data from the same Spreadsheet file. Same with normally pasting your Query formula in a different spreadsheet, it will not be able to get the data. For it to be able to Query data from other Spreadsheet you need to use it with importrange.
Also don't forget to change access to the file so those who use it for Query will actually be able to retrieve the data.
Reference:
Query From Another Spreadsheet
Related
Original Question:
I have multiple tabs in a Google Spreadsheet that represent different data sources. Currently, I have a variable (var = quote1location) that is equal to the sheet name that I would like to get my data from based on other logic.
Pretend that quote1location can equal 'Sheet1', 'Sheet2', or 'Sheet3' depending on the logic but for this case, it equals 'Sheet1'.
var totalpeople = quote1location.getRange('A1').getValue();
In the function above, Apps Script will return an error saying 'quote1location.getRange is not a function' because Apps Script is not substituting the value of the variable that I have designated ('Sheet1') but is using the variable name ('quote1location' instead. I would like Apps Script to process this as 'Sheet1.getRange('A1').getValue()'.
Your help would be appreciated
Answer:
Thank you all for your responses. What I was trying to do is use a string in the 'getRange()' function. Pretend I had two Google Sheets named 'Sheet1' and 'Sheet2' and I had a variable that helped me determine what sheet to grab as my data reference. I was trying to set a variable as either (var source = 1) or (var source = 2) so that I could then use this variable in my getRange() function like this: ('Sheet' + source).getRange('A1').getValue();
What I was trying to do here is if var source = 1, then I would get my data from 'Sheet1'. If the var source = 2, then I would get my data from 'Sheet2'.
The issue (as mentioned by those who responded) is that I was trying to use .getRange() on a string, not an object like a specific spreadsheet. Instead of using var source = 2 or var source = 1 I should be using
ss = SpreadSheetApp.getActiveSpreadsheet()
if(somevariable = somecondition){
var source = ss.getSheetbyName('Sheet1')
}
if(someothervariable = someothercondition){
var source = ss.getSheetByName('Sheet2')
}
Now when I use getRange()' on 'source', it will be calling the sheet that I have designated rather than trying to retrieve a range from a string which will not work.
Thank you very much to all who provided feedback.
I believe you are looking to do:
const quote1Location = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(`Sheet1`)
const totalPeople = quote1Location.getRange(`A1`).getValue()
Alternatively:
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
const quote1Location = `Sheet1`
const totalPeople = spreadsheet.getSheetByName(quote1Location)
.getRange(`A1`)
.getValue()
Whether these are the exact syntax you're hoping to use or not, I hope this helps you better understand how to accomplish accessing a Sheet.
I am using Google Sheets copyTo function. There are formulas in cells M2:P10 that are calculating a value from another sheet. I'm simply trying to use the copyTo function to paste the values to another sheet, but the pasting function results in blank output. I can't figure out why as everything seems perfectly fine here. Help!
var id = "1I7Ptwg26W_WrLty9y7U-8c8kGKS9t8aw3SF-M2JwgJ1";
var ss2 = SpreadsheetApp.openById(id).getSheetByName('Converted Data');
var ss5 = SpreadsheetApp.openById(id).getSheetByName('PastedConverted');
ss2.getRange('M2:P10').activate();
ss2.getRange('M2:P10').copyTo(ss5.getRange("M2:P10"), {contentsOnly:true});
Before:
After:
Well I am unsure why this works but not the other way around, but figured I'd give you what worked for me:
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('MyPage'), true);
spreadsheet.getRange('M:AB').activate();
spreadsheet.getRange('\'MyPage\'!M:AB').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
Although you have already posted an answer I think that the way you solved your problem is not the most optimal one.
Just to illustrate how the method copyTo() works.
You have an origin rang (the range you want to copy from) in which you invoke the copyTo() and the target(the place you want to copy to) as the input parameter.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ss1 = ss.getSheets()[0];
var ss2 = ss.getSheets()[1];
var origin = ss1.getRange("A1:A5");
var target = ss2.getRange("A1:A5");
origin.copyTo(target);
}
Adittionaly you can add more options to copy just the thing you need with the CopyPasteType.
Goal: Trying to copy part of some text from one cell on a spread sheet and pasting it on to another one.
I am still new to Javascript to please forgive if im going about this all wrong.
So on one spread sheet some information gets populated automatically from a service I use. I want to take part of that information and copy and paste it onto another spread sheet.
For this example the date gets populated in the cell A1 "February 28, 2017 at 10:38AM." I want to only copy the date February 28, 2017 and paste it onto another google sheet.
This is what my current code looks like:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("abc1234");
var source_sheet = ss.getSheetByName("Text");
var target_sheet = target.getSheetByName("Bills");
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A1:D4");
var cell = range.getCell(1, 1);
var string1 = cell.getValue();
var string2 = string1.split(" ", 2);
var target_range = target_sheet.getRange("J4");
string2.copyTo(target_range);
//Logger.log(string2);
}
The error I receive when i do this is:
TypeError: Cannot find function copyTo in object February,28,. (line 13, file "Test")
This maybe something simple i jsut cont figure it out
You need to use .setValue() to set the value of the range. So to set your range to the value in string2 you would replace line 13 with:
target_range.setValue(string2);
See the Tutorials for some examples of scripts. Especially the Workflows and end-to-end examples.
Modified script .. works when run manually, setvalue(date) does not work when run on time trigger. Needs another tweak ... ideas please?
function getData() {
var queryString = Math.random();
var ss = SpreadsheetApp.openByUrl('spreadsheet URL');
var cellFunction = '=IMPORTHTML("stats URL' + queryString + '","table",1)';
var timezone = "GMT+1";
var timestamp_format = "EEE, MMM d '#' HH:mm"; // Timestamp Format.
var date = Utilities.formatDate(new Date(), timezone, timestamp_format);
Logger.log(ss.getName());
SpreadsheetApp.getActiveSheet().getRange('AH1').setValue(date);
SpreadsheetApp.getActiveSheet().getRange('AF1').setValue(cellFunction);
There is no "ActiveSheet" when running on time trigger, hence it becomes undefined, use one of these methods from SpreadsheetApp to retrive the spreadsheet:
open(file)
Spreadsheet Opens the spreadsheet that corresponds to the given
openById(id)
Spreadsheet Opens the spreadsheet with the given ID.
openByUrl(url)
Spreadsheet Opens the spreadsheet with the given url.
and after it get the sheet with one of the following methods:
getSheetByName(name) Returns a sheet with the given name.
getSheets()[ indexOfTheSheet ] Returns a sheet with the given 0 based index
First off, here are two basic spreadsheets for what I am talking about:
Page one: https://docs.google.com/spreadsheets/d/1GZs_I9_beIO9xYBXatoxStRMmk9Aj3-UxPQpB9-iA-I/edit?usp=sharing
Page two: https://docs.google.com/spreadsheets/d/1R86_0SrAtyIJPAhMW0Ura-3gwOLn5l9u7Seuj2V0YCA/edit?usp=sharing
Essentially I am using a Google script to "update" the spreadsheet titled "The copy to update". This copy will automatically copy all of the pages from "The copy to pull updates from", delete the current pages on "The copy to update", and then rename the copied sheets back to what they were before. This means that any changes I make to "The copy to pull updates from" will automatically be updated on the other spreadsheet without having to redistribute the spreadsheet.
When the button is pressed on the "Update page" sheet the pages are successfully transferred across. The changes are successfully "updated" on the to update spreadsheet. However, the page updated first in the code has errors. Any cell with a formula that acquires data from another sheets returns "#REF!" with the error "Unresolved sheet name 'Insert sheet name here'." This means that the formula/cell can not see the newly copied sheet from the script. I can remedy this situation by clicking on any cell afflicted by this and pressing enter - Essentially "refreshing" the cell. However I am doing this on a project with 100+ cells like this and I only want to have to press one button to be able to do this.
Should I try and solve this issue using script, or change my method of updating the Spreadsheet pages a different way? Thanks to all help in advance!
Here is the script that I am using:
<code>
function Update() {
//Sets the ID of the page to update from
var ID = "1R86_0SrAtyIJPAhMW0Ura-3gwOLn5l9u7Seuj2V0YCA"
//Pulls the correct sheet using the ID
var source = SpreadsheetApp.openById(ID);
//Identifies the active spreadsheet in use to update. (The spreadsheet you pressed "Update" on)
var destination = SpreadsheetApp.getActiveSpreadsheet();
//Sheet to pull and copy to the current spreadsheet
var sheet1 = source.getSheetByName("1");
//Copying the sheet accross
sheet1.copyTo(destination);
//Identifies the old copy of the sheet
var sheet1 = destination.getSheetByName('1');
//Deletes the old copy of the sheet
destination.deleteSheet(sheet1);
//Gets the new copy of the sheet
var sheet1 = destination.getSheetByName('Copy of 1');
//Renames the new copy of the sheet
sheet1.setName("1")
//Repeating the same code with page 2
//Sheet to pull and copy to the current spreadsheet
var sheet1 = source.getSheetByName("2");
//Copying the sheet accross
sheet1.copyTo(destination);
//Identifies the old copy of the sheet
var sheet1 = destination.getSheetByName('2');
//Deletes the old copy of the sheet
destination.deleteSheet(sheet1);
//Gets the new copy of the sheet
var sheet1 = destination.getSheetByName('Copy of 2');
//Renames the new copy of the sheet
sheet1.setName("2")
//Repeating the same code
}
</code>
This is related to Force formula refresh through Apps Script
I'm having the exact same problem. Most of my formulas are =ArrayFormula formulas in the first or second row. My solution iterates through all cells in the first two rows of a given Spreadsheet and reevalutes any formulas.
This could probably be cleaned up to only modify the cell if it is a formula (rather than resetting the text value for non-formulas). It could also be modified to run over an entire Spreadsheet by changing the assigned range.
You might run this function on the sheet after it has been copied to the new location, or you could call myFunction while the desired sheet is active.
function updateFormulasTwoRows(given_sheet) {
var last_col = given_sheet.getDataRange().getLastColumn();
var range = given_sheet.getRange(1,1,2,last_col);
// contains empty strings or cell formulas
var formulas = range.getFormulas();
// contains text, formula errors, formula output
var contents = range.getValues();
// formulas[0][0].length > 1 ==> is a formula
for (var r = 0; r < range.getHeight(); r++) {
for (var c = 0; c < range.getWidth(); c++) {
var cell = range.getCell(r+1,c+1);
// clear only the contents, not notes or comments or formatting.
cell.clearContent();
if (formulas[r][c].length > 1) {
// cell was a formula, so insert the formula back in place
cell.setValue(formulas[r][c]);
} else {
// cell was not a formula, so insert the text content back in place
cell.setValue(contents[r][c]);
}
}
}
}
// run this after selecting a sheet to reevalute formulas on
function myFunction() {
var curr_sheet = SpreadsheetApp.getActiveSheet();
updateFormulasTwoRows(curr_sheet);
}
Building on #bryan's answer above, I found a more efficient version of the code is the following, which performs the clearContent() and setValue() calls at the range level, rather than on each individual cell, thus saving a lot of calls to the back-end.
var updateFormulasAllRows = function updateFormulasAllRows(sheet) {
var range = sheet.getDataRange();
var formulas = range.getFormulas();
var contents = range.getValues();
var rangeWidth = range.getWidth(), rangeHeight = range.getHeight();
for (var r = 0; r < rangeHeight; r++) {
for (var c = 0; c < rangeWidth; c++) {
if (formulas[r][c].length > 1) {
contents[r][c] = formulas[r][c];
}
}
}
range.clearContent().setValues(contents);
};
This also changes the code to run over all the rows of the spreadsheet as suggested as an improvement.