Передача данных из клиентского кода и внешних программ на сервер 1С:Предприятия
Содержание
Чтобы передать параметр с клиента на сервер 1С, вызовите из клиентской процедуры серверную процедуру формы (&НаСервере или &НаСервереБезКонтекста) либо экспортную функцию общего модуля с флагом «Вызов сервера» и передайте значение аргументом. Платформа сама сериализует его и доставит на сервер. Ограничение одно: тип значения должен быть доступен и на клиенте, и на сервере.
Если же «клиент» — это внешняя программа, сайт или другая база, параметры передают через HTTP-сервис, COM-соединение или веб-сервис SOAP. Ниже — оба уровня: код внутри конфигурации и интеграция снаружи, с рабочими примерами на встроенном языке.
Вызов сервера из клиентского кода: директивы и правила передачи
В управляемой форме каждая процедура помечается директивой компиляции. От неё зависит, где выполняется код и что уходит на сервер вместе с вызовом.
| Директива | Где выполняется | Что передаётся на сервер |
|---|---|---|
&НаКлиенте | на клиенте | ничего |
&НаСервере | на сервере | параметры + все данные формы |
&НаСервереБезКонтекста | на сервере | только параметры |
&НаКлиентеНаСервереБезКонтекста | там, откуда вызвана | без вызова сервера |
Разница между &НаСервере и &НаСервереБезКонтекста ощутима. При контекстном вызове туда и обратно гоняются реквизиты формы, включая табличные части документа на 500 строк. Если серверу нужен только ИНН, берите вызов без контекста.
Пример: найти контрагента по ИНН из поля формы
На форме есть строковый реквизит ИННДляПоиска и команда «Найти». Клиент передаёт строку, сервер возвращает ссылку.
&НаКлиенте
Процедура НайтиПоИНН(Команда)
Контрагент = НайтиКонтрагентаНаСервере(ИННДляПоиска);
Если ЗначениеЗаполнено(Контрагент) Тогда
Объект.Контрагент = Контрагент;
Иначе
Сообщить("Контрагент с ИНН " + ИННДляПоиска + " не найден");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция НайтиКонтрагентаНаСервере(Знач ИНН)
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ИНН = &ИНН");
Запрос.УстановитьПараметр("ИНН", СокрЛП(ИНН));
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Справочники.Контрагенты.ПустаяСсылка();
КонецФункции
Зачем писать Знач
Параметр серверного вызова без Знач работает как передача по ссылке: если сервер изменит его, новое значение вернётся на клиент. Платформа ради этого сериализует параметр второй раз, на обратном пути.
💡 Ставьте Знач перед каждым параметром, который сервер только читает. Это бесплатная экономия трафика, особенно для структур и массивов.
Какие типы можно передать
Сервер и клиент обмениваются только сериализуемыми значениями. Ориентир такой:
- ✅ Можно: Строка, Число, Дата, Булево, Неопределено, Null, ссылки на объекты базы, перечисления,
Структура,Массив,Соответствие, их фиксированные варианты,УникальныйИдентификатор,ДвоичныеДанные,ТабличныйДокумент,ХранилищеЗначения. - ❌ Нельзя:
ТаблицаЗначений,ДеревоЗначений,Запрос, объекты (СправочникОбъект,ДокументОбъект), менеджеры записей,ОписаниеОповещения.
Коллекции допустимы, только если всё внутри них тоже допустимо. Структура со вложенной таблицей значений на сервер не уйдёт.
Таблицу значений с сервера на клиент возвращают одним из трёх путей:
- Складывают в реквизит формы с типом «ТаблицаЗначений» через
ЗначениеВРеквизитФормы()и вызывают процедуру&НаСервере. - Превращают в массив структур, по одной на строку.
- Кладут во временное хранилище и передают на клиент только адрес.
Параметры формы и временное хранилище
Передать значение при открытии формы
Самый частый случай: клиент открывает форму и передаёт ей значения, а форма читает их уже на сервере, в ПриСозданииНаСервере.
&НаКлиенте
Процедура ОткрытьПодбор(Команда)
ПараметрыФормы = Новый Структура("Склад, Дата", Объект.Склад, Объект.Дата);
ОткрытьФорму("Обработка.ПодборТоваров.Форма.Форма", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры
В открываемой форме:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Склад") Тогда
Склад = Параметры.Склад;
КонецЕсли;
КонецПроцедуры
Параметры объявите на закладке «Параметры» редактора формы, с типами. Необъявленные значения доступны только внутри ПриСозданииНаСервере, и опечатку в имени никто не подсветит.
⚠️ Не называйте локальную переменную Параметры в модуле формы: это имя уже занято свойством самой формы.
Большие данные — через временное хранилище
Файл на 20 МБ или табличный документ на тысячи строк неудобно таскать параметром при каждом вызове. Для этого есть временное хранилище:
- На стороне, где данные появились, вызовите
ПоместитьВоВременноеХранилище(Значение, УникальныйИдентификатор). Второй аргумент — идентификатор формы, тогда хранилище очистится при её закрытии. - Получите строку-адрес и передайте её параметром.
- На другой стороне прочитайте значение:
ПолучитьИзВременногоХранилища(Адрес).
Адрес — короткая строка, поэтому повторные вызовы сервера остаются лёгкими. Тем же способом возвращают результат фонового задания: задание кладёт итог в хранилище, форма опрашивает его по адресу.
Тонкий и веб-клиент: что учесть при передаче
Тонкий клиент и веб-клиент выполняют клиентский код по одним правилам, но окружение у них разное.
- 🌐 Веб-клиент не создаёт
COMОбъекти не работает с локальными файлами напрямую. Файлы пользователя сначала помещают на сервер через диалог выбора и временное хранилище. - 🔁 Каждый вызов сервера — это сетевой запрос. В локальной сети тонкий клиент переживёт десяток лишних вызовов. Через интернет и в веб-клиенте каждый добавит заметную задержку.
- 🪟 Модальные окна в веб-клиенте ограничены. Результат диалога передают дальше через
ОписаниеОповещенияс дополнительными параметрами, а не через возвращаемое значение.
Пример передачи контекста в обработчик оповещения:
&НаКлиенте
Процедура УдалитьСтроку(Команда)
ДопПараметры = Новый Структура("ИдентификаторСтроки", Элементы.Товары.ТекущаяСтрока);
Оповещение = Новый ОписаниеОповещения("УдалитьСтрокуЗавершение", ЭтотОбъект, ДопПараметры);
ПоказатьВопрос(Оповещение, "Удалить строку?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура УдалитьСтрокуЗавершение(Ответ, ДопПараметры) Экспорт
Если Ответ = КодВозвратаДиалога.Да Тогда
Строка = Объект.Товары.НайтиПоИдентификатору(ДопПараметры.ИдентификаторСтроки);
Объект.Товары.Удалить(Строка);
КонецЕсли;
КонецПроцедуры
Модуль управляемого приложения и общие клиентские модули не имеют своего «сервера». Оттуда сервер вызывают через общий модуль с флагами «Сервер» и «Вызов сервера».
HTTP-сервис: как передать параметры на сервер 1С из любой программы
Когда данные шлёт сайт, мобильное приложение или скрипт на Python, удобнее всего HTTP-сервис. Он создаётся в ветке Общие → HTTP-сервисы конфигуратора, публикуется на веб-сервере и доступен по адресу вида https://сервер/база/hs/корневойURL/....
Три места, где лежат параметры
| Где | Пример запроса | Как прочитать в 1С |
|---|---|---|
Часть пути по шаблону /orders/{number} | /hs/api/orders/123 | Запрос.ПараметрыURL.Получить("number") |
| Строка запроса | ?format=short | Запрос.ПараметрыЗапроса.Получить("format") |
| Тело запроса (JSON, XML) | POST с {"inn":"..."} | Запрос.ПолучитьТелоКакСтроку() |
| Заголовки | X-Request-Id: ... | Запрос.Заголовки.Получить("X-Request-Id") |
Для POST с JSON обработчик выглядит так:
Функция ЗаказыPOST(Запрос)
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
Данные = ПрочитатьJSON(Чтение, Истина); // Истина — читать в Соответствие
Чтение.Закрыть();
Если ТипЗнч(Данные) <> Тип("Соответствие") Или Данные.Получить("inn") = Неопределено Тогда
Ответ = Новый HTTPСервисОтвет(400);
Ответ.УстановитьТелоИзСтроки("Не передан параметр inn");
Возврат Ответ;
КонецЕсли;
// ... обработка Данные.Получить("inn")
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки("{""result"":""ok""}");
Возврат Ответ;
КонецФункции
Вызов из другой базы 1С
Соединение = Новый HTTPСоединение("srv1c.local", 443, "api", "Пароль", , 30,
Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/trade/hs/api/orders");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки("{""inn"":""7701234567""}",
КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
ВызватьИсключение "Сервер вернул " + Формат(Ответ.КодСостояния, "ЧГ=0");
КонецЕсли;
Код выполняйте на сервере. Таймаут (здесь 30 секунд) задавайте всегда, иначе зависший сервис подвесит и вызывающий сеанс.
COM-соединение: параметры из Windows-программы
COM-соединение подходит, когда на той же Windows-машине работает другая программа: Excel, скрипт, вторая база 1С. Клиент подключается через компонент V83.COMConnector и вызывает экспортные функции общих модулей, у которых стоит флаг «Внешнее соединение».
Коннектор = Новый COMОбъект("V83.COMConnector");
База = Коннектор.Connect("Srvr=""srv1c"";Ref=""trade"";Usr=""Обмен"";Pwd=""***"";");
Остаток = База.ОбменДанными.ОстатокТовара("00-000123", ТекущаяДата());
Строки, числа, даты и булевы значения уходят как есть. Структуру или массив нужно создать уже в той базе: Параметры = База.NewObject("Структура").
Приёмы, которые экономят время:
- 📦 Передавайте строку, а не объект. Каждое обращение к свойству COM-объекта — межпроцессный вызов. Сериализуйте данные в JSON или XML, отправьте одной строкой и разберите на стороне базы.
- 🧩 Разрядность совпадает. 64-разрядная программа видит только 64-разрядный
comcntr.dll. Компонент регистрируют командойregsvr32из папкиbinнужной версии платформы, от администратора. - 🔢 Версия платформы. Номер
comcntr.dllдолжен совпадать с номером платформы сервера 1С, иначе соединение не установится.
COM работает только под Windows и только из толстого или тонкого клиента либо с сервера. Из веб-клиента и с Linux-сервера этот путь закрыт.
Веб-сервисы SOAP и планы обмена
SOAP: параметры со строгими типами
Веб-сервис описывают в ветке Общие → Веб-сервисы. У каждой операции есть список параметров с типами (xs:string, xs:decimal, xs:dateTime или типы из пакета XDTO). После публикации описание доступно по адресу .../ws/имя.1cws?wsdl.
Вызов из другой базы:
Определения = Новый WSОпределения("https://srv/trade/ws/orders.1cws?wsdl", "api", "Пароль");
Прокси = Новый WSПрокси(Определения, "http://example.org/orders", "Orders", "OrdersSoap");
Прокси.Пользователь = "api";
Прокси.Пароль = "Пароль";
Результат = Прокси.CreateOrder("7701234567", 15000);
Второй, третий и четвёртый аргументы WSПрокси — пространство имён, имя сервиса и имя точки подключения. Берите их из WSDL, а не угадывайте.
SOAP выбирают, когда второй стороне нужен формальный контракт и проверка типов. Для простых интеграций HTTP-сервис с JSON проще в отладке.
Планы обмена: когда нужен не параметр, а поток изменений
Если задача — регулярно передавать изменения справочников и документов, отдельные параметры не подходят. План обмена регистрирует изменения по узлам, а сообщение обмена несёт их пакетом в XML.
«Параметры» обмена хранят в реквизитах узла плана обмена: организацию, склад, дату начала синхронизации. Правила выгрузки читают их и решают, какие данные отправлять.
Внутри одной базы полезен ещё один приём: ДополнительныеСвойства объекта. Флаг, записанный в Объект.ДополнительныеСвойства.Вставить("ЗагрузкаИзОбмена", Истина), доступен в серверных обработчиках ПередЗаписью и ПриЗаписи этого объекта.
Внешние источники данных: параметры для чужой СУБД
Объект Общие → Внешние источники данных даёт серверу 1С прямой доступ к таблицам другой базы через ODBC. Параметры сюда передают двух видов.
Параметры соединения — строка подключения, логин, пароль. Их задают кодом на сервере:
ПараметрыСоединения = Новый ПараметрыСоединенияВнешнегоИсточникаДанных;
ПараметрыСоединения.СтрокаСоединения = "Driver={SQL Server};Server=sql01;Database=crm;";
ПараметрыСоединения.АутентификацияСтандартная = Истина;
ПараметрыСоединения.ИмяПользователя = "reader";
ПараметрыСоединения.Пароль = "***";
ВнешниеИсточникиДанных.CRM.УстановитьОбщиеПараметрыСоединения(ПараметрыСоединения);
ВнешниеИсточникиДанных.CRM.УстановитьСоединение();
Параметры запроса — как в обычном запросе 1С: &Дата, &Клиент, значения через Запрос.УстановитьПараметр(). Не склеивайте текст запроса со строкой от пользователя: параметр защищает от подстановки чужого кода, конкатенация — нет.
Клиентский код к внешнему источнику не обращается. Значение с формы сначала уходит на сервер обычным вызовом, а уже там подставляется в запрос.
Скорость и безопасность передачи параметров
Как не тормозить
- 🎯 Один вызов вместо пяти. Соберите всё нужное в
Структуруи получите ответ за одно обращение к серверу. - 🪶 Без контекста, где можно.
&НаСервереБезКонтекстане тащит форму. - 📎 Знач для входных параметров, адрес временного хранилища для тяжёлых данных.
- 🧹 Не вызывайте сервер в
ПриАктивизацииСтрокибез обработчика ожидания: при прокрутке списка это десятки вызовов в секунду.
Как не открыть дыру
Всё, что пришло с клиента, считайте недоверенным. Пользователь с доступом к отладке или внешней обработкой может вызвать серверную функцию с любыми аргументами.
- Проверяйте права внутри экспортной функции модуля «Вызов сервера»:
ПравоДоступа("Изменение", Метаданные.Документы.Заказ). - Не включайте привилегированный режим для всей функции. Включите его на минимальный участок и выключите сразу после.
- Никогда не передавайте в
Выполнить()иВычислить()строку, пришедшую от клиента или извне. - Для HTTP и SOAP — только HTTPS и отдельный пользователь с минимальной ролью. Пароль не кладите в URL.
- Проверяйте тип и диапазон:
ТипЗнч(Параметр) = Тип("Число"), длину строки, заполненность ссылки.
Частые вопросы
Как передать параметры в фоновое задание?
ФоновыеЗадания.Выполнить("ИмяМодуля.ИмяПроцедуры", МассивПараметров). Процедура должна быть экспортной в серверном общем модуле, а результат удобно вернуть через временное хранилище.Как передать значение параметра в отчёт на СКД?
КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Период", Значение). Имя должно совпадать с параметром схемы.Можно ли изменить параметр сеанса с клиента?
Почему значение параметра на клиенте изменилось после вызова сервера?
Знач, и серверная процедура его изменила. Платформа вернула новое значение обратно. Добавьте Знач, если такое поведение не нужно.