Google Apps Script: Полный курс от новичка до продвинутого — как стать экспертом?

Что такое Google Apps Script и зачем он нужен?

Google Apps Script (GAS) — это облачная платформа для разработки скриптов на базе JavaScript, позволяющая расширять функциональность и автоматизировать задачи в экосистеме Google Workspace. Она предоставляет доступ к API сервисов Google, таких как Таблицы, Документы, Календарь, Диск, Gmail и другие, позволяя создавать кастомные решения без необходимости развертывания сложной инфраструктуры.

Основная цель GAS — автоматизация рутинных операций, интеграция различных сервисов Google между собой и создание пользовательских дополнений. Это мощный инструмент для повышения продуктивности как отдельных пользователей, так и целых команд.

Обзор возможностей и преимуществ использования Google Apps Script

  • Автоматизация: Выполнение повторяющихся задач по расписанию или при наступлении определенных событий (триггеры).
  • Интеграция: Связывание данных и функций между различными приложениями Google Workspace (например, создание отчета в Документах на основе данных из Таблиц).
  • Расширение функциональности: Добавление пользовательских меню, диалоговых окон, боковых панелей и пользовательских функций в Google Таблицы, Документы и Формы.
  • Создание веб-приложений: Разработка простых веб-приложений и API, доступных по уникальному URL.
  • Доступность: Не требует установки ПО, разработка ведется в веб-редакторе.
  • База JavaScript: Использует популярный язык программирования, что упрощает вход для веб-разработчиков.

Настройка окружения и доступ к редактору Google Apps Script

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

  1. Из приложений Google Workspace: В Google Таблицах, Документах, Презентациях или Формах через меню Расширения -> Apps Script.
  2. Напрямую: Через панель управления Google Apps Script по адресу script.google.com.

При первом запуске редактора из конкретного документа создается скрипт, привязанный к этому документу (bound script). Скрипты, созданные через панель управления, являются автономными (standalone) и не привязаны к конкретному файлу.

Первый скрипт: Hello, World! в Google Apps Script

Создадим простой скрипт, который выводит сообщение в журнал выполнения.

/**
 * Выводит приветственное сообщение в логгер.
 */
function helloWorld(): void {
  const message: string = 'Привет, мир Google Apps Script!';
  Logger.log(message);
}

Для выполнения:

  1. Сохраните скрипт (иконка дискеты).
  2. Выберите функцию helloWorld в выпадающем списке рядом с иконкой отладки (жучок).
  3. Нажмите кнопку Выполнить.
  4. Предоставьте необходимые разрешения при первом запуске.
  5. Результат выполнения можно посмотреть в журнале (Ctrl + Enter или через меню Просмотр -> Журналы).

Глава 2: Основы программирования на Google Apps Script

Синтаксис и структура скрипта: переменные, типы данных, операторы

Google Apps Script основан на JavaScript (ES5, с поддержкой некоторых возможностей ES6+). Основные концепции идентичны:

  • Переменные: Объявляются с использованием var, let или const.
  • Типы данных: Поддерживаются стандартные типы JavaScript: string, number, boolean, object, null, undefined. Рекомендуется использовать JSDoc аннотации для статической типизации и улучшения читаемости кода.
  • Операторы: Арифметические (+, -, *, /), сравнения (==, ===, !=, !==, <, >), логические (&&, ||, !) и другие.

Структура скрипта обычно состоит из набора функций. Файл .gs может содержать одну или несколько функций.

Условные операторы и циклы: управление потоком выполнения

Управление ходом выполнения скрипта осуществляется с помощью стандартных конструкций JavaScript:

  • Условные операторы: if...else, switch.
  • Циклы: for, for...in, for...of, while, do...while.
/**
 * Обрабатывает числовые значения в массиве.
 * @param {number[]} data Массив чисел.
 * @param {number} threshold Пороговое значение.
 * @returns {number[]} Массив чисел больше порога.
 */
function filterNumbers(data: number[], threshold: number): number[] {
  const results: number[] = [];
  for (const num of data) {
    if (num > threshold) {
      results.push(num);
    } else {
      Logger.log(`Число ${num} не прошло проверку.`);
    }
  }
  return results;
}

Функции: создание и использование

Функции являются основными строительными блоками скрипта. Они могут принимать аргументы и возвращать значения. Рекомендуется декомпозировать сложные задачи на небольшие, переиспользуемые функции.

/**
 * Рассчитывает стоимость на основе цены и количества.
 * @param {number} price Цена за единицу.
 * @param {number} quantity Количество.
 * @returns {number} Общая стоимость.
 */
