1

I am new to Apps Script and struggling with the "getEventById()" function. My goal is to delete an event entry on Google Calendar via Google Sheets when you press a button. I already managed to get the event id via Apps Script and it´s Google API V3, but when I hand it over to "getEventById" as parameter, it returns null, even when I "hardcode" the id.

Here´s my code. I removed some parts since those aren´t important I think:

function calDate(){

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();

  var calId = spreadsheet.getRange("N1").getValue();
  var calEvent = CalendarApp.getCalendarById(calId);
  var ui = SpreadsheetApp.getUi();


  var selection = spreadsheet.getSelection();
  var selectedRow = selection.getActiveRange().getA1Notation();

  var rowRange = sheet.getRange(selectedRow);
  var rowNumber = rowRange.getRow();

  var colRange = sheet.getRange(selectedRow);
  var colNumber = colRange.getColumn();

  if (colNumber !== 15){
    //wait for showtime
  }
  else{
    // its showtime

    var combinedRange = "O" + rowNumber;

    var sheetData = sheet.getRange(rowNumber, 3, 1, 15).getValues();

    if(sheetData[0][12] == false){

      var dateStart = new Date(sheetData[0][7]);
      var dateEnd = new Date(sheetData[0][8]);
      var KdName = sheetData[0][0];
      var BV = event_id[0][4];
      var combinedNames = KdName + " - " + BV;


      var items = Calendar.Events.list(calId, {
        timeMin: dateStart.toISOString(),
        timeMax: dateEnd.toISOString(),
        q: combinedNames
      }).items;

    }
    else{
      var testVar = calEvent.getEventById(/*This is where I would put the htmlLink (the event-id)*/);
    console.log(testVar);
    }

    }
  }

Hopefully those informations are enough and if not, feel free to ask for more. I really hope you guys can help me out!

Kind regards

EDIT & SOLUTION

Okay guys, thanks to Mateo Randwolf, who kindly opened an issue at Google about this, I was able to figure it out. This is the link with an example how to get the the ID from the event and hand that id over to the "getEventById()" function. Or here as a code-block:

    function findEventID() {
      var now = new Date();
      var nextEvent = new Date(now.getTime() + (2 * 60 * 60 * 1000));
      var event = CalendarApp.getDefaultCalendar().getEvents(now, nextEvent);
      ID = event[0].getId();

      Logger.log('EventID: ' + event[0].getId());
      Logger.log(CalendarApp.getDefaultCalendar().getEventById(ID));
   }

Now it gets funny. This line:

Logger.log('EventID: ' + event[0].getId());

returns the event-id like it should.

But this one:

Logger.log(CalendarApp.getDefaultCalendar().getEventById(ID));

doesn´t show anything except "{}", which is weird. But if you apply "deleteEvent()" on it, like so:

calEvent.getEventById(ID).deleteEvent(); //calEvent is a CalendarApp, see above

It actually deletes the event from the calendar! With that, I´d say we found the solution or at least a bypass.

proljon
  • 13
  • 4
  • Can you share an image of the active sheet used in your script. I want to be able to see row and column numbers too. – Cooper Mar 02 '20 at 18:07
  • Unfortunately I can´t do that since it contains sensible data I am not allowed to share directly, sorry for that. – proljon Mar 02 '20 at 21:10
  • Are your events in your main calendar? Take a look at [this](https://developers.google.com/apps-script/reference/calendar/calendar-app#geteventbyidicalid), according to what the documentation says, ```getEventById()``` will only return events in the **default calendar** – Mateo Randwolf Mar 04 '20 at 10:18
  • @MateoRandwolf, thanks for your idea! Unfortunately it has nothing to do with that either. I think you can use calendars other than the default. But still I tried the default calendar and it doesn´t work, it still returns null. I also created an event manually, just to make sure my createEvent() is buggy, but still it returns null. I tried the following in order to print it out: `var testVar = CalendarApp.getDefaultCalendar().getEventById("The ID from the URL"); console.log(testVar);` And yes, the events are in the default calendar with the email as calendar-id. Thanks in advance! – proljon Mar 05 '20 at 12:57
  • `event[0].getId();` returns an iCalUID (see the docs at https://developers.google.com/apps-script/reference/calendar/calendar-event#getid) but are you sure `getEventById` wants that? The docs seem to hint that they're not the same id. – Fuhrmanator May 20 '20 at 18:13

4 Answers4

0

Using the Calendar API search query to find events in a calendar

function calDate(){
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var sh=ss.getActiveSheet();
  var calId=ss.getRange("N1").getValue();
  var calEvent=CalendarApp.getCalendarById(calId);
  var row=ss.getActiveRange().getRow();
  var col=ss.getActiveRange().getColumn()
  if (col!=15){
    //wait for showtime
  }else{
    var vs=sh.getRange(row, 3, 1, 15).getValues();
    if(vs[0][12] == false){
      var dateStart=new Date(vs[0][7]);//col J
      var dateEnd=new Date(vs[0][8]);//col K
      var KdName=vs[0][0];//col 3

event_id below is not defined

      var BV=event_id[0][4];//col G
      var combinedNames=KdName + " - " + BV;
      var items=Calendar.Events.list(calId, {timeMin: dateStart.toISOString(),timeMax: dateEnd.toISOString(),q: combinedNames}).items;
    }
    else{
      var testVar=calEvent.getEventById(/*This is where I would put the htmlLink (the event-id)*/);
      console.log(testVar);
    }
  }
}

Since you couldn't share your spreadsheet I share mine with an example

One thing that helps a lot is playing with the API explorer to figure what works and what doesn't. If you want to display all of the fields you can use * and this example proved very helpful as well

Here's the code:

function myOwnEventSearch() {
  var calendarId='***********calendar id**************';
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Sheet235');
  var sr=2;
  var sc=2
  var rg=sh.getRange(sr,sc,sh.getLastRow()-sr+1,sh.getLastColumn()-sc+1);
  var vA=rg.getValues();
  var hA=sh.getRange(sr-1,sc,1,sh.getLastColumn()-sc+1).getValues()[0];
  var idx={};//locates the data index from column header names
  hA.forEach(function(h,i){idx[h]=i;});
  var cal=CalendarApp.getCalendarById(calendarId);
  var html='<style>td,th{}</style><table><tr><th>Summary</th><th>Start</th><th>End</th><th>Id</th></tr>'
  for(var i=0;i<vA.length;i++) {
    if(!vA[i][idx['Id']] && vA[i][idx['DateFrom']] && vA[i][idx['DateTo']] && vA[i][idx['SearchString']]) {
      var request={timeMin:new Date(vA[i][idx["DateFrom"]]).toISOString(),timeMax:new Date(vA[i][idx["DateTo"]]).toISOString(),q:vA[i][idx["SearchString"]],showDeleted: false,singleEvents:true,maxResults:10,orderBy:"startTime"};
      var resp=Calendar.Events.list(calendarId, request);
      if(resp.items.length>0) {
        var idA=[];
        resp.items.forEach(function(item,j){
          html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>', item.summary,item.start,item.end,item.id);
          idA.push(item.id);
        });
        sh.getRange(i+sr,idx['Id']+sc).setValue(idA.join(', '))
      }
    }
  }
  html+='<table>';
  SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html).setWidth(800), "My Events")
}

