Триггер onOpen не активируется в форме Google

#google-apps-script #google-forms

#google-apps-script #google-forms

Вопрос:

Событие onOpen в моей форме Google активируется только тогда, когда я открываю форму для редактирования, но не тогда, когда я открываю ее для ответа (/ viewform). На самом деле, я просто хочу, чтобы он запускался, когда кто-то открывает форму для ответа, потому что мой скрипт обновляет поле со списком текущей информацией из таблицы. Я не уверен, что это лучший способ сделать это, но я открыт для предложений.

Я попытался создать функцию onOpen(), а также создать функцию doIt() и вручную добавить триггер в onOpen в меню Ресурсы> Добавить триггер. Триггер указан правильно и, похоже, работает, поскольку открытие формы для редакции обновляет ее должным образом. Возможно, тогда я получил неправильный обработчик триггера, но других для того, что я хочу, нет (только onEdit, который должен делать то, что делает onOpen, и onInstall).

Документы для этого невероятно лаконичны и полностью ориентированы на скрипты электронных таблиц. Однако они упоминают пользовательские перехваты, называемые устанавливаемыми триггерами, и один из них на самом деле:

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

Это говорит о том, что onOpen должен делать именно то, что я хочу… Так что теперь я очень смущен.

Кроме того, я не уверен, как будут работать разрешения. На данный момент, насколько я вижу, кажется, что любой, кому я предоставляю доступ к форме, может редактировать ее, и каждый может ответить на нее, если у человека есть URL. Есть ли способ внести людей в белый список, чтобы ответить на него? Мне не совсем нравится, что URL-адрес является единственным препятствием, мешающим посторонним просматривать данные, которые я загружаю в поле со списком, и, что наиболее важно, обновлять эти данные, отправляя форму… Кажется, что грубая сила может легко разгадать множество «секретных» форм таким образом… Или это нормально, с точки зрения безопасности, и я просто злюсь?

Ответ №1:

Триггер, который вам нужно установить, — это не an onOpen , а an onFormSubmit . is, который отображается в редакторе сценариев / ресурсах / текущем триггере сценария

см. иллюстрацию ниже введите описание изображения здесь

Как вы прочитали (но, по-видимому, не поняли), onOpen триггер срабатывает только тогда, когда кто-то открывает редактор форм, а не когда кто-то заполняет (отправляет) форму.

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

Если этот контроль доступа действительно жизненно важен для вас, вы могли бы добиться чего-то довольно эффективного, используя UiApp или HTML-сервис, но это было бы немного сложнее.

Что касается вашего последнего пункта о разрешениях, все очень просто: устанавливаемые триггеры запускаются от имени пользователя, создавшего триггер. Если вы это сделали, скрипт будет выполняться так, как если бы вы запускали его вручную, используя ваши привилегии и права доступа.

Комментарии:

1. Это тоже не сработает, потому что я хочу, чтобы поле со списком заполнялось элементами, когда пользователь открывает форму для ответа, чтобы он мог выбрать один, а не когда он его отправляет (это было бы слишком поздно)… Тем не менее, я попытался, и это не сработало. Опять же, я не уверен, существует ли этот триггер, но я открыт для других способов создания динамических списков со списком (например, select / options или вопросы с несколькими вариантами ответов)…

2. описанный вами рабочий процесс кажется невозможным… вы имеете в виду, что ваш скрипт создает это поле со списком? если да, hten form — неправильный способ сделать это … создайте его с помощью UiApp или HtmlService

3. Да, он в основном заполняет поле со списком данными из электронной таблицы. По сути, я хочу создать динамический выпадающий список, который загружает элементы из электронной таблицы. Например, список людей или что-то в этом роде. И это всегда должен быть актуальный список.

4. Вау, это ужасно! У меня в голове была целая системная идея, сильно зависящая от этой функции… Что ж, спасибо за ответы!

5. Я пометил его как правильный, поскольку @Sergeinsas указал, что то, что я пытался выполнить, невозможно, и поэтому мой вопрос остался без ответа. Может быть, он мог бы обновить свой ответ, чтобы добавить этот разговор, который у нас был в комментариях, или, может быть, кто-нибудь найдет обходной путь, и тогда я соответствующим образом обновлю принятый ответ 🙂

Ответ №2:

Я думаю, что хитрость в этом заключается в настройке вашего скрипта для запуска при редактировании электронной таблицы, в которой существуют данные, заполняющие форму. Вероятно, вам потребуется проверить onEdit(e) событие, чтобы узнать, действительно ли вам нужно действовать, например, проверять объект события на предмет того, что было отредактировано. Таким образом, как только вы обновляете исходные данные, форма обновляется для вас (по сравнению с тем, когда форма открыта).

Комментарии:

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

Ответ №3:

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

Пример: для источника данных электронной таблицы создайте триггер для изменения данных.

     function OnDataChange()
{
   let form = FormApp.openById("YourformID"); 
/* 
   or if data source are also linked to form, you could do this: 
   ss = SpreadsheetApp.getActiveSpreadsheet(); 
   form = FormApp.openByUrl(ss.getFormUrl());
 */

   let names = ss.getSheetByName("Names").getDataRange().getValues().map(x => x[0]).slice(1);
   FillItem(form,"Name",names)
   
} 
function FillItem(form,itemtitle,values)
{
  form.getItems().filter(el => el.getTitle()==itemtitle)
      .forEach( el => { 
           switch(el.getType()) {
             case FormApp.ItemType.LIST:
                  el.asListItem().setChoiceValues(values);
                  break;
             case FormApp.ItemType.MULTIPLE_CHOICE:
                  el.asMultipleChoiceItem().setChoiceValues(values);
                  break;
           }
      })
}
  

Измените вышеуказанный переключатель в соответствии с вашими потребностями.