function calculateTotal(price: number, quantity: number): number {
  if (price < 0 || quantity < 0) {
    throw new Error('Цена и количество не могут быть отрицательными.');
  }
  return price * quantity;
}

/**
 * Основная функция для демонстрации расчета.
 */
function runCalculation(): void {
  const itemPrice: number = 150.50;
  const itemCount: number = 10;
  try {
    const totalCost: number = calculateTotal(itemPrice, itemCount);
    Logger.log(`Общая стоимость: ${totalCost.toFixed(2)}`);
  } catch (e: any) {
    Logger.log(`Ошибка расчета: ${e.message}`);
  }
}

Работа с массивами и объектами

Массивы и объекты используются для хранения и структурирования данных. GAS предоставляет стандартные методы JavaScript для работы с ними (push, pop, slice, map, filter, reduce, Object.keys, etc.). При работе с сервисами Google (особенно Таблицами) часто приходится иметь дело с двумерными массивами.

Глава 3: Интеграция с сервисами Google Workspace

Работа с Google Sheets: чтение, запись и обработка данных

Сервис SpreadsheetApp предоставляет доступ к Google Таблицам. Основные операции включают открытие таблицы, выбор листа, чтение диапазона данных, запись данных и форматирование ячеек.

/**
 * Читает данные из указанного диапазона Google Таблицы
 * и возвращает строки с суммой больше заданного значения.
 * @param {string} spreadsheetId ID таблицы.
 * @param {string} sheetName Имя листа.
 * @param {string} rangeA1Not Notation диапазона (например, 'A1:C10').
 * @param {number} sumThreshold Порог суммы для фильтрации.
 * @returns {any[][]} Отфильтрованные строки.
 */
function getFilteredSheetData(spreadsheetId: string, sheetName: string, rangeA1Notation: string, sumThreshold: number): any[][] {
  try {
    const ss = SpreadsheetApp.openById(spreadsheetId);
    const sheet = ss.getSheetByName(sheetName);
    if (!sheet) {
      throw new Error(`Лист с именем '${sheetName}' не найден.`);
    }
    const range = sheet.getRange(rangeA1Notation);
    const values: any[][] = range.getValues(); // Получаем данные как двумерный массив

    // Пример: фильтрация строк, где сумма первых двух числовых столбцов больше порога
    const filteredData = values.filter((row: any[]) => {
      const val1 = typeof row[0] === 'number' ? row[0] : 0;
      const val2 = typeof row[1] === 'number' ? row[1] : 0;
      return (val1 + val2) > sumThreshold;
    });

    Logger.log(`Найдено ${filteredData.length} строк, удовлетворяющих условию.`);
    return filteredData;

  } catch (e: any) {
    Logger.log(`Ошибка при работе с таблицей: ${e.message}`);
    return [];
  }
}

/**
 * Записывает данные в новый лист Google Таблицы.
 * @param {string} spreadsheetId ID таблицы.
 * @param {string} newSheetName Имя нового листа.
 * @param {any[][]} data Данные для записи.
 */
function writeDataToNewSheet(spreadsheetId: string, newSheetName: string, data: any[][]): void {
  try {
    const ss = SpreadsheetApp.openById(spreadsheetId);
    let sheet = ss.getSheetByName(newSheetName);
    if (sheet) {
      sheet.clearContents(); // Очищаем, если лист существует
    } else {
      sheet = ss.insertSheet(newSheetName);
    }

    if (data.length > 0 && data[0].length > 0) {
      // Записываем данные в диапазон, начиная с A1
      sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
      Logger.log(`Данные успешно записаны на лист '${newSheetName}'.`);
    } else {
      Logger.log('Нет данных для записи.');
    }
  } catch (e: any) {
    Logger.log(`Ошибка при записи в таблицу: ${e.message}`);
  }
}

Автоматизация работы с Google Docs: создание, редактирование, форматирование

Сервис DocumentApp позволяет программно управлять Google Документами. Можно создавать новые документы, открывать существующие, добавлять и форматировать текст, таблицы, изображения.

/**
 * Создает Google Документ с отчетом на основе данных.
 * @param {string} docName Имя нового документа.
 * @param {string} reportTitle Заголовок отчета.
 * @param {any[][]} reportData Данные для таблицы в отчете.
 */
