Что такое массив и зачем он нужен в Google Apps Script?
Массив – это упорядоченная коллекция данных, где каждый элемент имеет свой индекс, начинающийся с 0. В Google Apps Script массивы позволяют эффективно хранить и обрабатывать наборы данных, особенно при работе с Google Sheets. Они необходимы для:
Хранения данных, полученных из Google Sheets, для последующей обработки или анализа.
Выполнения операций над набором значений, таких как фильтрация, сортировка, агрегация.
Передачи данных между функциями, скриптами и сервисами Google.
Основы работы с массивами в Apps Script (создание, инициализация)
В Apps Script массив можно создать несколькими способами:
Используя литерал массива: let myArray: any[] = []; — создается пустой массив.
С указанием начальных значений: let myArray: string[] = ["элемент1", "элемент2", "элемент3"]; — массив инициализируется значениями.
Используя конструктор Array: let myArray: number[] = new Array(5); — создается массив с предопределенным размером (5 элементов, изначально undefined).
/**
* Создает и инициализирует массив строк.
* @return {string[]} - Созданный массив.
*/
function createStringArray(): string[] {
let stringArray: string[] = ["apple", "banana", "cherry"];
return stringArray;
}
/**
* Создает пустой числовой массив.
* @return {number[]} - Пустой числовой массив.
*/
function createEmptyNumberArray(): number[] {
let numberArray: number[] = [];
return numberArray;
}Чтение и запись данных в массивы, доступ к элементам
Для доступа к элементам массива используется индекс элемента в квадратных скобках. Индексация начинается с 0.
let myArray: string[] = ["a", "b", "c"];
let firstElement: string = myArray[0]; // firstElement = "a"
myArray[1] = "new value"; // Изменяем значение второго элемента
console.log(firstElement);
console.log(myArray[1]);Взаимодействие массивов с Google Sheets: чтение данных из таблицы в массив
Apps Script позволяет легко читать данные из Google Sheets и записывать их в массивы. Это делается с помощью сервиса SpreadsheetApp. Вот пример:
/**
* Считывает данные из Google Sheets в массив.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} range - Диапазон ячеек для чтения (например, "A1:B10").
* @return {any[][]} - Двумерный массив, содержащий данные из таблицы.
*/
function readDataFromSheet(sheetName: string, range: string): any[][] {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName(sheetName);
if (!sheet) {
Logger.log("Лист с именем " + sheetName + " не найден.");
return [];
}
const dataRange = sheet.getRange(range);
const data: any[][] = dataRange.getValues();
return data;
}
// Пример использования:
let sheetData: any[][] = readDataFromSheet("Sheet1", "A1:C5");
console.log(sheetData);Основные операции с массивами в Google Sheets через Apps Script
Итерация по массиву: циклы `for` и `forEach`
Для перебора элементов массива используются циклы for и forEach. forEach удобен для простого перебора, for – когда нужен доступ к индексу.
let myArray: string[] = ["x", "y", "z"];
// Цикл for
for (let i: number = 0; i < myArray.length; i++) {
console.log("Элемент " + i + ": " + myArray[i]);
}
// forEach
myArray.forEach(function(element: string, index: number) {
console.log("Элемент " + index + ": " + element);
});Добавление и удаление элементов: `push`, `pop`, `shift`, `unshift`, `splice`
push(element): Добавляет элемент в конец массива.
pop(): Удаляет последний элемент массива и возвращает его.
shift(): Удаляет первый элемент массива и возвращает его.
unshift(element): Добавляет элемент в начало массива.
splice(start, deleteCount, ...items): Удаляет deleteCount элементов, начиная с индекса start, и вставляет items на их место.
let myArray: string[] = ["a", "b", "c"];
myArray.push("d"); // ["a", "b", "c", "d"]
myArray.pop(); // ["a", "b", "c"] (возвращает "d")
myArray.shift(); // ["b", "c"] (возвращает "a")
myArray.unshift("x"); // ["x", "b", "c"]
myArray.splice(1, 1, "y", "z"); // ["x", "y", "z", "c"]Преобразование массивов: `map`, `filter`, `reduce` (с примерами для Google Sheets)
map(callback): Создает новый массив, применяя callback к каждому элементу исходного массива.
filter(callback): Создает новый массив, содержащий только те элементы, для которых callback возвращает true.
reduce(callback, initialValue): Применяет функцию callback к аккумулятору и каждому элементу массива (слева направо), сводя его к одному значению.
/**
* Пример использования map для умножения чисел в массиве на 2.
* @param {number[]} numbers - Исходный массив чисел.
* @return {number[]} - Новый массив, где каждое число умножено на 2.
*/
function multiplyByTwo(numbers: number[]): number[] {
return numbers.map(function(number: number): number {
return number * 2;
});
}
/**
* Пример использования filter для фильтрации четных чисел из массива.
* @param {number[]} numbers - Исходный массив чисел.
* @return {number[]} - Новый массив, содержащий только четные числа.
*/
function filterEvenNumbers(numbers: number[]): number[] {
return numbers.filter(function(number: number): boolean {
return number % 2 === 0;
});
}
/**
* Пример использования reduce для суммирования чисел в массиве.
* @param {number[]} numbers - Исходный массив чисел.
* @return {number} - Сумма всех чисел в массиве.
*/
function sumNumbers(numbers: number[]): number {
return numbers.reduce(function(accumulator: number, currentValue: number): number {
return accumulator + currentValue;
}, 0); // 0 - начальное значение аккумулятора
}
//Примеры использования с данными из Google Sheets:
function processSheetData() {
let sheetData: any[][] = readDataFromSheet("Sheet1", "A1:A5"); // Предполагаем, что в столбце A числа
let numbers: number[] = sheetData.map(row => Number(row[0])); // Преобразуем в массив чисел
let multiplied: number[] = multiplyByTwo(numbers);
let even: number[] = filterEvenNumbers(numbers);
let sum: number = sumNumbers(numbers);
console.log("Умноженные на 2: " + multiplied);
console.log("Четные: " + even);
console.log("Сумма: " + sum);
}Поиск в массиве: `indexOf`, `includes`, `find`, `findIndex`
indexOf(element): Возвращает индекс первого вхождения element в массиве, или -1, если элемент не найден.
includes(element): Возвращает true, если массив содержит element, иначе false.
find(callback): Возвращает значение первого элемента в массиве, для которого callback возвращает true, или undefined, если такой элемент не найден.
findIndex(callback): Возвращает индекс первого элемента в массиве, для которого callback возвращает true, или -1, если такой элемент не найден.
let myArray: string[] = ["a", "b", "c", "b"];
let index: number = myArray.indexOf("b"); // index = 1
let includesB: boolean = myArray.includes("b"); // includesB = true
let found: string | undefined = myArray.find(function(element: string): boolean {
return element === "c";
}); // found = "c"
let foundIndex: number = myArray.findIndex(function(element: string): boolean {
return element === "c";
}); // foundIndex = 2Запись данных из массива в Google Sheets
Запись одномерного массива в столбец или строку
Для записи одномерного массива в Google Sheets, его нужно преобразовать в двумерный массив. Столбец получается, если каждый элемент одномерного массива становится строкой двумерного. Строка получается, если одномерный массив становится единственной строкой двумерного.
/**
* Записывает одномерный массив в столбец Google Sheets.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} startCell - Начальная ячейка для записи (например, "A1").
* @param {any[]} dataArray - Одномерный массив данных.
*/
function writeArrayToColumn(sheetName: string, startCell: string, dataArray: any[]) {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName(sheetName);
if (!sheet) {
Logger.log("Лист с именем " + sheetName + " не найден.");
return;
}
// Преобразуем одномерный массив в двумерный (столбец)
let data: any[][] = dataArray.map(function(item: any): any[] {
return [item];
});
const range = sheet.getRange(startCell).offset(0, 0, data.length, 1);
range.setValues(data);
}
/**
* Записывает одномерный массив в строку Google Sheets.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} startCell - Начальная ячейка для записи (например, "A1").
* @param {any[]} dataArray - Одномерный массив данных.
*/
function writeArrayToRow(sheetName: string, startCell: string, dataArray: any[]) {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName(sheetName);
if (!sheet) {
Logger.log("Лист с именем " + sheetName + " не найден.");
return;
}
// Преобразуем одномерный массив в двумерный (строка)
let data: any[][] = [dataArray];
const range = sheet.getRange(startCell).offset(0, 0, 1, dataArray.length);
range.setValues(data);
}
// Пример использования:
//writeArrayToColumn("Sheet1", "A1", [1, 2, 3, 4, 5]);
//writeArrayToRow("Sheet1", "A1", ["a", "b", "c", "d", "e"]);Запись двумерного массива в диапазон ячеек (матрицы)
Двумерный массив напрямую соответствует диапазону ячеек в Google Sheets. Используйте setValues для записи.
/**
* Записывает двумерный массив в диапазон ячеек Google Sheets.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} startCell - Начальная ячейка для записи (например, "A1").
* @param {any[][]} dataArray - Двумерный массив данных.
*/
function writeArrayToRange(sheetName: string, startCell: string, dataArray: any[][]) {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName(sheetName);
if (!sheet) {
Logger.log("Лист с именем " + sheetName + " не найден.");
return;
}
const numRows: number = dataArray.length;
const numCols: number = dataArray[0].length; // Предполагаем, что все строки имеют одинаковую длину
const range = sheet.getRange(startCell).offset(0, 0, numRows, numCols);
range.setValues(dataArray);
}
// Пример использования:
// let data: any[][] = [["A", "B", "C"], [1, 2, 3], ["X", "Y", "Z"]];
// writeArrayToRange("Sheet1", "A1", data);Оптимизация записи: использование `setValues` для повышения производительности
Для повышения производительности при записи больших объемов данных используйте метод setValues вместо многократного вызова setValue для каждой ячейки. setValues выполняет запись данных за один запрос к Google Sheets API, что значительно быстрее.
Обработка ошибок при записи данных в Google Sheets
При записи данных в Google Sheets необходимо учитывать возможные ошибки, такие как отсутствие доступа к таблице, неверный формат данных или превышение лимитов API. Рекомендуется использовать блоки try...catch для обработки исключений и логировать ошибки для отладки.
try {
writeArrayToRange("Sheet1", "A1", data);
} catch (e) {
Logger.log("Ошибка записи данных: " + e);
}Практические примеры использования массивов в Google Sheets Apps Script
Пример 1: Фильтрация данных из Google Sheets по условию (с использованием массивов)
Предположим, есть таблица с данными о продажах, и нужно отфильтровать записи по определенному региону.
/**
* Фильтрует данные о продажах из Google Sheets по региону.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} dataRange - Диапазон ячеек с данными о продажах (например, "A2:C100", где A - регион, B - продукт, C - объем продаж).
* @param {number} regionColumnIndex - Индекс столбца с регионом (начиная с 0).
* @param {string} targetRegion - Регион для фильтрации.
* @return {any[][]} - Двумерный массив с отфильтрованными данными.
*/
function filterSalesByRegion(sheetName: string, dataRange: string, regionColumnIndex: number, targetRegion: string): any[][] {
let data: any[][] = readDataFromSheet(sheetName, dataRange);
let filteredData: any[][] = data.filter(function(row: any[]): boolean {
return row[regionColumnIndex] === targetRegion;
});
return filteredData;
}
// Пример использования:
// let filteredSales: any[][] = filterSalesByRegion("SalesData", "A2:C100", 0, "North");
// writeArrayToRange("FilteredSales", "A1", filteredSales); // Запись отфильтрованных данных на другой листПример 2: Сортировка данных в Google Sheets (с использованием массивов и `sort`)
Сортировка данных в Google Sheets по определенному столбцу.
/**
* Сортирует данные из Google Sheets по указанному столбцу.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} dataRange - Диапазон ячеек с данными (например, "A2:C100").
* @param {number} sortColumnIndex - Индекс столбца для сортировки (начиная с 0).
* @param {boolean} ascending - `true` для сортировки по возрастанию, `false` - по убыванию.
* @return {any[][]} - Двумерный массив с отсортированными данными.
*/
function sortDataByColumn(sheetName: string, dataRange: string, sortColumnIndex: number, ascending: boolean): any[][] {
let data: any[][] = readDataFromSheet(sheetName, dataRange);
data.sort(function(a: any[], b: any[]): number {
if (a[sortColumnIndex] b[sortColumnIndex]) {
return ascending ? 1 : -1;
}
return 0;
});
return data;
}
// Пример использования:
// let sortedData: any[][] = sortDataByColumn("SalesData", "A2:C100", 2, false); // Сортировка по объему продаж по убыванию
// writeArrayToRange("SortedSales", "A1", sortedData);Пример 3: Поиск и замена данных в Google Sheets (с использованием массивов и регулярных выражений)
Поиск и замена текста в Google Sheets с использованием регулярных выражений.
/**
* Ищет и заменяет текст в указанном столбце Google Sheets, используя регулярное выражение.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} dataRange - Диапазон для поиска и замены.
* @param {number} columnIndex - Индекс столбца, в котором производить замену.
* @param {string} searchText - Регулярное выражение для поиска.
* @param {string} replaceText - Текст для замены.
*/
function findAndReplaceInColumn(sheetName: string, dataRange: string, columnIndex: number, searchText: string, replaceText: string) {
let data: any[][] = readDataFromSheet(sheetName, dataRange);
let regex: RegExp = new RegExp(searchText, "g"); // 'g' - глобальный поиск
for (let i: number = 0; i < data.length; i++) {
if (typeof data[i][columnIndex] === 'string') {
data[i][columnIndex] = data[i][columnIndex].replace(regex, replaceText);
}
}
writeArrayToRange(sheetName, dataRange, data);
}
// Пример использования:
// findAndReplaceInColumn("TextData", "A1:A10", 0, "old", "new"); // Замена "old" на "new" в столбце AПример 4: Группировка данных в Google Sheets (с использованием массивов и объектов)
Группировка данных по определенному столбцу и подсчет суммы значений в другом столбце.
/**
* Группирует данные в Google Sheets по указанному столбцу и суммирует значения в другом столбце.
* @param {string} sheetName - Имя листа Google Sheets.
* @param {string} dataRange - Диапазон ячеек с данными (например, "A2:B100", где A - категория, B - значение).
* @param {number} categoryColumnIndex - Индекс столбца с категорией.
* @param {number} valueColumnIndex - Индекс столбца со значением.
* @return {object} - Объект, где ключи - категории, а значения - суммы.
*/
function groupAndSum(sheetName: string, dataRange: string, categoryColumnIndex: number, valueColumnIndex: number): object {
let data: any[][] = readDataFromSheet(sheetName, dataRange);
let groupedData: { [key: string]: number } = {};
for (let i: number = 0; i < data.length; i++) {
let category: string = String(data[i][categoryColumnIndex]); // Ensure category is a string
let value: number = Number(data[i][valueColumnIndex]);
if (!groupedData[category]) {
groupedData[category] = 0;
}
groupedData[category] += value;
}
return groupedData;
}
// Пример использования:
// let groupedSales: object = groupAndSum("SalesData", "A2:B100", 0, 1); // Группировка продаж по категориям и суммирование
// Logger.log(JSON.stringify(groupedSales));Оптимизация и распространенные ошибки при работе с массивами в Apps Script
Управление памятью при работе с большими массивами
При работе с большими массивами в Google Apps Script важно учитывать ограничения по памяти. Старайтесь избегать создания ненужных копий массивов и освобождайте память, когда данные больше не нужны. Рассмотрите возможность использования потоковой обработки данных или разбиения массива на части для обработки.
Типичные ошибки и способы их устранения (например, выход за границы массива)
Выход за границы массива: Обращение к элементу с индексом, который больше или равен длине массива, приводит к ошибке. Всегда проверяйте длину массива перед обращением к элементам.
Неверный тип данных: Apps Script – язык с динамической типизацией, но важно следить за типами данных, хранящихся в массиве. Некорректный тип может привести к ошибкам при выполнении операций.
Изменение массива во время итерации: Изменение массива (добавление или удаление элементов) во время итерации по нему может привести к непредсказуемым результатам. Используйте копию массива для итерации или избегайте изменения исходного массива.
Лучшие практики работы с массивами для повышения производительности скриптов
Используйте setValues для массовой записи данных в Google Sheets.
Избегайте циклов for внутри циклов for (вложенных циклов) при обработке больших массивов. Рассмотрите возможность оптимизации алгоритма или использования других структур данных.
Профилируйте код для выявления узких мест и оптимизируйте их.
Альтернативные подходы к обработке данных: объекты и другие структуры
В некоторых случаях использование объектов (например, Map) или других структур данных может быть более эффективным, чем использование массивов. Например, для поиска данных по ключу объект может быть быстрее, чем массив. Выбор структуры данных зависит от конкретной задачи и требований к производительности.