Home > OS >  How to run a script on several gmail calendars
How to run a script on several gmail calendars

Time:10-03

I have multiple staff who input their day into a goggle calendar and I take the data and run stats. At the moment I can only take data from one calendar at a time. How can I take this script and make it work on several calendars?

Note that each calendar has its own target sheet. I've tried duplicating the script but only one version seems to work at a time.

function export_gcal_to_gsheet() {
  var mycal = "person email";
  var cal = CalendarApp.getCalendarById(mycal);
  var events = cal.getEvents(new Date("July 01, 2022 00:00:00 UTC"), new Date());
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PersonCalendar");
  sheet.clearContents();
  var calColor = cal.getColor();
  var colors = Calendar.Colors.get().calendar;
  var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
  var offset = 6;
  var { v, c } = events.reverse().reduce((o, e, i) => {
    var color = e.getColor();
    var row = offset   i   1;
    var c = colors[color] ? colors[color].background : calColor;
    var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
    o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), events[i].getStartTime(), events[i].getEndTime(), f, (''   events[i].getVisibility()), events[i].getDateCreated(), events[i].getLastUpdated(), events[i].getMyStatus(), events[i].getCreators(), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
    o.c.push([c]);
    return o;
  }, { v: [], c: [] });
  var values = [header, ...v];
  sheet.getRange(6, 1, values.length, values[0].length).setValues(values);
  sheet.getRange(7, 7, v.length - 1).setNumberFormat('.00');
  sheet.getRange(7, 15, c.length).setBackgrounds(c);
}

CodePudding user response:

Both of the following techniques distribute the output to separate sheets and leave most of the original code intact.

function exportcalenders() {
  const calids = [{ id: "calid", shnam: "Sheet Name"}];
  calids.forEach(obj => {
    var cal = CalendarApp.getCalendarById(obj.id);
    var events = cal.getEvents(new Date(new Date().getFullYear(),newDate().getMonth(),1),new Date());
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(obj.shnam);
    sheet.clearContents();
    var calColor = cal.getColor();
    var colors = Calendar.Colors.get().calendar;
    var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
    var offset = 6;
    var { v, c } = events.reverse().reduce((o, e, i) => {
      var color = e.getColor();
      var row = offset   i   1;
      var c = colors[color] ? colors[color].background : calColor;
      var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
      o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), events[i].getStartTime(), events[i].getEndTime(), f, (''   events[i].getVisibility()), events[i].getDateCreated(), events[i].getLastUpdated(), events[i].getMyStatus(), events[i].getCreators(), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
      o.c.push([c]);
      return o;
    }, { v: [], c: [] });
    var values = [header, ...v];
    sheet.getRange(6, 1, values.length, values[0].length).setValues(values);
    sheet.getRange(7, 7, v.length - 1).setNumberFormat('.00');
    sheet.getRange(7, 15, c.length).setBackgrounds(c);
  });

}

Here's another way using recursion:

This version assumes that all of the calendars are shared with you and thus accessible via getAllCalendars. The inclCals variable allows you to only include certain calendars from getAllCalendars list and snames is a list of sheets that you wish each calendar to be assigned two. The variable obj transfers all of that information to main cal via cacheService.

function xportcals() {
  let inclCals = ["CalName1", "CalName2", "CalName3", "CalName4"];
  let snames = ["Sheet1","Sheet2","Sheet3","Sheet4"]
  let obj = CalendarApp.getAllCalendars().reduce((a, c, i) => {
    let idx = inclCals.indexOf(c.getName());
    if (~idx) {
      a["cal"].push({ id: c.getId(), name: c.getName(),sheetname:snames[idx]});
    }
    return a;
  }, { cal: [], proc: { level: 0, som: 1, sod: 1 } });
  CacheService.getScriptCache().put("cals", JSON.stringify(obj), 300);
  maincals();
}

    function maincals() {
      let obj = JSON.parse(CacheService.getScriptCache().get("cals"));
      var cal = CalendarApp.getCalendarById(obj.cal[obj.proc.level]);
      var events = cal.getEvents(new Date(new Date().getFullYear(), newDate().getMonth() - obj.proc.som , obj.proc.sod), new Date());
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(obj.cal.sheetname);
      sheet.clearContents();
      var calColor = cal.getColor();
      var colors = Calendar.Colors.get().calendar;
      var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
      var offset = 6;
      var { v, c } = events.reverse().reduce((o, e, i) => {
        var color = e.getColor();
        var row = offset   i   1;
        var c = colors[color] ? colors[color].background : calColor;
        var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
        o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), events[i].getStartTime(), events[i].getEndTime(), f, (''   events[i].getVisibility()), events[i].getDateCreated(), events[i].getLastUpdated(), events[i].getMyStatus(), events[i].getCreators(), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
        o.c.push([c]);
        return o;
      }, { v: [], c: [] });
      var values = [header, ...v];
      sheet.getRange(6, 1, values.length, values[0].length).setValues(values);
      sheet.getRange(7, 7, v.length - 1).setNumberFormat('.00');
      sheet.getRange(7, 15, c.length).setBackgrounds(c);
      obj.proc.level  = 1;//increment the level counter
      CacheService.getScriptCache().put("cals", JSON.stringify(obj), 60);//save obj in cacheService
      if (obj.proc.level < obj.cal.length) {
        maincals();
      }
      return;
    }