function createDocumentReport(docName: string, reportTitle: string, reportData: any[][]): void {
  try {
    const doc = DocumentApp.create(docName);
    const body = doc.getBody();

    // Добавляем заголовок
    body.appendParagraph(reportTitle).setHeading(DocumentApp.ParagraphHeading.HEADING1);
    body.appendParagraph(`Отчет сгенерирован: ${new Date().toLocaleString()}`);
    body.appendHorizontalRule();

    // Добавляем данные в виде таблицы
    if (reportData.length > 0) {
      const table = body.appendTable(reportData);
      // Можно применить форматирование к таблице, заголовку и т.д.
      table.getRow(0).editAsText().setBold(true);
    }

    doc.saveAndClose();
    Logger.log(`Документ '${docName}' успешно создан. URL: ${doc.getUrl()}`);

  } catch (e: any) {
    Logger.log(`Ошибка при создании документа: ${e.message}`);
  }
}

Интеграция с Google Calendar: управление событиями и встречами

Сервис CalendarApp предоставляет интерфейс для взаимодействия с Google Календарем. Скрипты могут создавать, искать, изменять и удалять события календаря.

/**
 * Создает событие в Google Календаре.
 * @param {string} calendarId ID календаря ('primary' для основного).
 * @param {string} title Название события.
 * @param {Date} startTime Время начала.
 * @param {Date} endTime Время окончания.
 * @param {string[]} guests Список email гостей (опционально).
 */
function createCalendarEvent(calendarId: string, title: string, startTime: Date, endTime: Date, guests?: string[]): void {
  try {
    const calendar = CalendarApp.getCalendarById(calendarId);
    if (!calendar) {
      throw new Error(`Календарь с ID '${calendarId}' не найден.`);
    }

    const options: GoogleAppsScript.Calendar.EventOptions = {};
    if (guests && guests.length > 0) {
      options.guests = guests.join(',');
      options.sendInvites = true; // Отправить приглашения
    }

    const event = calendar.createEvent(title, startTime, endTime, options);
    Logger.log(`Событие '${title}' создано. ID: ${event.getId()}`);

  } catch (e: any) {
    Logger.log(`Ошибка при создании события: ${e.message}`);
  }
}

Отправка электронных писем через Gmail API

Сервис GmailApp (или более мощный MailApp) позволяет скриптам отправлять электронные письма, читать входящие сообщения, управлять метками и черновиками.

/**
 * Отправляет email с использованием GmailApp.
 * @param {string} recipient Адрес получателя.
 * @param {string} subject Тема письма.
 * @param {string} body Тело письма (может быть HTML).
 * @param {GoogleAppsScript.Mail.MailAdvancedParameters | undefined} options Дополнительные параметры (cc, bcc, htmlBody, attachments и т.д.).
 */
function sendEmail(recipient: string, subject: string, body: string, options?: GoogleAppsScript.Mail.MailAdvancedParameters): void {
  try {
    // MailApp более универсален, GmailApp дает больше контроля над Gmail
    MailApp.sendEmail(recipient, subject, body, options);
    // Альтернатива: GmailApp.sendEmail(recipient, subject, body, options);
    Logger.log(`Письмо успешно отправлено на адрес ${recipient}.`);
  } catch (e: any) {
    Logger.log(`Ошибка при отправке письма: ${e.message}`);
  }
}

/**
 * Пример отправки HTML письма с вложением из Google Drive.
 */
function sendReportEmail(): void {
  const recipient: string = 'example@example.com';
  const subject: string = 'Еженедельный отчет по кампаниям';
  const htmlBody: string = `
    <h1>Отчет по кампаниям</h1>
    <p>Уважаемый(ая) коллега,</p>
    <p>Во вложении находится еженедельный отчет по эффективности рекламных кампаний.</p>
    <p>С уважением,<br>Система автоматической отчетности</p>
  `;
  // Предполагается, что файл с ID 'YOUR_FILE_ID' существует на Google Drive
  try {
    const file = DriveApp.getFileById('YOUR_FILE_ID');
    const options: GoogleAppsScript.Mail.MailAdvancedParameters = {
      htmlBody: htmlBody,
      attachments: [file.getBlob()]
      // cc: 'manager@example.com'
    };
    sendEmail(recipient, subject, '', options); // Тело text/plain не используется, если есть htmlBody
  } catch(e: any) {
     Logger.log(`Не удалось получить вложение или отправить письмо: ${e.message}`);
  }
}

Глава 4: Продвинутые техники и возможности Google Apps Script

Работа с триггерами: автоматическое выполнение скриптов по расписанию или событиям

