К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как передать текущие данные на сервер

Как передать текущие данные формы на сервер в 1С: директивы &НаСервере, контекстный вызов, параметры процедур, типичные ошибки и проверка результата.

В управляемых формах 1С код выполняется в двух средах: на клиенте, где пользователь видит форму и вводит данные, и на сервере, где доступны запросы к базе, проведение документов и тяжёлые вычисления. Под «передачей текущих данных на сервер» обычно понимают отправку значений, введённых пользователем в форму, в серверную процедуру — для сохранения, проверки или расчёта.

Главное, что нужно понять: сервер не «видит» форму и её элементы. Всё, что требуется серверной процедуре, нужно передать явно — через параметры процедуры или через реквизиты формы, если используется контекстный вызов. Попытка обратиться из серверного кода к элементам формы или полям ввода — одна из самых частых ошибок начинающих разработчиков.

Способ передачи зависит от задачи: простые значения (числа, строки, ссылки) передаются параметрами напрямую, данные объекта целиком — через преобразование реквизита формы в прикладной объект, а большие массивы и таблицы — с учётом ограничений платформы. Ниже разобраны все рабочие варианты с примерами кода.

Как устроен клиент-серверный вызов в управляемой форме

Каждая процедура и функция модуля формы помечается директивой компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста или &НаКлиентеНаСервереБезКонтекста. Директива определяет, где код выполняется и какие объекты ему доступны.

Процедура &НаСервере — контекстная: она работает на сервере, но имеет доступ к реквизитам формы. При таком вызове платформа сериализует данные формы, передаёт их на сервер, выполняет код и возвращает изменённую форму обратно. Это удобно, но ресурсоёмко при большом объёме данных.

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

Передача простых значений через параметры процедуры

Самый прямой способ — объявить серверную функцию с параметрами и вызвать её из клиентской процедуры. Значения реквизитов формы (числа, строки, даты, ссылки, булево) передаются напрямую.

&НаКлиенте

Процедура РассчитатьСумму(Команда)

Итог = РассчитатьНаСервере(Объект.Количество, Объект.Цена, Объект.СтавкаНДС);

Объект.Сумма = Итог;

КонецПроцедуры

&НаСервереБезКонтекста

Функция РассчитатьНаСервере(Количество, Цена, СтавкаНДС)

Сумма = Количество * Цена;

Возврат Сумма + Сумма * СтавкаНДС / 100;

КонецФункции

Обратите внимание: из клиентской процедуры вызывается серверная функция по имени, как обычная процедура модуля. Платформа сама выполняет серверный вызов. Ссылки на объекты базы (справочники, документы) передаются без ограничений — по ссылке серверный код сможет прочитать любые данные объекта запросом или через объектное обращение.

Не передавайте параметрами сложные клиентские объекты: элементы формы, объекты типа ДанныеФормыСтруктура в серверную процедуру без контекста передать нельзя. Если нужно передать таблицу значений формы — её сначала преобразуют, об этом ниже.

Передача данных объекта целиком: РеквизитФормыВЗначение

Когда на сервере нужно работать с документом или элементом справочника как с прикладным объектом (заполнить табличные части, провести, вызвать типовые обработчики), используют контекстную серверную процедуру и метод РеквизитФормыВЗначение().

&НаКлиенте

Процедура ЗаполнитьТовары(Команда)

ЗаполнитьТоварыНаСервере();

КонецПроцедуры

&НаСервере

Процедура ЗаполнитьТоварыНаСервере()

Док = РеквизитФормыВЗначение("Объект");

Док.Товары.Очистить();

// ... заполнение табличной части запросом

ЗначениеВРеквизитФормы(Док, "Объект");

КонецПроцедуры

Здесь "Объект" — имя основного реквизита формы. Метод РеквизитФормыВЗначение создаёт на сервере объект (например, ДокументОбъект), а после изменений ЗначениеВРеквизитФормы возвращает данные обратно в форму. Без обратного преобразования пользователь изменений не увидит.

Передача таблиц и коллекций

Табличная часть формы имеет тип ДанныеФормыКоллекция, и в процедуру &НаСервереБезКонтекста её передать нельзя. Решение — преобразовать её в массив структур или таблицу значений.

&НаКлиенте

Процедура ПроверитьОстатки(Команда)

Строки = Новый Массив;

Для Каждого Стр Из Объект.Товары Цикл

Строки.Добавить(Новый Структура("Номенклатура,Количество",

Стр.Номенклатура, Стр.Количество));

КонецЦикла;

Результат = ПроверитьОстаткиНаСервере(Строки);

КонецПроцедуры

В контекстной серверной процедуре проще: табличная часть доступна через Объект.Товары после преобразования РеквизитФормыВЗначение, либо реквизит формы типа ДанныеФормыКоллекция выгружается методом Выгрузить() в таблицу значений.

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

Возврат результата с сервера обратно в форму

Есть три рабочих способа вернуть данные с сервера. Первый — возвращаемое значение функции: подходит для простых типов и массивов структур. Второй — изменение реквизитов формы в контекстной процедуре &НаСервере: после завершения вызова платформа сама синхронизирует форму. Третий — временное хранилище: серверная процедура помещает результат через ПоместитьВоВременноеХранилище() и возвращает адрес, а клиент забирает данные по адресу.

&НаСервереБезКонтекста

Функция ПолучитьДанныеНаСервере(ПараметрыОтбора)

// ... запрос к базе

Возврат ПоместитьВоВременноеХранилище(РезультатТаблица);

