Триггер onSubmit выполняется без отправки формы

Я создал форму Google, связал ее с листом для сбора ответов и добавил скрипт приложений, который запускается каждый раз при отправке формы. Прошел кучу тестов, все работает нормально - ответы на формы передаются, onSubmit функция работает отлично. Однако прошлой ночью мы получили несколько запусков скрипта, несмотря на то, что форма не была отправлена.

Глядя на страницу «Ответы» в самой форме, на момент получения уведомления не было представлений. Кроме того, это не общедоступная форма в моей организации, и только у одного человека есть ссылка, кроме меня. Он подтвердил, что не подавал форму во время казни.

В Google Sheet есть два листа: 1> Form Responses и 2> Data. Лист данных использует несколько функций QUERY для извлечения данных из листа ответов, форматируя их по-разному (например, помещая дефисы в телефонные номера, отображая некоторые поля в верхнем регистре и т. д.). Кроме того, заголовки листов данных помечены иначе, чем вопросы формы (например, «homeAdd1» вместо «Строка домашнего адреса 1»). Это связано с тем, что сценарий создает PDF-файл, используя ответы формы для замены заполнителей ('%homeAdd1%') в шаблоне Google Doc. Затем сценарий берет сгенерированный PDF-файл и отправляет его отправителю по электронной почте.

Опять же, все работало отлично до вчерашнего тестирования. В то время я этого не осознавал, но когда мой коллега вводил случайные значения для проверки формы, для строки домашнего адреса 2 он ввел только 5-значный почтовый индекс. Он сгенерировал PDF-файл в порядке, а также отправил его ему по электронной почте, но это привело к тому, что функция QUERY отобразила ошибку #VALUE. Функции выглядят следующим образом:

=QUERY(Responses!L2:S,"SELECT UPPER(L) UPPER(M)...

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

Может ли ошибка #VALUE в таблице Google, связанной с формой и скриптом приложения, вызвать осечку функции onSubmit? Это единственное, что я вижу, что могло быть причиной этого, но это не имеет смысла. Я исправил проблему с форматированием, но я не знаю, может ли ошибочное выполнение означать какую-то другую проблему.

С дополнительными отправками скрипт снова и снова отправлял самый последний PDF-файл. В течение 20 секунд он срабатывал 5 раз, каждый раз отправляя последний созданный PDF-файл по электронной почте. Глядя на журналы Stackdriver, нет ничего отличного от того, что мы тестировали вчера. Команды console.info и console.info работают нормально, и все они отображаются в списке как запущенные функцией onSubmit.

Вот сценарий:

Отправить функцию:

function onSubmit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
  var list = ss.getRange("A1:A").getValues();
  var row = list.filter(String).length;
  var email = ss.getRange(row,2).getValue();
  var newResponse = ss.getRange(row,3).getValue();
  if (newResponse == 'Generate New') {
    newOne(ss,row,email);
  } else if (newResponse == 'Upload Completed') {
    completed(ss,row,email);
  } else {
  }
}

Функция, которая была выполнена:

