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?
Related
I am getting the following error for the last line of my Apps Script code - “ Exception: The parameters (number[]) don't match the method signature for SpreadsheetApp.Range.setValues. (line 52, file "TaskCompletionDate")”
The code picks up the spreadsheet range using sheet.getDataRange() and based on certain conditions, picks values from this range to a column array called Col8.
After the array Col8 is completely written, I paste this Col8 into my spreadsheet. The error refers to this step.
Shortened version of my code is as follows:
var spreadsheet = SpreadsheetApp.openById("Spreadsheet_ID");
var sheet = spreadsheet.getSheetByName("Sheet_name");
var rows = sheet.getLastRow();
var range = sheet.getDataRange();
var values = range.getValues();
var today = new Date();
var yesterday = new Date();
yesterday.setDate(today.getDate()-1);
var Col8 = new Array(rows-1,1);
for (var i=2; i<=rows; i++)
{
if (values[i-1][1] == "Completed")
{
if (!values[i-1][8])
Col8[i-1][1].setValue(values[i-1][1]);
}
}
sheet.getRange(2,8,rows-1,1).setValues(Col8);
Spreadsheet columns can be seen here
What am I missing?
I am not a programmer, nor do I know JavaScript or Apps Script, but have been building small Apps Script snippets using the App Script documentation and other app script resources on the net.
This is the basic starting point. But I need information from your spreadsheet image in order to make sure the indices are correct. I noticed that you create today and yesterday but you don't actually use them.
function myfunvtion() {
var ss=SpreadsheetApp.openById("Spreadsheet_ID");
var sh=ss.getSheetByName("Sheet_name");
var rg=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn());
var vs=rg.getValues();
var today=new Date();
var yesterday=new Date(today.getFullYear(),today.getMonth(),today.getDate()-1);
var oA=[];
for (var i=0; i<vs.length;; i++) {
if (values[i][1]=="Completed" && !values[i][18]) {
oA.push([vs[i][1]]);//it looks like your fixing something in your spreads
}
}
sh.getRange(2,8,oA.length,1).setValues(oA);
}
So I want a google spreadsheet to take data from a calendar with two tabs. One tab will be where the data is inputted; "ss.". The second tab will be a settings tab where you can select the DateFrom, DateTo and CurrentEmail; "ssSettings". When the user enters the dates to and from, they can also see what email the script is currently getting its information from and they can change it if they want. I set the variable for "datefrom" and "dateto" but when I try to do the same for the "currentEmail" i get the following error;
TypeError: Cannot call method "getEvents" of null. (line 8, file "Code")
anyone know how to solve this? Im fairly new to google script. This is my script;
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GettingEvents")
var ssSettings = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GettingEventsSettings");
var DateFrom = ssSettings.getRange("B1").getValue();
var DateTo = ssSettings.getRange("B2").getValue();
var CurrentEmail = ssSettings.getRange("B3").getValue();
var cal = CalendarApp.getCalendarById(CurrentEmail);
var events = cal.getEvents(DateFrom, DateTo);
var lr = ss.getLastRow();
ss.getRange(2, 1, lr, 5).clearContent();
for(var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var sd = events[i].getStartTime();
var ed = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
ss.getRange(i+2,1).setValue(title);
ss.getRange(i+2,2).setValue(sd);
ss.getRange(i+2,3).setValue(ed);
ss.getRange(i+2,4).setValue(loc);
ss.getRange(i+2,5).setValue(des);
}
}
I'd like the settings tab to look like this, or something that can be edited by the user without screwing with the code.
The reason you are getting the TypeError: Cannot call method "getEvents" of null. (line 8, file "Code") is because the script you are using is not bound to the active spreadsheet. The .getActive() method returns the currently active spreadsheet, or null if there is none, which happened in your case in the code provided above.
In order to be able to interact with the Spreadsheet, you have to update your code to this:
var as = SpreadsheetApp.openById("YOUR_SPREADSHEET_ID");
var ss = as.getSheetByName("GettingEvents")
var ssSettings = as.getSheetByName("GettingEventsSettings");
The .openById() method opens the Spreadsheet with the specified id and therefore you can get the sheets by their name.
Furthermore, I suggest you take a look at these links since they might be of help in your future development:
Class SpreadsheetApp - openById();
Class SpreadsheetApp - getActive().
You can use something like this get the info on all of your calendars:
function calinfo() {
var cals=CalendarApp.getAllCalendars();
var calObj={nameA:[]};
cals.forEach(function(cal,i){calObj[cal.getName()]=cal.getId();calObj.nameA.push(cal.getName());});
Logger.log(JSON.stringify(calObj));
}
I have the following app script associated with a Google Spreadsheet that is accepting data from a Google Form:
function writePatientData() {
var spreadsheet = SpreadsheetApp.openById("<spreadsheet id>");
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//get last row in active/main sheet
var numRows = sheet.getLastRow();
//get last row of data
var last_row = sheet.getSheetValues(numRows, 1, 1, 23);
//get patientID (column V) in last row of sheet
var lastPatientID = sheet.getRange(numRows,3).getValue();
//find patient sheet based on patientID and make it active, then write to it
var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
var activePatientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
activePatientSheet.getRange(activePatientSheet.getLastRow()+1, 1,1,23).setValues(last_row);
}
What this script is doing is writing data (a row) to another sheet within this spreadsheet based on the the patientID (column V). This works as it should when I manually run the script. However, when I set a trigger to run this script (either onSubmit or edit) nothing happens. I created another function that just writes a message to the logs and set a trigger for that function and it works, so I think there is something in the script that is causing it to fail. Any ideas appreciated.
There are a few issues with your code. I tried to fix it while commenting each line I changed. Hopefully that is clear enough, please comment if you have any questions and I'll try to clarify.
function writePatientData() {
var spreadsheet = SpreadsheetApp.getActive(); //no need for id if the script is on the same spreadsheet
//var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//setActiveSheet will not work from a trigger like on-form-submit (what if no-one has the sheet open, or multiple have)
var sheet = spreadsheet.getSheets()[0]; //if you want the first sheet, just get it, no need to "activate"
var numRows = sheet.getLastRow();
var last_row = sheet.getSheetValues(numRows, 1, 1, 23)[0]; //added [0] since it is just one row
//var lastPatientID = sheet.getRange(numRows,3).getValue(); //you already have this in memory
var lastPatientID = last_row[2]; //arrays are zero based, that's why 2 instead of 3
//btw, you mention column V, but this is actually C
//var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
//you already have the spreadsheet, no need to get it again
var patientSheet = spreadsheet.getSheetByName(lastPatientID);
//var activePatientSheet = spreadsheet.getSheetByName(lastPatientID); //this is the exact same as above, why?
patientSheet.appendRow(last_row); //appendRow is just simpler than getRange(getLastRow).setValues
}
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.
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 });