Google Apps Scripts – Работа с триггером onEdit (реакция на изменения в таблице) и классом LanguageApp (перевод текста в Google Spreadsheets) и работа с HTML Service (вывод модального окна и сайдбара в Google Spreadsheets).

Автоматизация Google Таблиц с Apps Script: Триггеры, Перевод и Интерфейсы

Google Apps Script предоставляет мощные инструменты для автоматизации работы в Google Таблицах.

  • HTML Service для создания модальных окон и сайдбаров.
    Оригинальный код слева и с исправлениями справа(пример из тех, что рассмотели в классе).
  • Триггер onEdit для реакции на изменения в ячейках(срабатывает при любом изменении ячейки).
  • Класс LanguageApp для автоматического перевода текста(С помощью LanguageApp можно переводить текст прямо в ячейках).

1. Триггеры для автоматизации процессов

Реакция на изменения в реальном времени

Триггер onEdit позволяет создавать интеллектуальные таблицы, которые автоматически реагируют на действия пользователя. При любом изменении ячейки можно:

  • Проверять корректность введенных данных
  • Автоматически пересчитывать зависимые показатели
  • Изменять оформление ячеек по заданным правилам
  • Отправлять уведомления о важных изменениях

2. Инструменты перевода контента

Встроенные возможности локализации

Сервис LanguageApp предоставляет мощный функционал для работы с многоязычным контентом:

  • Мгновенный перевод текста между языками
  • Поддержка более 100 языковых пар
  • Интеграция перевода непосредственно в ячейки таблиц
  • Возможность создания мультиязычных шаблонов документов

3. Пользовательские интерфейсы

Расширение возможностей таблиц

С помощью HTML Service можно значительно улучшить взаимодействие пользователей с таблицами, создавая:

  • Всплывающие окна с важной информацией
  • Боковые панели для быстрого доступа к функциям
  • Кастомные формы ввода данных
  • Интерактивные элементы управления

4. Оптимизация работы скриптов

Повышение эффективности

Для стабильной работы автоматизированных решений важно:

  • Учитывать ограничения выполнения скриптов
  • Реализовывать обработку ошибок
  • Оптимизировать время выполнения операций
  • Логировать ключевые события

5. Практические примеры применения

Реальные кейсы автоматизации

Типовые сценарии использования включают:

  • Системы контроля качества данных
  • Многоязычные шаблоны документов
  • Персонализированные панели управления
  • Автоматизированные отчетные системы

6. Рекомендации по разработке

Лучшие практики

Для создания надежных решений следует:

  • Четко структурировать код
  • Использовать понятные наименования
  • Документировать функционал
  • Тестировать в различных сценариях

Оригинальный код слева и с добавленими справа.

// Функция onEdit является триггером, который срабатывает при завершении ввода данных в ячейку Таблицы пользователем
// https://developers.google.com/apps-script/guides/triggers/#onedite
function onEdit(e) {
  Logger.log(e);

  // Получаем диапазон ячеек, в которых произошли изменения
  // https://developers.google.com/apps-script/reference/spreadsheet/range
  var range = e.range;

  // Лист, на котором производились изменения
  // https://developers.google.com/apps-script/reference/spreadsheet/sheet
  var sheet = range.getSheet();

  // Проверяем, нужный ли это нам лист
  Logger.log(sheet.getName());
  if (sheet.getName() != 'Перевод текста') {
    return false;
  }

  // Переводить необходимо текст, введённый только в первую колонку.
  // Проверяем стартовую позицию диапазона
  Logger.log(range.getColumn());
  if  (range.getColumn() != 1) {
    return false;
  }

  for (var i = 1; i <= range.getNumRows(); i++) {
    var cell = range.getCell(
      i, // номер строки
      1 // номер колонки
    );

    // Получаем текст на русском
    var russianText = cell.getValue();

    // Переводим текст на английский
    // https://developers.google.com/apps-script/reference/language/language-app
    var translatedText = LanguageApp.translate(
      russianText, // текст
      'ru', // с какого языка переводим
      'en' // на какой язык переводим
    );

    // Вставляем переведённый текст во вторую колонку
    sheet.getRange(
      cell.getRowIndex(), // номер строки
      2 // номер столбца
    ).setValue(translatedText);
  }

}
// Функция onOpen() запускается всегда при открытии документа
// https://developers.google.com/apps-script/guides/triggers/#onopen
function onOpen() {
 
  // Создаём новое меню
  // https://developers.google.com/apps-script/reference/base/ui#createmenucaption
  SpreadsheetApp.getUi()
      .createMenu('Kosnpekti näited')
      .addItem('Пример', 'myFunction5_1') // При нажатии откроется модальное окно
      .addToUi();
}