КонецФункции

Хранилище особенно удобно, когда результат нужен не сразу или используется в фоновом задании: адрес хранилища формы обычно берут из УникальныйИдентификатор формы, чтобы данные жили, пока открыта форма.

Способы передачи данных на сервер

Параметры процедуры &НаСервереБезКонтекста

Подходит для простых значений и ссылок; самый лёгкий вызов, но коллекции формы требуют преобразования.

Контекстный вызов &НаСервере

Подходит для работы с объектом целиком через РеквизитФормыВЗначение; проще код, но тяжелее вызов при больших данных.

Временное хранилище

Подходит для больших результатов и фоновых заданий; требует контроля времени жизни данных.

Минимизация серверных вызовов и производительность

Каждый серверный вызов — это сетевой обмен. Пять вызовов подряд в цикле будут ощутимо медленнее одного вызова с передачей массива. Поэтому действует простое правило: собирайте все нужные серверу данные на клиенте заранее и вызывайте сервер один раз.

Проверки, не требующие данных базы (заполненность полей, формат введённой строки, арифметика), выполняйте на клиенте — это мгновенно и не нагружает сервер. На сервер выносите только то, что требует доступа к базе, прав серверного контекста или тяжёлых вычислений.

Если операция длительная (загрузка прайса, групповое проведение), используйте механизм длительных операций БСП или фоновые задания, чтобы форма не «зависала» в ожидании ответа сервера.

Типичные ошибки
01
Обращение к элементам формы из &НаСервереБезКонтекста — код падает с ошибкой, потому что сервер не видит форму.
02
Передача ДанныеФормыКоллекция параметром в бесконтекстную процедуру — тип не сериализуется, вызов завершается ошибкой.
03
Забытый ЗначениеВРеквизитФормы после РеквизитФормыВЗначение — изменения есть на сервере, но пользователь их не видит.
04
Серверный вызов в цикле по строкам вместо одного вызова с массивом — форма работает медленно.
05
Возврат ТаблицыЗначений в клиентскую процедуру тонкого клиента — тип недоступен на клиенте.

Как проверить, что данные переданы корректно

Самый надёжный инструмент — отладчик конфигуратора: поставьте точку останова в первой строке серверной процедуры и проверьте значения параметров. Если параметры пустые или имеют неожиданный тип — проблема на клиентской стороне, в момент формирования вызова.

Полезно временно добавить в серверную процедуру запись в журнал регистрации через ЗаписьЖурналаРегистрации() или вывод через Сообщить() — сообщения с сервера доходят до клиента после завершения вызова. Для проверки возврата результата убедитесь, что клиентская процедура получила значение ожидаемого типа: ТипЗнч() помогает быстро локализовать несоответствие.

Контрольные точки

Как проверить результат

Параметры в отладчике на входе в серверную процедуру
Норма

Значения соответствуют данным формы, типы ожидаемые

Тревожный признак

Параметры неопределены или тип не совпадает — ошибка в клиентском вызове

Данные формы после контекстного вызова
Норма

Изменения видны пользователю сразу после завершения процедуры

Тревожный признак

На сервере данные изменились, а в форме нет — пропущен ЗначениеВРеквизитФормы

Скорость работы формы
Норма

Один серверный вызов на действие пользователя

Тревожный признак

Десятки вызовов в цикле, заметные паузы

Часто задаваемые вопросы

Чем отличается &НаСервере от &НаСервереБезКонтекста?

Директива &НаСервере даёт доступ к реквизитам и данным формы: платформа передаёт контекст формы на сервер и обратно. &НаСервереБезКонтекста работает изолированно — все данные приходят только через параметры. Бесконтекстный вызов быстрее и предпочтительнее, когда форму менять не нужно.

Можно ли передать на сервер элемент формы, например поле ввода?

Нет. Элементы формы существуют только на клиенте. Передавать нужно не элемент, а связанные с ним данные — значение реквизита формы или объекта, которое элемент отображает.

Как передать табличную часть документа в бесконтекстную серверную функцию?

Преобразуйте её на клиенте в массив структур или на сервере в контекстной процедуре выгрузите методом Выгрузить() в таблицу значений. Сам тип ДанныеФормыКоллекция параметром передать нельзя.

Почему изменения, сделанные на сервере, не видны в форме?

Чаще всего после РеквизитФормыВЗначение забыли вызвать ЗначениеВРеквизитФормы для возврата данных в форму. Реже — изменения вносились в отдельный объект по ссылке, который не связан с реквизитом формы.

Когда стоит выносить операцию в фоновое задание вместо обычного серверного вызова?

Когда операция занимает больше нескольких секунд: загрузка файлов, групповая обработка документов, тяжёлые отчёты. Обычный вызов блокирует форму на всё время выполнения, а фоновое задание позволяет показать индикатор и не мешать пользователю.

Можно ли вызвать серверную процедуру общего модуля из формы?

Да, если у общего модуля установлены флаги «Сервер» и «Вызов сервера». Обращение идёт по имени: ИмяМодуля.ИмяФункции(Параметры). Это стандартный способ вынести серверную логику из формы в переиспользуемый код.

Итог

Что важно запомнить

Серверные процедуры получают данные только через параметры или контекст формы. Простые значения передавайте параметрами в &НаСервереБезКонтекста, объект целиком — через РеквизитФормыВЗначение с обязательным обратным преобразованием, коллекции — массивами структур. Объединяйте вызовы и проверяйте результат отладчиком.