Google Apps Script: Как перебрать диапазон?

Что такое диапазон (Range) в Google Sheets и Google Apps Script?

В Google Sheets и Google Apps Script, диапазон (Range) представляет собой прямоугольную область на листе, состоящую из одной или нескольких ячеек. Это может быть одна ячейка, строка, столбец или блок ячеек. Диапазоны являются фундаментальным понятием, так как именно через них происходит взаимодействие скрипта с данными в таблице.

Зачем нужно перебирать диапазоны?

Перебор (итерация) по диапазону необходим во многих сценариях, включая:

Валидация данных: Проверка соответствия данных в диапазоне определенным критериям.

Преобразование данных: Изменение формата, типа или значений ячеек в диапазоне.

Поиск данных: Нахождение определенных значений или записей в диапазоне.

Агрегация данных: Вычисление сумм, средних значений и других статистических показателей для данных в диапазоне.

Автоматизация задач: Выполнение повторяющихся операций над данными в диапазоне, таких как отправка электронных писем или обновление информации в других системах.

Обзор основных методов для работы с диапазонами

Google Apps Script предоставляет несколько методов для работы с диапазонами, наиболее важные из которых:

getRange(): Получает диапазон ячеек. Может принимать различные параметры, определяющие границы диапазона.

getValue()/getValues(): Получает значение/значения из одной или нескольких ячеек диапазона. getValues() возвращает двумерный массив.

setValue()/setValues(): Устанавливает значение/значения в одной или нескольких ячейках диапазона. setValues() принимает двумерный массив.

getRow()/getColumn(): Возвращает номер строки или столбца первой ячейки диапазона.

getNumRows()/getNumColumns(): Возвращает количество строк или столбцов в диапазоне.

Основные способы перебора ячеек в диапазоне

Использование циклов `for` для перебора строк и столбцов

Классический способ перебора диапазона – использование вложенных циклов for. Этот метод обеспечивает полный контроль над процессом итерации.

/**
 * Перебирает диапазон ячеек с использованием циклов for.
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для перебора.
 */
function iterateRangeWithForLoops(range: GoogleAppsScript.Spreadsheet.Range): void {
  const numRows: number = range.getNumRows();
  const numColumns: number = range.getNumColumns();

  for (let i: number = 1; i <= numRows; i++) {
    for (let j: number = 1; j <= numColumns; j++) {
      const cellValue: any = range.getCell(i, j).getValue();
      console.log(`Ячейка (${i}, ${j}): ${cellValue}`);
      // Дополнительная обработка cellValue...
    }
  }
}

Метод `getValues()` для получения двумерного массива и его обработки

Метод getValues() возвращает двумерный массив, представляющий данные из диапазона. Это позволяет обрабатывать данные в памяти, что часто быстрее, чем обращение к ячейкам по отдельности.

/**
 * Перебирает диапазон ячеек, используя getValues().
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для перебора.
 */
function iterateRangeWithGetValues(range: GoogleAppsScript.Spreadsheet.Range): void {
  const values: any[][] = range.getValues();

  for (let i: number = 0; i < values.length; i++) {
    for (let j: number = 0; j < values[i].length; j++) {
      const cellValue: any = values[i][j];
      console.log(`Ячейка (${i + 1}, ${j + 1}): ${cellValue}`);
      // Дополнительная обработка cellValue...
    }
  }
}

Перебор с помощью `forEach()` (только для массивов, полученных из диапазона)

После получения двумерного массива с помощью getValues(), можно использовать метод forEach() для перебора строк и элементов внутри каждой строки. Этот подход часто выглядит более лаконично.

/**
 * Перебирает диапазон ячеек, используя forEach().
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для перебора.
 */
function iterateRangeWithForEach(range: GoogleAppsScript.Spreadsheet.Range): void {
  const values: any[][] = range.getValues();

  values.forEach((row: any[], rowIndex: number) => {
    row.forEach((cellValue: any, columnIndex: number) => {
      console.log(`Ячейка (${rowIndex + 1}, ${columnIndex + 1}): ${cellValue}`);
      // Дополнительная обработка cellValue...
    });
  });
}

Примеры кода для различных сценариев перебора

Пример 1: Перебор всех ячеек диапазона и изменение их значений