Here's the spreadsheet before the script runs.

Spreadsheet before the script runs

Here's the dialog that displays the search results.

The Search Results

Here's what the spreadsheet looks like after running script:

The Event Ids were copied into the Id column

The Event Ids were copied into the Id Column

And these were the four events I created on my calendar::

enter image description here

Cooper
  • 59,616
  • 6
  • 23
  • 54
  • My bad, I did some quick changes before I posted it in here, and var BV = event_id is supposed to be var BV = sheetData[0][4], but I forgot to change that too for this post, I´m sorry. – proljon Mar 02 '20 at 21:10
  • Thanks for the work. I tried to adapt some parts of it, but I run into a permission error which says, that I have no permissions to use "https://www.googleapis.com/auth/script.container.ui", although I should have and I already added it into the appsscript.json manifest. I also managed to get the event-id´s from the calendar before, maybe I didn´t clarify myself enough, I´m sorry for that. My script adds an event to the calendar with a button click, and even when I copy/paste the event-id from the calendar-url, I get "null" from "getEventById()". – proljon Mar 03 '20 at 10:35
0

Issue

Hi ! So it seems to me that getEventById() has a bug that returns null instead of the event object as I was getting the exact same behaviour you were reporting in this question. I have filed this behaviour to the public issue tracker, you can find it here with all the discussion on this behaviour.

I hope this has helped you. Let me know if you need anything else or if you did not understood something. :)

Mateo Randwolf
  • 2,823
  • 1
  • 6
  • 17
  • 1
    Thank you very much for your hard work! I guess I´ll have to wait then since I don´t think I can bypass that... If I have any questions, I´ll send you a PN! – proljon Mar 11 '20 at 14:19
  • If you have problems like this, see above under "EDIT & SOLUTIONS", thanks! – proljon Mar 16 '20 at 10:07
  • I read the issue (and posted). I don't think it's a bug per se. The event's getId() call is documented as: `Gets the unique iCalUID of the event. Note that the iCalUID and the event id used by the Calendar v3 API and Calendar advanced service are not identical and cannot be used interchangebly. One difference in their semantics is that in recurring events all occurrences of one event have different ids while they all share the same iCalUIDs.` Still, `getEventById` seems borked if you can't get each of these two ids through the API. – Fuhrmanator May 20 '20 at 18:07
0

Here is how I worked around this. I stored all the events (from the range I was interested in) in a JavaScript Map() so I can find them later:

  var cal = CalendarApp.getCalendarById("/* supply your calendar ID here*/");
  if (!cal) {
    Logger.log("Calendar not found for ID:" + calendarID);
  } else {
    var calEvents = cal.getEvents(new Date("March 8, 2010"), new Date("March 14, 2025"));
    // Store them by eventId for easy access later
    var calEventMap = new Map();
    for (var j in calEvents) {
      calEventMap.set(calEvents[j].getId(), calEvents[j]);
    }

    /* Later when you need to look up by iCalID... */

    var calEvent = calEventMap.get(eventID);

  }
Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
0

Works for me when you get the calendar by id like this:

const calendar = CalendarApp.getCalendarById("theCalendarId");

const event = calendar.getEventById("someEventId");

Now the event is not null, but the actual event, and you can do whatever you want with it from here!

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
jhn
  • 1
  • 1