Триггеры позволяют запускать функции автоматически без участия пользователя. Они бывают:

  • Простые (Simple Triggers): Встроенные функции, такие как onOpen(e), onEdit(e), onInstall(e). Выполняются автоматически при открытии/редактировании документа или установке дополнения. Имеют ограничения по возможностям (не могут вызывать сервисы, требующие авторизации).
  • Устанавливаемые (Installable Triggers): Настраиваются программно (ScriptApp.newTrigger()) или вручную через интерфейс редактора. Могут запускаться:
    • По времени (Time-driven): С заданной периодичностью (каждые N минут/часов, ежедневно, еженедельно и т.д.).
    • По событиям (Event-driven): При изменении таблицы (ON_CHANGE), отправке формы (ON_FORM_SUBMIT), событиях календаря и т.д.
/**
 * Создает триггер, запускающий функцию 'dailyReport' каждый день в 8 утра.
 */
function createTimeDrivenTrigger(): void {
  // Удаляем старые триггеры для этой функции, чтобы избежать дублирования
  const triggers = ScriptApp.getProjectTriggers();
  for (const trigger of triggers) {
    if (trigger.getHandlerFunction() === 'dailyReport') {
      ScriptApp.deleteTrigger(trigger);
    }
  }

  // Создаем новый триггер
  ScriptApp.newTrigger('dailyReport')
    .timeBased()
    .atHour(8)
    .everyDays(1)
    .create();
  Logger.log('Ежедневный триггер для функции dailyReport создан.');
}

/**
 * Пример функции, которая может запускаться по триггеру.
 */
function dailyReport(): void {
  Logger.log('Запуск ежедневного отчета...');
  // Здесь логика генерации и отправки отчета
}

Использование библиотек: переиспользование кода и расширение функциональности

Библиотеки позволяют упаковать набор функций скрипта и использовать его в других проектах Google Apps Script. Это способствует переиспользованию кода и созданию модульных приложений.

Для создания библиотеки:

  1. В скрипте, который будет библиотекой, создайте версию через меню Развертывание -> Управление развертываниями.
  2. Скопируйте Идентификатор скрипта.

Для использования библиотеки:

  1. В скрипте, где она будет использоваться, откройте раздел Библиотеки (+).
  2. Вставьте Идентификатор скрипта библиотеки, нажмите Поиск и Добавить.
  3. Выберите версию и задайте идентификатор (например, MyLibrary).
  4. Функции библиотеки будут доступны через этот идентификатор: MyLibrary.someFunction().

Разработка пользовательских интерфейсов (UI): создание диалоговых окон и боковых панелей

GAS позволяет создавать пользовательские интерфейсы внутри Google Документов, Таблиц, Форм и как самостоятельные веб-приложения с использованием сервиса HtmlService. Этот сервис позволяет создавать UI на основе стандартных HTML, CSS и JavaScript (клиентская часть).

  • Диалоговые окна и боковые панели: Отображаются внутри родительского приложения Google Workspace.
  • Веб-приложения: Автономные приложения, доступные по URL.

Взаимодействие между серверным кодом GAS (.gs файлы) и клиентским JavaScript в HTML осуществляется через google.script.run.

// --- Код в Code.gs --- 

/**
 * Отображает боковую панель в Google Таблицах.
 */
function showSidebar(): void {
  const html = HtmlService.createHtmlOutputFromFile('Sidebar')
      .setTitle('Моя боковая панель');
  SpreadsheetApp.getUi().showSidebar(html);
}

/**
 * Серверная функция, вызываемая из клиентского скрипта.
 * @param {string} sheetName Имя листа для активации.
 * @returns {string} Статус операции.
 */
function activateSheetByName(sheetName: string): string {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
    if (sheet) {
      sheet.activate();
      return `Лист '${sheetName}' активирован.`;
    } else {
      return `Лист '${sheetName}' не найден.`;
    }
  } catch (e: any) {
    return `Ошибка: ${e.message}`;
  }
}

// --- Код в Sidebar.html --- 

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    Введите имя листа: <input type="text" id="sheetNameInput" />
    <button onclick="activateSheet()">Активировать лист</button>
    <div id="status"></div>

    <script>
      function activateSheet() {
        const sheetName = document.getElementById('sheetNameInput').value;
        const statusDiv = document.getElementById('status');
        statusDiv.innerHTML = 'Выполняется...';

        google.script.run
          .withSuccessHandler(updateStatus)
          .withFailureHandler(showError)
          .activateSheetByName(sheetName);
      }

      function updateStatus(message) {
        document.getElementById('status').innerHTML = message;
      }

      function showError(error) {
        document.getElementById('status').innerHTML = 'Ошибка: ' + error.message;
      }
    </script>
  </body>
