Google Calendar event from sheets script ends a day early - google-apps-script

I have a sheets file that creates a calendar event when a button is clicked. The calendar event is based off of a user entered due date, and script created start date, a entered location, and an entered description all pulled from certain cells in the spreadsheet. The problem is that when I go to the calendar the event ends a day before the due date (or beginning of the day of the due date) and I want it to show for the entire due date. For example if I enter a due date of july 17th into the spreadsheet, when I create the calendar event it only runs through the 16th. Is there a way to get the events to schedule to the end of the day or an easy way to just offset the end date by one day in the script.
var Description = sheetTemplate.getRange('B12').getValue(); //gets discription from Cell B12
var Location = sheetTemplate.getRange('C5') .getValue(); //gets location of work order from cell C5
var StartDate = sheetTemplate.getRange('C4').getValue(); //Start Date from Cell C4
var DueDate = sheetTemplate.getRange('E5').getValue(); //Gets Due Date From Cell E5
//This portion of the code schedules the WO on the calendar//
var eventCal = CalendarApp.getCalendarById("XXXXX") ;//Get the Maintenance Calendar
var options = { 'location': Location,
'description':Description
} //sets event details
var WOevent = eventCal.createAllDayEvent(WOname,StartDate,DueDate,options);//creates a calendar event
WOevent.setColor('10') // sets the color of the calendar event to green

You have two options
Either you manually add a day to the dueDate
This can be done with new Date(ms):
var DueDate = sheetTemplate.getRange('E5').getValue();
DueDate = new Date(DueDate.getTime() + 24*60*60*1000);
Or you use the method createEvent(title, startTime, endTime, options) instead of createAllDayEvent()
This allows you to specify the end time on the DueDate:
var DueDate = sheetTemplate.getRange('E5').getValue();
DueDate = new Date(DueDate);
DueDate.setHours(23);
DueDate.setMinutes(59);
var WOevent = eventCal.createEvent(WOname,StartDate,DueDate,options);

Related

How to update event time in Google calendar from Google sheet by event name

I have a number of Futsal(indoor soccer) teams and am trying to make managing the calendar really easy.
Currently I pull the game details into a spreadsheet using an IMPORTHTML function with a query attached, then sort the data to process either by team or can do all teams at once.
All import sheets are set up with the same configuration to keep it simple.
Calendar ID is in B3
Start date and time is from B5:B100
End date and time is from C5:C100
The game name title from D5:D100 (displayed like "Cunning Stunts ✰✰ vs Borussia Dropkicks ☆✰")
Very rarely does the team change however the times can be adjusted throughout the season and I'd like to run the script and update the appointment time.
I can import games into the calendar without any problem as I've worked that bit out but cannot get my head around changing the time of an entry based on the event name.
I have tried a large amount of trial and error using other people questions around getId() functions and also if/else but I can only create duplicate events.
I'm fairly fresh to this world but am eager to continue learning and don't give up easily so any help would be appreciated.
Here is what I have working so far.
function gameImport() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("b3").getValue();
var cal = CalendarApp.getCalendarById(calendarId);
var calendarName = cal.getName();
Browser.msgBox("Export Calendar = " + calendarName);
var games = spreadsheet.getRange("A5:D100").getValues();
for (x=0; x<games.length; x++) {
var details = games[x];
var startTime = new Date(details[1]); //Start date and time
var endTime = new Date(details[2]); //End date and time
var title = details[3]; //Game title
cal.createEvent(title,startTime,endTime);
Browser.msgBox("Great Sucess");
}
}

Modify a Google Calendar recurrence in Apps Script

I'm trying to create a script that, given a date, will change the end date of all my recurrent events this week to that date. Unfortunately, I can't find a way to update a recurrence info.
First, I iterate all events in the week. Then, thanks to the API, I can get the recurrence info of every event:
var eventId = event.getId().split("#")[0];
var eventFromAPI = Calendar.Events.get(ID_CALENDARIO_MENUS, eventId);
var cadenaRecurrencia = eventFromAPI["recurrence"];
witch then I use to create a new recurrence to overwrite the existing one in the event.
var recurrencia = CalendarApp.newRecurrence().addWeeklyRule().onlyOnWeekdays(arrayWeekdays).until(fecha);
But when I try to set the new recurrence, it asks me for a start date that should be the original, and I can't seem to retrieve that data:
var serie = calendario_menus.getEventSeriesById(eventoId);
serie.setRecurrence(recurrencia, date);
Is there a way to access an event's recurrence, modify it so it changes for all the events that use the recurrence and update it?
Thanks for your help.

Script places the dates correctly on my goog cal, then misplaces them all one day early, then places the last one correctly again

