понедельник, 24 апреля 2017 г.

Объединение календаря и таблицы Google

Google таблицы прекрасный кросс-платформенный инструмент для работы с информацией. С этим трудно поспорить - из любой точки Земли, с любого современного устройства легко получить доступ к ней, если есть великий и могучий Интернет.


Если чего-то не хватает для нужд человечества, всегда можно написать свой скрипт, который может всё, ну или практически всё.

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

И первый пример связан с возможностью объединить таблицу с календарём Google. Это открывает широкие возможности для пользователя ОС Android: всегда быть в курсе предстоящих событий, дней рождений всей родни, друзей, клиентов. Для этого даже не надо заглядывать в приложение календарь на Android смартфоне, оно само напомнит обо всех событиях.

Итак, скрипт

function saveBirthdays() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var data = sheet.getDataRange().getValues();
  var calname = CalendarApp.getCalendarsByName("Дни рождения клиентов");
  if (calname.length > 0) 
{
   var currentCalendar = calname[0];
}
  else 
{
   var currentCalendar = CalendarApp.createCalendar("Дни рождения клиентов");
}
  var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
  for (var j = 0 ; j < events.length; j++)
{
   events[j].deleteEvent();
}
  for (var i = 1; i < data.length; i++) 
{
   var Data = new Date(data[i][1]);
   var now = new Date().getMonth();
   var month = now+1;
   if ((Data.getMonth()<=month)&&(Data.getMonth()>=month-1)){
   var Name = data[i][0];
   var Phone = data [i][2]; 
   var event = currentCalendar.createAllDayEventSeries("Сегодня "+Name+" празднует день рождения. Не забудь поздравить \n"+", номер телефона:"+Phone,Data,CalendarApp.newRecurrence().addYearlyRule());
    event.addEmailReminder(0);
    event.addPopupReminder(0)
    }
  }
}

Что делает скрипт?
  1. Пропуская 1-ю строчку (заголовок таблицы), берёт данные из текущей таблицы в которой в 1-м столбике Фамилия, Имя, Отчество вашего клиента, во 2-м - дата рождения, в 3-м номер телефона; 
  2. Создаёт календарь (если такого нет) под названием "Дни рождения клиентов";
  3. Для исключения повторяющихся событий, удаляются все события из данного календаря в промежутке 01.01.2010 - 01.01.2030 (если нужно просто очистить календарь, придётся подключать дополнительные библиотеки);
  4. Создаются предстоящие события - дни рождения клиентов в текущем месяце и следующем (т.к. существует ограничение Google на создание слишком большого количества событий за короткий промежуток времени, а клиентов может быть много);
  5. Добавляет оповещение по почте и всплывающее напоминание   
Теперь можно добавить триггер на выполнение скрипта по расписанию 1 раз в месяц, либо добавить кнопку. Не забываем добавить синхронизацию календаря в смартфоне.


