Задача
Выгрузить облачную google таблицу в Bitrix24
В данном примере показывается процесс настройки передачи данных из googleSheets в Bitrix24 с помощью встроенного функционала Apps script
Сценарий
Сценарий следующий:
Есть таблица с данными. В качестве первой строки — заголовки таблицы. Выгрузить данные этой таблицы в MoreKit, обработать данные внутри логической схемы, передать в Bitrix24.
Выгрузка будет работать по нажатию на кнопку, которая появится в таблице в процессе настройки. Каждая выгруженная строка будет окрашена в желтый цвет, чтобы при повторном нажатии на кнопку она повторно не выгружалась.
Пример таблицы, данные из которой будем передавать

Лучше заранее создайте в битрикс24 поля к сущностям, куда будут заполняться данные
Подключение Bitrix24 в Morekit
Перед добавлением сервиса bitrix24 в morekit, необходимо установить приложение MoreKit в маркетплейсе. Для установки приложения требуется подписка на маркетплейс Bitrix24

После установки приложение MoreKit в маркетплейс bitrix24, можно приступать к добавлению сервиса в Morekit. Для этого в проекте нажмите Добавить сервис, найдите в списке Bitrix24. При подключении сервиса будет запрошена ссылка на ваш битрикс24

Введите ссылку в формате https://мой-домен.bitrix24.ru. После этого произойдет редирект на страницу с вашим битриксом, подтвердите авторизацию
Если все правильно — сервис появится в списке сервисов и у него будет статус Готово

Создание процесса
После подключения Bitrix24 в MoreKit создадим процесс. При создании процесса нужно выбрать тип Другое
На данный процесс будем отсылать данные из таблицы, которые затем будут передаваться в Битрикс24
На данной стадии достаточно только создать процесс и скопировать ссылку из первоначального блока, чтобы указать ее в скрипте Appscript


Настройка отправки в таблице
После создания процесса — настроим отправку данных из таблицы
В таблице переходим в Расширения —> Apps script

После перехода в Apps Script вы увидите пустую функцию, полностью сотрите ее

Далее, скопируйте скрипт и вставьте его в Appscript
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Выгрузка')
.addItem('Отправить', 'sendData')
.addItem('Удалить', 'deleteYellowRows')
.addToUi();
}
function sendData() {
sendUncoloredRows();
}
function deleteYellowRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; //Номер листа
var lastRow = sheet.getLastRow();
var coloredRanges = sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn()).getBackgrounds();
var rowsToDelete = [];
for (var i = 0; i < lastRow - 1; i++) {
if (coloredRanges[i].join() === Array(sheet.getLastColumn()).fill('#ffff00').join()) {
rowsToDelete.push(i + 2);
}
}
if (rowsToDelete.length > 0) {
rowsToDelete.reverse();
rowsToDelete.forEach(function(rowIndex) {
sheet.deleteRow(rowIndex);
});
Logger.log("Удалено строк: " + rowsToDelete.length);
} else {
Logger.log("Нет строк для удаления");
}
}
function sendUncoloredRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; //Номер листа
var lastRow = sheet.getLastRow();
var dataRange = sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn());
var data = dataRange.getValues();
var coloredRanges = dataRange.getBackgrounds();
var rowsToSend = [];
var uniqueRowsSet = new Set();
var startTime = new Date().getTime();
var elapsedTime = 0;
var totalSent = 0;
var totalSkipped = 0;
// !!!!!!!!!! НАСТРОЙКИ !!!!!!!!!!!
var url = "https://ep.morekit.io/xxxxxxxxxxxxxxxxxxxxxxxxxx";
var batchSize = 50;
var timeout = 355000; // ~5 минут
var maxRetries = 3;
// !!!!!!!!!! НАСТРОЙКИ !!!!!!!!!!!
Logger.log("Начало обработки. Всего строк: " + (lastRow - 1));
for (var i = 0; i < lastRow - 1; i++) {
// Проверка на желтый фон и непустые строки
if (coloredRanges[i].join() !== Array(sheet.getLastColumn()).fill('#ffff00').join() &&
data[i].some(cellValue => cellValue !== '' && cellValue !== null && String(cellValue).trim() !== '')) {
var jsonObject = {};
for (var j = 0; j < data[i].length; j++) {
var header = sheet.getRange(1, j + 1).getValue();
jsonObject[header] = data[i][j];
}
// Нормализация JSON для проверки уникальности
var normalizedJson = JSON.stringify(jsonObject)
.replace(/\s+/g, '')
.toLowerCase();
if (!uniqueRowsSet.has(normalizedJson)) {
uniqueRowsSet.add(normalizedJson);
rowsToSend.push(jsonObject);
// Закрашиваем сразу, но будем проверять успешность отправки
paintRowYellow(sheet, i + 2, sheet.getLastColumn());
Logger.log("Добавлена строка " + (i + 2) + " для отправки");
} else {
totalSkipped++;
Logger.log("Пропущен дубликат строки " + (i + 2));
}
}
// Проверка на отправку пакета
elapsedTime = new Date().getTime() - startTime;
if (rowsToSend.length >= batchSize || elapsedTime >= timeout) {
Logger.log("Отправка пакета из " + rowsToSend.length + " строк...");
var success = sendWithRetry(rowsToSend, url, maxRetries);
if (success) {
totalSent += rowsToSend.length;
Logger.log("Пакет успешно отправлен");
} else {
Logger.log("Ошибка при отправке пакета");
}
rowsToSend = [];
startTime = new Date().getTime();
}
}
// Отправка оставшихся строк
if (rowsToSend.length > 0) {
Logger.log("Отправка последнего пакета из " + rowsToSend.length + " строк...");
var success = sendWithRetry(rowsToSend, url, maxRetries);
if (success) {
totalSent += rowsToSend.length;
Logger.log("Последний пакет успешно отправлен");
} else {
Logger.log("Ошибка при отправке последнего пакета");
}
}
Logger.log("Обработка завершена. Итого: отправлено " + totalSent + ", пропущено " + totalSkipped);
SpreadsheetApp.getUi().alert("Готово!", "Обработка завершена.\nОтправлено: " + totalSent + "\nПропущено: " + totalSkipped, SpreadsheetApp.getUi().ButtonSet.OK);
}
function sendWithRetry(batchData, url, maxRetries) {
var attempts = 0;
var success = false;
while (attempts < maxRetries && !success) {
attempts++;
Logger.log("Попытка " + attempts + " из " + maxRetries);
success = sendBatch(batchData, url);
if (!success && attempts < maxRetries) {
Utilities.sleep(1000 * attempts);
}
}
return success;
}
function sendBatch(batchData, url) {
var options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(batchData),
'muteHttpExceptions': true,
'followRedirects': true,
'validateHttpsCertificates': true
};
try {
Logger.log("Отправка пакета на " + url);
var response = UrlFetchApp.fetch(url, options);
var responseCode = response.getResponseCode();
var responseText = response.getContentText().substring(0, 1000); // Длина лога
Logger.log("HTTP код: " + responseCode);
Logger.log("Ответ сервера: " + responseText);
return responseCode >= 200 && responseCode < 300;
} catch (e) {
Logger.log("Ошибка при отправке: " + e.message);
return false;
}
}
function paintRowYellow(sheet, rowIndex, columnCount) {
try {
var range = sheet.getRange(rowIndex, 1, 1, columnCount);
range.setBackground("#ffff00");
Logger.log("Строка " + rowIndex + " закрашена в желтый");
return true;
} catch (e) {
Logger.log("Ошибка закрашивания строки " + rowIndex + ": " + e.message);
return false;
}
}Если у вас в таблице несколько листов, укажите порядковый номер листа (отсчет начинается с нуля). Например, если у вас два листа, выгрузить нужно со второго — вместо [0] напишите [1]

