Автоматизация Google Таблиц: Google Apps Script

В главе 5 ты писал(а) макросы на VBA для Excel. У Google Таблиц свой инструмент автоматизации — Google Apps Script. Это ДРУГАЯ платформа: другой язык (JavaScript, а не VBA), другой редактор, другие названия объектов. Но идея та же самая — код, который сам читает и меняет ячейки листа вместо того, чтобы это делал человек руками.

К концу темы ты сможешь:
— открыть редактор Apps Script и получить доступ к активной таблице и листу из кода;
— прочитать и записать значение ячейки и целого диапазона;
— пройти циклом по диапазону ячеек;
— добавить своё меню, которое появляется при открытии таблицы (onOpen);
— написать код, который реагирует на правку ячейки пользователем (onEdit);
— назвать одно принципиальное ограничение простых триггеров.

Честно: это другая платформа, не продолжение VBA. Код на VBA работать в Google Таблицах не будет и наоборот. Если ты работаешь только в Excel — эта тема пригодится, если когда-нибудь придётся автоматизировать Google Таблицы (например, у клиента или в команде, где принят этот инструмент).

Где писать код: редактор Apps Script

Открой Google Таблицу → меню Расширения → Apps Script (Extensions → Apps Script). Откроется отдельный редактор кода — это и есть Apps Script, платформа на основе JavaScript для расширения Google Таблиц (а также Gmail, Календаря, Диска).

Первый запуск попросит разрешение. Когда ты в первый раз сохранишь или запустишь свой скрипт, Google покажет экран «Этому проекту нужен доступ к вашему аккаунту» с кнопкой «Разрешить». Это нормально и ожидаемо — без этого скрипт не сможет читать и менять твою же таблицу; просто нажми «Разрешить» (может понадобиться выбрать аккаунт и подтвердить ещё раз, если Google покажет предупреждение «Google не проверила это приложение» — это стандартное предупреждение для собственных, непубликуемых скриптов, не признак ошибки).

Доступ к текущей таблице и листу из кода даёт объект SpreadsheetApp:

var ss = SpreadsheetApp.getActiveSpreadsheet();  // вся таблица (файл)
var sheet = SpreadsheetApp.getActiveSheet();     // текущий (активный) лист

Контрольный вопрос. На каком языке программирования написан код в Google Apps Script?

АVBA (Visual Basic for Applications)
БJavaScript
ВPython
Гсобственный язык Google без аналогов

Подсказка: Это тот же язык, на котором пишут скрипты для веб-страниц.

Онлайн-проверка ответа появится позже

Range: читаем и пишем значения ячеек

getRange(...) возвращает объект Range — ссылку на ячейку или диапазон. Дальше с ним работают методами: getValue()/setValue(значение) — для ОДНОЙ ячейки, getValues()/setValues(массив) — для целого диапазона (в виде двумерного массива строк и столбцов). У Range есть и служебные методы: getRow()/getColumn() возвращают НОМЕР строки/столбца этой ячейки (числом) — пригодится, когда нужно узнать не значение ячейки, а её положение на листе.

var sheet = SpreadsheetApp.getActiveSheet();
var r1 = sheet.getRange('A1');        // по адресу
var r2 = sheet.getRange(1, 1);        // по номеру (строка, столбец)
var val = r1.getValue();              // прочитать одну ячейку
r1.setValue(42);                      // записать одну ячейку
var grid = sheet.getRange('A1:B10').getValues();   // двумерный массив
sheet.getRange('A1:B10').setValues(grid);          // размер массива = размер диапазона

Задание. Какой метод нужно вписать вместо пропуска?

Исходный код для этого задания:

Таблица «Задачи»: A1 — статус первой задачи. Нужно получить доступ к этой ячейке по номеру строки и столбца (1-я строка, 1-й столбец).
var cell = sheet.____(1, 1);

Подсказка: Это тот же метод, что и для получения ячейки по адресу ‘A1’, только с двумя числами вместо строки-адреса.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Задание. Что окажется в переменной result после выполнения этого кода? Впиши число.

Исходный код для этого задания:

В ячейке D4 листа хранится число 7. Код:
var c = sheet.getRange('D4').getValue();
var result = c * 3;

Подсказка: getValue() читает содержимое ровно той ячейки, на которую ссылается getRange.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Контрольный вопрос. Диапазон B2:C4 (2 столбца, 3 строки) содержит числа. Чем результат getValues() отличается от getValue() для этого же диапазона?

Арезультат будет одинаковым в обоих случаях
БgetValue() работает только с текстом, getValues() — только с числами
ВgetValues() нужно вызывать только для целого листа, а не для диапазона
ГgetValues() вернёт двумерный массив всех ячеек диапазона, а getValue() — значение только ОДНОЙ (первой) ячейки диапазона

Подсказка: Обрати внимание на окончание -s в названии метода — оно намекает на множественное число.

Онлайн-проверка ответа появится позже

Задание. Какой метод нужно вписать вместо пропуска?

Исходный код для этого задания:

Нужно записать число 100 в ячейку D5 текущего листа.
sheet.getRange('D5').____(100);

Подсказка: Это метод-пара к getValue(), только для записи, а не для чтения.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Цикл по диапазону: обходим ячейки как в VBA For Each

В Google-документации прямо сказано: не стоит дёргать ячейки по одной внутри цикла — это медленно. Правильный приём — прочитать ВЕСЬ диапазон разом методом getValues() (получится двумерный массив), а затем обойти этот массив обычным циклом for:

function processRange() {
  var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
  for (var i = 0; i < data.length; i++) {      // строки
    for (var j = 0; j < data[i].length; j++) {  // столбцы внутри строки
      // работа с data[i][j]
    }
  }
}