122 комментария:

  1. Роман, а как можно осуществить такой вариант. Например есть таблица, где есть столбец с именами клиентов, есть столбец с планируемой датой встречи.. как сделать, чтобы данные отправлялись с таблицы в календарь?

    ОтветитьУдалить
  2. Нужно попробовать поработать с текстом для планируемой встречи. Там где текст для празднования д.р. поменять на "планируется встреча" с таким то таким то. Ну и дату поставить нужную.

    ОтветитьУдалить
  3. Спасибо, подскажите как можно добавить время встречи и прикрутить кнопку на выполнение скрипта

    ОтветитьУдалить
    Ответы
    1. в данном скрипте создаётся событие на весь день.

      Во втором столбце вводить дату в формате

      8.11.2017 21:32:00

      где время понятно?

      и поменять в скрипте createAllDayEventSeries(блаблабла) на
      createEvent('описание',data,new Date(data+1*60 * 60 * 1000))

      Будет создано событие и будет считаться что ваша встреча будет проходить 1 час.


      Ну и в

      event.addEmailReminder(0)
      event.addPopupReminder(0)

      0 поменять на количество минут за которое Вас нужно предупредить о встрече.

      Удалить
    2. про кнопки можно здесь посмотреть https://www.youtube.com/watch?v=sDMY9o23uBM

      Удалить
    3. Роман, выскочила ошибка "Время начала мероприятия не должно быть позже времени окончания.". Я выложил скрин кода, вроде сделал так как надо https://yadi.sk/i/QLD4lkcJ3PXUnL, а также скрин таблички https://yadi.sk/i/EjCltLIZ3PXVFV

      Удалить
    4. I'm sorry. Давно писал, вылетело всё из головы.

      В строке data+1*60*60*100 переменная data нужно написать с заглавной буквы, т
      е. Data+1*60*60*1000.

      Моя ошибка :) Виноват, исправлюсь.:)

      Удалить
    5. К сожалению не спасло ситуацию, та же ошибка(

      Удалить
    6. Доступ к таблице дадите? Разберусь. igro83@gmail.com

      Удалить
    7. Век живи, век учись. Вроде плёвая задача, решение на поверхности. Но если проходит много времени начинаешь и забывать особенности работы со временем.

      В общем строка преобразуется в

      var event = currentCalendar.createEvent("Сегодня запланирована встреча с "+Name+". \n"+", номер телефона:"+Phone,Data,new Date(Data.getTime()+1*60*60*1000))

      У Вас поправил

      Удалить
  4. Роман, спасибо вам большое за скрипт и кнопку)). Вы мастер!

    ОтветитьУдалить
    Ответы
    1. Спасибо. Посмотрите другие статьи в блоге. Вдруг найдёте ещё что-то интересное для себя.:)

      Удалить
  5. Роман, добрый вечер. Занимаюсь упрощением работы с базой клиентов в таблице гугл. Сделал кнопку для создания события в календаре из текущей строчки.Одновременно установил 3 скрипта (звонки,задачи, встречи) . Вот встречи со звонками нуждаются в хронометраже, а задачи нужно установить на весь день. Подскажите что добавить в скрипт или что убрать ,чтобы событие создавалось на целый день и не нужно было вводить время и событие устанавливалось вверх календаря

    ОтветитьУдалить
    Ответы
    1. В моей статье создаются события на весь день. Дни рождения клиентов - события на весь день.

      в строчке

      var event = currentCalendar.createAllDayEventSeries("Сегодня "+Name+" празднует день рождения. Не забудь поздравить \n"+", номер телефона:"+Phone,Data,CalendarApp.newRecurrence().addYearlyRule());

      создаются события на весь день причем повторяющиеся 1 раз в год.

      Если строчку заменить на

      var event = currentCalendar.createAllDayEvent("Сегодня "+Name+" празднует день рождения. Не забудь поздравить \n"+", номер телефона:"+Phone,Data);

      то будут создаваться события на целый день только без повторений.

      Удалить
    2. ОК. Спасибо, буду править. Ещё Роман подскажите отчего-то перестала работать замена времени события : заменяю в выражении Date(Data.getTime()+1*60*60*1000)) - +1 на 0.15 и ничего не меняется. Так же уведомления тоже не встают : event.addEmailReminder(0)
      event.addPopupReminder(0)

      Удалить
    3. В javascript время хранится в миллисекундах, поэтому если хочется установить длительность события в минутах нужно +15*60*1000 если время 15 минут. Ну и напоминание не добавляется из-за ошибки с 0.15.

      Удалить
  6. Здравствуйте Роман,
    Очень интересная статья.
    У меня возникла проблема, все работает когда я вручную запускаю скрипт, но когда я запускаю триггер - нет. Хотя уверен что он написан правильно.
    Моя таблица находиться на 3 аркуше документа, и с того что я понимаю триггер автоматически читает 1-ый аркуш а не 3-ий.
    Можно ли вместо getActiveSheet написать getSheetById или getSheetByName или что то другое, что будет указывать путь именно к этому файлу к этому аркушу к этой таблице?

    Буду очень благодарен за помощь, идеально было бы если бы Вы проверили то что я там понаписывал :)

    ОтветитьУдалить
    Ответы
    1. getSheetByName('Название листа') - прямо идеально Ваш вариант.

      Удалить
    2. Блииин а я ставил двойные скобки.
      Спасибо - ты лучший

      Удалить
    3. Добрый день! Очень полезная информация
      Не могу разобраться в тригерах как мне через OnEdit () запускать скрипт при редактировании Даты.
      Заранее Спасибо!

      Удалить
    4. Здравствуйте.
      Через функцию onEdit() этого не сделать.
      Необходимо авторизовать триггер вручную: меню Изменить-Триггеры текущего проекта. Кнопка +Добавление триггера, выбрать функцию, тип события При изменении.

      Удалить
  7. Здравствуйте.В первом столбце список клиентов. Как можно создать во втором столбце кнопки, при нажатии на которую открывается папка, расположенная на компьютере с именем клиента? Заранее спасибо

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

      Удалить
  8. Спасибо огромное за скрипт, очень пригодился! Подскажите, где добавить -1, чтоб напоминание было за день до события?)

    ОтветитьУдалить
    Ответы
    1. event.addEmailReminder(0);
      event.addPopupReminder(0)

      0 - количество минут до события. Если поставить 60 - то уведомления за час. 60*24 - уведомление за сутки

      Удалить
  9. Привет.
    Уже обращался к Вам по данной теме.
    Сейчас, у меня возникла новая проблема.
    Есть у меня такой скрипт:
    function addEvents() {
    var ss = SpreadsheetApp.openById("1LeJQXi0SEzIxXOVmOEG3dlckIBv56ZclLnDwkncqoCc").getSheetByName('Oswiadczenia');
    var lr = ss.getLastRow();
    var cal = CalendarApp.getCalendarById("est-pologne.eu_j28dmjh32cdbqpagj3npg6kadk@group.calendar.google.com");
    var currentCalendar = CalendarApp.getCalendarById("est-pologne.eu_j28dmjh32cdbqpagj3npg6kadk@group.calendar.google.com");
    var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
    for (var j = 0;j<events.length; j++)
    {
    events[j].deleteEvent();


    }

    var data = ss.getRange("A2:C” + lr).getValues();
    for(var i = 0;i<data.length;i++){
    cal.createAllDayEvent(data[i][0], data[i][1], {description: 'data[i][2]'});
    }
    }
    И последная строка просто не работает, хотя раньше работала. Потом начал ковыряться в ней и перестала работать строка var data=.....
    Думаю что проблема в том, что ОНО не правильно читает данные и понимает о чем идет речь.
    Есть ли другой способ показать програме о каких данных идет речь ?
    Спасибо

    ОтветитьУдалить
  10. К коментарию више. Cannot find method createAllDayEvent(string,string,object). (line 16, file "Code") - вот такую ошибку выдает

    ОтветитьУдалить
    Ответы
    1. Попробуйте в строчке
      cal.createAllDayEvent(data[i][0], data[i][1], {description: 'data[i][2]'});

      data[i][1] заменить на
      new Date(data[i][1])

      Удалить
  11. Добрый день.

    Спасибо за скрипт, очень полезный, но нужно немного заточить. Подскажите пожалуйста:

    1) если я хочу работать с конкретным листом Input я должен во второй строке написать:
    var sheet = SpreadsheetApp.getSheetByName('Input');
    Правильно?
    Но выдает ошибку: TypeError: невозможно найти функцию getSheetByName в обьекте SpreadsheetApp. (строка 2, файл "Код")
    Что я делаю не так?

    2) Нужно убрать ежегодное повторение события. Делаю по Вашему рецепту и пропадает событие за этот день и через день. Что может быть?

    3) Я хочу исключить вывод номера телефон в напоминании. Если я удаляю +Phone,Data,CalendarApp.newRecurrence().addYearlyRule()); - выжает ошибку.

    Спасибо!

    ОтветитьУдалить
    Ответы
    1. 1. SpreadsheetApp.getActiveSpreadsheet.getSheetByName('Input')
      2.createAllDayEvent создает событие без повторения, посмотрите комментарий выше.
      3. Смотрите п.2

      Удалить
    2. Роман, спасибо за ответ. Но все равно не очень получается.

      1. Появляется такая ошибка: TypeError: Не удается обнаружить функцию getSheetByName в объекте function getActiveSpreadsheet() {/* */}.

      2. Я пробовал createAllDayEvent но тупо пропадает часть событий. То есть, при createAllDayEventSeries - все ОК а при createAllDayEvent остается лишь 30% всех событий. Никакой логики не вижу. Вся моя строчка выглядит так: var event = currentCalendar.createAllDayEvent("Сегодня "+Name+" празднует День Рождения "+Phone,Data);

      3. Куда смотреть? Нужно просто убрать телефон. Конструкция var event = currentCalendar.createAllDayEvent("Сегодня "+Name+" празднует День Рождения); порождает ошибку <>. Что не так?

      4. Если я даю доступ со своего календаря на другой аккаунт - напоминание event.addPopupReminder(0) со скрипта работает на другом аккаунте? Или там нужно задавать отдельное напоминание?

      Благодарю

      Удалить
    3. Можете подготовить пример с данными и открыть доступ к примеру? Помогу разобраться.:)

      Удалить
    4. Конечно! Все подготовил и отправил на е-мейл.
      Спасибо))

      Удалить
  12. Еще один вопрос: может ли скрипт работать с календарями другого аккаунта? Если да, то как его туда направить?
    Спасибо

    ОтветитьУдалить
    Ответы
    1. Достаточно с другого аккаунта открыть соответствующий доступ к нужному календарю Вашей учетке.

      Удалить
  13. Доброго дня!

    Задача следующая: нужно переносить из таблицы с графиком платежей список платежей на дату в событие календаря. Таблица формата "Дата", "Статья", "Сумма". Записей немного. Желательно видеть платежи за одну дату в одном событии.

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

    function Payments() {
    var sheet = SpreadsheetApp.getActiveSheet();
    var data = sheet.getDataRange().getValues();
    var calname = CalendarApp.getCalendarsByName("График платежей");
    if (calname.length > 0)
    {
    currentCalendar = CalendarApp.getCalendarsByName("График платежей")[0];
    }
    else
    {
    var calendar = CalendarApp.createCalendar("График платежей");
    var currentCalendar = calendar;
    }
    var events = currentCalendar.getEvents(new Date(2018,01,01),new Date(2050,01,01));
    for (var j = 0 ; j < events.length; j++)
    {
    events[j].deleteEvent();
    }
    for (var i = 1; i < data.length; i++)
    {
    var Date = new Date(data[i][0]);
    var now = new Date().getMonth();
    var month = now+3;
    if ((Data.getMonth()<=month)&&(Data.getMonth()>=month-1)){
    var item = data[i][1];
    var Sum = data [i][2];
    var event = currentCalendar.createAllDayEventSeries("Платежи в этом периоде:"+item,Sum,CalendarApp.newRecurrence().addYearlyRule());
    event.addEmailReminder(0);
    event.addPopupReminder(0)
    }
    }
    }

    ОтветитьУдалить
    Ответы
    1. var event = .....

      замените на строчку

      var event=currentCalendar.createAllDayEvent('Платежи в этом периоде: '+item+'. На сумму: '+Sum,Date)

      Удалить
    2. Прошу прощения, в конце не Date, а Data.

      Удалить
    3. Роман, а может быть такое, что у меня что-то не так с каким-либо настройками? этот вариант у меня тоже не работает и я сам уже как только не пытался исправить. извините за настойчивость.

      Удалить
    4. Дайте доступ на igro83@gmail.com к таблице. Как смогу посмотрю, помогу.:)

      Удалить
    5. Работает! Спасибо огромное!!

      Удалить
  14. Роман, добрый день! Помогите пожалуйста, разобраться. В моей таблице несколько листов, на них аналогичные таблицы с клиентами для разных студий, для каждой студии создается свой календарь с событиями. У меня получается реализовать только обновление всех календарей сразу и иногда календарь падает от перегруза. Может ли скрипт понимать, в каком из листов были изменения и обновлять информацию только для этого календаря?
    И еще не совсем понимаю, чем отличается триггер на изменение и на редактирование. Если ставлю их, в календаре начинается дикий ад, поэтому пока обновление каждые 2 часа. Каждый час тоже падает. Сократила удаление событий на 1 год, думаю вообще сделать этот интервал динамическим. И перебор строк ограничить, пока их немного, но количество будет расти.

    ОтветитьУдалить
    Ответы
    1. Здесь логика работы скрипта должна быть другой. Ставится триггер на редактирование на дату и название события ( имя клиента). И обновление событий производить по одному, сделав дополнительный столбец для id события.
      Не так давно появилась возможность установки триггера на изменение события в календаре. Основываясь на этом можно сделать двустороннюю синхронизацию таблица-}календарь, календарь-}таблица.

      Удалить
  15. Роман, здравствуйте! Очень классный блог :)
    Подскажите, пожалуйста! Имеется 2 таблицы и,соответственно, два календаря для них. При нажатии на ссылку в событии (условно) 1го календаря, нужно предоставить выпадающий список, с возможностью выбрать нужное значение из 1й таблицы.
    И все эти данные (из строки первой таблицы) переместить на другой лист 2й таблицы --> и информация отображается во втором календаре.
    Премного благодарна!

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Пример таблицы в вашем случае жизненно необходим. :)
      Честно не понял, что, где и как.
      igro83@gmail.com

      Удалить
  16. Рома, здравствуйте!
    На вашей странице нашла обсуждение своей ошибки при реализации подобной задачи, а именно "Время начала мероприятия не должно быть позже времени окончания." Ваши рекомендации по поводу заглавных букв учла, но проблему не решило, можете подсказать, что еще может быть, я так понимаю, подобное обращение ранее было решено.

    ОтветитьУдалить
    Ответы
    1. https://ignatov-script.blogspot.com/2017/04/google.html?showComment=1510173171614#c7043649417068069662 это?

      Удалить
  17. Роман, подскажите пожалуйста. Как сделать в гугл таблицах зауковое напоминание, например: менеджеру нужно перезвонить клиенту через неделю, возможно чтобы окно всплывало со звуком ?

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Необходимо добавление возможности вызова html страницы при таком напоминании. А в html можно запихнуть всё что нужно и не нужно :)

      Найти можно по ключевым словам -

      SpreadsheetApp.getUi().showModalDialog(),

      ну и тег для html - audio autoplay

      Удалить
  18. Добрый день, Роман! Ваш скрипт очень помог! Но сейчас потребовались доработки, которые я не знаю как внести. Немного опишу мою ситуацию: каждую неделю я составляю недельный план для сотрудников в таком виде: Исполнитель, Дата, Описание задачи, как доработать скрипт так, чтобы задача каждому исполнителю адресно ставилась в его календарь?
    Ваше скрипт, которыя я немного изменил под себя ниже. Буду благодарен! Заранее спасибо!

    function saveBirthdays() {
    var sheet = SpreadsheetApp.getActiveSheet();
    var data = sheet.getDataRange().getValues();
    var calname = CalendarApp.getCalendarsByName('Задачи');
    if (calname.length > 0)
    {
    currentCalendar = calname[0];
    }
    else
    {
    var calendar = CalendarApp.createCalendar('Задачи');
    var currentCalendar = calendar;
    }
    var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
    for (var j = 0 ; j < events.length; j++)
    {
    events[j].deleteEvent();
    }
    for (var i = 1; i < data.length; i++)
    {
    var Data = new Date(data[i][1]);
    var now = new Date().getMonth();
    var month = now+1;
    if ((Data.getMonth()<=month)&&(Data.getMonth()>=month-1)){
    var Name = data[i][0];
    var Phone = data [i][2];
    var event = currentCalendar.createAllDayEventSeries("Задача "+Phone,Data,CalendarApp.newRecurrence().addYearlyRule());
    event.addEmailReminder(0);
    event.addPopupReminder(0)
    }
    }
    }

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Создайте у себя календари для сотрудников, и откройте к ним доступ сотрудникам(каждому свой).
      События перебрасывайте в зависимости от сотрудника в соответствующий календарь.

      Удалить
  19. Т.е. перебрасывать руками? Чтоб скрипта автоматом переносил события в нужный календарь нельзя сделать?

    ОтветитьУдалить
    Ответы
    1. Руками долго и неинтересно
      var calname = CalendarApp.getCalendarsByName('Задачи'); - здесь задаётся календарь куда перебрасывать, если в цикле менять название то и события будут перебрасываться в нужный календарь автоматом.

      Удалить
  20. Вроде понял! )) Буду пробовать! Огромное спасибо!

    ОтветитьУдалить
  21. Роман, добрый день!
    У меня есть несколько вопросов:
    1. Можно сделать так что бы каждый раз когда я запускал скрипт не создавался новый календарь;
    2. что бы формулировка текста подтягивалась из таблицы, а не прописанная в скрипте.

    ОтветитьУдалить
    Ответы
    1. Добрый.
      1. Каждый раз календарь не создаётся. Если календарь с названием существует, то используется он. Новый создаётся только в случае когда календаря с таким названием нет.
      2. Также как даты берутся из таблицы, можно организовать подстановку текста из таблицы.

      Удалить
    2. Я в этом деле новичок, и немного сложновато.
      У меня следующий скрипт, за основу взял ваш. Но мне интересно создать что то вроде производственного календаря, где дата начала и дата окончания будет взято из таблицы. Можете помочь где я сделал ошибку:
      function saveBirthdays() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet();
      var data = sheet.getDataRange().getValues();
      var calname = CalendarApp;
      if (calname.length > 0)
      {
      currentCalendar = calname[0];
      }
      else
      {
      var calendar = CalendarApp;
      var currentCalendar = calendar;
      }
      var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
      for (var j = 0 ; j < events.length; j++)
      {
      events[j].deleteEvent();
      }
      for (var i = 1; i < data.length; i++)
      {
      var Data = new Date(data[i][1]);
      var now = new Date().getMonth();
      var month = now+1;
      if ((Data.getMonth()<=month)&&(Data.getMonth()>=month-1)){
      var Name = data[i][0];
      var Phone = data [i][2];
      var event = currentCalendar.createEvent ("Сегодня необходимо: "+Name+". \n"+", номер телефона:"+Phone,Data,new Date(Data.getTime()+1*60*60*1000),new Date(Data.getTime()+1*60*60*1000));
      event.addEmailReminder(0);
      event.addPopupReminder(30)
      }
      }
      }

      Удалить
    3. Здесь проще увидеть Вашу таблицу. igro83@gmail.com

      Удалить
  22. Взял за основу ваш скрипт. Все работает, даже дописал немного, добавил возможность определения локации то есть переноса адреса места события в гугл календарь, а также перенос описания по событию.
    вот скрипт (может кому то будет полезно):
    function saveBirthdays() {
    var sheet = SpreadsheetApp.getActiveSheet();
    var data = sheet.getDataRange().getValues();
    var calname = CalendarApp.getCalendarsByName("Тест");
    if (calname.length > 0)
    {
    var currentCalendar = calname[0];
    }
    else
    {
    var calendar = CalendarAppCalendarApp.createCalendar("Тест");
    var currentCalendar = calendar;
    }
    var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
    for (var j = 0 ; j < events.length; j++)
    {
    events[j].deleteEvent();
    }
    for (var i = 1; i < data.length; i++)
    {
    var Data = new Date(data[i][1]);
    var now = new Date().getMonth();
    var month = now+1;
    if ((Data.getMonth()<=month)&&(Data.getMonth()>=month-1)){
    var Name = data[i][0];
    var Phone = data [i][2];
    var loc = data[i][3];
    var desc = data[i][4];
    var event = currentCalendar.createEvent ("Сегодня необходимо: "+Name+". \n"+", номер телефона:"+Phone,Data,new Date(Data.getTime()+1*60*60*1000),{location:loc,description:desc});
    event.addEmailReminder(0);
    event.addPopupReminder(30)
    }
    }
    }

    Но я все равно не могу задать getSheetByName, не работает выдает ошибку...(((

    ОтветитьУдалить
    Ответы
    1. Все решил:
      var sheet = SpreadsheetApp.getActive().getSheetByName('test')
      Можете помочь с подтягиванием в событие другого человека (второго или сразу нескольких) по электронной почте, которая указывается в гугл таблице

      Удалить
    2. Куда и как подтягивать человека? Вы про доступ к мероприятию другой учетке?

      Удалить
  23. Да.
    Например, я руководитель у меня есть заказ на котором нужно сделать определенные работы, и я определяю кто поедет по этому адресу из сотрудников. Мне нужно сделать, что бы в Гугл таблице помимо клиента, номера телефона, адреса и описания, вставала почта сотрудника (вопрос не в подтягивании посты в самой Гугл таблице) и потом в календаре сформировалось событие, которое смогу видеть я как автор всего кдендаря и выбранный сотрудник (другие заказы он не увидит).
    (Пробовал в Гугл календаре добавить участника, но потом когда появляется какие то изменив в любом из моих заказов и я запуская скрипт - все участники стираются)

    ОтветитьУдалить
    Ответы
    1. Создаёте у себя календари для сотрудников, предоставляете доступ каждому сотруднику (каждому свой). В зависимости от электронного адреса кидаете мероприятия в свой календарь и в календарь сотрудника.

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

      Удалить
    2. Марсель, давайте перейдём в личное общение по электронной почте. Адрес Вы знаете.

      Удалить
  24. Добрый день Роман!
    Нужна Ваша помощь, не могу связать таблицу с календарём

    ОтветитьУдалить
    Ответы
    1. Здравствуйте. Не раз писал уже адрес электронной почты. igro83@gmail.com.
      В версии блога для компьютера, справа есть форма для обращения.

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

    ОтветитьУдалить
    Ответы
    1. Добрый.
      Впервые с таким сталкиваюсь. Таблицу покажете? igro83@gmail.com

      Удалить
    2. Здравствуйте, Роман! У меня такая же проблема, что при заполнении календаря события проставляются на день раньше. Подскажите, как Вы решили эту проблему?
      Спасибо!

      Удалить
    3. Подскажите, как Вы решили проблему с тем, что события проставляются на один день раньше?

      Удалить
    4. Никак не решили. Нет смельчаков чтобы показать свой код. Если не решили всё ещё пишите на мой майл - igro83@gmail.com

      Удалить
    5. отправила на имейл

      Удалить
    6. Аналогичная проблема.
      Код ваш полностью.
      Часовой пояс выставлен GMT-5. Как его исправить - понятия не имею.

      Удалить
    7. На всякий случай, размещу решение для будущих поколений :)
      1. В настройках включить отображение appsscript.json в редакторе https://prnt.sc/zthndk
      2. В редакторе в файле appsscript.json изменить часовой пояс на необходимый https://prnt.sc/zthr66

      Удалить
    8. СПАСИБО!! 3 часа мучились, пока вас не нашли :)

      Удалить
  26. Здравствуйте. я хочу внедрить это скрипт под список дел. я помощник юриста, и мне нужно привязывать дела из таблиц к календарю, чтобы планировать и отмечать судебные заседания и прочие дела. это возможно?

    ОтветитьУдалить
    Ответы
    1. Конечно возможно. Главное правильно описать что Вам необходимо, а мне переделать скрипт. Мой е-майл - igro83@gmail.com

      Удалить
    2. Роман, добрый день
      у меня случилась аналогичная проблема, подробнее выслал на почту, заранее спасибо

      Удалить
    3. Доброго времени суток.
      Воспользуйтесь Logger для обнаружения ошибки, которая возникает.
      Либо попробуйте запустить в режиме дебага.

      Удалить
  27. Здравствуйте а можно сделать так чтоб в определенное время мне приходило оповещение например дата оплаты 12.12.2020 и мне в этот день приходит оповещение на почту. Что сегодня оплата чего либо

    ОтветитьУдалить
    Ответы
    1. Доброго.
      Конечно можно: поработать с текстом, пройтись по комментариям к статье, переделать скрипт.

      Удалить
  28. Добрый днеь ! Нужно сделать синронизацию гугл таблицы и гугл календарь, чтобы при заполнении таблицы , попадало в гугл календарь когда звонить. КАк это сделать , и куда коды вставлять ?

    ОтветитьУдалить
    Ответы
    1. Доброго времени суток.
      В статье, по-моему, описано что да как сделать.

      Удалить
  29. Роман, большое спасибо! Всё получилось! Это просто супер!)

    ОтветитьУдалить
  30. Здравствуйте, Роман

    Подскажите, здесь уже писалось ранее о синхронизации с календарем не только первый лист, но и другие. Я так понял, что нужно вначале кода прописать:
    var sheet = SpreadsheetApp.getActiveSpreadsheet.getSheetByName('Лист 1');
    var sheet = SpreadsheetApp.getActiveSpreadsheet.getSheetByName('Лист 2');
    var sheet = SpreadsheetApp.getActiveSpreadsheet.getSheetByName('Лист 3');
    Но выдаёт ошибку:
    TypeError: SpreadsheetApp.getActiveSpreadsheet.getSheetByName is not a function (строка 3, файл Код)
    Подскажите пжл-та, что не так?
    Если в календарь отправлять только первый лист, то все работает хорошо

    ОтветитьУдалить
    Ответы
    1. Доброго.
      Если вы 3 раза одной и той же переменной присвоите разные значения будет воспринято только последнее присвоение и скрипт будет работать только для последнего листа.
      Скорее вам нужно рассматривать листы в массиве и обрабатывать в цикле.
      Ошибка, которую описали возможно связана с неправильным вводом названий функций.

      Удалить
  31. Здравствуйте, реализовал ваш скрипт, но у меня почему-то не добавились события в календарь. Подскажите, пожалуйста в чем проблема. Доступ предоставил.

    ОтветитьУдалить
    Ответы
    1. Доброго дня.
      Скорее всего, у вас несколько календарей с одинаковыми названиями. Проверьте и оставьте только один.

      Удалить
    2. И ещё. Невнимательно прочитали что делает скрипт
      4. Создаются предстоящие события - дни рождения клиентов в текущем месяце и следующем (т.к. существует ограничение Google на создание слишком большого количества событий за короткий промежуток времени, а клиентов может быть много);
      Даты у вас из прошлого месяца.

      Удалить
  32. Здравствуйте Роман. Ваш пример очень мне помог. Использую 520 строк в таблице.
    Помогите пожалуйста со следующей ситуацией.
    После запуска скрипта через 5 минут появляется сообщение "превышено максимально допустимое время выполнения".

    ОтветитьУдалить
  33. Здравствуйте. А можно ли сделать перенос дат из Гугл Календаря в таблицы. Вообще конечная цель построение диаграммы Ганта на основе Гугл календаря. Спасибо

    ОтветитьУдалить
    Ответы
    1. Доброго дня.
      Да, перенос дат со всеми данными в таблицу возможен, смотрите документацию google по методам. Например, здесь - https://developers.google.com/apps-script/reference/calendar/calendar-app#geteventsstarttime,-endtime
      В этом скрипте реализовано только удаление событий. Вы можете их не удалять, а обрабатывать определённым образом.

      Удалить
  34. добрый день. подскажите пожалуйста как сделать что быв календарь переносились несколько столбцов с 4 по 10 и в календаре забивалось по датам с начало по окончанию?

    ОтветитьУдалить
    Ответы
    1. Доброго дня.
      Для формирования событий с началом и окончанием нужно воспользоваться документацией к методам CalendarApp - https://developers.google.com/apps-script/reference/calendar/calendar-app#createEvent(String,Date,Date)
      Для формирования полей календаря достаточно просмотреть данный скрипт и увидеть что

      var Name = data[i][0];
      var Phone = data [i][2];

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

      Удалить
  35. Добрый день, Роман. Воспользовалась Вашим скриптом, дни рождения добавились, но даты на 1 день раньше, чем указано в таблице. С чем это может быть связано? Буду рада дельному совету)

    ОтветитьУдалить
    Ответы
    1. Доброго.
      Чуть выше https://ignatov-script.blogspot.com/2017/04/google.html?showComment=1613542875811#c3279067394354364345
      человек решил правкой часовых поясов в скрипте, таблице и календаре.

      Удалить
  36. Вопрос про повторяющееся событие. Если вызывать скрипт и применять данный код относительно задач, то создается дубликат. Как исключить дублирование?

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

      Удалить
    2. Немного непонятно...То есть при запуске скрипта, событие которое уже было заново заносится в календарь, так как присваивается новый ID? Как в таком случае закрепить ID за событием? Создаем столбец...и?))

      Удалить
    3. Вы точно правильно поняли что делает данный скрипт? И посмотрели пункт 3 в части Что делает скрипт?

      Удалить
    4. Возможно понимаю, но не так, "Для исключения повторяющихся событий, удаляются все события из данного календаря в промежутке 01.01.2010 - 01.01.2030 (если нужно просто очистить календарь, придётся подключать дополнительные библиотеки);"
      Однако повторяющиеся события есть при повторном запуске скрипита.
      Почему?)

      Удалить
    5. Не могу знать.) Может у вас два календаря с одинаковыми названиями?

      Удалить
    6. С дублями та же беда. При повторном запуске скрипта появляется точно такое же событие в том же календаре. Видимо очистка календаря не работает. Как это исправить?

      Удалить
    7. Эта часть кода отвечает за удаление
      var events = currentCalendar.getEvents(new Date(2010,01,01),new Date(2030,01,01));
      for (var j = 0 ; j < events.length; j++)
      {
      events[j].deleteEvent();
      }

      удаляются мероприятия в первом попавшемся календаре с названием Дни рождения клиентов

      Вангую наличие двух календарей с одним и тем же названием.

      Удалить
  37. Роман, нет ли у вас мануала по написанию скрипта отправки писем из таблицы?

    ОтветитьУдалить
    Ответы
    1. Лучший мануал - официальная документация google. В моём блоге есть статья про генерацию документов по шаблону - там как раз есть отправка файла pdf на почту.

      Удалить
  38. Роман, добрый день, спасибо вам за код. Подскажите, пожалуйста, если в ваш вариант добавить 4 столбец, в котором будет написан текст с привязанной к нему гиперссылкой, каким образом можно из этого 4 столбца извлечь именно саму ссылку и в событии добавлять ее через {description: } в нотацию к событию? Спасибо!

    ОтветитьУдалить
    Ответы
    1. Доброго.
      В коде data - массив содержащий данные листа, data[i][0] - первый столбец строки, data[i][1] - второй.....
      event.setDescription(здесь нужный элемент массива) задаст описание.

      Удалить
    2. Таким способом вытягивается текст, но не привязанная к нему гиперссылка, а как вытащить именно гиперссылку?

      Удалить
    3. Это уже сложнее, смотрите методы getRichTextValue() для range в документации google.

      Удалить
  39. Здравствуйте. Подскажите пожалуйста как задать уведомление именно в день рождения? К примеру событие (день рождение 1 августа) событие создается, но уведомление устанавливается максимум в этот же день 1 августа в 00:00. Как сделать чтобы уведомление приходило 1 августа в 09:00. event.addPopupReminder() устанавливает уведомление в минутах до

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      В api уведомления устанавливаются только до события, то что делается в web интерфейсе календаря, либо приложения на android - какая то скрытая возможность. Как вариант ставить событие не на весь день, а на определённое время.

      Удалить
    2. Да, НО...
      Давно искал возможность исправить недоработку разработчиков Гугла в плане отображения возраста именинника при наступлении дня рождения. То что из обычного календаря необходимо было создать события ручками и чтобы приходили уведомления я молчу, это буквально 1-15 часа делов. Но отображение возраста... Меня долго терзал этот вопрос. На просторах интернета нашел скрипит, немного изменил его под свои запросы и всё хорошо - и возраст считает, и окончание правильно склоняется год, года, лет, НО... Уведомления ставятся максимум в 00:00 того же дня... Создать обычное событие не сложно, вопрос в том что для дня рождения событие нужно на весь день. Отсюда вывод - криворукость разработчиков. Честно, не понятно чем они мотивируют эти косяки...

      Удалить
  40. Здравствуйте. Скрипт добавляет событие. А как добавлять задачу из таблицы?

    ОтветитьУдалить
    Ответы
    1. Доброго дня. Согласно документации гугл - https://developers.google.com/apps-script/advanced/tasks

      Удалить
    2. А ваш скрипт возможно изменить под task& или его полностью перерабатывать?

      Удалить
    3. Код и методы разные. Конечно перерабатывать.

      Удалить
  41. Спасибо, за скрипт и ответы другим пользователям смогла адаптировать под напоминание оплат

    ОтветитьУдалить