@Coolinator

Как удалить листы вложенным циклом?

У меня в таблице есть страницы с единой структурой "Название + метка + номер". Мне нужно написать скрипт, который удаляет все страницы с меткой и номером начиная с 2 и до выбранного. Я написал следующий код:

function delete() {
  let NumSheets = getActiveSheet().getNumSheets()
  let getActiveSheet = SpreadsheetApp.getActiveSpreadsheet()
  let sheets = getActiveSheet().getSheets()
  let totalNum = 6

  for (let a = 2; a <= totalNum ;a++) {
      for (let i = 0; i < NumSheets; i++) {
      
      if (getActiveSheet.getSheets()[i].getSheetName().toString().includes(`метка ${a}`)) {
      getActiveSheet.deleteSheet(sheets[i]);
      NumSheets = getActiveSheet.getNumSheets()
      }
    }
   }
  }


Когда находится подходящий лист, он успешно удаляется и цикл идёт дальше.

Проблема в том, что когда номер после метки увеличивается, цикл по новой перебирает страницы и как только доходит до страницы с номером удаленной ранее выдаёт Exception: Нет листа с идентификатором "1794292525".

Что нужно добавить в цикл, чтобы данные о листах обновились и чтобы цикл не ссылался на удаленный лист?
  • Вопрос задан
  • 65 просмотров
Решения вопроса 2
oshliaer
@oshliaer Куратор тега Google Apps Script
Google Products Expert
Пример в Таблице https://docs.google.com/spreadsheets/d/1jyvFyJ8BHX...

Как вариант, более универсальное решение

function run() {
  const book = SpreadsheetApp.getActive();
  const matcher = new RegExp('метка (\\d+$)', 'i');
  const sheetChecker = (sheet) => {
    const [_, num] = sheet.getSheetName().match(matcher) || [];
    if (Number(num) >= 2 || Number(num) <= 6)
      book.deleteSheet(sheet);
  }
  deleteSheets_(book, sheetChecker);
}

/**
 * @param {globalThis.SpreadsheetApp.Spreadsheet} book
 * @param {SheetChecker} sheetChecker
 * @returns {void}
 */
function deleteSheets_(book, sheetChecker) {
  book.getSheets().forEach(sheet => {
    if (sheetChecker(sheet)) {
      book.deleteSheet(sheet);
    }
  });
}

/**
 * Проверяет, подходит ли лист для обработки
 * @callback SheetChecker
 * @param {globalThis.SpreadsheetApp.Sheet} sheet
 * @returns {boolean}
 */


Теперь, переопределяя sheetChecker, можно удалять любые листы, которые будут валидны проверке в этой функции.
Ответ написан
Комментировать
@Coolinator Автор вопроса
Разобрался, нужно получать getNumSheets внутри цикла и всё получается.

function clearSheets() {
  let NumSheets = getActiveSheet().getNumSheets()
  let totalNum = 6
  
  for (let a = 2; a <= totalNum ;a++) {
      for (let i = 0; i < NumSheets; i++) {
     
      if (getActiveSheet().getSheets()[i].getSheetName().toString().includes(`Метка ${a}`)) {
      let sheets = getActiveSheet().getSheets();
      getActiveSheet().deleteSheet(sheets[i]);
      NumSheets = getActiveSheet().getNumSheets()
              
      }
    }
   }
  }
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы