Как запустить скрипт на нескольких календарях gmail

У меня есть несколько сотрудников, которые вводят свой день в календарь очков, а я беру данные и веду статистику. На данный момент я могу брать данные только из одного календаря за раз. Как мне взять этот скрипт и заставить его работать на нескольких календарях?

Обратите внимание, что у каждого календаря есть свой целевой лист. Я пытался продублировать сценарий, но работает только одна версия.

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);
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
116
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашем сценарии используется только один идентификатор календаря. Чтобы использовать несколько идентификаторов календаря, когда ваш сценарий показа изменен для использования нескольких идентификаторов календаря, как насчет следующей модификации?

Модифицированный скрипт 1:

В этой модификации все значения вынесены на лист "PersonCalendar".

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);
}
  • В этой модификации путем извлечения значений из нескольких идентификаторов календаря все полученные значения помещаются в электронную таблицу.

Модифицированный скрипт 2:

В этой модификации значения каждого календаря вынесены на каждый лист.

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);
  });
}

Модифицированный скрипт 3:

В этой модификации значения каждого календаря вынесены на каждый лист. А при использовании Sheets API стоимость процесса немного снижается по сравнению с «Измененным скриптом 2». Итак, пожалуйста, включите Sheets API в расширенных сервисах Google.

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);
}

Примечание:

  • В этом случае, когда у вас нет прав доступа к идентификаторам календаря, возникает ошибка. Пожалуйста, будьте осторожны с этим.

Спасибо, Танайке, как всегда. Позвольте мне реализовать это на моем конце и посмотреть, как все это работает. Меня беспокоит стоимость процесса, поэтому на данном этапе я определенно склоняюсь к моду 3.

RoosterMagic22 03.10.2022 08:40

Привет, Танайке, я получаю эту ошибку в Mod 1: 6:19:29 AM Error TypeError: Не удается прочитать свойство getEvents нулевого calendarIds.reduce.vv @ Untitled.gs:10 export_gcal_to_gsheet @ Untitled.gs:8

RoosterMagic22 03.10.2022 22:25

Мод 2 работает отлично, спасибо вам. Я буду тестировать другие моды, но я даю себе только 1 час каждое утро, чтобы работать над кодированием, так что потерпите меня, и я свяжусь с вами по другим модам.

RoosterMagic22 04.10.2022 00:13

@RoosterMagic22 Спасибо за ответ. Что касается Mod 2 works perfectly, результат «Измененного сценария 3» такой же, как и «Измененный сценарий 2». Разница только в стоимости процесса.

Tanaike 04.10.2022 00:16

Я знаю, что не могу понять, что я делаю неправильно, на самом деле это меня немного раздражает. Я уверен, что это что-то простое.

RoosterMagic22 04.10.2022 00:22

@RoosterMagic22 Спасибо за ответ. Я глубоко извиняюсь за это.

Tanaike 04.10.2022 00:23

извините, приятель, я не знаю, что делаю, я все еще получаю следующие ошибки в моде 3 9:05:57 AM Error TypeError: Cannot read property 'toString' of null events.reverse.reduce.v @ Code.gs :17 obj.reduce.valuesBatchUpdate @ Code.gs:12 export_gcal_to_gsheet @ Code.gs:6

RoosterMagic22 05.10.2022 01:36

@RoosterMagic22 Спасибо за ответ. Я должен извиниться за мое плохое знание английского языка. К сожалению, я не могу понять I don't know what I'm doing, Im still getting the following erros on mod 3 9:05:57 AM Error TypeError: Cannot read property 'toString' of null events.reverse.reduce.v @ Code.gs:17 obj.reduce.valuesBatchUpdate @ Code.gs:12 export_gcal_to_gsheet @ Code.gs:6 . Могу я спросить вас о деталях этого?

Tanaike 05.10.2022 02:47

Оба следующих метода распределяют вывод по отдельным листам и оставляют большую часть исходного кода нетронутой.

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);
  });

}

Вот еще один способ использования рекурсии:

В этой версии предполагается, что все календари доступны вам и поэтому доступны через getAllCalendars. Переменная inclCals позволяет вам включать только определенные календари из списка getAllCalendars, а snames — это список листов, которым вы хотите назначить два календаря. Переменная obj передает всю эту информацию в main cal через 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;
    }

Я не тестировал эту конкретную версию, но я протестировал более простую версию, и большинство частей, которые не являются общими для того, что я тестировал, являются вашим исходным кодом, который предположительно работает.

О, эта рекурсия выглядит интересной, и я вижу, как она будет работать — позвольте мне реализовать ее со своей стороны и вернуться к вам.

RoosterMagic22 03.10.2022 08:35

Привет, Купер. Я пробую реверсивное кодирование и получаю следующие ошибки, есть идеи? 6:07:49 AM Error TypeError: Не удается прочитать свойство getEvents нулевых maincals @ Code.gs: 18 xportcals @ Code.gs: 12

RoosterMagic22 03.10.2022 22:09

Хорошо, тогда кал должен быть нулевым, так как же выглядит obj.

Cooper 03.10.2022 22:24

Доступны ли вам все календари, с которыми вы работаете? Если нет, то это let obj = CalendarApp.getAllCalendars().reduce((a, c, i) => { может не сработать для вас.

Cooper 03.10.2022 22:30

Что вы имеете в виду, когда спрашиваете, как выглядит OBJ? Означает ли это, что окончательный сценарий?

RoosterMagic22 03.10.2022 22:32

Да, календари определенно доступны мне, я вижу их в календаре Google, и когда я пробую отдельный скрипт, он работает нормально.

RoosterMagic22 03.10.2022 22:33

Вы понимаете, как работает функция сокращения?

Cooper 03.10.2022 22:38

Я понимаю это на очень базовом уровне, приятель, я буду продолжать тестировать, а также тестировать другие моды, но я даю себе только 1 час каждое утро, чтобы работать над кодированием, так что потерпите меня, и я свяжусь с вами. У вас, вероятно, есть дела поважнее, но я подумал, что вам может быть интересно, как это происходит - в любом случае спасибо за вашу помощь.

RoosterMagic22 04.10.2022 00:14

Другие вопросы по теме