// Функция onEdit является триггером, который срабатывает при завершении ввода данных в ячейку Таблицы пользователем
// https://developers.google.com/apps-script/guides/triggers/#onedite
function onEdit(e) {
  Logger.log(e);
 
  // Получаем диапазон ячеек, в которых произошли изменения
  // https://developers.google.com/apps-script/reference/spreadsheet/range
  var range = e.range;
 
  // Лист, на котором производились изменения
  // https://developers.google.com/apps-script/reference/spreadsheet/sheet
  var sheet = range.getSheet();
 
  // Проверяем, нужный ли это нам лист
  Logger.log(sheet.getName());
  if (sheet.getName() != 'Перевод текста') {
    return false;
  }
 
  // Переводить необходимо текст, введённый только в первую колонку.
  // Проверяем стартовую позицию диапазона
  Logger.log(range.getColumn());
  if  (range.getColumn() != 1) {
    return false;
  }
 
  for (var i = 1; i <= range.getNumRows(); i++) {
    var cell = range.getCell(
      i, // номер строки
      1 // номер колонки
    );
 
    // Получаем текст на русском
    var russianText = cell.getValue();
 
    // Переводим текст на английский
    // https://developers.google.com/apps-script/reference/language/language-app
    var translatedText = LanguageApp.translate(
      russianText, // текст
      'ru', // с какого языка переводим
      'en' // на какой язык переводим
    );

    var translatedText2 = LanguageApp.translate(
      russianText, // текст
      'ru', // с какого языка переводим
      'fr' // на какой язык переводим
    );
 
    // Вставляем переведённый текст во вторую колонку
    sheet.getRange(
      cell.getRowIndex(), // номер строки
      2 // номер столбца
    ).setValue(translatedText);

  // Вставляем переведённый текст во вторую колонку
    sheet.getRange(
      cell.getRowIndex(), // номер строки
      3 // номер столбца
    ).setValue(translatedText2);
  }
}

Результат на странице “Перевод текста”(вводим слово на русском и оно отображается в колонках 2 и 3 на английском и французском языках)

function onOpen добавила в навигацию отдельную кнопку Konspekti näited, нажимая на которую можно увидеть название скрипта “Пример”, запускающую function myFunction5_1

function myFunction5_1 (Оригинальный код слева и дополненный справа)

Функция парсинга заголовков статей с Habr в Google Таблицах

Эта функция автоматизирует процесс получения заголовков статей с сайта Habr.com и сохраняет их в Google Таблице. Она работает следующим образом:

  1. Получение данных из таблицы
    • Функция находит активную Google Таблицу и конкретный лист с названием ‘links’
    • Считывает все данные из этого листа в виде массива
  2. Обработка каждой строки
    • Функция перебирает строки таблицы, начиная со второй (первая строка считается заголовком)
    • Для каждой строки берется URL из первого столбца
  3. Отправка запросов к сайту
    • Для каждого URL выполняется HTTP-запрос с особыми параметрами безопасности:
      • muteHttpExceptions – продолжать работу даже при ошибках HTTP
      • validateHttpsCertificates – игнорировать проблемы с SSL-сертификатами
  4. Анализ результатов
    • Проверяется код ответа сервера
    • При успешном ответе (код 200) из HTML-кода страницы извлекается текст между тегами <title>
  5. Сохранение результатов
    • Найденные заголовки записываются во вторую колонку таблицы напротив соответствующих URL
    • Если заголовок не найден, записывается сообщение “Заголовок не найден”

Требования к данным:

  • Входные URL должны находиться в первом столбце
  • Первая строка таблицы должна содержать заголовки столбцов
  • Лист с именем ‘links’ должен существовать в таблице
// Вариант 1. Используется метод UrlFetchApp.fetch
function myFunction5_1() {
 
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName('links');
    var values = sheet.getDataRange().getValues();
 
    for (var i = 1; i < values.length; i++) {
        var url = values[i][0];
 
        // https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
        // Загружаем страницу по указанному url
        var response = UrlFetchApp.fetch(url, {
            'muteHttpExceptions': true, // Не выбрасывать исключения, если код ответа != 200
            'validateHttpsCertificates': false, // Игнорировать невалидные сертификаты при HTTPS запросах
        });
 
        // https://developers.google.com/apps-script/reference/url-fetch/http-response
        var responseCode = response.getResponseCode(); // Код ответа сервера
        var content = response.getContentText(); // Получаем html код страницы
 
        if (responseCode === 200) {
 
            // Получаем название поста
            var title = content.match(/title>(.*?)\</)[1];
 
// Вставляем название в таблицу
sheet.getRange(
i + 1, // номер строки
2 // номер столбца
).setValue(title);
 
}
}
 
}
// Вариант 1. Используется метод UrlFetchApp.fetch
function myFunction5_1() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName('links');
    var values = sheet.getDataRange().getValues();
    var startTime = new Date();

    for (var i = 1; i < values.length; i++) {
        var url = values[i][0];
        var rowStartTime = new Date(); // Начальное время для текущего URL

        var response = UrlFetchApp.fetch(url, {
            'muteHttpExceptions': true,
            'validateHttpsCertificates': false,
        });

        var responseCode = response.getResponseCode();
        var content = response.getContentText();

        if (responseCode === 200) {
            // Извлечение заголовка
            var title = content.match(/title>(.*?)\</)[1];
            sheet.getRange(i + 1, 2).setValue(title);

            // Извлечение мета-описания
            var metaDescriptionMatch = content.match(/<meta name="description" content="(.*?)"/);
            var metaDescription = metaDescriptionMatch ? metaDescriptionMatch[1] : "No description";
            sheet.getRange(i + 1, 3).setValue(metaDescription); // Записываем в третий столбец

            // Логирование времени выполнения для текущего URL
            var rowEndTime = new Date();
            var rowTimeDiff = (rowEndTime - rowStartTime) / 1000; // Время в секундах
            sheet.getRange(i + 1, 4).setValue(rowTimeDiff + " sec"); // Записываем в четвёртый столбец
        }
    }
}

В коде справа дополнены выводы мета-описания и времени выполнения для обрабатываемого URL.

  • Если описание найдено, оно записывается в третий столбец. Если нет — записывается “No description”.
  • Для каждого URL измеряется время выполнения (от начала запроса до завершения обработки).
    Время записывается в четвёртый столбец в формате “X sec”.