Как работать с двумерными массивами в Google Apps Script?

Что такое двумерный массив и зачем он нужен?

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

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

Области применения двумерных массивов в Google Sheets и других сервисах

Двумерные массивы широко используются в Google Apps Script, особенно при работе с Google Sheets. Вот некоторые примеры:

  • Чтение данных из Google Sheets: Получение данных из диапазона ячеек в двумерный массив для дальнейшей обработки.
  • Запись данных в Google Sheets: Запись данных из двумерного массива в диапазон ячеек.
  • Форматирование данных: Изменение формата ячеек на основе данных, хранящихся в массиве.
  • Создание отчетов: Агрегация и обработка данных для создания отчетов и дашбордов.
  • Работа с данными из других сервисов: Обработка данных, полученных из внешних API, например, данных Google Analytics или рекламных платформ.

Синтаксис объявления и инициализации двумерного массива

В Google Apps Script двумерный массив объявляется как массив массивов. Вот несколько способов инициализации:

  • Пустой массив:

    /**
     * Объявляет пустой двумерный массив.
     * @returns {Array<Array<any>>}
     */
    function createEmptyArray(): Array<Array<any>> {
      const myArray: Array<Array<any>> = [];
      return myArray;
    }
    
  • С предопределенными значениями:

    /**
     * Объявляет и инициализирует двумерный массив с предопределенными значениями.
     * @returns {Array<Array<string>>}
     */
    function createInitializedArray(): Array<Array<string>> {
      const myArray: Array<Array<string>> = [
        ['Имя', 'Возраст', 'Город'],
        ['Иван', '30', 'Москва'],
        ['Мария', '25', 'Санкт-Петербург']
      ];
      return myArray;
    }
    

Создание и заполнение двумерных массивов

Создание пустого двумерного массива заданного размера

Чтобы создать пустой двумерный массив заданного размера, можно использовать вложенные циклы:

/**
 * Создает пустой двумерный массив заданного размера.
 * @param {number} rows Количество строк.
 * @param {number} cols Количество столбцов.
 * @returns {Array<Array<null>>}
 */
function createEmptyArrayWithSize(rows: number, cols: number): Array<Array<null>> {
  const myArray: Array<Array<null>> = [];
  for (let i = 0; i < rows; i++) {
    myArray[i] = [];
    for (let j = 0; j < cols; j++) {
      myArray[i][j] = null;
    }
  }
  return myArray;
}

Заполнение массива данными вручную

Данные можно добавлять в массив вручную, обращаясь к элементам по индексу:

/**
 * Заполняет двумерный массив данными вручную.
 * @param {Array<Array<any>>} myArray Двумерный массив для заполнения.
 * @returns {Array<Array<any>>}
 */
function fillArrayManually(myArray: Array<Array<any>>): Array<Array<any>> {
  myArray[0][0] = 'Заголовок 1';
  myArray[0][1] = 'Заголовок 2';
  myArray[1][0] = 'Данные 1';
  myArray[1][1] = 'Данные 2';
  return myArray;
}

Заполнение массива данными из Google Sheets (getSheet().getDataRange().getValues())

Наиболее распространенный способ — чтение данных непосредственно из Google Sheets:

/**
 * Заполняет двумерный массив данными из Google Sheets.
 * @param {string} spreadsheetId ID таблицы Google Sheets.
 * @param {string} sheetName Название листа.
 * @returns {Array<Array<any>> | null} Двумерный массив с данными из Google Sheets или null в случае ошибки.
 */
function fillArrayFromSheet(spreadsheetId: string, sheetName: string): Array<Array<any>> | null {
  try {
    const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
    const sheet = spreadsheet.getSheetByName(sheetName);
    if (!sheet) {
      Logger.log(`Лист с именем ${sheetName} не найден.`);
      return null;
    }
    const dataRange = sheet.getDataRange();
    const values: Array<Array<any>> = dataRange.getValues();
    return values;
  } catch (e) {
    Logger.log(`Произошла ошибка: ${e}`);
    return null;
  }
}

Генерация данных для заполнения массива (примеры с формулами и условиями)

Можно генерировать данные для массива, используя формулы и условия. Например, сгенерировать данные о кликах и конверсиях для рекламной кампании:

/**
 * Генерирует данные для двумерного массива на основе формул и условий.
 * @param {number} rows Количество строк (дней).
 * @returns {Array<Array<number>>}
 */
function generateMarketingData(rows: number): Array<Array<number>> {
  const data: Array<Array<number>> = [];
  for (let i = 0; i < rows; i++) {
    const clicks: number = Math.floor(Math.random() * 1000);
    const conversionRate: number = Math.random() * 0.05; // 0-5%
    const conversions: number = Math.floor(clicks * conversionRate);

    data[i] = [clicks, conversions];
  }
  return data;
}

Работа с элементами двумерного массива

Доступ к элементам массива по индексу (строка, столбец)

Доступ к элементам осуществляется по индексу строки и столбца, начиная с 0:

const value: any = myArray[rowIndex][columnIndex];
Реклама

Изменение значений элементов массива

Изменение значений происходит аналогично доступу:

myArray[rowIndex][columnIndex] = newValue;

Перебор элементов массива с использованием циклов (for, for…of)

Для перебора элементов массива используются циклы for или for...of:

// Цикл for
for (let i = 0; i < myArray.length; i++) {
  for (let j = 0; j < myArray[i].length; j++) {
    const element: any = myArray[i][j];
    // Обработка элемента
  }
}

// Цикл for...of
for (const row of myArray) {
  for (const element of row) {
    // Обработка элемента
  }
}

Примеры обработки данных в массиве (суммирование, поиск, фильтрация)