function newOne(ss,row,email) {
  var name = ss.getRange(row,4).getValue();
  console.info('Function Start - ' + name);
  var newType = ss.getRange(row,6).getValue();
  var copyFile = DriveApp.getFileById('[file id]').makeCopy();
  var copyDoc = DocumentApp.openById(copyFile.getId());
  var copyBody = copyDoc.getActiveSection();
  // Replacing variables with values on spreadsheet
  console.info('Create file start - ' + name);
  var newInfo = ss.getRange(row, 1, 1, 29).getDisplayValues();
  var header = ss.getRange(1, 1, 1, 29).getDisplayValues();
  for (var i = 1; i <= 5; i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  var x;
  if (newType == 'Office 1') {
    x = 6;
  } else if (newType == 'Office 2') {
    x = 15;
  } else {
  }
  for (var i = x; i <= (x + 8); i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  copyBody.replaceText('%' + header[0][26] + '%', newInfo[0][26].toString());
  // Create the PDF file, rename it, and delete the doc copy
  copyDoc.saveAndClose();
  var newFile = DriveApp.createFile(copyFile.getAs('application/pdf'));
  newFile.setName('New - ' + name + '.pdf');
  copyFile.setTrashed(true);
  console.info('Create file finished - ' + name);
  //Mails PDF to submitter
  console.info('Pre-email log for ' + name);
  MailApp.sendEmail(email,'Email Subject','', {
                    noReply: true,
                    htmlBody: "<body>Hello, and thank you.</body>",
                    attachments: [newFile]
                    });
  console.info('Email sent for ' + name);
  appFile.setTrashed(true);
}

Любое понимание/помощь будут оценены; Спасибо!

Джош

Раньше у меня было многократный запуск одной отправки (решение - блокировка скрипта, которая возвращается после нескольких секунд ожидания), но я никогда не видел полностью пустой при отправке. я не могу представить, что что-либо, хранящееся на странице результатов, может вызвать такое поведение.

J. G. 30.04.2019 23:13

@ Дж. Г. что ж, рад узнать, что ошибка на странице результатов вряд ли приведет к случайным отправкам. И да, не уверен, что это за пустые представления посреди ночи.

Josh 01.05.2019 18:39
Стоит ли изучать 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
2
614
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Насколько я знаю, onSubmit(e) работает не так, как вы ожидаете.

Я думаю, что вы ищете триггер onFormSubmit, попробуйте использовать следующее из Документация класса SpreadsheetTriggerBuilder, чтобы создать триггер скрипта, который выполняется каждый раз, когда кто-то отправляет ответ на вашу связанную форму:

var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("function name")
  .forSpreadsheet(sheet)
  .onFormSubmit()
  .create();

Я использую устанавливаемый триггер, что позволяет мне выбирать, какую функцию запускать при отправке формы (из панели инструментов сценариев приложений). Будет ли создание нового триггера каждый раз иметь преимущество, которого не было бы при использовании устанавливаемого триггера? Я относительно новичок в скриптах приложений (~ 1 год), поэтому раньше не слышал о Trigger Builder. И как этот строитель будет запущен? Не уверен, что следую.

Josh 01.05.2019 18:37

Создание триггера с помощью построителя триггеров, а не так, как вы упомянули, на самом деле не сильно отличается. Как только вы запустите скрипт построителя триггеров, он добавит триггер туда, где вы обычно ищете их.

ross 01.05.2019 21:59
Ответ принят как подходящий

Ложные триггеры нежелательных событий

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

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

Не знаю, почему я не наткнулся на ваш вопрос, когда искал, но спасибо за помощь! Я собираюсь вставить эту логику if (e.values && !e.values[1]){return;} в верхнюю функцию, чтобы перехватывать любые нежелательные отправки (требуются все ответы). Надеюсь, это решит проблему! Обычно это происходит за одну ночь, так что сегодня вечером я снова проверю это.

Josh 01.05.2019 18:31

На самом деле, это должно быть примером, который работал в моей ситуации с моим набором вопросов. По сути, я видел, что требуемые вопросы в ложных триггерах были пустыми в массиве e.values. Поэтому я просто решил использовать этот факт, чтобы исключить эти нежелательные триггеры из запуска моей функции. Итак, вам захочется взглянуть на то, как вы выглядите. Поэтому я бы рекомендовал записывать время и массив e.values ​​и смотреть, как они выглядят.

Cooper 01.05.2019 18:40

Попался; да, я добавил запись console.info, чтобы фиксировать e.values ​​каждый раз, когда выполняется функция top (перед строкой if (e.values...), и при повторном тестировании они приходят в норму. Я буду следить за этими журналами, чтобы увидеть, пусты ли значения, и я предполагаю, что если они пусты, оператор if предотвратит это снова. Если они не пусты, мне нужно посмотреть, что еще может быть причиной нежелательных представлений.

Josh 01.05.2019 18:46

Что ж, похоже, это исправили! На панели инструментов сценариев приложений я вижу дополнительные отправки, но выполнение функции длится доли секунды, так как оно улавливается этой строкой if (e.values && !e.values[1]){return;}. e.values[1] для моей формы это обязательное поле, и это просто текстовое поле. Я заметил, что иногда в этих дополнительных представлениях действительно появляются значения, и обычно это даты или просто числовые значения. У нас не включена опция, позволяющая людям редактировать свои ответы постфактум, поэтому я не уверен, что с этим происходит. В любом случае, сейчас выглядит хорошо! Спасибо!

Josh 03.05.2019 15:57

У меня есть установка электронной таблицы и соответствующей формы, где я часто получаю дубликаты событий отправки формы по необъяснимым причинам. В других установках этого не происходит. Если это ваша ситуация, вы не можете просто проверить, является ли событие нулевым, потому что, чтобы проверить его на нуль, вам нужно что-то проверить. Если он не определен, вы получите сообщение об ошибке. Итак, сначала проверьте, не определено ли оно. Попробуйте этот код:

`function formSubmitted(e) {
  // Deal with the unusual case that this is a bogus event
  if ((typeof e === "undefined") || (e == null) || (e.length == 0))  { 
    Logger.log("formSubmitted() received a bogus or empty event");
    return;
  }
  ...`

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