Ignoring Formula Column with LastRow script - google-apps-script

I'm fairly new to AppScript, so I apologise if this is crazy easy and I'm just hopeless. I've searched a bunch, but solutions were all in slightly different formats that I wasn't sure how to utilise.
The script works to import my sheets information into the calendar, but I want my first column to be a formula column and I can't figure out how to ignore it while using LastRow.
I got the code from a tutorial online, but if you all have suggestions on what to do better/differently, let me know. Thank you!
I've tried a few different iterations in this line:
var count = spreadsheet.getRange("B2:H"+lr+"").getValues();
But I it's been trial and error, with only errors being the result.
function CreateEvent() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange('K1').getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
var lr = spreadsheet.getLastRow();
Logger.log(lr);
var count = spreadsheet.getRange("B2:H"+lr+"").getValues();
for (x=0; x<count.length; x++) {
var shift = count[x];
var summary = shift[0];
var guests = shift[2];
var description = shift[3];
var location = shift[4];
var startTime = shift[5];
var endTime = shift[6];
var event = {
'location': location,
'description': description,
'guests':guests +',',
}
eventCal.createEvent(summary, startTime, endTime, event)
}
}

Your approach is right, there is only one step that you need to take in order to create the event. The startTime and endTime parameters have to be Date type, no String. To achieve that you need to add the following changes:
var startTime = new Date(shift[5]);
var endTime = new Date(shift[6]);
With this code the strings will be converted into dates and the createEvent method will work. Please, ask for more clarification if I haven't explained myself adequately.
As a sidenote I want to commet one little thing, in the following line:
var count = spreadsheet.getRange("B2:H"+lr+"").getValues();
The last "" are not needed at all and may cause confusion, but it does certainly work. For clarity, I recommend just using:
var count = spreadsheet.getRange("B2:H"+lr).getValues();

Related

Trying to add Guests in Spreadsheet Script to Calendar App

I am trying to add Guests in "Options" for automatically add a schedule from Google Sheets into Calendar. I have watched videos (which don't discuss this and lead to no answers when others ask this question) and don't know enough to find the CalendarApp info helpful.
Can someone help? (FYI, I also want to stop duplicating events every time this is run) This is my Script:
function addEvents(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var cal = CalendarApp.getCalendarById("c_kdaqhj8lkd7u68s8thinbnjpik#group.calendar.google.com");
var events = cal.getEvents(new Date ("02/8/2019 12:00 AM"), new Date("02/28/2019 11:59 PM"));
for (var i=0;i<events.length;i++){
var ev = events[i];
ev.deleteEvent();
}
var data = ss.getRange("A2:F"+ lr).getValues();
for(var i = 0;i<data.length;i++){
cal.createEvent(data[i][0], data[i][1], data[i][2], guests:"data[i][3]", "data[i][4]", {description:data[i][5]});
}
}
try this:
cal.createEvent(data[i][0], data[i][1], data[i][2], {guests:`${data[i][3]},${data[i][4]}`, description:data[i][5]});
Reference
Your main problem was that you weren't including guests in the same JavaScript object as description and that guests must be an string including comma separated values. The following script has self explanatory comments and also checks whether an event already exists on the date and time your are trying to insert your event to avoid duplicate events:
function addEvents(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var cal = CalendarApp.getCalendarById("YOURCALENDARID");
var data = ss.getRange("A2:F"+ lr).getValues();
for(var i = 0;i<data.length;i++){
// According to the documentation if no event was found on those date times it will return null
// However if you delete an event this will return an empty array so we also have to check against that
if(cal.getEvents(data[i][1], data[i][2])==null || cal.getEvents(data[i][1], data[i][2]).length==0 ){
// Options must be a Javascript object and specifically the paramter guests is a string so your data must be integrated
// in such a string
cal.createEvent(data[i][0], data[i][1], data[i][2],{guests: ''+data[i][3]+','+data[i][4]+'', description:data[i][5]});
}
}
}
Reference
createEvent(title,title, startTime, endTime, options), please not the information regarding options and more specifically guests within options.
getEvent(startTime, endTime)

Google Sheets to Googel Calendar - Duplications

I've been reading a few questions and help on managing a google sheet then transferring info to google calendar via email.
I'm using the below code which i pulled from various places and its working really well however a couple of things i'm struggling with:
every time i run the script it duplicates the events, how do i stop this from happening every time the script is run - but still allow for say, addition of new email addresses down the line or update the calendar entry?
cant quite get the starttime and endtime to work nicely - the script is run off a tab in a google sheet that pulls its data from another tab (data entry)to make life easier for my users; is there a trick to the format for yyyy-mm-dd-hh:mm:ss?
possible to setup a line of code as part of this to send out automatic reminders say 7 days out from the event?
Appreciate any and all help on this!
Code thats working right now:
function CreateEvent() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange('***<LINKTOCELLTHATHASCALENDARID>***').getValue();
var eventCal = CalendarApp.getCalendarById('***CALENDARID<DELETED>***');
var lr = spreadsheet.getLastRow();
Logger.log(lr);
var count = spreadsheet.getRange("A2:F"+lr+"").getValues();
for (x=0; x<count.length; x++) {
var shift = count[x];
var title = shift[0];
var startTime = shift[1];
var endTime = shift[2];
var guests = shift[3];
var description = shift[4];
var location = shift[5];
var event = {
'location': location,
'description': description,
'guests':guests +',',
'sendInvites': 'True',
}
eventCal.createEvent(title, startTime, endTime, event)
}
}
function CreateEvent() {
var sh=SpreadsheetApp.getActiveSheet();
var calendarId=sh.getRange('***<LINKTOCELLTHATHASCALENDARID>***').getValue();
var eventCal=CalendarApp.getCalendarById('***CALENDARID<DELETED>***');
var drg=sh.getRange(2,1,sh.getLastRow()-1,7);
var dA=drg.getValues();
var crg=sh.getRange(2,7,sh.getLastRow()-1,1);//save that event was created in column G
var cA=crg.getValues();
for (i=0;i<dA.length;i++) {
var shift=dA[i];
var title=shift[0];
var startTime=shift[1];
var endTime=shift[2];
var guests=shift[3];
var description=shift[4];
var location=shift[5];
if(!shift[6]) {
var event={'location': location,'description': description,'guests':guests +',','sendInvites': 'True'}
eventCal.createEvent(title, startTime, endTime, event)
cA[i][0]="CREATED";//keeps this event from being created again
}
}
crg.setValues(cA);
}

