Всем доброе утро. Мне нужна ваша помощь. Мне нужно запустить этот скрипт, чтобы удалить дубликаты в листе формы ответа Google.

Я скопировал этот код в электронную таблицу, потому что он выдал мне эту ошибку непосредственно в форме TypeError: Не удалось вызвать метод getSheetByName со значением null. (строка 16, файл "UPDATEcontact"):

function updateExisting(columnWithUniqueIdentifier,sheetTabName) {
  var dataFromColumnToMatch,lastColumn,lastRow,rowWithExistingUniqueValue,rowOfDataJustSaved,
      sh,ss,valueToSearchFor;

  // USER SETTINGS - if the values where not passed in to the function
  if (!columnWithUniqueIdentifier) {//If you are not passing in the column number
    columnWithUniqueIdentifier = 2;//Hard code column number if you want
  }

  if (!sheetTabName) {//The sheet tab name was not passed in to the function
    sheetTabName = "compleanno2020";//Hard code if needed
  }
  //end of user settings

  ss = SpreadsheetApp.getActiveSpreadsheet();//Get the active spreadsheet - this code must be in a project bound to spreadsheet
  sh = ss.getSheetByName(sheetTabName);


  lastRow = sh.getLastRow();
  lastColumn = sh.getLastColumn();

  //Logger.log('lastRow: ' + lastRow)

  rowOfDataJustSaved = sh.getRange(lastRow, 1, 1, lastColumn).getValues();//Get the values that were just saved

  valueToSearchFor = rowOfDataJustSaved[0][columnWithUniqueIdentifier-1];
  //Logger.log('valueToSearchFor: ' + valueToSearchFor)

  dataFromColumnToMatch = sh.getRange(1, columnWithUniqueIdentifier, lastRow-1, 1).getValues();
  dataFromColumnToMatch = dataFromColumnToMatch.toString().split(",");
  //Logger.log('dataFromColumnToMatch: ' + dataFromColumnToMatch)

  rowWithExistingUniqueValue = dataFromColumnToMatch.indexOf(valueToSearchFor);
  //Logger.log('rowWithExistingUniqueValue: ' + rowWithExistingUniqueValue)

  if (rowWithExistingUniqueValue === -1) {//There is no existing data with the unique identifier
    return;
  }

  sh.getRange(rowWithExistingUniqueValue + 1, 1, 1, rowOfDataJustSaved[0].length).setValues(rowOfDataJustSaved);
  sh.deleteRow(lastRow);//delete the row that was at then end
}

Теперь у меня есть эта проблема.

Если я запускаю макрос щелчком мыши, все работает.

Хотя, если я связываю макрос с триггером, я получаю это сообщение об ошибке: Невозможно преобразовать [объектный объект] в (класс). at updateExisting (NOduplicate: 29)

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

Функция updateExisting:

function updateExisting() {
  var s = SpreadsheetApp.getActiveSheet(),
//      s = ss.getSheetByName(''),
      lastRow = s.getLastRow(),
      lastValues = s.getRange('A'+lastRow+':C'+lastRow).getValues(),
      name = lastValues[0][0],
      allNames = s.getRange('B2:B').getValues(), 
      row, len;

  // TRY AND FIND EXISTING NAME
  for (row = 0, len = allNames.length; row < len - 1; row++)
    if (allNames[row][0] == name) {
      // OVERWRITE OLD DATA
      s.getRange('A2').offset(0, 0, row, 
lastValues.length).setValues([lastValues]);
      // DELETE THE LAST ROW
      s.deleteRow(lastRow);
      break;}
}

Как я могу решить эту проблему? Большое спасибо всем вам.

Обновление существующей функции завершено:

function updateExisting() {
  var s = SpreadsheetApp.getActiveSheet(),
      s = ss.getSheetByName('compleanno2020'),
      lastRow = s.getLastRow(),
      lastValues = s.getRange('A'+lastRow+':E'+lastRow).getValues(),
      name = lastValues[0][0],
      allNames = s.getRange('B2:B').getValues(), 
      row, len;

  // TRY AND FIND EXISTING NAME
  for (row = 0, len = allNames.length; row < len - 1; row++)
    if (allNames[row][0] == name) {
      // OVERWRITE OLD DATA
      s.getRange('A2').offset(0, 0, row, 
lastValues.length).setValues([lastValues]);
      // DELETE THE LAST ROW
      s.deleteRow(lastRow);
      break;}
}


