I'm posting after having read different posts here in SO, and still, I didn't manage to solve my problem.
What I'm trying to do is basically to retrieve from Google Calendars the events from different calendars and have them listed in an excel file.
The script below correctly gets the events from the first calendar, but not from the others. From the others, I basically get an empty array.
Here is the code I'm working with:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var sheetsoptions = ss.getSheetByName("Options");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
// var id_cal = sheet.getRange("C2").getValue();
var id_cal = sheetsoptions.getRange("A5:A6").getValues();
var arrayLength = id_cal.length;
var cell_events = 5;
for (var j = 0; j < arrayLength; j++) {
if (id_cal[j] == ""){
break;
}
else{
var cal = CalendarApp.getCalendarById(id_cal[j]);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
sheet.getRange(cell_events,1).setValue(title);
sheet.getRange(cell_events,2).setValue(start_time);
sheet.getRange(cell_events,3).setValue(end_time);
sheet.getRange(cell_events,4).setValue(loc);
sheet.getRange(cell_events,5).setValue(des);
sheet.getRange(cell_events,6).setValue(vis);
cell_events++;
}
}
}
Logger.log("Events have been added to the Spreadsheet");
}
Thanks in advance for your help.
Luca
I think you just had a small issue with your calid being a 2d array. Try this, it's almost the same thing that you had, written a little differently.
function getEvents() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Sheet1");
var sheetsoptions = ss.getSheetByName("Options");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
var calid = sheetsoptions.getRange("A5:A6").getValues().flat().filter(id => id);//test for truthiness
var row = 5;
calid.forEach(id => {
var cal = CalendarApp.getCalendarById(id);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
events.forEach(ev => {
var title = ev.getTitle();
var start_time = ev.getStartTime();
var end_time = ev.getEndTime();
var loc = ev.getLocation();
var des = ev.getDescription();
var vis = ev.getVisibility();
sheet.getRange(row++, 1, 1, 6).setValues([[title, start_time, end_time, loc, des, vis]]);//this should save some time writing all five columns at the same time
});
});
Logger.log("Events have been added to the Spreadsheet");
}
Issue:
You are using the same variables for minimum and maximum dates when listing calendar events and for getting the start and end time of each event (start_time, end_time).
Because of this, after the first calendar iteration, start_time and end_time are not the times defined in cells A2 and B2, but the start and end times of the last event in the first calendar.
Solution:
Update one of the two sets of variables so there's no confusion. For example:
var event_start_time = events[i].getStartTime();
var event_end_time = events[i].getEndTime();
// ...
sheet.getRange(cell_events,2).setValue(event_start_time);
sheet.getRange(cell_events,3).setValue(event_end_time);
Note:
Consider using setValues to write all event values at once instead of setValue, in order to minimize calls to Sheets service and improve efficiency (see Use batch operations).
Related
I have the following Google Sheets Apps Script to extract calendar invites to a Google Sheet, however, I am trying to make some adjustments that I am struggling to find a solution for:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
var id_cal = sheet.getRange("P5").getValue();
var cal = CalendarApp.getCalendarById(id_cal);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
var guestlist = events[i].getGuestList();
sheet.getRange(i+5,1).setValue(title);
sheet.getRange(i+5,2).setValue(start_time);
sheet.getRange(i+5,3).setValue(end_time);
sheet.getRange(i+5,4).setValue(des);
sheet.getRange(i+5,5).setValue(vis);
sheet.getRange(i+5,6).setValue(guestlist);
}
Logger.log("Events have been added to the Spreadsheet");
}
How do I amend this script to:
Extract from several calendars that I have the email addresses in a range of cells (Z1:Z25) instead of just 1 calendar. I have attempted changing the range, but it only pulls the calendar from the top cell.
Include all accepted/pending attendees (including the organiser). I have attempted to add .getGuestList, but this returns 'EventGuest'
Include the calendar that event was taken from
I believe your goal is as follows.
You want to retrieve the events from multiple Calendars by the calendar IDs which are retrieved from the cells "Z1:Z25" of the Spreadsheet.
As the data, from Include all accepted/pending attendees (including the organiser)., you want to add the user's email addresses.
You want to add the calendar IDs as the additional value.
Modification points:
In your script, only one Calendar ID is used. In order to achieve your goal, it is required to retrieve the calendar IDs from the cells "Z1:Z25".
About I have attempted to add .getGuestList, but this returns 'EventGuest', the method of getGuestList() returns EventGuest object. I think that this is the reason for your issue.
In your script, setValue is used in a loop. In this case, the process cost becomes high. Ref
When these points are reflected in your script, it becomes as follows.
Modified script:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var [start_time, end_time] = sheet.getRange("A2:B2").getValues()[0];
var dates = [new Date(start_time), new Date(end_time)]; // If the cell value is date object, you can also use [start_time, end_time]
var ids = sheet.getRange("Z1:Z25").getValues().reduce((ar, [z]) => {
if (z) ar.push(z);
return ar;
}, []);
var values = ids.flatMap(id_cal => {
var cal = CalendarApp.getCalendarById(id_cal);
if (!cal) return [];
var events = cal.getEvents(...dates);
return events.map(e => {
var title = e.getTitle();
var start = e.getStartTime();
var end = e.getEndTime();
var des = e.getDescription();
var vis = e.getVisibility().toString(); // or e.getVisibility()
var guestlist = e.getGuestList().map(f => f.getEmail()).join(",");
return [id_cal, title, start, end, des, vis, guestlist];
});
});
sheet.getRange(5, 1, values.length, values[0].length).setValues(values);
Logger.log("Events have been added to the Spreadsheet");
}
When this script is run, the calendar IDs are retrieved from "Z1:Z25" of "Sheet1". And, the events are retrieved, and the values are retrieved from each event. In this case, the calendar ID, event title, start time, end time, description, visibility, and guest email addresses are put on the sheet in order.
If you want to change the order of values, please modify return [id_cal, title, start, end, des, vis, guestlist];.
If you want to change the user's email to the user's name, please modify f.getEmail() to f.getName().
Note:
This modified script is a simple modification. So, please modify this for your actual situation.
References:
map()
Class EventGuest
Try something like this:
function getEvents() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("Sheet1");
var start = sh.getRange("A2").getValue();
var end = sh.getRange("B2").getValue();
const ids = [];
CalendarApp.getAllCalendars().forEach(c => ids.push(c.getId()));
ids.forEach(id => {
let cal = CalendarApp.getCalendarById(id);
let events = cal.getEvents(new Date(start), new Date(end));
for (var i = 0; i < events.length; i++) {
var title = events[i].getTitle();
var start = events[i].getStartTime();
var end = events[i].getEndTime();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
var guestlist = events[i].getGuestList();
let row = sh.getLastRow() + 1
sh.getRange(sh.getLastRow() + 1, 1,1,5).setValues([[title,start,end,des,vis,guestlist]]);
}
})
Logger.log("Events have been added to the Spreadsheet");
}
I'll leave it up to you to add the additional items as this is not a venue for getting free scripts.
I need help adjusting the script to return the calendar guest names only (not email) and put the names into 1 cell with each name separated by a comma.
I found a script that does this with the guests email, but I cannot figure out how to edit the script to return Names only. Here is the spreadsheet:
Daily Reminders
Any help would be appreciated.
Thank you for taking a look.
I have spent 3 days working on this. First I watched this video to learn to get the event, then had to read this previous, similar, but not really!, solution and have played with, and read this App Script Developer Site for 3 days until I figured out how to get the emails.
function getTomorrowEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Tomorrow");
var start_time = sheet.getRange("b2").getValue();
var end_time = sheet.getRange("d2").getValue();
var id_cal = sheet.getRange("B1:F1").getValue();
var cal = CalendarApp.getCalendarById(id_cal);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var guests = events[i].getGuestList();
var guestEmails = "";
for (var j = 0; j < guests.length; j++) {
var guest = guests[j].getEmail();
guestEmails += guest+", ";
}
sheet.getRange(i+4,2).setValue(title);
sheet.getRange(i+4,3).setValue(start_time);
sheet.getRange(i+4,4).setValue(end_time);
sheet.getRange(i+4,5).setValue(loc);
sheet.getRange(i+4,6).setValue(des);
sheet.getRange(i+4,7).setValue(guestEmails);
}
Logger.log("Events have been added to the Spreadsheet");
}
I believe your goal is as follows.
About guestEmails in your showing script, you want to retrieve the user's name instead of the email address.
Issue and workaround:
When I saw getName() of Class EventGuest, it says the guest's name, or the guest's email address if the name is not available. Ref
When I saw attendees[].displayName of Event of Calendar API, it says The attendee's name, if available.. Ref
When I tested getName() in my calendar, no value is returned. Although, unfortunately, I'm not sure about your actual calendar, if you can retrieve the user's name, you can achieve your goal by the following modification.
From
var guest = guests[j].getEmail();
To
var guest = guests[j].getName();
If this modification was not the direct solution to your situation, it is required to convert the email address to the user's name. In this case, how about the following modification?
Modified script:
In this case, ContactsApp is used for converting the email address to the name.
From:
var guest = guests[j].getEmail();
To:
var guest = ContactsApp.getContact(guests[j].getEmail()).getFullName();
Or, I think that you can also use People API as follows. Before you use this script, please enable People API at Advanced Google services.
From
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var guests = events[i].getGuestList();
var guestEmails = "";
for (var j = 0; j < guests.length; j++) {
var guest = guests[j].getEmail();
guestEmails += guest+", ";
}
To
var res = People.People.Connections.list("people/me", { personFields: "emailAddresses,names", pageSize: 1000 });
var obj = res.connections.reduce((o, e) => (o[e.emailAddresses[0].value] = e.names ? e.names[0].displayName : e.emailAddresses[0].value, o), {});
for (var i = 0; i < events.length; i++) {
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var guests = events[i].getGuestList();
var guestEmails = "";
for (var j = 0; j < guests.length; j++) {
var guest = obj[guests[j].getEmail()] || guests[j].getEmail();
guestEmails += guest + ", ";
}
References:
getContact(emailAddress)
Method: people.connections.list
I have the following code for adding Calendar events from Google Sheets, but it is not working. It is not showing any errors or anything, just that it is not updating the Calendar. Any ideas what I might have done wrong? I tried without the "new Date" on the Start and End dates as well.
function addEvent() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var calendar = ss.getSheetByName("Calendar");
var eventCal = CalendarApp.getCalendarsByName("Test");
var lr = calendar.getLastRow();
var data = calendar.getRange("A2:D"+lr).getValues();
for (i=0; i<data.lenght; i++){
var taskTitle = data[i][0];
var taskDesc = data[i][1];
var startDate = new Date(data[i][2]);
var endDate = new Date(data[i][3]);
//Browser.msgBox('SPX'+':'+taskTitle+':'+startDate+':'+endDate+':'+taskDesc, Browser.Buttons.OK_CANCEL);
eventCal.createEvent(taskTitle,startDate,endDate,{description: taskDesc});
}
}
Here is the sheet I am using.
Title
Description
Start Date
End Date
Test
Test
3/27/2021 13:00:00
3/27/2021 14:00:00
Test 1
Test 2
3/24/2021 13:00:00
3/24/2021 18:00:00
So this might be a good starting point to begin debugging again.
function addEvent() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var calendar = ss.getSheetByName("Calendar");
var eventCal = CalendarApp.getCalendarsByName("Test");
var lr = calendar.getLastRow();
var data = calendar.getRange("A2:D" + lr).getValues();
if (eventCal.length) {
for (i = 0; i < data.lenght; i++) {//length is mispelled
var taskTitle = data[i][0];
var taskDesc = data[i][1];
var startDate = new Date(data[i][2]);
var endDate = new Date(data[i][3]);
eventCal[0].createEvent(taskTitle, startDate, endDate, { description: taskDesc });//taking element zero in the array
}
}
}
Apologies if this has been covered but I am trying to write a script for a google form that when completed will send 'events' to my google calendar. I want these events to be all-day events but the closest I could get to making that work was the below but I still get the time 00:00 on it.. Can anyone help?
///this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "bj8vckkvvhnq4ujr2sb914n03c#group.calendar.google.com";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 4;
var endDtId = 5;
var titleId = 2;
var descId = 3;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
startDt.setHours(0);
startDt.setMinutes(00);
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
endDt.setHours(23);
endDt.setMinutes(59);
var subOn = "Submitted on :"+sheet.getRange(lr,formTimeStampId,1,1).getValue();
var desc = "Added by :"+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()
createEvent(calendarId,title,startDt,endDt,desc);
}
function createEvent(calendarId,title,startDt,endDt,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(startDt);
var end = new Date(endDt);
var loc = '';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
There is a different function "createAllDayEvent" used to create all day events.
https://developers.google.com/apps-script/reference/calendar/calendar#createAllDayEvent(String,Date,Object)
I have been trying for days now, reading other posts, playing with other scripts that have been close to the same purpose and nothing works. I am trying to make a script that will take information from a web based google form, along with a month/day and turn it into a re-occuring event in the Calendar.
It is finally posting to the Calendar NOW but every event comes up undefined under December 31, 2015 - with no further information, altho at least it is reoccurring.
Any help would be greatly appreciated as I try to understand this coding and how to do it. Thank you!
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "id#group.calendar.google.com";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 5;
var endDtId = 5;
var titleId = 2;
var descId = 3;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
// startDt.setHours(0);
// startDt.setMinutes(00);
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
// endDt.setHours(23);
// endDt.setMinutes(59);
// var subOn = "Submitted on :"+sheet.getRange(lr,formTimeStampId,1,1).getValue();
var desc = sheet.getRange(lr,descId,1,1).getValue();
var title = sheet.getRange(lr,titleId,1,1).getValue();
createAllDayEvent(calendarId,title,startDt,endDt,recurrence,loc,desc);
}
function createAllDayEventSeries(calendarId,title,startDt,endDt,recurrence,loc,desc) {
var cal = CalendarApp.getCalendarById('id#group.calendar.google.com');
var start = new Date(startDt);
var end = new Date(endDt);
var loc = descId;
var desc = "Happy Birthday "+titleId+" of "+descId;
// Creates a rule that recurs every week for ten weeks.
var recurrence = CalendarApp.newRecurrence().addYearlyRule();
var event = cal.createAllDayEventSeries(title, start, recurrence, {
description : desc,
location : loc
});
};
I created a form and tested with the following code:
// Column data constants
var nameCol = 2;
var birthdayCol = 3;
var descriptionCol = 4;
var locationCol = 4;
var calendarId = '[id]#group.calendar.google.com';
/* Send Confirmation Email with Google Forms */
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("CreateCalendarEvent")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function createEvent() {
var ss = SpreadsheetApp.getActiveSheet();
var rows = ss.getDataRange();
var lr = rows.getLastRow();
var start = ss.getRange(lr,birthdayCol,1,1).getValue();
start.setHours(0);
start.setMinutes(00);
var title = ss.getRange(lr,nameCol,1,1).getValue() + " Birthday";
var desc = ss.getRange(lr,descriptionCol,1,1).getValue();
var loc = ss.getRange(lr,locationCol,1,1).getValue();
var recurrence = CalendarApp.newRecurrence().addYearlyRule();
Logger.log("accessing calendar");
var externalCalendar = CalendarApp.getCalendarById(calendarId);
externalCalendar.createAllDayEventSeries(title, start, recurrence, {
description : desc,
location : loc
});
}
function getRelativeDate(daysOffset, hour) {
var date = new Date();
date.setDate(date.getDate() + daysOffset);
date.setHours(hour);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
}
function CreateCalendarEvent(e) {
try {
Logger.log("creating event");
createEvent();
} catch (e) {
Logger.log(e.toString());
}
}
This sets a trigger function when the form is submitted, make sure that you change the value of the calendar id to the one provided by your calendar.