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.
Related
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).
I have multiple sheets with different dates and different calendar ids. The intention is to have the script go over each sheet and import it in the calendar with the corresponding calander id. I have it working for one sheet/calendar, but i cant figure out how to expand the code to go over each sheet. This is what i have that works for one sheet/calendar:
function scheduleshifts() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("B2").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
var BBB = spreadsheet.getRange("BO1").getValue();
var CCC = "BL2:"
var signups = spreadsheet.getRange(CCC+BBB).getValues();
for (x=0; x<signups.length; x++){
var shift = signups[x];
var startTime = shift[0];
var endTime = shift[1];
var title = "Werken";
eventCal.createEvent(title, startTime, endTime);
}
}
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu('Sync to Calendar').addItem("Schedule shifts now", 'scheduleshifts').addToUi();
}
Creating Events from multiple sheets and muliple calendar ids
function scheduleshifts() {
const ss = SpreadsheetApp.getActive();//included sheets. If you are always using all sheets then remove this line and the filter section.
const inclshts = ["Sheet1","Sheet2","Sheet3"];
const shts = ss.getSheets().filter(s => ~inclshts.indexOf(s.getName()) ).forEach(sh => {
let eventCal = CalendarApp.getCalendarById(sh.getRange("B2").getDisplayValue());//id is in each sheet
let signups = sh.getRange(`BL2:${sh.getRange("BO1").getValues()}`);
Logger.log(`BL2:${sh.getRange("BO1").getValues()}`);
Logger.log(JSON.stringify(sh.getRange("BO1").getValues()));
Logger.log(JSON.stringify(signups));
signups.forEach((r,i)=>{
eventCal.createEvent("Werken",new Date(r[1]),new Date(r[2]);
});
});
}
I'm trying to return a list of specific email addresses of all event attendees on a GSuite calendar with a script and I can only return either an ID number or a list that appears only as "EventGuest, EventGuest, EventGuest...."
Is it possible to return the email address itself? Thanks in advance for any guidance here!
This is the basic script that I'm working with:
function listCalendarAttendees(){
var calendar = CalendarApp.getCalendarById('AnyCalendarTEST#gmail.com');
var sheet = SpreadsheetApp.openById('TEST ID').getSheetByName('Bobs Calendar');
var startTime = new Date();
var endTime = new Date(startTime.getTime()+(1000*60*60*24*7));
var events = calendar.getEvents(startTime, endTime);
Logger.log('Number '+events.length);
for(var x=0;x<events.length;x++){
var event = events[x];
var messages = event.getTitle();
var eventStart = event.getStartTime();
var emails = event.getCreators().toString();
var descriptions = event.getDescription();
var guestListLength = event.getGuestList().length;
var guestListNames =event.getGuestList().toString();
sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}
}
You want to retrieve the emails of all guests in the event.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
getGuestList() returns the object of EventGuest[]. In this case, the email can be retrieved by getEmail() from EventGuest.
When appendRow() is used in the for loop, the process cost will be high. So in this modification, setValues() is used instead.
Modified script:
When your script is modified, it becomes as follows.
From:
for(var x=0;x<events.length;x++){
var event = events[x];
var messages = event.getTitle();
var eventStart = event.getStartTime();
var emails = event.getCreators().toString();
var descriptions = event.getDescription();
var guestListLength = event.getGuestList().length;
var guestListNames =event.getGuestList().toString();
sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}
To:
var values = []; // Added
for(var x=0;x<events.length;x++){
var event = events[x];
var messages = event.getTitle();
var eventStart = event.getStartTime();
var emails = event.getCreators().toString();
var descriptions = event.getDescription();
var guestListLength = event.getGuestList().length;
var guestListNames = event.getGuestList().map(function(e) {return e.getEmail()}).join(","); // Modified
values.push([messages,eventStart,emails,descriptions,guestListLength,guestListNames]); // Modified
}
sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values); // Added
In this modification, the emails are separated by , and it is put to a cell.
References:
getGuestList()
Class EventGuest
getEmail()
If I misunderstood your question and this was not the direction you want, I apologize.
Event Guest is an object. Here are it's methods:
getEmail()
getAdditionalGuests()
getGuestStatus()
getName()
I am trying to create a Google Apps Script that will list all the Google Classroom courses that are active and archived, along with the ID, NAME, SECTION, and COURSESTATE. Everything works except that I have no idea how to fix the .getRange so that it will put all the information in the Google Spreadsheet. The error I get is "Incorrect range height, was 4 but should be 10". If I put the .getRange as simply "A1:D1", it will overwrite what is there for each Class until the script finishes, so I know the rest of the script works, but I can't figure out how to put the range so that all the Classes can be listed. What I have up to now is this:
function listCourses() {
var response = Classroom.Courses.list();
var courses = response.courses;
if (courses && courses.length > 0) {
for (i = 0; i < courses.length; i++) {
var course = courses[i];
var ids = course.id;
var title = course.name;
var sec = course.section;
var state = course.courseState;
var arr1 = [];
arr1.push(ids,title,sec,state);
var arr2 = [];
while(arr1.length) arr2.push(arr1.splice(0,1));
var s = SpreadsheetApp.getActiveSpreadsheet();
var sh = s.getSheetByName('LISTS');
for (var x=0; x<arr2.length; x++){
var newRow = sh.getLastRow() + 1;
// Here in the .getRange is where it gives me the error. A new row should be added for each Class until all the Classes (with the information mentioned above) are listed.
sh.getRange(1, 1, newRow, arr2[0].length).setValues(arr2);
}
}}}
Try something like this:
I don't use Classroom API much and I only have one class in it but this works for it.
function listCourses() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('LISTS');
var response = Classroom.Courses.list();
var courses = response.courses;
var arr=[];//You could put column headers in here
for (i = 0; i < courses.length; i++) {
var course = courses[i];
var ids = course.id;
var title = course.name;
var sec = course.section;
var state = course.courseState;
arr.push([title,sec,state]); //you could also go sh.appendRow([title,sec,state]); here if you wish and avoid the use of the two dimensional array all together as suggested in the other answer.
}
sh.getRange(1, 1, arr.length, arr[0].length).setValues(arr);
}
Jason. You could bypass the range issue by using append row. This will however mean manipulating the data so that each class's details is on one row. I prefer this approach because it is let prone to errors. Also it automatically finds the next empty row in the sheet, so you don't need to get the last row.
function appendRow() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
// Try is added to catch failures on automated scripts
try {
sheet.appendRow(['cell1','cell2','cell3'])
} catch (e){
Logger.log(e)
// Could send an email here to alert script failure
}
// In a loop
var data = [['row 1 cell 1','row 1 cell 2'],['row 2 cell 1','row 2 cell 2 ']]
data.forEach(function(item){
sheet.appendRow(item)
})
}
I have a spreadsheet with a list of events, but need to insert them into their own respective calendars. So far I have this:
function pushCalendars() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (i in sheets){
if (sheets.length > 1){
var lastRow = sheets[i].getLastRow();
var range = sheets[i].getRange(3,1,lastRow,100);
var data = range.getValues();
for (i in data){
var row = data[i];
var title = row[0];
var title2 = row[1];
var date = row[2];
var desc = row[3];
var calName = ss.getSheetByName("Resorts").getRange('E3').getValue();
var cal = CalendarApp.openByName(calName);
cal.createAllDayEvent(title,date);
}
}
}
Let me know if you have any solutions!
If the calendars are owned by your user you will face no problems.
The only thing that you need to change in your code is to create the calendars that still does not exists with this piece of code:
// Creates a new calendar named "Travel Plans" with a summary and color.
var calendar = CalendarApp.createCalendar('Travel Plans', {
summary: 'A calendar to plan my travel schedule.',
color: CalendarApp.Color.BLUE
});
Logger.log('Created the calendar "%s", with the ID "%s".',
calendar.getName(), calendar.getId());
The API documentation can be found here.
If the calendars belongs to other user you will need to have administrative permissions to modify it and you need to log with OAuth plus calling the calendar API using URLFetch (Calendar API can be found here.)
I always get my calendars by id, since the calendars already exist, you could get the calendar ID from the Calendar Settings, and insert them into the script as Project Properties. Then all you need to do is load the id that matches the name.
Change these two lines:
var calName = ss.getSheetByName("Resorts").getRange('E3').getValue();
var cal = CalendarApp.openByName(calName);
To this:
var calName = ss.getSheetByName("Resorts").getRange('E3').getValue();
var calID = ScriptProperties.getProperty(calName);
var cal = CalendarApp.getCalendarByID(calID);
https://developers.google.com/apps-script/guides/properties#scriptProperties for reference on ScriptProperties.