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 Таблице. Она работает следующим образом:
- Получение данных из таблицы
- Функция находит активную Google Таблицу и конкретный лист с названием ‘links’
- Считывает все данные из этого листа в виде массива
- Обработка каждой строки
- Функция перебирает строки таблицы, начиная со второй (первая строка считается заголовком)
- Для каждой строки берется URL из первого столбца
- Отправка запросов к сайту
- Для каждого URL выполняется HTTP-запрос с особыми параметрами безопасности:
muteHttpExceptions
– продолжать работу даже при ошибках HTTPvalidateHttpsCertificates
– игнорировать проблемы с SSL-сертификатами
- Для каждого URL выполняется HTTP-запрос с особыми параметрами безопасности:
- Анализ результатов
- Проверяется код ответа сервера
- При успешном ответе (код 200) из HTML-кода страницы извлекается текст между тегами
<title>
- Сохранение результатов
- Найденные заголовки записываются во вторую колонку таблицы напротив соответствующих 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”.