The script places the dates correctly on my Google Calendar, then misplaces them all one day early, then places the last one correctly again.
input from google sheet, displayed in Google Calendar
1/4/23 -> 1/4/23 put in goog cal correctly
1/8/23 -> 1/7/23 - one day off
2/5/23 -> 2/4/23 - one day off
6/18/23 -> 6/17/23 - one day off
10/15/23 -> 10/15/23 - correct
function addEvents(){
var ss =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var cal =
CalendarApp.getCalendarById("#group.calendar.google.com");
var data = ss.getRange("A1:C" + lr).getValues();
for(var i = 0; i<data.length;i++){
cal.createAllDayEvent(data[i][0], new Date(data[i][1]),
{description:'PRO: ' + data[i][2]});
}
}
three columns in the google sheet
title, date, and description
Try GetDisplayValues()
var data = ss.getRange("A1:C" + lr).GetDisplayValues();
and potentially format the column as yyyy-MM-dd.
This will ensure the data the script is using is the same as you see on the sheet. Formatting the column will ensure new Date() converts the the data correctly.
If its still off add a couple hours to your Date object to ensure the time is firmly in the middle of the day.
let today = new Date();
today.setHours(today.getHours() + 4);

Creating a calendar event from cell data

I've got my bit of code that allows me to enter a date and time and it will create a calendar event. The only problem is the date and time have to be entered in a cell that is formatted Date/Time. If I take the date from one cell and the time from another and try to create a string using these I get an error that the "calendar.createEvent" doesn't work with strings.
How do I turn my string into a date and time?
var calendar = CalendarApp.getCalendarById("xxxxxxx");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var datesheet = ss.getSheetByName("Schedule Job")
var start = datesheet.getRange("C19").getValue() & " " & datesheet.getRange("C20").getValue();
var end = datesheet.getRange("C30").getValue();
calendar.createEvent("Test",start,end);
instead of creating a string with them, try just adding them.
With a Date in A1 and a time in B1 put this formula in a cell:
=A1+B1
and then select the cell and choose Format>Number>DateTime
run your script off that value.

Alternative to using triggers to automatically send email for each calendar event created

I am trying to automate certain parts of my workflow for scheduling clients with Google Calendar. I've successfully managed to capture new/edited/deleted events in Google Apps Script using a trigger which detects changes and Calendar.event.list to sync those changes with a spreadsheet.
I create a new row, or edit an existing one, in my spreadsheet of all the clients. What I desire to do is three days before the appointment with the client, automatically generate a custom email with all of their details, to send them as a reminder regarding the appointment.
My plan was every time a new row was created in the Spreadsheet (when a new Calendar event was created), was to make a new email trigger. That trigger would execute code to create an email, with all of the clients info.
function createEmailTrigger(event) {
var today = new Date();
today.setHours(0,0,0,0); // Don't care about time
// Create Email Trigger three days before
const sendDaysBefore = 3;
var daysBefore = new Date(event.start);
daysBefore.setDate(daysBefore.getDate() - sendDaysBefore);
var trigger = ScriptApp.newTrigger('sendEmail')
.timeBased()
.at(daysBefore)
.create();
associateEventWithTrigger(trigger.getUniqueId(), event);
return trigger.getUniqueId();
}
associateEventWithTrigger connects the trigger id with the Calendar event. sendEmail would then create a new email with all of the client's info, which came from the Calendar event. When the trigger is executed, it deletes the trigger since it won't be used again.
All of this was working fine, as I was testing one Calendar event at a time. However, once I decided to sync all of this year's Calendar events, the script very quickly threw this error:
Exception: This script has too many triggers. Triggers must be deleted from the script before more can be added.
Apparently you can only have 20 triggers per user/script. This is very inconvenient, as I was expecting to create hundreds of triggers.
Therefore, I need to rethink how to go about doing this. Any suggestions? I appreciate it.
Proposed workaround
This script is designed to be run on a time-driven trigger that runs daily.
function sendReminderEmails() {
let file = SpreadsheetApp.getActive();
let sheet = file.getSheetByName("Sheet1");
let range = sheet.getDataRange();
let values = range.getValues();
// removing headers
values.shift()
values.forEach(row => {
let name = row[0]
let email = row[1]
let date = row[2]
// Date object representing time now
let now = new Date();
// helper variables
let second = 1000;
let minute = second * 60;
let hour = minute * 60;
let day = hour * 24;
// gets time to appointment in milliseconds
let timeToApp = date.getTime() - now.getTime()
if (timeToApp > 2 * day && timeToApp < 3 * day) {
MailApp.sendEmail(
email,
"Remember Your Appointment",
"Hello " + name + ",\nYou have an appointment coming up soon."
)
}
})
}
This is based on a sample spreadsheet like this:
So you would need to adapt it to your particular format.
Script walkthrough
It is based on the date object.
If your dates are stored as formatted dates in your spreadsheet, when you getValues, Apps Script will automatically pass them as Date object. Alternatively you can cast them as Date objects in Apps Script if needed.
The script starts off by getting all the values in the target sheet.
It initialized a new Date object that represents the time now.
It then goes through each row of the target sheet and gets a value for how long until the appointment.
If the value is between 2 days and 3 days, then an email is sent.
I Think you could make an script to search events every day , events that are 3 days ahead , select then and send email. So it will be just one script that will be triggeres every day, using the date trigger mode.