Вызов конечной точки API при изменении любых файлов Google Таблиц

Чего я хочу добиться:

Каждый раз, когда ячейка изменяется в любом листе Google на моем общем диске (любым пользователем в домене), я хочу вызвать конечную точку API и включить информацию о том, какая ячейка была отредактирована.

Мой подход: я считаю, что надстройка скриптов приложений Google - это то, что мне нужно. Установлен для всех пользователей в домене.

Я вижу, что есть "связанные" сценарии и автономные сценарии. Для автономных скриптов я не могу создавать никаких других триггеров, кроме триггеров на основе таймера и календаря. Связанные скрипты кажутся навсегда привязанными к одному листу и никак не повлияют на другие листы.

Что мне не хватает?

Я нахожу в блогах несколько сквозных руководств по созданию связанных скриптов, но ничего общего с междоменными вещами.


comment
Похоже, вам действительно нужно взглянуть на корпоративный API, доступный для Drive   -  person tehhowch    schedule 15.01.2020


Ответы (1)


Всего этого можно добиться с помощью отдельного скрипта. Создайте автономный скрипт и выполните следующие действия:

Шаг 1. Получите идентификаторы таблиц

Сначала вам нужно получить id различных электронных таблиц на вашем общем диске. Вы можете сделать это в самом скрипте Google Apps, если используете Advanced Drive Service (см. Справочник ниже). Чтобы активировать эту службу, перейдите к Resources > Advanced Google services... в редакторе сценариев и включите Drive API.

Затем напишите функцию, которая будет возвращать массив электронной таблицы ids на общем диске. Для этого вам нужно будет позвонить Drive.Files.list. Это может быть что-то вроде следующих строк (укажите свой общий driveId в соответствующей строке):

function getFileIds() {
  var params = {
    corpora: "drive",
    driveId: "your-shared-drive-id", // Please change this accordingly
    includeItemsFromAllDrives: true,
    q: "mimeType = 'application/vnd.google-apps.spreadsheet'",
    supportsAllDrives: true
  }
  var files = Drive.Files.list(params)["items"];
  var ids = files.map(function(file) {
    return file["id"];
  })
  return ids;
}

Шаг 2. Создайте триггеры для каждой таблицы

Установите триггер onEdit программно для каждой электронной таблицы (триггер редактирования запускает функцию каждый раз, когда редактируется соответствующая электронная таблица, поэтому я предполагаю, что это именно тот триггер, который вам нужен). Для этого будет использоваться ids, полученный на шаге 1. Это могло быть что-то похожее на это:

function createTriggers(ids) {
  ids.forEach(function(id) {
    var ss = SpreadsheetApp.openById(id);
    createTrigger(ss);
  })
}

function createTrigger(ss) {
  ScriptApp.newTrigger('sendDataOnEdit')
    .forSpreadsheet(ss)
    .onEdit()
    .create();
}

Функция createTriggers получает массив ids в качестве параметра и для каждого id создает onEdit триггер: каждый раз, когда любая из этих таблиц редактируется, функция sendDataOnEdit будет запускаться, и именно здесь вы захотите вызвать конечную точку API с информацией о редактируемая ячейка.

Шаг 3. Вызов конечной точки API

Функция sendDataOnEdit должна получить данные из редактируемой ячейки и куда-то их отправить.

function sendDataOnEdit(e) {
  // Please fill this up accordingly
  var range = e.range;
  var value = range.getValue();
  UrlFetchApp.fetch(url, params) // Please fill this up accordingly
}

Во-первых, он может получить информацию о ячейке, которая была отредактирована с помощью объекта события, переданного функции в качестве параметра e (вы можете получить ее столбец, ее строку, ее значение, лист и электронную таблицу, в которой она расположена, и т. Д. ). Например, чтобы получить значение ячейки, вы можете сделать e.range.getValue(). Проверьте ссылку, которую я предоставил, чтобы получить более подробную информацию об этом.

Во-вторых, когда вы правильно получили данные, которые хотите отправить, вы можете использовать UrlFetchApp.fetch(url, params), чтобы сделать запрос на свой URL. В приведенной ниже ссылке вы можете увидеть параметры, которые вы можете указать здесь (например, метод HTTP, полезные данные и т. Д.).

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

(Вы должны соответствующим образом отредактировать эту функцию, чтобы получать и отправлять именно то, что вы хотите. Я написал пример).

Подводя итог:

Чтобы создать триггеры, вы должны запустить createTriggers один раз (если вы запустите его несколько раз, он начнет создавать дубликаты). Запустите, например, эту функцию, которая сначала получает файл ids через Drive API, а затем создает соответствующие триггеры:

function main() {
  var ids = getFileIds();
  createTriggers(ids);
}

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

function deleteTriggers() {
  var triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(function(trigger) {
    ScriptApp.deleteTrigger(trigger);
  })
}

Ссылка:

Я надеюсь, что это поможет.

person Iamblichus    schedule 15.01.2020
comment
Ух ты! Это в 10 раз более детализировано и полезно, чем я когда-либо ожидал. Огромное спасибо! - person WPFUser; 16.01.2020
comment
iamblichus, попробовав это немного, я обнаружил два досадных ограничения. 1. Существует квота на 20 триггеров для каждого сценария приложения, что означает, что это не будет работать для более чем 20 листов (если я не сделаю несколько сценариев). 2. Похоже, что нет хорошего способа автоматической подписки на добавление новых файлов. Есть ли у вас какие-либо предложения по этим вопросам? - person WPFUser; 28.01.2020
comment
@WPFUser (1) Если имеется более 20 листов, я бы подумал о том, чтобы разместить их в разных папках и иметь другой сценарий для отслеживания файлов из каждой из этих разных папок (измените вызов в getFileIds, чтобы он отслеживал файлы в каждой конкретную папку, а не только на всем общем диске). (2) Каждый раз, когда добавляется новый файл, вам придется удалить и снова создать триггеры. Это можно сделать, просто запустив deleteTriggers, а затем createTriggers, которые можно объединить в единственную функцию. - person Iamblichus; 28.01.2020
comment
Чтобы это работало для всех пользователей в моем домене, мне нужно зарегистрировать его как приложение и установить для всех пользователей. Если я правильно понимаю, мне нужно было бы создавать все больше и больше приложений, каждое с одним скриптом каждое, поскольку мы получаем все больше и больше листов. Я также не понимаю, как я могу автоматически запускать триггеры удаления и создания (или новую функцию триггера обновления) при создании файла. Я мог бы подписаться на изменения диска, но тогда я не получал бы первые правки вновь созданных листов, так как есть некоторая задержка. В моем случае это не кажется хорошим решением, поскольку оно просто не масштабируется и / или слишком ручное. - person WPFUser; 28.01.2020
comment
@WPFUser рассмотрите возможность того, что то, о чем вы просите, может быть невозможно. Все службы имеют ограничения, и некоторые из необходимых вам функций не были указаны в исходном вопросе (например, необходимость для всех пользователей в домене иметь возможность использовать это). Я серьезно сомневаюсь, что у вас есть подход, который приближается к тому, чего вы хотите достичь. - person Iamblichus; 28.01.2020
comment
Возможно, в этом вы правы. И я искренне признателен за ваш ответ. Тем не менее, необходимость его работы для всех пользователей указывается и остается. т.е. всякий раз, когда ячейка изменяется в любом листе Google на моем общем диске (любым пользователем в домене), я хочу вызвать конечную точку API и включить информацию о том, какая ячейка была отредактирована. - person WPFUser; 28.01.2020