Скрипт Google Apps getSheetByName возвращает значение null при использовании переменной в качестве аргумента

#javascript #google-apps-script #google-sheets

#язык JavaScript #google-приложения-скрипт #google-листы

Вопрос:

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

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

Ниже приведен фрагмент кода.

 var myIds = [111, 222, 333, 444]; var myUsers = ['aaa', 'bbb', 'ccc', 'ddd'];  ...  switch (param) {  case 1:  break;  case 2:  for (let i = 0; i lt; myIds.length; i  ) {  if (value == myIds[i]) {  userName = myUsers[i];  break;  }  }  userName = 'ETC';  break; }  if (userName != 'ETC') {  let inSheet = 'In '   userName;  let outSheet= 'Out '   userName;  if (checkIn == true)  sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(inSheet));  else  sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(outSheet)); } else  sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName('ETC'));  

Вместо того, чтобы переходить на соответствующие листы ввода / вывода, все вместо этого переходит на лист ETC. В другое время на простынях вообще не было бы никаких изменений. Было бы весьма признателен, если бы кто-нибудь мог объяснить, почему это происходит, в дополнение к вопросу.

Заранее спасибо.

Ответ №1:

break; Внутренняя часть вашего for цикла только вырывается из for цикла, а не сама case . Таким образом , вы выходите из for и в конечном итоге включаетесь userName = "ETC"; , что перезаписывает любое значение, которое может быть установлено циклом.

Вместо этого вы можете использовать indexOf или findIndex :

 case 2:  const index = myIds.indexOf(value); // Or `.findIndex(id =gt; id == value)` if you need `==` not `===`  userName = index === -1 ? "ETC" : myUsers[index];  break;  

Если вам действительно нужен for цикл, вы можете назначить userName его перед циклом, чтобы цикл перезаписывался "ETC" :

 case 2:  userName = "ETC";  for (let i = 0; i lt; myIds.length; i  ) {  if (value == myIds[i]) {  userName = myUsers[i];  break;  }  }  break;  

Примечание: Я рекомендую избегать параллельных массивов, таких как myIds и myUsers . Очень легко в конечном итоге обновить одно, а не другое. Вместо этого рассмотрим массив объектов:

 const users = [  {id: 111, name: "aaa"},  {id: 222, name: "bbb"},  {id: 333, name: "ccc"},  {id: 444, name: "ddd"}, ];  

Тогда в первом приведенном выше примере будет использоваться find :

 case 2:  const user = users.find(({id}) =gt; id == value);  userName = user ? user.name : "ETC";  break;  

В действительно современной среде с необязательной цепочкой и нулевым объединением вы могли бы перейти userName = user ? user.name : "ETC"; на userName = user?.name ?? "ETC"; , но в условной версии нет ничего плохого.


Примечание 2: Вы использовали let в своем for цикле, поэтому, похоже, используете более современный ГАЗ, поддерживающий функции ES2015 . Я предлагаю не использовать var в новом коде, всегда используйте let или const .

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

1. спасибо за отличный ответ! Я хотел бы подробнее остановиться на исходном вопросе, однако, где теперь , после размещения всего в массиве объектов, когда я пытаюсь использовать getSheetByName("In " users[i].name) , он возвращает ошибку, в которой говорится, что он не может прочитать свойство » имя » неопределенного. У меня есть users массив в качестве глобальной переменной, так что это не должно быть проблемой.

2. @Shironats — Проблема не users в том , что это users[i] … или, более конкретно, это i недопустимый индекс в users массиве. Я не могу сказать вам, почему нет, потому что я понятия не имею, в чем i там ценность. Но этой строки кода не существует ни в вопросе, ни в ответе. Вы все равно будете использовать userName его там, нет users[i].name ; просто userName меняется то, как вы его устанавливаете.

3. Спасибо за разъяснение, я прояснил эту проблему. Однако теперь, когда я использую этот find(({id}) =gt; ... метод, я не получаю никаких новых входных данных, хотя по логике вещей все должно быть указано на листе «ETC». Все еще пытаюсь понять, что пошло не так.

Ответ №2:

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