I'm very new to Javascript and Apps Script I'm looking to create a function that updates another sheet based on the date in a specific range of the active sheet. I run and there are no errors but it is not transferring the values from the active sheet to the named sheet "January".
Please help me see what I'm not seeing.
function myFunction2() {
const spreadsheetIds = ["https://docs.google.com/spreadsheets/d/1FpZZJrYrVqHLSCp3i5vY0qGWPOFD7lsUKu1DIa52C18/edit#gid=0"];// Please set your spreadshet IDs.
const srcSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = srcSpreadsheet.getSheetByName("January");
if (!srcSheet) return;
const values = srcSheet.getRange("A2:D32").getValues();
if (values.filter(r => r.join("")).length == 0) return;
for (let i = 0; i < spreadsheetIds.length; i++) {
const dstSpreadsheet = SpreadsheetApp.openById(spreadsheetIds[i]);
const targetSheet = dstSpreadsheet.getSheetByName("Cab5");
if (targetSheet) {
targetSheet.getRange(targetSheet.getLastRow() + 1, 3, values.length,
values[0].length).setValues(values);
}
}
}
Master data
output 1 user 2
I want to send data, but it's a different Google Drive email
Master data gmail#gmail.com
send data to
output 1 user 2 yahoo#gmail.com
Modification points:
In your script, spreadsheetIds has the URL. By this, I think that an error occurs at SpreadsheetApp.openById(spreadsheetIds[i]);. But, you say I run and there are no errors. So, I'm worried that you might have miscopied your script.
From transferring the values from the active sheet to the named sheet "January", in this case, I think that const srcSheet = srcSpreadsheet.getSheetByName("January"); is const srcSheet = srcSpreadsheet.getActiveSheet();. And, const targetSheet = dstSpreadsheet.getSheetByName("Cab5"); is const targetSheet = dstSpreadsheet.getSheetByName("January");.
About copy.to send data, but it's a different Google Drive email, in this case, please confirm that you have permission for putting the values to the Spreadsheet of another user account. If you don't have it, an error occurs at const dstSpreadsheet = SpreadsheetApp.openById(spreadsheetIds[i]);. Please be careful about this. Before you test the script, please confirm whether the destination Spreadsheet has already been shared with your account as the writer.
When these points are reflected in your script, it becomes as follows.
Modified script:
function myFunction2() {
const spreadsheetIds = ["1FpZZJrYrVqHLSCp3i5vY0qGWPOFD7lsUKu1DIa52C18"]; // Modified
const srcSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = srcSpreadsheet.getActiveSheet(); // Modified
if (!srcSheet) return;
const values = srcSheet.getRange("A2:D32").getValues();
if (values.filter(r => r.join("")).length == 0) return;
for (let i = 0; i < spreadsheetIds.length; i++) {
const dstSpreadsheet = SpreadsheetApp.openById(spreadsheetIds[i]);
const targetSheet = dstSpreadsheet.getSheetByName("January"); // Modified
if (targetSheet) {
targetSheet.getRange(targetSheet.getLastRow() + 1, 3, values.length,
values[0].length).setValues(values);
}
}
}
Related
I've struggled with this for a while & have put it off because I've always been able to just edit the SOURCE spreadsheet and add an IF statement with the TABNAME.
Meaning, in an adjacent column, I'll write, if Cell = blank, do nothing, if not give me tab name.. then I'll simply include that column in my import.
After putting off the true issue for a while, I'm unable to edit the source sheet in this instance -- causing me to go down a rabbit hole of trying to alter this script.
Here's what I have:
A script that imports sheet to sheet (prefer this over importrange):
function scheduleimport() {
//#NotOnlyCurrentDoc
var values = SpreadsheetApp.openById('spreadsheetID').
getSheetByName('SourceSheet').getRange('A1:N').getValues();
SpreadsheetApp.getActive().getSheetByName('DestinationSheet').
getRange(1,1,values.length,values[0].length).setValues(values);}
This works super well & I've lived off it for a while...
What I'm looking to accomplish is putting the TABNAME of the source sheet in the column right next to the import range (only in cells where the range has values - not the entire destination sheet).
I came across this script that uses the length of a specific column & places a value wherever designated. I tweaked it to include the TABNAME:
function fillColB() {
var s = SpreadsheetApp.getActiveSheet();
tabname = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var data = s.getRange("a1:a").getValues();
var data_len = data.length;
for(var i=0; i<data_len; i++) {
if(data[i][0].length == 0) {
s.getRange(i+1,2).setValue("");
} else {
s.getRange(i+1,2).setValue(tabname);
}
}
}
I tried tying these together - essentially, getting the length of the import, and adding in the TABNAME as a value next to the last column. I am struggling heavy with it though -- any guidance would be much appreciated.
How about this:
function scheduleimport() {
const ss = SpreadsheetApp.openById('spreadsheetID');
const sh1 = ss.getSheetByName("SourceSheet");
const vs = sh1.getRange('A1:N' + sh1.getLastRow()).getValues();
const sh2 = ss.getSheetByName('DestinationSheet');
sh2.getRange(1, 1, vs.length, vs[0].length).setValues(vs);
sh2.getRange(1,sh2.getLastColumn() +1).setValue(sh1.getName());
}
I may have read you code incorrectly but for an import I would think that you might wish the source spreadsheet and the destination spreadsheet to be different. So this next one provides that functionality
function scheduleimport() {
const ss = SpreadsheetApp.openById(gobj.globals.testsourceid);//ids are coming from global object in the active sheet
const dss = SpreadsheetApp.getActive();
const sh1 = ss.getSheetByName("Sheet0");
const vs = sh1.getRange('A1:N' + sh1.getLastRow()).getValues();
const sh2 = dss.getSheetByName('Sheet1');
sh2.getRange(1, 1, vs.length, vs[0].length).setValues(vs);
sh2.getRange(1,sh2.getLastColumn() +1).setValue(sh1.getName());
}
Putting the sheet name into a newlast column on all rows of the transferred data set.
function scheduleimport() {
const ss = SpreadsheetApp.openById(gobj.globals.testsourceid);//ids are coming from global object in the active sheet
const dss = SpreadsheetApp.getActive();
const sh1 = ss.getSheetByName("Sheet0");
const vs = sh1.getRange('A1:N' + sh1.getLastRow()).getValues();
const sh2 = dss.getSheetByName('Sheet1');
sh2.getRange(1, 1, vs.length, vs[0].length).setValues(vs);
sh2.getRange(1,sh2.getLastColumn() +1,vs.length).setValue(sh1.getName());
}
I'm trying to run this code that will get the first 7 columns from sheet1 in spreadsheet1 and paste them in sheet2 in spreadsheet2, but im keep getting this error which I dont know why.
Exception: The number of rows in the range must be at least 1. 6th line
function MoveCode(){
const ss1 = SpreadsheetApp.getActive();
const ss2 = SpreadsheetApp.openById("1zU__ccPIMst54whmyrbmRnDRRjOtQBFPzXhw6NsFqpU");//or url whatever
const ssh = ss1.getSheetByName('Sheet1');
const dsh = ss2.getSheetByName('Sourcing');
const vs = ssh.getRange(2,1,ssh.getLastRow() - 1,7).getValues();
dsh.getRange(2,1,vs.length,vs[0].length).setValues(vs);
}
test3 is the spreadsheet that i want to paste the data to
from.
If you need anymore explanation please let me know
I think that in your script when ssh.getLastRow() is less than 2, such an error occurs. Because ssh.getLastRow() - 1 is 0 and -1. For example, I think that when the sheet "Sheet1" has only the header row and no values, such an error occurs. In order to remove this issue, how about the following modification?
Modified script:
function MoveCode(){
const ss1 = SpreadsheetApp.getActive();
const ss2 = SpreadsheetApp.openById("###");//or url whatever
const ssh = ss1.getSheetByName('Sheet1');
const dsh = ss2.getSheetByName('Sourcing');
const lastRow = ssh.getLastRow();
if (lastRow < 2) return;
const vs = ssh.getRange(2, 1, lastRow - 1, 7).getValues();
dsh.getRange(2, 1, vs.length, vs[0].length).setValues(vs);
}
By this modification, when the sheet "Sheet1" has only the header row and no values, the script is finished.
Added:
From your replying and adding the sample images, when I saw your images, I thought that in your script, ssh and dsh are used as the source sheet and destination sheet, respectively. But in your sample image, I thought that you might want to use ssh and dsh as the destination sheet and the source sheet, respectively. If my understanding is correct, how about the following sample script?
Modified script:
In this case, please be careful about SpreadsheetApp.getActive() and SpreadsheetApp.openById("###") for each sheet.
function MoveCode(){
const ss1 = SpreadsheetApp.getActive();
const ss2 = SpreadsheetApp.openById("###");//or url whatever
const ssh = ss1.getSheetByName('Sheet1');
const dsh = ss2.getSheetByName('Sourcing');
const lastRow = dsh.getLastRow();
if (lastRow < 2) return;
const vs = dsh.getRange(2, 1, lastRow - 1, 7).getValues();
ssh.getRange(2, 1, vs.length, vs[0].length).setValues(vs);
}
I am a beginner with JavaScript and have been taking courses for a few months. I have a couple of scripts I have written so far that are up and running. I have an issue that I can’t get past which is very important to find a resolution for, so I’m hoping someone can help.
I have google survey’s that are being submitted and an on even form generator script that creates a form and produces a link in google sheets. The problem I’m having is that I need to be able to filter forms that belong to certain person on to a different spreadsheet using a script. I have written the script a few ways to try to achieve this but have been unsuccessful. The script works as intended but it removes the form generator links when it’s copied or moved.
Here is the filter script I had written:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var trn = ss.getSheetByName('Hull - NY');
var originalData = trn.getRange(2, 1, trn.getLastRow() - 1, 12).getValues();
var centerManager = 'Brooks, Robert';
if (trn.getColumn() == 3 && trn.getValue() == 'Brooks, Robert') {
var r = originalData.getRow();
var data = originalData.filter(function (item) {
return item[1] === centerManager;
});
var targetSheet = ss.insertSheet(centerManager);
targetSheet.getRange(2, 1, data.length, data[0].length).setValues(data).getLastRow();
}
}
I appreciate any help that could be provided!
You must read the formulas and then use the formula instead of the cell value, where a formula exist.
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const trn = ss.getSheetByName('Hull - NY');
const sourceRange = trn.getDataRange()
const originalValues = sourceRange.getValues();
const originalFormulas = sourceRange.getFormulas()
const centerManager = 'Brooks, Robert';
const MANAGER_COL = 2
const data = []
originalValues.forEach((row,i)=>{
if(row[MANAGER_COL-1] === centerManager){
originalFormulas[i].forEach((formula,i)=>{
if(formula[i]){
row[i] = formula
}
})
data.push(row)
}
});
const targetSheet = ss.insertSheet(centerManager);
if(data.length>0){
targetSheet.getRange(2, 1, data.length, data[0].length).setValues(data).getLastRow();
}
}
I am building on a previous project in which I have a Google Form which takes responses in a Google Sheet and uses a template Sheet to populate the Form responses and have that generate a new Sheet document. This is a very dumbed-down version of what I'm trying to execute in reality, but the goals remain the same: I am trying to replace text across multiple tabs in the template Sheet when generating a new one.
Currently, in my Apps Script, I have code which is successfully able to make a copy of the template file and name it accordingly:
//Enter collected info into Requirements Template
const googleSheetTemplate = DriveApp.getFileById('1wqCwMhpuDLReU1hE1CbcDL-Vdw_4zge1xM6oOl34Ohg');
const destinationFolder = DriveApp.getFolderById('1GxNZQmP8mxHBhVl5AMoqBFs8sAIYzcm3');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 2');
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId());
const A1 = newSheet.getDataRange();
And the next few lines which are meant to be able to find and replace certain strings within the newly copied Sheet are as follows:
A1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
A1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
A1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
A1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
The issue I am experiencing is that the first tab of the Sheet gets populated, but the second tab does not.
Is there more I must add somewhere in order to get the second tab filled out? Is this even possible in Google Apps Script?
Entire code below:
function myFunction() {
// get the spreadsheet information
const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//const responseSheet = ss.getSheetByName('Form Responses 2');
const data = ss.getDataRange().getValues();
//console.log(data);
// Loop over the rows
data.forEach((row,i) => {
// Identify whether notification has been sent
if (row[4] === '') {
// Get the Form info
var emailTo = "jeffreyabr#gmail.com"
var subject = 'Car Request';
const Timestamp = row[0];
var Car = row[1];
var Color = row[2];
var requestor = row[3]
var delivery = row[5];
//Form variable declarations
formTime = Timestamp;
formCar = Car;
formColor = Color;
formName = requestor;
formDelivery = delivery;
//Enter collected info into Requirements Template
const googleSheetTemplate = DriveApp.getFileById('1wqCwMhpuDLReU1hE1CbcDL-Vdw_4zge1xM6oOl34Ohg');
const destinationFolder = DriveApp.getFolderById('1GxNZQmP8mxHBhVl5AMoqBFs8sAIYzcm3');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 2');
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId());
const A1 = newSheet.getDataRange();
A1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
A1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
A1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
A1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
const orderLink = newSheet.getUrl();
//Add URL to Sheet
sheet.getRange(i + 1, 7).setValue(orderLink)
orderBlob = [];
//Get the blob of order attachment
if(row[6]){
var order1 = row[6].split(', ');
order1.forEach(url => {
var orderFileId = url.replace('https://drive.google.com/open?id=','');
var orderFile = DriveApp.getFileById(orderFileId);
orderBlob.push(orderFile.getBlob());
});
}
let body = '';
// Generate email
var html = HtmlService.createTemplateFromFile("email.html");
var htmlText = html.evaluate().getContent();
// Send email
GmailApp.sendEmail(emailTo, subject, body, {htmlBody: htmlText, attachments: orderBlob})
// Mark as Notified
const g = 'Notification sent';
ss.getRange(i + 1,5).setValue(g);
}
})
}
Answer
You can try a looping method to access all of the sheet tabs inside of your newSheet Spreadsheet file using the getSheets() method.
Just replace part of your script from the creation of newSheet to the last line of A1.createTextFinder with the script below:
[UPDATED]
Sample Script
const newSheet = SpreadsheetApp.openById(copy.getId());
for (currentSheet = 0; currentSheet < newSheet.getSheets().length; currentSheet++) {
const a1 = newSheet.getSheets()[currentSheet].getDataRange();
a1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
a1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
a1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
a1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
}
Sample Test:
Sample copy of the newSheet file w/ 2 sheet tabs
Script test demonstration
The newSheet file that contains 2 sheet tabs:
Sheet 1
Sheet 2
I would like to clone/copy a google sheet and locate it in a drive, The script i have at the moment is working for this element but the contents appear blank becuase of formulas/importranges
Please can you help with this. Current script is
function cloneGoogleSheet2() {
const destFolder = DriveApp.getFolderById("xxxxxxxxxxx");
const file = DriveApp.getFileById("xxxxxxxxxxxxxxx").makeCopy("xxxxxxxxx", destFolder);
const ss = SpreadsheetApp.openById(file.getId());
const sheets = ss.getSheets();
sheets.forEach(sh=>{
let rng = sh.getDataRange();
rng.copyTo(rng, {contentsOnly:true});
SpreadsheetApp.flush();
});
}
Reference to similar question below
Copy a spreadsheet file to Google Drive and replace all the formulas with values
Explanation:
Unfortunately:
importranges can not be allowed programmatically. So you need to set get the values from the source spreadsheet and paste them to the newly created (target) spreadsheet.
copyTo can not be used between two different spreadsheets, so you can use getValues and setValues instead.
The logic is to iterate over the source sheets and for every sheet get values and copy them to the corresponding target sheets.
Solution:
function cloneGoogleSheet2() {
const destFolder = DriveApp.getFolderById("folder_id");
const source_id = "spreadsheet_id_to_copy";
const source_ss = SpreadsheetApp.openById(source_id);
const file = DriveApp.getFileById(source_id).makeCopy("new_file", destFolder);
const target_ss = SpreadsheetApp.openById(file.getId());
const source_sheets = source_ss.getSheets();
const target_sheets = target_ss.getSheets();
source_sheets.forEach((sh,i)=>{
let values = sh.getDataRange().getValues();
target_sheets[i].getDataRange().setValues(values);
SpreadsheetApp.flush();
})
}