I'm trying to create a sheet that creates events into multiple google calendars from a single google sheet. I am using a sheet modified from the fantastic solution on this post Create Google Calendar Events from Spreadsheet but prevent duplicates from Mogsdad. However I have been triplicating my work to go into 3 different calendars and would like to have my first go at programming. My idea is I would like to go one step further and add a drop down column (labeled status) containing either (Unconfirmed, Save the date, Confirmed) which would then create an even in one or all three calendars named the same as the conditional drop down.
My sheet is arranged as :-
Date | Title | Start Time | End Time | Location | Description | Even ID | Status | Confirmed details | Confirmed Start time | confirmed end time |
As you can see my idea is to have slightly different info in the confirmed calendar than the other two.
The existing code i'm using is
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the exportEvents() function.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "30kpfnt5jlnooo688qte6ladnk#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var id = row[6]; // Sixth column == eventId
// Check if event already exists, delete it if it does
try {
var event = cal.getEventSeriesById(id);
event.deleteEventSeries();
row[6] = ''; // Remove event ID
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
row[6] = newEvent; // Update the data array with event ID
debugger;
}
// Record all event IDs to spreadsheet
range.setValues(data);
}
So I realize I need to define the new info to go into the "confirmed" calendar as well as the 2 additional calendars. My issue is I don't know how to fit in a series of if loops to direct events to the 3 calendars. I would also like the calendars to be additive e.g. all events appear in "unconfirmed calendar" events get added to save the date when uprated to that status and then finally appear in "confirmed" when set to that. So a confirmed event appears in all 3 calendars but an unconfirmed only appears there.
I'm virtually brand new to programming so please be nice and excuse my blatant plagarism of others work (thanks Mogsdad) and I appreciate any help!
Welcome to programming! Once you get the hang of it, you'll want to script every Google product you use. :)
If I understand your question correctly, you would like to be able to choose which calendar an event goes into when you run the function exportEvents(). There are several ways to do this, and you don't need any additional loops! You can make use of objects and refer to them by name.
What I would do first, where you currently define cal and calId, is create an object that defines the three calendars like this:
var cal1 = "30kpfnt5jlnooo688qte6ladnk#group.calendar.google.com";
var cal2 = "string url for second calendar";
var cal3 = "string url for third calendar";
var calendars = {
Unconfirmed: CalendarApp.getCalendarById(cal1),
SaveTheDate: CalendarApp.getCalendarById(cal2),
Confirmed: CalendarApp.getCalendarById(cal3)
}
The object calendars now contains the calendar objects for the three calendars such that the key is the status and the value is the object. Then, when you're grabbing the data for each row, add
var cal = row[7];
Now, cal contains the string indicating the status. You can make great use of chaining by making one change to your newEvent definition:
var newEvent = calendars[cal].createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
What's happening here is calendars[cal] gets the calendar object corresponding to the string in the table, to which you can then add the new event. This does require making a change to your sheet - change the label in your status column from 'Save the Date' to 'SaveTheDate' so it matches the variable name. That should do it!
EDIT
To add the event to multiple calendars, I would use if statements, but you don't need a loop. Something like the following would work:
calendars['Unconfirmed'].createEvent(title... // Add to unconfirmed no matter what
if (cal != 'Unconfirmed'){
calendars['SaveTheDate'].createEvent(title... // Add to SaveTheDate only if not Unconfirmed
}
if (cal == 'Confirmed'){
calendars['Confirmed'].createEvent(title... // Only add to Confirmed if Confirmed
}
Related
I'm using the following code to check if there are cancelled events in a Google Calendar. It works fine for regular, non-recurring events. However, I run into issue when the user has deleted a single event in a recurring event series.
function checkForCancelledEvents(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Data Source");
ss.setActiveSheet(sheet);
//sort by date added
var lastRow = sheet.getLastRow();
var range = sheet.getRange(1,2,lastRow, 5)
var values = range.getValues();
//in the array the 3 position is the eventId, the 4 position is the calendar ID, I'm putting more into the array since I was playing around with also using the start date or time to solve the problem
//loop through all using Calendar.Events.get
for (i=1;i<values.length;i++) {
var splitEventID = values[i][3].toString().split("#")[0] //remove the calendarID from the eventID
if (Calendar.Events.get(values[i][4],splitEventID).status === "cancelled") {
//the below clears the content of the row that contains the cancelled events
//the range has to start at i + 1 since the values include the header row, but the for loop starts at 1 instead of 0 to prevent the API from calling with data from header row (which produces an error). So i + 1 gives the accurate row number for which the cancelled event lives
var clearRange = sheet.getRange(i + 1,1,1,7)
clearRange.clearContent()
} else {
//Logger.log("this is NOT cancelled")
}
}
}
The issue is that recurring events all contain the same eventID and calendarID. They have the same iCalUID as well. Recurring events do have a different id but non-recurring events don't have the same id format. I tried to use Calendar.event.list and add the timeMin of each event within the recurring series, however the event was still listed as confirmed even though it was deleted.
Is there a way to find if a single event within a recurring series has been deleted?
I believe your goal is as follows.
From Is there a way to find if a single event within a recurring series has been deleted?, you want to know whether even one of the events from the recurring events is removed using Google Apps Script.
In this case, I thought that when the method of "Events: instances" is used, your goal might be able to be achieved. The sample script is as follows.
Sample script:
Before you use this script, please enable Calendar API at Advanced Google services.
var calendarId = "###"; // Please set the calendar ID.
var eventId = "###"; // Please set the event ID.
var ar = [];
var pageToken = "";
do {
var res = Calendar.Events.instances(calendarId, eventId, {maxResults: 2500, showDeleted: true, pageToken});
if (res.items.length > 0) ar = [...ar, ...res.items.filter(({status}) => status == "cancelled")];
pageToken = res.nextPageToken;
} while (pageToken);
if (ar.length > 0) {
// When "ar" has the values, the events are deleted from the recurring events.
// do something.
}
In the above script, you can see the information of the deleted events at ar.
Note:
This is a simple sample script. So please modify this for your actual situation.
Reference:
Events: instances
I am woefully ignorant here, so any help is much appreciated. My apps script code is sloppy af and piecemealed together from examples online. I know it is trash and does not account for most of what I need. That's why I'm here. My goal is to auto-populate google calendar events from multiple sheets in a workbook and create a trigger so that anytime content is edited in those cells a new event populates (or the event edited) but repeat events aren't created.
The cells I'd be pulling data from will be the same for each sheet:
C4:C24 (these cells hold the title of the event) and
E4:F24 (these cells hold start date and time and end date and time respectively).
The trigger I have set up is on edit but when I make an edit, duplicate events get created each time, which I do not want.
Any help is incredibly appreciated. Thank you!
// function to retrieve data from Sheet and add to Calendar
function simpleSheetsToCalendar() {
// get spreadsheet
var spreadsheet = SpreadsheetApp.getActiveSheet();
var eventCal =
CalendarApp.getCalendarById('actualCalendarId');
var signups = spreadsheet.getRange("C4:F24").getValues();
for (x=0; x<signups.length;x++)
{
var shift = signups[x];
var task= shift[0];
var startTime = shift[2];
var endTime = shift[3];
eventCal.createEvent(task, startTime, endTime);} }
I believe your goal is as follows.
You want to retrieve the values from the cells "C4:F24" from multiple sheets in a Google Spreadsheet.
The columns "C", "E", and "F" are the event title, start time, and end time, respectively.
You want to create a new event to a Google Calendar using the retrieved values. At that time, you don't want to create the duplicated event title.
Sample script:
In this sample script, in order to retrieve all titles of the calendar event, Calendar API is used. So before you use this script, please enable Calendar API at Advanced Google services. And, please set sheetNames and calendarId.
function simpleSheetsToCalendar() {
var sheetNames = ["Sheet1", "Sheet3",,,]; // Please set the sheet names you want to use.
var calendarId = "###"; // Please set your calendar ID.
// 1. Retrieve all events from the Calendar and create an object for checking the duplicated titles.
var events = [];
var pageToken = "";
do {
var res = Calendar.Events.list(calendarId, {maxResults: 2500, fields: "nextPageToken,items(summary)", pageToken});
events = events.concat(res.items);
pageToken = res.nextPageToken;
} while(pageToken);
var obj = events.reduce((o, e) => Object.assign(o, {[e.summary]: true}), {});
// 2. Retrieve sheets from a Google Spreadsheet and retrieve the values from "C4:F24", and create an object for creating new events.
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var values = spreadsheet.getSheets().reduce((o, sheet) => {
if (!sheetNames.includes(sheet.getSheetName())) return o;
var signups = sheet.getRange("C4:F24").getValues();
signups.forEach(([title,,startTime,endTime]) => {
if (!obj[title] && title && startTime && endTime && !o[title]) o[title] = {startTime,endTime};
});
return o;
}, {});
// 3. Create new events.
var ar = Object.entries(values);
if (ar.length == 0) return;
var eventCal = CalendarApp.getCalendarById(calendarId);
ar.forEach(([title, {startTime, endTime}]) => eventCal.createEvent(title, startTime, endTime));
}
When this script is run, all event titles in the calendar are retrieved, and the values are retrieved from "C4:F24" on the multiple sheets in a Google Spreadsheet. And then, new events are created by checking the duplicated title.
Note:
In this sample script, the event title is checked for checking the duplicated events. If you want to check other properties, please modify the above sample script.
References:
Events: list
reduce()
forEach()
I am currently using app script to sync my google sheet to google calendar. The process is quite simple, my script only takes a date and title from the spreadsheet and creates an all day event on that date with that title.
The problem I am facing is that if I accidentally key in the wrong date or I have to update one of the dates inside the spreadsheet, on running the scheduleShifts function again, all the events are created again which results in many duplicate events that I did not intend to be there. I'm trying to find a solution that helps either updates the title of the event or deletes the event and create a new one in the case where the date that is in the spreadsheet is wrong.
It also isn't very efficient to update the data in the spreadsheet and then update the calendar because in the event where quite a few dates or titles have to be changed, it would take quite a bit of time to change them all in the calendar. It would also be very troublesome to delete the current calendar, create a new one, copy that id into the spreadsheet and then update everything again.
This is what my current code looks like:
function scheduleShifts()
{
/*Identify calendar*/
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("C1").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
/*Import data from the spreadsheet*/
var signups = spreadsheet.getRange("C4:F73").getValues();
/*Create events*/
for (x=0; x<signups.length; x++)
{
var shift = signups[x];
var title = shift[0];
var date = shift[3];
eventCal.createAllDayEvent(title, date);
}
}
/*Make the script shareable for others to use*/
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Sync to Calendar')
.addItem('Schedule shifts', 'scheduleShifts')
.addToUi();
}
I have tried to avoid duplicating events by retrieving all the events with Advanced Calendar Service, pushing their titles into an array and then verifying with IndexOf. However, I am unsure if this method will work if the title stays the same while there is an update in the date of that event.
The code that I referenced from to do this:
var existingEvents=Calendar.Events.list(calendarId);
var eventArray=[];
existingEvents.items.forEach(function(e){eventArray.push(e.summary)});
for (x=0; x<signups.length; x++) {
var shift = signups [x];
var startTime = shift[0];
var endTime = shift[1];
var inspector = shift[2];
if(eventArray.indexOf(inspector)==-1){
eventCal.createEvent(inspector, startTime, endTime);
}else{
Logger.log('event exists already');
}
}
If anyone needs more info feel free to ask in the comments, your help would be greatly appreciated.
You have developed a script to create events using data from a sheet.
You want to be able to update previously created events while avoiding creating duplicates.
Step 1. Avoid creating duplicates:
In order to avoid creating duplicates, you could make the script write the corresponding eventId when each event has been created. This way, next time the script runs, it can check whether the eventId is populated (in which case the event already exists), and only create the event if it doesn't exist. It could be something like this (in this sample, the eventIds are written to column G):
function scheduleShifts() {
const spreadsheet = SpreadsheetApp.getActiveSheet();
const calendarId = spreadsheet.getRange("C1").getValue();
const eventCal = CalendarApp.getCalendarById(calendarId);
const signups = spreadsheet.getRange("C4:G7").getValues();
for (let x = 0; x < signups.length; x++) {
const shift = signups[x];
const title = shift[0];
const date = shift[3];
const eventId = shift[4];
if (eventId == "") { // Check the event doesn't exist
const newEvent = eventCal.createAllDayEvent(title, date);
const newEventId = newEvent.getId();
spreadsheet.getRange(4 + x, 7).setValue(newEventId); // Write new eventId to col G
}
}
}
Step 2. Update events:
Regarding the update process, I'd suggest you to install an onEdit trigger, either manually or programmatically. This this action requires authorization, a simple onEdit trigger would not work here (see Restrictions).
This way, you can use the event object to only update the event corresponding to the row that was edited, thus avoiding having to update all events every time, which would make the process very inefficient. The update process itself would consist on calling setTitle and setAllDayDate.
The function fired by the onEdit trigger could be something like this:
function updateEvent(e) {
var editedRow = e.range.getRow();
var editedData = e.source.getActiveSheet().getRange(editedRow, 3, 1, 5).getValues()[0];
var eventId = editedData[4];
try {
var event = CalendarApp.getEventById(eventId);
event.setTitle(editedData[0]);
event.setAllDayDate(editedData[3]);
} catch(err) {
console.log("There was a problem updating the event. This event might not exist yet.");
}
}
Notes:
You may not want to manually set the range (C4:G73) if the number of events might vary. You can use methods like getLastRow() no make this range dynamic, based on the spreadsheet content.
The eventId that are used here, corresponding to Class CalendarEvent, are not identical to the API Event resource. Take this into account in case you use the Advanced Service.
Situation
I have a calendar with a lot of events on it (staff appraisals).
I've made a load of modifications (changing the length of the event etc.) but the invitations are going to people who have a lotus notes calendar (poor people).
This means that unless I trigger what would be called "Send notification?" in the click-with-your-mouse version of things, they have no way of knowing that the event has been updated.
(Similar Q)
In this example, the event I'm trying to trigger is the same one as is triggered when the Send Update? modal is accepted with send.
Code
Here's some example code that gets all the events on the Appraisals calendar and changes their location to 'the moon'.
function fixInvitations(){
//get the callendar named "Appraisals"
var cApp = CalendarApp.getCalendarsByName("Appraisals")[0];
var events = cApp.getEvents(new Date(), new Date("Dec 30 2014"));
for (eIndex in events){
var event = events[eIndex];
event.setLocation("the moon");
}
}
Question
How do I trigger an update to all parties invited to an event so that the changes are reflected in their calendars?
Currently these events are now on the moon, but the update hasn't told people who are on non-Google calendars about the change.
Helpful, but not that helpful fact
The update email that manually triggering sends contains a .ics file (Gist of the contents). This contains a VCALENDAR and a VEVENT. From the Wikipedia page on VEVENTs
For sending an UPDATE for an event the UID should match the original UID. the other component property to be set is:
SEQUENCE:<Num of Update>
I.e., for the first update:
SEQUENCE:1
So if there was a way to manually build an email with a .ics attachment it would solve the problem, but that feels like massive overkill. This is mentioned here but not resolved.
The Google Calendar API supports the flag sendNotifications for event updates:
https://developers.google.com/google-apps/calendar/v3/reference/events/update
I would file a feature request for App Script to expose the flag and in the meantime use the Calendar API directly for updating events just like an external API:
https://developers.google.com/apps-script/guides/services/external
I was struggling with this one a bit and got some help from ekoleda+devrel#google.com: Ability for Calendar to send email invitation to users added via addGuest http://code.google.com/p/google-apps-script-issues/issues/detail?id=574
A couple of pointers to hopefully save people some time:
Note that CalendarApp and the Advanced Calendar service use different
event ID formats:
CalendarApp returns event IDs with "#google.com" at the end ex. b3gv...a5jrs#google.com
The Advanced Calendar service/Calendar API expects an event ID that does not have #google.com ex. b3gv...a5jrs
Here's some working code:
function sendInvite(calendarId, eventId, email) {
var event = Calendar.Events.get(calendarId, eventId);
if(event.attendees) {
event.attendees.push({
email: email
});
} else {
event.attendees = new Array({email: email});
}
event = Calendar.Events.patch(event, calendarId, eventId, {
sendNotifications: true
});
}
One final note for those following along - you won't receive an email notification if you're the event owner and you're trying to add your own email address. This makes sense in the calendar world since you wouldn't go into your own calendar event, add yourself as an attendee, and expect to be prompted as to whether or not you want to inform yourself. However, it's probably a common way for people to try and test things (I don't have a domain test account and I can't always reliably test things with my personal gmail account). So if you're testing with your own account and thinking that things aren't working please keep this in mind. Once you try things with a non-event owner account the invite will be sent via email.
I think one solution is to create a spreadsheet with the column headers: Event ID, Event Name, Description, Start Time, End Time, Location,Guest List, and then add this script to the spreadsheet. calendarImport() will import all of your calendar events and write them to the sheet. Then, you can modify the event in the spreadsheet line (change location to the Moon), and run calendarCreateEvent to create a new event based on the changes you made. It will automatically send out notifications to all old attendees to accept the new event, as it is a new invitation.
I am pretty close to that solution, but I have a hangup, now, on accessing the calendar to create a new event. I think it's because I'm calling it from an onEdit event function. It's getting late, but if you rewrite the third part of the script to get the events data range, then a for/if loop to check the added versus modified date, then you should be able to create a new event, and delete the old event. This would push a notification of the change in event details to everyone who had accepted the old event already.
I think, given the code example you put up in the beginning, you probably already know how to do that, but if you don't, I could probably throw something together tomorrow night to search for old events that have been recreated and delete them.
Here's my spreadsheet and code in action.
function calendarImport(){
//http://www.google.com/google-d-s/scripts/class_calendar.html#getEvents
// The code below will retrieve events between 2 dates for the user's default calendar and
// display the events the current spreadsheet
var cal = CalendarApp.getDefaultCalendar();
var calId = cal.getId();
var sheet = SpreadsheetApp.getActiveSheet();
var sheetName = SpreadsheetApp.getActiveSheet().setName(calId +" Calendar Data");
var events = cal.getEvents(new Date("March 9, 2014"), new Date("March 14, 2014"));
for (var i=0;i<events.length;i++) {
//http://www.google.com/google-d-s/scripts/class_calendarevent.html
Logger.log(events);
var details=[[events[i].getId(),events[i].getTitle(), events[i].getDescription(), events[i].getStartTime(), events[i].getEndTime(),events[i].getLocation()]];
var guestList = events[i].getGuestList();
var guestArray = [];
for (var n in guestList){
var guestEmail = (guestList[n].getEmail());
guestArray.push(guestEmail);
Logger.log(guestArray);
}
var row=i+1;
var range=sheet.getRange(row+1,1,1,6);
range.setValues(details);
var guestRange = sheet.getRange(row+1,7,1,1);
guestRange.setValues([guestArray]);
var dateAdded = Utilities.formatDate(new Date(), "GMT-6","MM/dd/yy HH:mm:ss");
var dateAddedRange = sheet.getRange(row+1,8,1,1);
dateAddedRange.setValue(dateAdded);
}
}
function onEdit(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var calId = CalendarApp.getDefaultCalendar().getId();
var sh = ss.getSheetByName(sheetName);
var actSht = event.source.getActiveSheet();
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
Logger.log(index);
var dateCol = actSht.getLastColumn();
var calId
var lastCell = actSht.getRange(index,dateCol);
var date = Utilities.formatDate(new Date(), "GMT-6", "MM/dd/yyyy HH:mm:ss");
lastCell.setValue(date);
var modifiedRow = sh.getRange(index,1,1,ss.getLastColumn()).getValues();
Logger.log(modifiedRow[0][7])
if (modifiedRow[0][7] < modifiedRow[0][8]){
var firstAdded = modifiedRow[0][7];
var dateModified = modifiedRow[0][8];
calendarCreateEvent(index,firstAdded,dateModified,calId);
}
}
function calendarCreateEvent(index,firstAdded,dateModified,calId){
var sheet = SpreadsheetApp.getActiveSheet();
var added = firstAdded;
var modified = dateModified;
var startRow = index; // First row of data to process
var calId = calId;
Logger.log(calId);
Logger.log(startRow);
Logger.log(added);
Logger.log(modified);
if (modified - added > "0"){
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 9);
var data = dataRange.getValues();
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
var row = data[i];
var eventId = row[0]
var title = row[1]; // First column
var desc = row[2]; // Second column
var tstart = row[3];
var tstop = row[4];
var loc = row[5];
var guests = row[6];
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc, guests:guests});//.addGuest(guests);
var newEventId = newEvent.getId();
Logger.log(newEventId);
}
}
}
I got an email from Gooogle today saying that they've added a feature to app script that makes this possible.
Updates:
Status: Fixed
Owner: ekoleda+devrel#google.com
Labels: -Priority-Medium
Comment #11 on issue 574 by ekoleda+devrel#google.com: Ability for Calendar to send email invitation to users added via addGuest
http://code.google.com/p/google-apps-script-issues/issues/detail?id=574
This is now possible using the Advanced Calendar service:
https://developers.google.com/apps-script/advanced/calendar
You can use Calendar.Events.patch() to add attendees, and if you set the optional parameter sendNotifications to "true" the attendees will get an invite.
https://developers.google.com/google-apps/calendar/v3/reference/events/patch
I'm going to try to solve this problem today and then edit this response to reflect that.
Data:
Row 1 - Have some Formulas and Format
Row 2 - Have the column name
A3 = XXXXXX (Subjet)
B3 = Call to Customer (Description)
C3 = 00:15:00 (Duration for the Event)
F3 = 5/12/20013 18:41:00 (StartDate)
I3 = 5/12/2013 18:56:00 (EndDate) (EndDate = sum from F3 + C3)
J3 = EventID (As read other topic to avoid duplicate is need identify each event with an ID.)
H3 = "Yes" (Create or Update Event) "Delete" (Delete the Event)
The appoiment will increase or decrease depend of the day for example one day many will have 20 and other 3.
All event will create & updated from the spreadsheet because we have created a exclusive Calendar for it.
Situation:
We have a lot of calls per day and is very estressfull create an event using calendar.
That why we have an spreadsheet where all information is updateded automatically when we modify the Column B.
We want to create a Calendar Event for each row > 3
We want to prevent duplicated
If in the the column H the content is "Yes" the script should be Create or Update the event with the new date for that row. If said "Delete" should be only delete the EventID associated with that row.
Important: We update the start & end date every 15 or 30 min because we manage critical incident.
Test:
We try to use the script uploaded in this answer Here but the function only work for first two rows.
When we add new Subject and we run the script, the scrip not update the calendar.
Also we not if the first event is automatically updated with the information for the last row.
SCRIPT (1):
This Script Delete & Re-Create every time the Event. I want to update the existing event if exist or create it is doesn't exist.
This Script run for every row in the sheet. I want to run only just for the row modificated.
Didn't check Column H
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the exportEvents() function.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() == "Sheet1"){
var activeCell = sheet.getActiveCell(); //Detec the ActiveCell
var row = activeCell.getRow(); //Detect the ActiveRow
var headerRows = 2; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "8au195cppi3smt6m138cgjpr3o#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var title = row[0]; // [0] First column// [1] Second column
var tstart = row [5];
var tstop = row [8];
var desc = row[1];
var id = row[9]; // Nine column == eventId
// Check if event already exists, delete it if it does
try {
var event = cal.getEventSeriesById(id);
event.deleteEventSeries();
row[9] = ''; // Remove event ID
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc}).getId();
row[9] = newEvent; // Update the data array with event ID
debugger; }
// Record all event IDs to spreadsheet
range.setValues(data);
}
}
try changing
data = range.getValues();
to
data = range.getDisplayValues();
From my knowledge getDisplayValues will retrieve string value of the cell