I did not test this particular version but I did test a simpler version and most of the parts that are not common to what I tested are your original code which presumably works.

CodePudding user response:

In your script, only one Calendar ID is used. In order to use multiple Calendar IDs, when your showing script is modified for using multiple Calendar IDs, how about the following modification?

Modified script 1:

In this modification, all values are put to "PersonCalendar" sheet.

function export_gcal_to_gsheet() {
  var calendarIds = ["person email1", "person email2",,,]; // Please set your Calendar IDs.

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PersonCalendar");
  sheet.clearContents();
  var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
  var colors = Calendar.Colors.get().calendar;
  var { vv, cc } = calendarIds.reduce((oo, mycal) => {
    var cal = CalendarApp.getCalendarById(mycal);
    var events = cal.getEvents(new Date("July 01, 2022 00:00:00 UTC"), new Date());
    var calColor = cal.getColor();
    var offset = 6;
    var { v, c } = events.reverse().reduce((o, e, i) => {
      var color = e.getColor();
      var row = offset   i   1;
      var c = colors[color] ? colors[color].background : calColor;
      var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
      o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), events[i].getStartTime(), events[i].getEndTime(), f, (''   events[i].getVisibility()), events[i].getDateCreated(), events[i].getLastUpdated(), events[i].getMyStatus(), events[i].getCreators(), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
      o.c.push([c]);
      return o;
    }, { v: [], c: [] });
    oo.vv = [...oo.vv, ...v];
    oo.cc = [...oo.cc, ...c];
    return oo;
  }, { vv: [], cc: [] });
  var values = [header, ...vv];
  sheet.getRange(6, 1, values.length, values[0].length).setValues(values);
  sheet.getRange(7, 7, vv.length - 1).setNumberFormat('.00');
  sheet.getRange(7, 15, cc.length).setBackgrounds(cc);
}
  • In this modification, by retrieving the values from multiple Calendar IDs, all retrieved values are put to the Spreadsheet.

Modified script 2:

In this modification, the values of each Calendar are put to each sheet.

function export_gcal_to_gsheet() {
  var obj = [{ mycal: "person email1", sheetName: "PersonCalendar" }];
  var colors = Calendar.Colors.get().calendar;
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  obj.forEach(({ mycal, sheetName }) => {
    var cal = CalendarApp.getCalendarById(mycal);
    var events = cal.getEvents(new Date("July 01, 2022 00:00:00 UTC"), new Date());
    var sheet = ss.getSheetByName(sheetName);
    sheet.clear(); // or sheet.clearContents();
    var calColor = cal.getColor();
    var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
    var offset = 6;
    var { v, c } = events.reverse().reduce((o, e, i) => {
      var color = e.getColor();
      var row = offset   i   1;
      var c = colors[color] ? colors[color].background : calColor;
      var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
      o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), events[i].getStartTime(), events[i].getEndTime(), f, (''   events[i].getVisibility()), events[i].getDateCreated(), events[i].getLastUpdated(), events[i].getMyStatus(), events[i].getCreators(), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
      o.c.push([c]);
      return o;
    }, { v: [], c: [] });
    var values = [header, ...v];
    sheet.getRange(6, 1, values.length, values[0].length).setValues(values);
    sheet.getRange(7, 7, v.length - 1).setNumberFormat('.00');
    sheet.getRange(7, 15, c.length).setBackgrounds(c);
  });
}

Modified script 3:

In this modification, the values of each Calendar are put on each sheet. And, by using Sheets API, the process cost is reduced a little from that of "Modified script 2". So, please enable Sheets API at Advanced Google services.

function export_gcal_to_gsheet() {
  var obj = [{ mycal: "person email1", sheetName: "PersonCalendar" },,,]; // Please set calendar IDs and sheet names.

  var colors = Calendar.Colors.get().calendar;
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var { valuesBatchUpdate, batchUpdate } = obj.reduce((oo, { mycal, sheetName }) => {
    var cal = CalendarApp.getCalendarById(mycal);
    var calColor = cal.getColor();
    var events = cal.getEvents(new Date("July 01, 2022 00:00:00 UTC"), new Date());
    var header = ["Calendar Address", "Event Title", "Event Description", "Event Location", "Event Start", "Event End", "Calculated Duration", "Visibility", "Date Created", "Last Updated", "MyStatus", "Created By", "All Day Event", "Recurring Event", "Color"];
    var offset = 6;
    var { v, c } = events.reverse().reduce((o, e, i) => {
      var color = e.getColor();
      var row = offset   i   1;
      var c = colors[color] ? colors[color].background : calColor;
      var f = `=(HOUR(F${row}) (MINUTE(F${row})/60))-(HOUR(E${row}) (MINUTE(E${row})/60))`;
      o.v.push([mycal, events[i].getTitle(), events[i].getDescription(), events[i].getLocation(), (events[i].getStartTime().getTime() / 1000 / 86400)   25569, (events[i].getEndTime().getTime() / 1000 / 86400)   25569, f, (''   events[i].getVisibility()), (events[i].getDateCreated().getTime() / 1000 / 86400)   25569, (events[i].getLastUpdated().getTime() / 1000 / 86400)   25569, events[i].getMyStatus().toString(), events[i].getCreators().join(","), events[i].isAllDayEvent(), events[i].isRecurringEvent(), c]);
      o.c.push([c]);
      return o;
    }, { v: [], c: [] });
    var sheetId = ss.getSheetByName(sheetName).getSheetId();
    var hexToRgb = hex => { // Ref: https://stackoverflow.com/a/11508164
      var bigint = parseInt(hex, 16);
      var red = ((bigint >> 16) & 255) / 255;
      var green = ((bigint >> 8) & 255) / 255;
      var blue = (bigint & 255) / 255;
      return { red, green, blue }
    };
    oo.valuesBatchUpdate.push({ range: `'${sheetName}'!A6`, values: [header, ...v] });
    oo.batchUpdate.push(
      { updateCells: { fields: "*", range: { sheetId } } },
      { repeatCell: { range: { sheetId, startRowIndex: 6, endRowIndex: 6   v.length, startColumnIndex: 6, endColumnIndex: 7 }, cell: { userEnteredFormat: { numberFormat: { pattern: '.00', type: "NUMBER" } } }, fields: "userEnteredFormat.numberFormat" } },
      { repeatCell: { range: { sheetId, startRowIndex: 6, endRowIndex: 6   v.length, startColumnIndex: 4, endColumnIndex: 6 }, cell: { userEnteredFormat: { numberFormat: { pattern: 'yyyy/MM/dd', type: "DATE" } } }, fields: "userEnteredFormat.numberFormat" } },
      { repeatCell: { range: { sheetId, startRowIndex: 6, endRowIndex: 6   v.length, startColumnIndex: 8, endColumnIndex: 10 }, cell: { userEnteredFormat: { numberFormat: { pattern: 'yyyy/MM/dd', type: "DATE" } } }, fields: "userEnteredFormat.numberFormat" } },
      { updateCells: { rows: c.map(([hex]) => ({ values: [{ userEnteredFormat: { backgroundColor: hexToRgb(hex.replace("#", "")) } }] })), range: { sheetId, startRowIndex: 6, endRowIndex: 6   c.length, startColumnIndex: 14, endColumnIndex: 15 }, fields: "userEnteredFormat.backgroundColor" } }
    );
    return oo;
  }, { valuesBatchUpdate: [], batchUpdate: [] });
  var ssId = ss.getId();
  Sheets.Spreadsheets.batchUpdate({ requests: batchUpdate }, ssId);
  Sheets.Spreadsheets.Values.batchUpdate({ data: valuesBatchUpdate, valueInputOption: "USER_ENTERED" }, ssId);
}

Note:

  • In this case, when you have no permissions for accessing the Calendar IDs, an error occurs. Please be careful about this.
  • Related