Примеры обработки данных:

  • Суммирование значений столбца:

    /**
     * Суммирует значения в указанном столбце двумерного массива.
     * @param {Array<Array<number>>} myArray Двумерный массив.
     * @param {number} columnIndex Индекс столбца для суммирования.
     * @returns {number}
     */
    function sumColumn(myArray: Array<Array<number>>, columnIndex: number): number {
      let sum: number = 0;
      for (let i = 0; i < myArray.length; i++) {
        sum += myArray[i][columnIndex];
      }
      return sum;
    }
    
  • Поиск элемента:

    /**
     * Ищет элемент в двумерном массиве.
     * @param {Array<Array<any>>} myArray Двумерный массив.
     * @param {any} targetElement Элемент для поиска.
     * @returns {boolean}
     */
    function searchElement(myArray: Array<Array<any>>, targetElement: any): boolean {
      for (let i = 0; i < myArray.length; i++) {
        for (let j = 0; j < myArray[i].length; j++) {
          if (myArray[i][j] === targetElement) {
            return true;
          }
        }
      }
      return false;
    }
    

Примеры практического применения двумерных массивов

Чтение и запись данных в Google Sheets с использованием двумерных массивов

Пример чтения и записи данных (объединение примеров выше):

/**
 * Читает данные из Google Sheets, обрабатывает их и записывает обратно в другой лист.
 */
function processSheetData() {
  const spreadsheetId: string = 'your_spreadsheet_id';
  const sourceSheetName: string = 'SourceSheet';
  const targetSheetName: string = 'TargetSheet';

  const data: Array<Array<any>> | null = fillArrayFromSheet(spreadsheetId, sourceSheetName);

  if (!data) {
    Logger.log('Не удалось прочитать данные из таблицы.');
    return;
  }

  // Пример обработки: умножение всех числовых значений на 2
  const processedData: Array<Array<any>> = data.map(row =>
    row.map(cell => (typeof cell === 'number' ? cell * 2 : cell))
  );

  // Запись обработанных данных в другой лист
  try {
    const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
    let targetSheet = spreadsheet.getSheetByName(targetSheetName);
    if (!targetSheet) {
      targetSheet = spreadsheet.insertSheet(targetSheetName);
    }
    targetSheet.clearContents(); // Очистка листа перед записью

    const range = targetSheet.getRange(1, 1, processedData.length, processedData[0].length);
    range.setValues(processedData);

    Logger.log('Данные успешно обработаны и записаны в таблицу.');
  } catch (e) {
    Logger.log(`Произошла ошибка при записи данных: ${e}`);
  }
}

Форматирование данных в Google Sheets на основе данных из массива

Можно изменять формат ячеек на основе данных в массиве. Например, выделять ячейки с высокими значениями:

/**
 * Форматирует ячейки в Google Sheets на основе данных из массива.
 * @param {string} spreadsheetId ID таблицы Google Sheets.
 * @param {string} sheetName Название листа.
 * @param {Array<Array<number>>} data Двумерный массив с данными.
 */
function formatSheetData(spreadsheetId: string, sheetName: string, data: Array<Array<number>>): void {
  const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  const sheet = spreadsheet.getSheetByName(sheetName);
  if (!sheet) {
    Logger.log(`Лист с именем ${sheetName} не найден.`);
    return;
  }

  for (let i = 0; i < data.length; i++) {
    for (let j = 0; j < data[i].length; j++) {
      if (typeof data[i][j] === 'number' && data[i][j] > 1000) {
        sheet.getRange(i + 1, j + 1).setBackground('yellow');
      }
    }
  }
}

Реализация поиска и фильтрации данных в Google Sheets с помощью массивов

Массивы можно использовать для поиска и фильтрации данных в Google Sheets:

/**
 * Фильтрует данные в Google Sheets на основе заданного критерия.
 * @param {string} spreadsheetId ID таблицы Google Sheets.
 * @param {string} sheetName Название листа.
 * @param {number} columnIndex Индекс столбца для фильтрации.
 * @param {string} filterValue Значение для фильтрации.
 */
function filterSheetData(spreadsheetId: string, sheetName: string, columnIndex: number, filterValue: string): void {
  const data: Array<Array<any>> | null = fillArrayFromSheet(spreadsheetId, sheetName);
  if (!data) {
    Logger.log('Не удалось прочитать данные из таблицы.');
    return;
  }

  const filteredData: Array<Array<any>> = data.filter(row => row[columnIndex] === filterValue);

  // Вывод отфильтрованных данных (например, в лог)
  Logger.log(JSON.stringify(filteredData));
}

Создание динамических отчетов и дашбордов на основе данных из массива

Можно создавать динамические отчеты и дашборды, используя массивы для агрегации и обработки данных, а затем отображать результаты в Google Sheets или Google Docs.

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

Советы по эффективному использованию памяти

  • Избегайте создания очень больших массивов: Если это возможно, обрабатывайте данные частями.
  • Удаляйте ненужные данные: Освобождайте память, удаляя данные, которые больше не нужны.
  • Используйте правильные типы данных: Используйте наиболее подходящий тип данных для каждого элемента массива, чтобы минимизировать использование памяти.

Избежание лишних операций чтения/записи данных в Google Sheets

  • Минимизируйте количество вызовов getValues() и setValues(): Читайте и записывайте данные большими блоками.
  • Кэшируйте данные: Если данные не меняются часто, кэшируйте их в скрипте, чтобы избежать повторных чтений из Google Sheets.

Использование встроенных функций JavaScript для работы с массивами

Используйте встроенные функции JavaScript, такие как map(), filter(), reduce(), forEach() для эффективной обработки массивов. Они часто быстрее и более читабельны, чем ручные циклы.


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