Интеграция таблиц с 1С
Связать 1С:Предприятие 8.3 с таблицей Coverse можно двумя способами. Они не исключают друг друга.
| Способ | Кто начинает обмен | Когда подходит | Что нужно со стороны 1С |
|---|---|---|---|
| 1С отправляет в таблицу | 1С | нужно сразу видеть проведённые документы, оплаты, изменения остатков | программист 1С добавляет около 30 строк кода; база может стоять в локальной сети |
| Таблица забирает из 1С | скрипт по расписанию | нужны справочники, документы за период, данные для отчёта | включить стандартный интерфейс OData; база должна быть доступна из интернета |
Если 1С должна писать в таблицу большие объёмы данных без скрипта, можно обращаться к API Coverse Таблиц напрямую: начните с руководства Первая интеграция.
1С отправляет в таблицу
1С отправляет JSON с данными документа на адрес вебхука скрипта, скрипт записывает строку. Запрос идёт из 1С наружу, поэтому способ работает и для базы в локальной сети: нужен только выход в интернет.
1. Скрипт в таблице
Создайте скрипт и вставьте код. Он записывает документ на лист «Документы 1С», а повторную отправку того же документа обновляет, а не дублирует.
const SHEET = "Документы 1С";
function onWebhook(event) {
if (!event) return;
if (!event.json) {
console.warn("Тело запроса не JSON:", event.body);
return;
}
const doc = event.json;
if (!doc.id) {
console.warn("В документе нет id:", JSON.stringify(doc));
return;
}
const values = [
asText(doc.id),
asText(doc.number),
Utilities.toDate(doc.date) || "",
asText(doc.client),
Number(doc.total) || 0,
new Date(),
];
const sheet = Coverse.table.getSheetByName(SHEET) || Coverse.table.insertSheet(SHEET);
if (sheet.getLastRow() === 0) {
sheet.appendRow(["ID", "Номер", "Дата", "Контрагент", "Сумма", "Получено"]);
}
const rows = sheet.getRange(1, 1, sheet.getLastRow(), 1).getValues();
const index = rows.findIndex((row) => String(row[0]) === values[0]);
if (index === -1) {
sheet.appendRow(values);
} else {
sheet.getRange(index + 1, 1, 1, values.length).setValues([values]);
}
}
function asText(value) {
const text = String(value === undefined || value === null ? "" : value);
return text.charAt(0) === "=" ? "'" + text : text;
}
id— уникальный идентификатор документа в 1С. По нему скрипт находит уже записанную строку.- Дату 1С передаёт без часового пояса, например
2026-10-19T12:30:00.Utilities.toDateпонимает её в часовом поясе владельца скрипта и возвращаетnull, если дата не распознана, поэтому одна неверная дата не остановит скрипт. asTextне даёт тексту, который начинается с=, стать формулой.
2. Адрес вебхука
- На вкладке «Триггеры» добавьте триггер «По вебхуку» с функцией
onWebhook. - Скопируйте адрес вида
https://app.coverse.team/api/hooks/scripts/whs_…. - Если 1С выходит в интернет с постоянного адреса, укажите его в поле «Разрешённые IP-адреса» триггера.
Подробнее: Вебхуки.
3. Код в 1С
Программист 1С добавляет процедуру отправки в общий модуль, который выполняется на сервере: из тонкого клиента HTTP-запросы недоступны. Сервер и путь берутся из адреса вебхука: сервер — app.coverse.team, путь — всё, что после него, начиная с /api/hooks/…. Адрес лучше хранить в константе или настройке, а не в коде.
Процедура ОтправитьВCoverse(Данные, ПутьВебхука) Экспорт
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
Настройки = Новый НастройкиСериализацииJSON;
Настройки.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
Настройки.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДата;
ЗаписатьJSON(Запись, Данные, Настройки);
Текст = Запись.Закрыть();
Соединение = Новый HTTPСоединение("app.coverse.team", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL());
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос = Новый HTTPЗапрос(ПутьВебхука, Заголовки);
Запрос.УстановитьТелоИзСтроки(Текст, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
ВызватьИсключение "Coverse ответил " + Строка(Ответ.КодСостояния) + ": " + Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;
КонецПроцедуры
Пример вызова для документа реализации. Названия реквизитов зависят от конфигурации, подставьте свои:
Данные = Новый Структура;
Данные.Вставить("id", Строка(Документ.Ссылка.УникальныйИдентификатор()));
Данные.Вставить("number", Документ.Номер);
Данные.Вставить("date", Документ.Дата);
Данные.Вставить("client", Строка(Документ.Контрагент));
Данные.Вставить("total", Документ.СуммаДокумента);
ОтправитьВCoverse(Данные, ПутьВебхука);
Тело отправляется в UTF-8 без метки BOM: с меткой Coverse не распознает JSON. Для HTTPS-соединения нужна платформа 8.3 с поддержкой TLS 1.2.
Что отвечает Coverse
| Код | Что значит | Что делать в 1С |
|---|---|---|
200, тело OK | запрос принят и поставлен в очередь скрипта | ничего |
| 401 | подпись неверная, если в триггере включена проверка подписи | проверьте настройки подписи |
| 403 | адрес 1С не в списке разрешённых, триггер выключен или скрипты недоступны на тарифе владельца | текст причины в поле error ответа |
| 404 | неверный путь вебхука | скопируйте адрес из карточки триггера заново |
| 413 | тело больше 100 КБ | отправляйте документы по одному, без лишних реквизитов |
| 429 | больше 60 запросов в минуту, очередь скрипта переполнена или закончилась норма минут | повторите позже, заголовок Retry-After подскажет, через сколько секунд |
Ответ 200 означает, что запрос принят, но скрипт выполняется уже после ответа. Если скрипт упадёт с ошибкой, 1С об этом не узнает: результат видно только в журнале скрипта.
Где вызывать отправку
Не отправляйте запрос прямо внутри проведения документа: если сеть или Coverse недоступны, проведение замедлится или завершится ошибкой. Надёжнее при проведении только отмечать документ к отправке, а отправлять регламентным заданием раз в несколько минут:
- отправляйте не больше 60 документов в минуту на один адрес;
- при ответе 429 или ошибке сети повторяйте попытку позже, остальные коды требуют исправления настроек;
- повторная отправка безопасна: скрипт обновит строку по
id.
Таблица забирает из 1С через OData
У 1С:Предприятия 8.3 есть стандартный интерфейс OData: справочники, документы и регистры доступны по HTTP в формате JSON. Скрипт по расписанию запрашивает нужные данные и записывает их на лист.
1. Включите OData
Облачная 1С (1cfresh.com). Интерфейс OData в приложениях 1С:Фреш уже включён. Пользователь с полными правами открывает Администрирование → Синхронизация данных → Настройки стандартного интерфейса OData (в некоторых приложениях раздел называется «Администрирование и НСИ» или «Настройки»):
- На вкладке «Состав» отметьте объекты, которые нужны скрипту, например документ заказа клиента и справочник номенклатуры.
- На вкладке «Авторизация» создайте отдельного пользователя для обмена и запишите логин и пароль.
Адрес интерфейса выглядит так: https://1cfresh.com/a/<приложение>/<номер области>/odata/standard.odata/. Подробнее — в статье 1С:Фреш.
Своя база.
- В конфигураторе откройте Администрирование → Публикация на веб-сервере и отметьте «Публиковать стандартный интерфейс OData».
- Задайте состав объектов, доступных через OData. В типовых конфигурациях это делается в режиме 1С:Предприятие обработкой «Настройка стандартного интерфейса OData», в остальных — программно, процедурой
УстановитьСоставСтандартногоИнтерфейсаOData. - Создайте пользователя для обмена с ролью «Удаленный доступ OData» или с полными правами. Лучше отдельного, с логином латиницей.
- Опубликованная база должна открываться из интернета по HTTPS с действительным сертификатом. Скрипты не обращаются к адресам локальной сети, а из портов доступны 80, 443 и с 1024 по 65535.
Адрес интерфейса: https://<ваш сервер>/<имя публикации>/odata/standard.odata/.
2. Узнайте имена объектов
Объекты в OData называются по виду и имени в конфигурации: Catalog_Номенклатура, Document_ЗаказКлиента, InformationRegister_КурсыВалют. Имена зависят от конфигурации. Список доступных объектов вернёт адрес интерфейса с параметром ?$format=json, а реквизиты объекта видны в ответе на пробный запрос. Стандартные поля: Ref_Key (ссылка), Code и Description у справочников, Number, Date и Posted у документов, DeletionMark (пометка удаления).
3. Сохраните доступ в секреты
На вкладке «Секреты» скрипта добавьте:
ODATA_URL— адрес интерфейса, заканчивается на/odata/standard.odata/;ODATA_USER— логин пользователя обмена;ODATA_PASSWORD— пароль.
4. Код скрипта
Скрипт каждый раз загружает заказы за последние 7 дней и переписывает ими лист «Заказы из 1С». Так в таблице всегда актуальная картина, включая исправленные и распроведённые документы, и не нужно следить за повторами.
const ENTITY = "Document_ЗаказКлиента";
const DAYS = 7;
const SHEET = "Заказы из 1С";
const PAGE = 500;
const MAX_PAGES = 20;
function main() {
const base = Secrets.get("ODATA_URL");
const user = Secrets.get("ODATA_USER");
const password = Secrets.get("ODATA_PASSWORD");
if (!base || !user || !password) throw new Error("Добавьте секреты ODATA_URL, ODATA_USER и ODATA_PASSWORD");
const url = base.replace(/\/?$/, "/") + encodeURIComponent(ENTITY);
const auth = "Basic " + Utilities.base64Encode(user + ":" + password);
const from = Utilities.formatDate(Utilities.addDays(Utilities.today(), -DAYS), "yyyy-MM-dd'T'HH:mm:ss");
const items = [];
for (let page = 0; page < MAX_PAGES; page++) {
const query = [
"$format=json",
"$filter=" + encodeURIComponent("Date ge datetime'" + from + "' and DeletionMark eq false"),
"$select=" + encodeURIComponent("Ref_Key,Number,Date,Posted,СуммаДокумента"),
"$orderby=" + encodeURIComponent("Date,Ref_Key"),
"$top=" + PAGE,
"$skip=" + page * PAGE,
].join("&");
const response = Http.get(url + "?" + query, {
headers: { Authorization: auth, Accept: "application/json" },
});
if (!response.ok) throw new Error("1С ответила с кодом " + response.status + ": " + response.text().slice(0, 500));
const chunk = response.json().value || [];
items.push(...chunk);
if (chunk.length < PAGE) break;
if (page === MAX_PAGES - 1) throw new Error("Документов больше " + PAGE * MAX_PAGES + ", уменьшите DAYS");
}
const rows = items.map((item) => [
item.Ref_Key,
asText(item.Number),
Utilities.toDate(item.Date) || "",
item.Posted === true,
Number(item.СуммаДокумента) || 0,
]);
const sheet = Coverse.table.getSheetByName(SHEET) || Coverse.table.insertSheet(SHEET);
sheet.getRange("A1:E").clear();
sheet.getRange(1, 1, 1, 5).setValues([["Ссылка", "Номер", "Дата", "Проведён", "Сумма"]]);
if (rows.length > 0) {
sheet.getRange(2, 1, rows.length, 5).setValues(rows);
}
console.log("Загружено документов:", rows.length);
}
function asText(value) {
const text = String(value === undefined || value === null ? "" : value);
return text.charAt(0) === "=" ? "'" + text : text;
}
Что подставить своё:
ENTITY— имя объекта из шага 2.- Реквизиты в
$selectи вrows:СуммаДокумента— пример, в вашей конфигурации сумма может называться иначе. DAYS— за сколько дней загружать.
Что важно в коде:
- Документы загружаются страницами по 500 через
$topи$skip, до 20 страниц. Если документов больше, скрипт остановится с ошибкой, а не запишет неполные данные. - Параметры запроса собираются вручную, а значения кодируются через
encodeURIComponent, потому что в фильтре есть пробелы, кавычки и кириллица. - Дата в фильтре записывается как
datetime'2026-10-12T00:00:00', это синтаксис OData. - Ответ — объект с массивом
value, по элементу на документ. - Скрипт очищает столбцы A:E листа «Заказы из 1С» и записывает их заново. Документы старше
DAYSдней с листа уходят. Свои формулы и заметки держите на другом листе или в столбцах правее E.
5. Проверьте и включите расписание
- Нажмите «Запустить»: в журнале появится «Загружено документов: N», на листе — таблица заказов.
- На вкладке «Триггеры» добавьте триггер «По расписанию», например каждый час.
Если что-то не работает
| Симптом | Причина | Что сделать |
|---|---|---|
| Http.fetch: запросы на внутренние адреса запрещены. | адрес 1С во внутренней сети | опубликуйте базу с адресом, доступным из интернета, или используйте способ «1С отправляет в таблицу» |
| Http.fetch: порт … запрещён. | веб-сервер 1С на порту ниже 1024, кроме 80 и 443 | перенесите публикацию на порт 443 или выше 1024 |
| Http.fetch: сертификат сервера не прошёл проверку. | у публикации самоподписанный сертификат | установите сертификат, выданный центром сертификации |
| Http.fetch: сервер не ответил вовремя. | 1С не ответила за 15 секунд | уменьшите PAGE, DAYS или число реквизитов в $select |
| Http.fetch: ответ больше 2097152 байт. | ответ 1С больше 2 МБ | уменьшите PAGE или число реквизитов |
| 1С ответила с кодом 401 | неверный логин или пароль, или у пользователя нет прав на объект | проверьте секреты, роль пользователя и состав объектов OData |
| 1С ответила с кодом 404 или 400 | неверное имя объекта или реквизита | сверьте имена со списком, который возвращает адрес интерфейса |
| в 1С ошибка «Coverse ответил 403» или 404 | адрес 1С не разрешён в триггере или неверный путь вебхука | см. таблицу Что отвечает Coverse |
| в журнале «Тело запроса не JSON» | 1С отправила тело с меткой BOM или не в JSON | отправляйте тело через УстановитьТелоИзСтроки с ИспользованиеByteOrderMark.НеИспользовать |
| дата пустая | 1С передала дату в другом формате | передавайте дату как в примере: ФорматДатыJSON.ISO, ВариантЗаписиДатыJSON.ЛокальнаяДата |
Частые вопросы
Можно ли связать таблицу с 1С без своего сервера?
Да. 1С может сама отправлять документы на вебхук скрипта, а скрипт может по расписанию забирать данные из 1С через стандартный интерфейс OData.
Работает ли интеграция с 1С в локальной сети?
Да, если 1С отправляет данные в таблицу: запрос идёт из 1С наружу. Забирать данные из 1С скриптом можно, только если база опубликована с адресом, доступным из интернета.
Подходит ли облачная 1С:Фреш?
Да. В 1С:Фреш стандартный интерфейс OData уже включён, нужно выбрать объекты и создать пользователя для обмена в настройках OData.
Что дальше
- Вебхуки
- Внешние сервисы: все параметры
Http.fetch. - Быстрые и экономные скрипты
- API Coverse Таблиц: запись из 1С напрямую, без скрипта.