Задание. Сколько раз всего выполнится тело внутреннего цикла (по всем i и j вместе)? Впиши число.

Исходный код для этого задания:

Таблица «Заявки»: столбец A — номер заявки, столбец B — статус. Диапазон данных — пять строк (A1:B5, два столбца в каждой строке).
var data = sheet.getRange('A1:B5').getValues();
for (var i = 0; i < data.length; i++) {
  for (var j = 0; j < data[i].length; j++) {
    // счётчик += 1
  }
}

Подсказка: Внутренний цикл проходит по столбцам КАЖДОЙ строки — сколько столбцов в одной строке, и сколько всего строк?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

onOpen — своё меню при открытии таблицы

Функция onOpen(e) — простой триггер: Apps Script вызывает её сам, когда пользователь открывает таблицу. Внутри неё через SpreadsheetApp.getUi() можно добавить своё меню:

function onOpen(e) {
  SpreadsheetApp.getUi()
      .createMenu('Мои инструменты')
      .addItem('Запустить проверку', 'myFunction')
      .addToUi();
}

Контрольный вопрос. Когда Apps Script сам вызывает функцию onOpen(e)?

Апри каждом изменении любой ячейки
Бтолько когда автор скрипта нажимает «Выполнить» в редакторе
Вкогда пользователь открывает таблицу
Граз в сутки по расписанию

Подсказка: Название функции говорит само за себя — вспомни, что означает «open».

Онлайн-проверка ответа появится позже

Задание. Какой метод нужно вписать вместо пропуска?

Исходный код для этого задания:

Нужно, чтобы новый пункт меню назывался «Очистить пометки» и запускал функцию clearMarks.
SpreadsheetApp.getUi()
    .createMenu('Мои инструменты')
    .____('Очистить пометки', 'clearMarks')
    .addToUi();

Подсказка: Метод добавляет один пункт (item) в уже созданное меню.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

onEdit — реагируем на правку ячейки

Функция onEdit(e) — тоже простой триггер: срабатывает при КАЖДОМ изменении значения ячейки пользователем. Параметр e — объект события, у него есть поля e.range (Range отредактированной ячейки) и e.value (новое значение, только если правили одну ячейку):

function onEdit(e) {
  var range = e.range;
  range.setNote('Изменено: ' + new Date());
}

Ограничение простых триггеров. onOpen и onEdit — «простые» триггеры, и у них есть жёсткое ограничение: они НЕ МОГУТ обращаться к сервисам, требующим авторизации, — например, простой триггер не может отправить письмо через Gmail (сервис Gmail требует авторизации, а простой триггер её не проходит). Для таких задач нужен «устанавливаемый» (installable) триггер — он настраивается отдельно и таких ограничений не имеет, но выходит за рамки этой темы.

Задание. Какое поле объекта события нужно вписать вместо пропуска?

Исходный код для этого задания:

Внутри функции onEdit(e) нужно получить объект той ячейки, которую только что отредактировал пользователь (тот же объект, с которым работают getValue()/setValue()).
function onEdit(e) {
  var editedCell = e.____;
}

Подсказка: Название поля прямо говорит, что оно хранит — диапазон (по-английски).

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Контрольный вопрос. Почему простой триггер onEdit НЕ подходит для отправки уведомления на email при изменении ячейки?

АonEdit никогда не срабатывает при изменении текста, только чисел
Бпростой триггер не может обращаться к сервисам, требующим авторизации (например, Gmail), а для этого нужен installable-триггер
Вemail можно отправить только из VBA, а не из Apps Script
Гпростые триггеры вообще не существуют в Google Таблицах

Подсказка: Вспомни ограничение, о котором говорилось сразу после примера onEdit.

Онлайн-проверка ответа появится позже

Задание. Какой метод Range нужно вписать вместо пропуска, чтобы добавить заметку к ячейке?

Исходный код для этого задания:

Таблица «Склад»: столбец B — количество товара на складе. Нужно: если пользователь ИЗМЕНИЛ ячейку в столбце B и записал в неё число меньше 5 — добавить к этой ячейке заметку «Мало на складе».
function onEdit(e) {
  if (e.range.getColumn() == 2 && e.value < 5) {
    e.range.____('Мало на складе');
  }
}

Подсказка: Этот же метод уже встречался в примере темы — он прикрепляет текстовую заметку к ячейке, не меняя её значение.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Итог

Итог. Apps Script — платформа на JavaScript для Google Таблиц, редактор открывается через Расширения → Apps Script. SpreadsheetApp.getActiveSpreadsheet()/getActiveSheet() дают доступ к таблице и листу; getRange(…) возвращает Range, у него getValue()/setValue() — для одной ячейки, getValues()/setValues() — двумерный массив для диапазона. Диапазон лучше читать целиком и обходить циклом for, а не по одной ячейке. onOpen(e) срабатывает при открытии таблицы (годится для своего меню через SpreadsheetApp.getUi()), onEdit(e) — при правке ячейки пользователем (e.range, e.value). Оба — простые триггеры и не могут обращаться к сервисам, требующим авторизации (например, Gmail) — для этого нужен installable-триггер.

Бонус: Google Формы → автоматическая запись в таблицу

Ещё один инструмент Google для сбора данных — Google Формы. Ответы на форму можно направить прямо в Google Таблицу: в редакторе формы на вкладке «Ответы» есть кнопка создания связанной таблицы — каждый новый ответ появляется в таблице отдельной строкой автоматически, без единой строчки кода. А дальше к этой таблице ответов уже можно применить всё, что ты изучил(а) в этой теме и теме 6.1 — от простых формул до триггера onEdit.

← Назад · ↑ В начало урока · ⌂ В начало курса · Вперёд: Дашборды и отчёты →

Школа Виктора Комлева