My Javascript IF statement seems to think two identical values from a google sheets sheet do not match

I'm trying to write a script where the dates in a column are compared against todays date, and if the dates in the column match, an email is sent.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var rotDate = sheet.getRange("F6").getValue();
var today = sheet.getRange("F1").getValue();
//var today = new Date().toLocaleDateString(); // Today's date, without time
var dumpCell = sheet.getRange("J3");
var dumpCell2 = sheet.getRange("J4");
var dumpCell3 = sheet.getRange("J5");
if(rotDate==today) {
//dumpCell is there to dump a value in a cell if the IF statement is true
dumpCell.setValue(rotDate);
MailApp.sendEmail("this is where my email would go", "subject", "body");
}
//these dump the compared vars into cells so they can be checked against one another manually
dumpCell2.setValue(rotDate)
dumpCell3.setValue(today)
}
This is as far as I've gotten. The Values in F6 and F1 are identical, I've typed them out, retyped them, copied and pasted, etc. But for some reason, my if statement just won't run. It behaves as if the two values are different, and I can't work out why.
If I change var rotDate and var today to matching strings, eg "123" then it seems to work as expected.
This is a screenshot of my test data sheet. There are other columns there with other data which were meant to be used for more testing, but I didn't get that far.
Does anyone know what I might be doing wrong?
After trying a variety of approaches, I cracked it using a code snippet from Jon Lin's answer here:
Compare two dates Google apps script
After realizing that the fault was with trying to compare two dates (either a date in an adjacent cell, or a procedurally generated date whenever the function is run, I knew I had to do some better formatting with the data I was intending to compare. This is my repaired code that now works as expected:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var rotDate = sheet.getRange("F6").getValues();
var today = new Date();
//sample values
var sYyyy = Utilities.formatDate(new Date(rotDate), "GMT+8","yyyy");
var sMm = Utilities.formatDate(new Date(rotDate), "GMT+8","MM");
var sDd = Utilities.formatDate(new Date(rotDate), "GMT+8","dd");
//Test Values
var tYyyy = Utilities.formatDate(new Date(today), "GMT+8","yyyy");
var tMm = Utilities.formatDate(new Date(today), "GMT+8","MM");
var tDd = Utilities.formatDate(new Date(today), "GMT+8","dd");
//var rotDate = sheet.getRange("F6").getValue();
//var today = sheet.getRange("F1").getValue();
//var today = new Date().toLocaleDateString(); // Today's date, without time
var dumpCell = sheet.getRange("J3");
var dumpCell2 = sheet.getRange("J4");
var dumpCell3 = sheet.getRange("J5");
if (sYyyy + sMm + sDd == tYyyy + tMm + tDd) {
//if(rotDate===today) {
//dumpCell is there to dump a value in a cell if the IF statement is true
dumpCell.setValue(rotDate);
MailApp.sendEmail("tv18766#gmail.com", "subject", "body");
}
//these dump the compared vars into cells so they can be checked against one another manually
dumpCell2.setValue(rotDate)
dumpCell3.setValue(today)
}

Doing Math with Date Values