Далее — найдите часть с настройками в скрипте. В нее вставьте скопированную ссылку из MoreKit для вашего процесса. Ссылка должна быть в кавычках. После ковычек не потяряйте ;

После вставки ссылки нажмите сверху на дискету, либо используется комбинацию клавиш CTRL + S, чтобы сохранить скрипт
Развертывание скрипта
Далее необходимо развернуть наш скрипт, чтобы его функционал применился к таблице. Нажимаем Начать развертывание —> Новое развертывание

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

Далее нажимаем Начать развертывание. Если развертывание попросит доступ


После подтверждения выдачи прав доступа к таблице — увидим окно с выполненным развертыванием

Далее — переходим назад в таблицу и обновляем страницу. Если все сделано верно — над таблицей увидите кнопку Выгрузка

Далее — попробуем отправить данные. Нажимаем на кнопку Выгрузка и Отправить. После нажатия — строки начнут закрашиваться в желтый цвет

Так как в таблице 4 строки с данными — в MoreKit должно придти 4 события.
Проверим это: вернемся в схему, перейдем во вкладку События


Видим, что события успешно дошли. Если развернуть событие и перейти во входящие данные — увидим данные, которые были в строке

Теперь останется выстроить логическую схему передачи данных в Битрикс24
В данном примере схема будет выполнять следующие действия:
- Будет искаться контакт по номеру телефона и email в битрикс24, чтобы не создавать дубли по контактам
- Если контакта нет — создаваться новый контакт и сделка к нему
- Если контакт есть — создаваться сделка
- Перед постановкой задачи будет проверяться значение Нужно связаться из таблицы. Если там будет написано Да, будем ставить задачу в сделку
Схема будет выглядеть следующим образом

Описание блоков схемы
#1 Найти контакты — поиск контакта по номеру телефона, который приходит из таблицы

#2 Найти контакты — Если контакт не нашелся по номеру телефона, ищем его по email адресу

#3 Создать контакты — если контакт не был найден ни по телефону, ни по email, создаем новый контакт

#4 Создать сделку — создаем сделку. Привязываем к сделке найденный или созданный контакт, выбираем стадию и воронку сделки, заполняем поле Уникальный код

#5 Проверка — Проверяем значение столбцы Нужно связаться. Если в таблице было Да — схема пойдет направо, по зеленой галочке. Если нет — вниз, т.е. процесс завершится

#7 Дата и время — создаем дату со сдвигом на день вперед. Дата будет нужна для подстановки в срок выполнения задачи

#6 Создать задачу — создаем задачу. Заполняем срок, название, описание

Тестирование схемы
Проверить работоспособность можно следующим образом:
- Снять желтую заливку с выгруженных строк таблицы и нажать на кнопку выгрузки еще раз.
- Повторить события в MoreKit. Напротив каждого события есть значок его перезапуска. При перезапуске события — его входящие данные переотправляются на процесс, но применяются уже к новой схеме.
Повторим событие из MoreKit, жмите на значок перезапуска события

После перезапуска — значок исчезнет. Это значит — что данные переотправляются на процесс и применяются к новой схеме. Можно идти смотреть в Битрикс24 результат создания. После повтора четырех наших событий — видим 4 сделки в системе

Перейдем в сделку, где ставилась задача

Видим, что все данные, которые мы выбирали в блоке создания сделки — заполнились. Также прикрепился контакт, создалась задача сроком на 1 день
Подведем итоги
В данном кейсе рассмотрели, как можно выгрузить данные из Google Sheets в MoreKit с помощью Apps Script.
В MoreKit получили данные из таблицы, выстроили логическую схему, убедились в успешной передаче данных внутри битрикс24 по итогам выгрузки