function updateExisting(columnWithUniqueIdentifier,sheetTabName) {
  var dataFromColumnToMatch,lastColumn,lastRow,rowWithExistingUniqueValue,rowOfDataJustSaved,
      sh,ss,valueToSearchFor;

  // USER SETTINGS - if the values where not passed in to the function
  if (!columnWithUniqueIdentifier) {//If you are not passing in the column number
    columnWithUniqueIdentifier = 2;//Hard code column number if you want
  }

  if (!sheetTabName) {//The sheet tab name was not passed in to the function
    sheetTabName = "compleanno2020";//Hard code if needed
  }
  //end of user settings

  ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1vdHMZkDnE8Ua4XWcv45cmNkYPqqcK8THkRhVfMo0a78/edit#gid=1182430309');//Get the active spreadsheet - this code must be in a project bound to spreadsheet
  sh = ss.getSheetByName(sheetTabName);


  lastRow = sh.getLastRow();
  lastColumn = sh.getLastColumn();

  //Logger.log('lastRow: ' + lastRow)

  rowOfDataJustSaved = sh.getRange(lastRow, 1, 1, lastColumn).getValues();//Get the values that were just saved

  valueToSearchFor = rowOfDataJustSaved[0][columnWithUniqueIdentifier-1];
  //Logger.log('valueToSearchFor: ' + valueToSearchFor)

  dataFromColumnToMatch = sh.getRange(1, columnWithUniqueIdentifier, lastRow-1, 1).getValues();
  dataFromColumnToMatch = dataFromColumnToMatch.toString().split(",");
  //Logger.log('dataFromColumnToMatch: ' + dataFromColumnToMatch)

  rowWithExistingUniqueValue = dataFromColumnToMatch.indexOf(valueToSearchFor);
  //Logger.log('rowWithExistingUniqueValue: ' + rowWithExistingUniqueValue)

  if (rowWithExistingUniqueValue === -1) {//There is no existing data with the unique identifier
    return;
  }

  sh.getRange(rowWithExistingUniqueValue + 1, 1, 1, rowOfDataJustSaved[0].length).setValues(rowOfDataJustSaved);
  sh.deleteRow(lastRow);//delete the row that was at then end
}
0
Mauro Mancini 25 Ноя 2019 в 13:36

1 ответ

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

0
carlesgg97 25 Ноя 2019 в 14:25
Большое спасибо за ответ. Я пытался использовать этот код, но он всегда выдает одну и ту же ошибку ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1vdHMZkDnE8Ua4XWcv45cmNkYPqqcK8THkRhVfMo0a78/edit#gid=1182430309');//Get the active spreadsheet - this code must be in a project bound to spreadsheet sh = ss.getSheetByName(sheetTabName); Можете ли вы прислать мне пример кода?
 – 
Mauro Mancini
25 Ноя 2019 в 15:06
Спасибо за ответ. Используя этот код, который вы только что прокомментировали, какую именно ошибку вы получаете и где? Кроме того, из какого контекста вы его запускаете (я полагаю, триггер на основе времени?)?
 – 
carlesgg97
25 Ноя 2019 в 15:19
Прошу прощения но я реально неопытный :D Когда запускаю скрипт вручную у меня работает. Если я запускаю его с помощью TRIGGER, он всегда выдает мне эту ошибку: ОШИБКА: невозможно преобразовать [object Object] в (class). (строка 29, файл "NOduplicate") Я устанавливаю триггер следующим образом: Он запускается во время развертывания: Head Выберите источник события: из электронной таблицы Выберите тип события: при отправке формы
 – 
Mauro Mancini
25 Ноя 2019 в 15:36
Какое значение вы передаете как columnWithUniqueIdentifier? Убедитесь, что это номер. Вы можете сделать это, зарегистрировав его значение, добавив строку, например Logger.log(typeof columnWithUniqueIdentifier). Эта строка должна вывести Number. Что касается сообщения об ошибке, которое вы описываете, кажется, что аргумент, переданный функции, в вашем случае представляет собой объект.
 – 
carlesgg97
25 Ноя 2019 в 16:08
@ carlesgg97 Я загрузил изображение своего рабочего листа вверху сообщения. Значение «columnWithUniqueIdentifier», которое я передаю, представляет собой столбец 2 — адрес электронной почты, который должен быть УНИКАЛЬНЫМ — без дубликатов. Или как я могу это сделать?
 – 
Mauro Mancini
25 Ноя 2019 в 17:40