I am trying to use the difference between two dates in my Google Sheet to determine the number of rows down that the originRange will be copied.
I'm getting an error 'Cannot convert NaN to (class)' so I'm assuming I need to change the format of the date in some part of the formula but I am completely stuck.
The dates in the Google Sheet are formatted "10/26/2016" & "12/31/2016" if that helps at all.
function fillNewReport () {
var startDate = responseSheet.getRange('C2');
var endDate = responseSheet.getRange('G2');
var dateDiff = (endDate - startDate) + 1;
var newReport = ss.getSheetByName('Copy of Form Responses 1');
var originRange = newReport.getRange(2,2,1,22);
var newRange = newReport.getRange(2,2,dateDiff,22);
originRange.copyTo(newRange);
}
Any help with this will be greatly appreciated.
Thank you,
EDIT: Part 2
I think I've got the right formatting now, as I'm no longer getting an error. But the formula is not responding. No rows are being copied. Any suggestions?
function fillNewReport () {
var startDateValue = responseSheet.getRange('C2').getValue();
var endDateValue = responseSheet.getRange('G2').getValue();
var startDateMilli = new Date(startDateValue);
var endDateMilli = new Date(endDateValue);
var startDate = startDateMilli.getDate();
var endDate = endDateMilli.getDate();
var dateDiff = (endDate - startDate) + 1;
var newReport = ss.getSheetByName('Copy of Form Responses 1');
var originRange = newReport.getRange(2,2,1,22);
var newRange = newReport.getRange(2,2,dateDiff,22);
originRange.copyTo(newRange);
}
In your code startDate and endDate are ranges, not values !
So first thing is to change that using getValue().
You will then get date objects that wont behave as you expect because unlike days in spreadsheets javascript date objects are more complex objects, they have date and time properties and have a native value of the number of milliseconds since the reference date...
Anyway, all you have to do is using the date methods described in all javascript reference on the internet, ask Google for "JS DATE"
Then do the math you need, this part will be easy I think.
edit
As I wrote in the comments, I'm not sure I understand what result you want to get...
I tried a test changing a few details and I get a result... you tell me if that's what you wanted.
function fillNewReport () {
var startDateValue = responseSheet.getRange('C2').getValue();
var endDateValue = responseSheet.getRange('G2').getValue();
var startDateMilli = new Date(startDateValue);
var endDateMilli = new Date(endDateValue);
Logger.log('startDateMilli = '+startDateMilli+' endDateMilli = '+endDateMilli);
var startDate = startDateMilli.getDate();
var endDate = endDateMilli.getDate();
var dateDiff = (endDate - startDate) + 1;
Logger.log('dateDiff = '+dateDiff);
var newReport = ss.getSheetByName('Copy of Form Responses 1');
var originRange = newReport.getRange(2,2,1,22);
var newRange = newReport.getRange(2,2,dateDiff,22);
originRange.copyTo(newRange);
}
or like this to copy only one row
...
var originValues = newReport.getRange(2,2,1,22).getValues();
Logger.log('originValues = '+originValues);
var newRange = newReport.getRange(2+dateDiff,2,1,22); // copies to the other sheet but dateDiff rows underneath...
newRange.setValues(originValues);
}

Cannot find function createEvent (or createAllDayEvent) in object Calendar. (Google Spreadsheet App)

Okay here is my code that is causing the error. It seems to be just the line where I attempt to add the all day event. I thought it was a date formatting issue but the line I commented out below it was created to test that and it resulted in the same error. So I am stumped. What needs to change to correct the error, or what does the error actually mean.
function cal1() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 300; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 26); //What data will be used
var data = dataRange.getValues();
var cal = CalendarApp.getCalendarsByName("Production Schedule"); //Gets the correct calendar
for (i in data) {
var row = data[i];
var title = row[4]; // Column with Title
var desc = row[3]; // Column with Description
var date = row[8]; //Column with Date
var loc = row[5]; //Column with Location
cal.createAllDayEvent(title, date, {description:desc,location:loc});
//cal.createEvent("Test", new Date("3/10/2010 14:30:00"), new Date("3/10/2010 14:30:00"));
}
}
var cal = CalendarApp.getCalendarsByName("Production Schedule"); //Gets the correct calendar
That gives you an array of calendars with that name (since Calendars can share names and therefore there can be more than one). Try this:
var cal = CalendarApp.getCalendarsByName("Production Schedule")[0]; //Gets the correct calendar
That will give you the first (likely only) Calendar with that name.
if you are not sure about the 'date' variable being actually a date you could use
cal.createAllDayEvent(title, new Date(date), {description:desc,location:loc});
that said, it is quite easy to check with the logger
Logger.log(date)
should return a date value in the form Tue Sep 18 03:00:00 PDT 2012
I have same problem with getCalendarsByName.
Rather, I use getCalendarById and it solved well. I think calendar name can get some confusion though, and bug.
You can find your calendar id on calendar setting, something like: 123xyz#group.calendar.google.com
Script will goes like this:
var cal = CalendarApp.getCalendarById("123xyz#group.calendar.google.com");