In this spreadsheet there are 3 sheets. One called Juniper, one called Archive Juniper, and one called Template Juniper.
On a daily basis staff fill out the Juniper form. On a time based trigger I need delete the old "Archive Juniper", rename "Juniper" to "Archive Juniper", and copy "Template Juniper" to "Juniper". Effectively it just archives yesterday's and creates a new blank one based off of a template.
My code is below. It worked very well for quite a white but a few days ago it stopped working. I'm not a programmer so any help would be fantastic. I'm getting an invalid argument error on the ss.setActiveSheet(ss.getSheetByName(mainSheet));
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = 0;
var template = 0;
var mainSheet = 0;
var archive = 0;
var templateSheet = 0;
var sheet = 0;
mainSheet = ('Juniper');
template = ('Template '+mainSheet);
archive = ('Archive '+mainSheet);
ss.setActiveSheet(ss.getSheetByName(archive));
ss.deleteActiveSheet()
ss.setActiveSheet(ss.getSheetByName(mainSheet));
ss.renameActiveSheet(archive)
templateSheet = ss.getSheetByName(template);
ss.insertSheet(mainSheet,ss.getSheets().length,{template:templateSheet });
ss.moveActiveSheet(1);
Sorry for the ugly code, I'm awful at best.
-Jon
That error should only occur if the script can't find a sheet with the name 'Juniper' and returns null into the method that makes it active. I've cleaned up the code a bit to remove the extra stuff, can you tell us if this works?
EDIT: I tried it out and had issues, too. The code below works for me.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mainName = "Juniper";
var mainSheet = ss.getSheetByName(mainName);
var templateName = "Template " + mainName;
var templateSheet = ss.getSheetByName(templateName);
var archiveName = "Archive " + mainName;
var archiveSheet = ss.getSheetByName(archiveName);
ss.setActiveSheet(archiveSheet);
SpreadsheetApp.flush();//Makes sure the sheet is active before deleting
ss.deleteActiveSheet();
mainSheet.setName(archiveName);
//Inserts it as first sheet, so no need to move it
ss.insertSheet(mainName,0,{ template : templateSheet });
Related
I have the below code to take a list of events in a Google Sheet and schedule them into a Google Calendar.
function addEvents(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var calId = ss.getRange("C4").getValue();
var cal = CalendarApp.getCalendarById(calId);
var lr = ss.getLastRow();
var data = ss.getRange("B9:F" + lr).getValues();
for(var i = 0;i<data.length;i++){
cal.createEvent(data[i][0], data[i][1], data[i][2], {location: data[i][3], description: data[i][4]});
}
}
I've used this script before with no issues, but now I'm getting the following error message and can't for the life of me figure out what is going on:
TypeError: Cannot read property 'createEvent' of null
I ultimately would like to add an if statement to this code that grabs the newly created Event ID and puts it in the last column of the data on the sheet, and I would like to be asking for help with that, but at this point I just need step one to work.
Any thoughts?
I've been using Excel for the longest time but would now need to use Google sheet for the new company that I work for. Seems like it is harder than I expected.
I am creating a form to track how long an employee finishes a certain task for a client.
A simple form that I created where I hide the details on Form!F1:J1 (F1 - Time now, G1 - Name of employee, H1 - Client name, I1 - task done and J1 - Start/End the task
I just want to copy and paste the values to the next empty row on the Tracker sheet.
I tried to search previous answers but doesn't seem to work. I always get an error message:
"ReferenceError: database is not defined"
on the var copyToSheet = database.getSheetByName('Tracker!A1'); part. Here's what I got.
function Done() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var source = ss.getSheetByName('Form');
var dataToCopy = source.getRange('F1:J1');
var copyToSheet = database.getSheetByName('Tracker!A1');
var sourceValues = dataToCopy.getValues();
var lastRow = copyToSheet.getLastRow();
copyToSheet.getRange(lastRow + 1, 1, sourceValues.length, sourceValues[0].length).setValues(sourceValues);
dataToCopy.clear({
contentsOnly: true
});
}
I was able to find the correct code somewhere and just changed it a bit.
function Done() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Form");
var pasteSheet = ss.getSheetByName("Tracker");
var source = copySheet.getRange(1,6,1,5); //from which row number, from which column number, 1, how many cells to copy
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,1,5);
source.copyTo(destination,{contentsOnly:true});
//this is to delete what you input on the form after it copies and pastes to the tracker
var ss = SpreadsheetApp.getActive().getSheetByName("Form");
var cell = ss.getRange("C4:C7");
cell.clearContent();
};
So the gist of my project is to copy new data added to spreadsheet A to spreadsheet B. The intention is to use spreadsheet A as an input method and spreadsheet B as a log of all data input into A from all of time. A master sheet so to speak. Note that this will be run on a time-based trigger and all data from sheet a will be deleted.
I've taken some code from Stackoverflow (thank you to who made it) and made some changes. I'm able to copy over the first set of data from A to B but when I delete the data from A, add new data and run the code I lose all I've input in B. I may as well have use =importrange.
My solution was logical and to take the getLastRow of B and put this before setting setValues. Theoretically, this should get the last row of B and input the new data from A into the last row of B. Easy right, NO, I've been trying to figure this out for days and many hours reading similar cases but I'm not able to get past this hurdle.
I'm speculating that I've misunderstood something in my variable SRange, A1Range or SData.
Any help would be super helpful.
function CopyDataToNewSheet() {
var sss = SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXX');
var ss = sss.getSheetByName('Sheet1');
var lr = ss.getLastRow();
var lc = ss.getLastColumn();
var SRange = ss.getRange(2,1,lr,lc);
var A1Range = SRange.getA1Notation();
var SData = SRange.getValues();
var tss = SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXX');
var ts = tss.getSheetByName('Sheet1');
var tlr = ts.getLastRow()+1;
Logger.log(tlr);
tlr.getRange(A1Range).setValues(SData);
}
function CopyDataToNewSheet() {
var ss=SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXX');
var sh=ss.getSheetByName('Sheet1');
var srg=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn());
var dA=srg.getValues();
var tss=SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXX');
var tsh=tss.getSheetByName('Sheet1');
tsh.getRange(tsh.getLastRow()+1,1,dA.length,dA[0].length).setValues(dA);
}
I'm new to Google Apps Script and I'm trying without luck to automate a previously manual process. The script is within a sheet which takes form responses, converts them to a document and then emails the respondent with a copy. Here's the code in question:
function createDocFromSheet(){
var templateid = "1E7zzpvDF0U66aNqJdkUqjONx4wQRarkcWDy28NVqafU"; // get template file id
var folder = DriveApp.getFolderById("1-8lae1z_Z-Sy1IczUyB2JvCqCBV8zB5D")// folder name of where to put completed quotes
// get the data from sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues();
var username = Session.getActiveUser(); // get their email
var dateNow = new Date(); // get date, clumsily
var dateD = dateNow.getDate();
var dateM = dateNow.getMonth();
var dateY = dateNow.getYear();
// for each row, fill in the template with response data
for (var i in data){
var row = data[i];
// make copy and set active
var docid = DriveApp.getFileById(templateid).makeCopy(row[7]+" - Postal Quote",folder).getId();
var doc = DocumentApp.openById(docid);
var body = doc.getActiveSection();
// date - working
body.replaceText("%D%", dateD);
body.replaceText("%M%", dateM+1);
body.replaceText("%Y%", dateY);
// address - working
body.replaceText("%FNAME%", row[2]);
body.replaceText("%SNAME%", row[3]);
body.replaceText("%ADDL1%", row[4]);
body.replaceText("%ADDL2%", row[5]);
This is setup to trigger on form submit but instead of running the script on the last row it runs for all previous responses as well. This was fine previously when responses were copied to a separate sheet and processed in bulk but I'm lost with how to make it run on only the new response.
Can anyone point me in the right direction?
Line 8; var data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues(); in this line you are getting the range A2:whatever the last row and column is, that's why it's going over the entire range.
Changing it to var data = sheet.getRange(sheet.getLastRow()-1, 1, 1, sheet.getLastColumn()).getValues(); should work.
or you can use the e parameter of the onFormSubmit event.
var getSubmission = e.range.getValues();
Have a look at the documentation for the e parameter, it's can be difficult to use in the beginning when debugging but it's very useful when you get the hang of it.
I have the following script, the idea being that when a user submits a form (and when the sheet populates that answer) it uses the information given to create a new sheet with some of the info they gave used to populate it.
So in step by step it should look like this:
User submits form
Sheet updates
Sheet creates new tab/sheet
Sheet renames newly created sheet to reflect the contents of column E
(their name)
Sheet actions an IMPORTRANGE in cell A1 of the newly
created and named sheet.
This would have to work whenever a new entry is added.
This is what I have so far, the new sheet based on a template is working but I can't figure out the rename or the IMPORTRANGE parts. If anyone could take a look and give me a hand that would be ace!
function FormSubmit(){
Logger.log('Form Submited');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var Name = sheet.getRange(lastRow, 4).getValue();
var templateSheet = ss.getSheetByName('Template');
ss.insertSheet(1, {template: templateSheet});
var sourceSheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sheetNumber, sourceSheet, newSheetName;
for( sheetNumber = 0; sheetNumber < sourceSheets.length; sheetNumber++) {
sourceSheet = sourceSheets[sheetNumber];
newSheetName = sourceSheet.getRange("E3").getValue();
sourceSheet.setName(newSheetName);
}
}
It's unclear what you are asking about "IMPORTRANGE". Sandy already wrote a way to retrieve the name from the actual form submit, however, I will go with your method of pulling it from the spreadsheet as it makes little difference to actually setting the name of the sheet.
The simplest solution is to set the name of the sheet immediately on insert. Read on that here but in essence what we would do is instead of
ss.insertSheet(1, {template: templateSheet});
instead, let's say you store the name in a variable newSheetName. Then we will have
ss.insertSheet(newSheetName, 1, {template: templateSheet});
or if you do not care where the sheet is inserted (or to be exact you want it to be at the end) this also works:
ss.insertSheet(newSheetName, {template: templateSheet});
Now I would also like to address this block in general:
var sourceSheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sheetNumber, sourceSheet, newSheetName;
for( sheetNumber = 0; sheetNumber < sourceSheets.length; sheetNumber++) {
sourceSheet = sourceSheets[sheetNumber];
newSheetName = sourceSheet.getRange("E3").getValue();
sourceSheet.setName(newSheetName);
}
to start, var sourceSheets = SpreadsheetApp.getActiveSpreadsheet().getSheets(); can be entirely replaced with var sourceSheets = ss.getSheets() as you already retrieved the spreadsheet.
This block will perform a name set for all of your sheets. Which is something you might not want as you have your form responses as well as the template sheet.