</html>

Обработка ошибок и отладка скриптов

Надежные скрипты требуют грамотной обработки ошибок и эффективной отладки.

  • Обработка ошибок: Используйте блоки try...catch...finally для перехвата и обработки исключений во время выполнения. Логируйте ошибки с помощью Logger.log или console.log (для V8 runtime).
  • Отладка: Редактор GAS предоставляет встроенный отладчик. Вы можете устанавливать точки останова (breakpoints), выполнять код пошагово (F10, F11), проверять значения переменных.
  • Логирование: Logger.log() выводит сообщения в панель журналов (доступна через Ctrl + Enter или меню Просмотр -> Журналы). console.log() выводит сообщения в Stackdriver Logging (теперь Cloud Logging), что предпочтительнее для сложных и долго работающих скриптов.
  • Execution transcript / Журнал выполнения: Показывает последовательность вызовов API и их статус.

Глава 5: Как стать экспертом Google Apps Script и ресурсы для скачивания

Рекомендации по улучшению навыков программирования на Google Apps Script

  1. Практика: Регулярно решайте реальные задачи автоматизации для себя или коллег.
  2. Изучайте JavaScript: Глубокое понимание JavaScript (включая ES6+ возможности, асинхронность) критически важно.
  3. Читайте документацию: Официальная документация Google Apps Script — основной источник информации по API сервисов.
  4. Анализируйте чужой код: Изучайте примеры скриптов, библиотеки, решения на форумах.
  5. Пишите чистый код: Следуйте принципам SOLID, используйте JSDoc для типизации, пишите комментарии, форматируйте код.
  6. Оптимизируйте вызовы API: Минимизируйте количество обращений к сервисам Google (например, читайте/пишите данные массивами, а не по ячейкам).
  7. Изучайте V8 Runtime: Переход на современный движок V8 открывает доступ к новым возможностям JavaScript и повышает производительность.

Обзор полезных ресурсов: документация, форумы, сообщества

  • Официальная документация Google Apps Script: Содержит справочники по всем сервисам, руководства, примеры кода и информацию о квотах.
  • Stack Overflow: Огромное количество вопросов и ответов по GAS с тегом google-apps-script.
  • Google Workspace Developers Blog: Новости, анонсы, статьи о разработке для Google Workspace.
  • Сообщества разработчиков: Ищите профильные сообщества в социальных сетях или на специализированных платформах.

Хотя запрос упоминает «скачать курс», официальных полных курсов для скачивания в виде единого файла обычно нет. Обучение строится на изучении документации, примеров и практическом опыте.

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

Ищите готовые решения и примеры скриптов на GitHub, в блогах разработчиков и на Stack Overflow. Часто разработчики делятся своими наработками. Анализируя эти примеры, можно почерпнуть идеи и подходы к решению задач.

Примеры областей применения:

  • Автоматизация отчетности: Сбор данных из разных источников (Таблицы, Google Analytics) и формирование отчетов в Документах или Таблицах.
  • Управление лидами (CRM): Обработка данных из Google Форм, создание задач в Календаре, отправка уведомлений.
  • Массовые рассылки: Персонализированная отправка писем на основе данных из Таблиц.
  • Управление проектами: Интеграция Календаря, Диска и Таблиц для отслеживания задач.
  • Кастомные инструменты: Создание боковых панелей в Таблицах для упрощения ввода или анализа данных.

Советы по оптимизации и масштабированию скриптов

  • Минимизация вызовов API: Самое важное правило. Используйте методы, работающие с массивами (getValues, setValues, appendRow и т.д.) вместо поштучных операций в циклах.
  • Кэширование: Используйте CacheService для временного хранения данных, к которым часто обращаетесь, чтобы уменьшить количество вызовов API.
  • Пакетная обработка: Если нужно обработать большой объем данных, разбивайте задачу на части, используя триггеры по времени и сохраняя состояние между запусками (например, в PropertiesService или в ячейке таблицы).
  • Понимание квот: Изучите ограничения Google Apps Script (время выполнения скрипта, количество вызовов API в день, количество триггеров и т.д.) и проектируйте скрипты с их учетом.
  • Использование V8 Runtime: Включайте современный движок для повышения производительности и доступа к актуальным возможностям JavaScript.
  • Асинхронность (ограниченно): Хотя GAS в основном синхронный, для внешних запросов (UrlFetchApp) можно использовать асинхронные подходы, если это применимо.

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