/**
 * Перебирает диапазон и умножает каждое числовое значение на 2.
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для обработки.
 */
function multiplyByTwo(range: GoogleAppsScript.Spreadsheet.Range): void {
  const values: any[][] = range.getValues();
  const newValues: any[][] = values.map((row: any[]) => {
    return row.map((cellValue: any) => {
      if (typeof cellValue === 'number') {
        return cellValue * 2;
      } else {
        return cellValue;
      }
    });
  });
  range.setValues(newValues);
}
Реклама

Пример 2: Перебор только определенных строк или столбцов (с условием)

/**
 * Перебирает диапазон и выделяет жирным шрифтом ячейки в столбце A, если значение в столбце B больше 100.
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для обработки.
 */
function formatBasedOnCondition(range: GoogleAppsScript.Spreadsheet.Range): void {
  const numRows: number = range.getNumRows();

  for (let i: number = 1; i  100) {
      range.getCell(i, 1).setFontWeight('bold');
    }
  }
}

Пример 3: Поиск конкретного значения в диапазоне

/**
 * Ищет конкретное значение в диапазоне и возвращает координаты первой найденной ячейки.
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для поиска.
 * @param {any} searchValue Значение для поиска.
 * @return {{row: number, column: number} | null} Объект с координатами ячейки или null, если значение не найдено.
 */
function findValueInRange(range: GoogleAppsScript.Spreadsheet.Range, searchValue: any): { row: number; column: number } | null {
  const values: any[][] = range.getValues();

  for (let i: number = 0; i < values.length; i++) {
    for (let j: number = 0; j < values[i].length; j++) {
      if (values[i][j] === searchValue) {
        return { row: i + 1, column: j + 1 };
      }
    }
  }

  return null;
}

Пример 4: Обработка диапазона с разными типами данных

/**
 * Перебирает диапазон и выводит тип данных каждой ячейки в консоль.
 *
 * @param {GoogleAppsScript.Spreadsheet.Range} range Диапазон для обработки.
 */
function logDataTypes(range: GoogleAppsScript.Spreadsheet.Range): void {
  const values: any[][] = range.getValues();

  values.forEach((row: any[], rowIndex: number) => {
    row.forEach((cellValue: any, columnIndex: number) => {
      console.log(`Ячейка (${rowIndex + 1}, ${columnIndex + 1}): Тип данных - ${typeof cellValue}, Значение - ${cellValue}`);
    });
  });
}

Оптимизация перебора диапазонов для повышения производительности

Минимизация обращений к Google Sheets (пакетная обработка)

Операции чтения и записи в Google Sheets – ресурсоемкие. Сократите количество обращений, выполняя пакетную обработку данных. Вместо чтения и записи каждой ячейки по отдельности, используйте getValues() и setValues() для работы с целыми диапазонами.

Использование `getValues()` и `setValues()` для массового чтения и записи

Как упоминалось выше, getValues() и setValues() позволяют значительно повысить производительность за счет пакетной обработки. Загрузите данные в массив, обработайте его в памяти и затем запишите обратно в таблицу.

Избегание ненужных итераций и условий

Оптимизируйте логику скрипта, чтобы избежать ненужных итераций и условий. Например, если вам нужно обработать только определенные ячейки, используйте более точные параметры getRange() для получения только нужного диапазона.

Распространенные ошибки и способы их решения

Ошибка: Неправильный индекс строки или столбца

В Google Apps Script, индексы строк и столбцов начинаются с 1, а не с 0, как в массивах JavaScript. При использовании getValues(), возвращается массив, в котором индексы начинаются с 0. Помните об этом при обращении к ячейкам.

Ошибка: Превышение лимитов выполнения скрипта

Google Apps Script имеет ограничения на время выполнения скрипта. Если скрипт обрабатывает большие объемы данных, он может быть прерван. Оптимизируйте код, уменьшите количество обращений к Sheets и рассмотрите возможность использования триггеров, запускающих скрипт по частям.

Ошибка: Некорректная обработка типов данных

Убедитесь, что вы корректно обрабатываете типы данных, полученные из ячеек. Например, если ожидается числовое значение, а в ячейке находится текст, скрипт может выдать ошибку. Используйте typeof или isNaN() для проверки типов данных.


Добавить комментарий