Разработка и Конфигурация · 11 мин
1С: как передать текущие данные на сервер
Как передать текущие данные формы на сервер в 1С: директивы &НаСервере, контекстный вызов, параметры процедур, типичные ошибки и проверка результата.
В управляемых формах 1С код выполняется в двух средах: на клиенте, где пользователь видит форму и вводит данные, и на сервере, где доступны запросы к базе, проведение документов и тяжёлые вычисления. Под «передачей текущих данных на сервер» обычно понимают отправку значений, введённых пользователем в форму, в серверную процедуру — для сохранения, проверки или расчёта.
Главное, что нужно понять: сервер не «видит» форму и её элементы. Всё, что требуется серверной процедуре, нужно передать явно — через параметры процедуры или через реквизиты формы, если используется контекстный вызов. Попытка обратиться из серверного кода к элементам формы или полям ввода — одна из самых частых ошибок начинающих разработчиков.
Способ передачи зависит от задачи: простые значения (числа, строки, ссылки) передаются параметрами напрямую, данные объекта целиком — через преобразование реквизита формы в прикладной объект, а большие массивы и таблицы — с учётом ограничений платформы. Ниже разобраны все рабочие варианты с примерами кода.
Как устроен клиент-серверный вызов в управляемой форме
Каждая процедура и функция модуля формы помечается директивой компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста или &НаКлиентеНаСервереБезКонтекста. Директива определяет, где код выполняется и какие объекты ему доступны.
Процедура &НаСервере — контекстная: она работает на сервере, но имеет доступ к реквизитам формы. При таком вызове платформа сериализует данные формы, передаёт их на сервер, выполняет код и возвращает изменённую форму обратно. Это удобно, но ресурсоёмко при большом объёме данных.
Процедура &НаСервереБезКонтекста не имеет доступа к данным формы: всё необходимое передаётся только через параметры, а результат — через возвращаемое значение. Такой вызов легче и предпочтительнее, когда не нужно менять саму форму.
Передача простых значений через параметры процедуры
Самый прямой способ — объявить серверную функцию с параметрами и вызвать её из клиентской процедуры. Значения реквизитов формы (числа, строки, даты, ссылки, булево) передаются напрямую.
&НаКлиенте
Процедура РассчитатьСумму(Команда)
Итог = РассчитатьНаСервере(Объект.Количество, Объект.Цена, Объект.СтавкаНДС);
Объект.Сумма = Итог;
КонецПроцедуры
&НаСервереБезКонтекста
Функция РассчитатьНаСервере(Количество, Цена, СтавкаНДС)
Сумма = Количество * Цена;
Возврат Сумма + Сумма * СтавкаНДС / 100;
КонецФункции
Обратите внимание: из клиентской процедуры вызывается серверная функция по имени, как обычная процедура модуля. Платформа сама выполняет серверный вызов. Ссылки на объекты базы (справочники, документы) передаются без ограничений — по ссылке серверный код сможет прочитать любые данные объекта запросом или через объектное обращение.
Не передавайте параметрами сложные клиентские объекты: элементы формы, объекты типа ДанныеФормыСтруктура в серверную процедуру без контекста передать нельзя. Если нужно передать таблицу значений формы — её сначала преобразуют, об этом ниже.
Передача данных объекта целиком: РеквизитФормыВЗначение
Когда на сервере нужно работать с документом или элементом справочника как с прикладным объектом (заполнить табличные части, провести, вызвать типовые обработчики), используют контекстную серверную процедуру и метод РеквизитФормыВЗначение().
&НаКлиенте
Процедура ЗаполнитьТовары(Команда)
ЗаполнитьТоварыНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТоварыНаСервере()
Док = РеквизитФормыВЗначение("Объект");
Док.Товары.Очистить();
// ... заполнение табличной части запросом
ЗначениеВРеквизитФормы(Док, "Объект");
КонецПроцедуры
Здесь "Объект" — имя основного реквизита формы. Метод РеквизитФормыВЗначение создаёт на сервере объект (например, ДокументОбъект), а после изменений ЗначениеВРеквизитФормы возвращает данные обратно в форму. Без обратного преобразования пользователь изменений не увидит.
Передача таблиц и коллекций
Табличная часть формы имеет тип ДанныеФормыКоллекция, и в процедуру &НаСервереБезКонтекста её передать нельзя. Решение — преобразовать её в массив структур или таблицу значений.
&НаКлиенте
Процедура ПроверитьОстатки(Команда)
Строки = Новый Массив;
Для Каждого Стр Из Объект.Товары Цикл
Строки.Добавить(Новый Структура("Номенклатура,Количество",
Стр.Номенклатура, Стр.Количество));
КонецЦикла;
Результат = ПроверитьОстаткиНаСервере(Строки);
КонецПроцедуры
В контекстной серверной процедуре проще: табличная часть доступна через Объект.Товары после преобразования РеквизитФормыВЗначение, либо реквизит формы типа ДанныеФормыКоллекция выгружается методом Выгрузить() в таблицу значений.
Для очень больших объёмов (десятки тысяч строк) сериализация при каждом вызове заметно тормозит форму. В таких случаях данные лучше обрабатывать порциями или перенести операцию в фоновое задание с помещением результата во временное хранилище.
Возврат результата с сервера обратно в форму
Есть три рабочих способа вернуть данные с сервера. Первый — возвращаемое значение функции: подходит для простых типов и массивов структур. Второй — изменение реквизитов формы в контекстной процедуре &НаСервере: после завершения вызова платформа сама синхронизирует форму. Третий — временное хранилище: серверная процедура помещает результат через ПоместитьВоВременноеХранилище() и возвращает адрес, а клиент забирает данные по адресу.
&НаСервереБезКонтекста
Функция ПолучитьДанныеНаСервере(ПараметрыОтбора)
// ... запрос к базе
Возврат ПоместитьВоВременноеХранилище(РезультатТаблица);
КонецФункции
Хранилище особенно удобно, когда результат нужен не сразу или используется в фоновом задании: адрес хранилища формы обычно берут из УникальныйИдентификатор формы, чтобы данные жили, пока открыта форма.
Способы передачи данных на сервер
Подходит для простых значений и ссылок; самый лёгкий вызов, но коллекции формы требуют преобразования.
Подходит для работы с объектом целиком через РеквизитФормыВЗначение; проще код, но тяжелее вызов при больших данных.
Подходит для больших результатов и фоновых заданий; требует контроля времени жизни данных.
Минимизация серверных вызовов и производительность
Каждый серверный вызов — это сетевой обмен. Пять вызовов подряд в цикле будут ощутимо медленнее одного вызова с передачей массива. Поэтому действует простое правило: собирайте все нужные серверу данные на клиенте заранее и вызывайте сервер один раз.
Проверки, не требующие данных базы (заполненность полей, формат введённой строки, арифметика), выполняйте на клиенте — это мгновенно и не нагружает сервер. На сервер выносите только то, что требует доступа к базе, прав серверного контекста или тяжёлых вычислений.
Если операция длительная (загрузка прайса, групповое проведение), используйте механизм длительных операций БСП или фоновые задания, чтобы форма не «зависала» в ожидании ответа сервера.
Как проверить, что данные переданы корректно
Самый надёжный инструмент — отладчик конфигуратора: поставьте точку останова в первой строке серверной процедуры и проверьте значения параметров. Если параметры пустые или имеют неожиданный тип — проблема на клиентской стороне, в момент формирования вызова.
Полезно временно добавить в серверную процедуру запись в журнал регистрации через ЗаписьЖурналаРегистрации() или вывод через Сообщить() — сообщения с сервера доходят до клиента после завершения вызова. Для проверки возврата результата убедитесь, что клиентская процедура получила значение ожидаемого типа: ТипЗнч() помогает быстро локализовать несоответствие.
Как проверить результат
Значения соответствуют данным формы, типы ожидаемые
Параметры неопределены или тип не совпадает — ошибка в клиентском вызове
Изменения видны пользователю сразу после завершения процедуры
На сервере данные изменились, а в форме нет — пропущен ЗначениеВРеквизитФормы
Один серверный вызов на действие пользователя
Десятки вызовов в цикле, заметные паузы
Часто задаваемые вопросы
Чем отличается &НаСервере от &НаСервереБезКонтекста?
Директива &НаСервере даёт доступ к реквизитам и данным формы: платформа передаёт контекст формы на сервер и обратно. &НаСервереБезКонтекста работает изолированно — все данные приходят только через параметры. Бесконтекстный вызов быстрее и предпочтительнее, когда форму менять не нужно.
Можно ли передать на сервер элемент формы, например поле ввода?
Нет. Элементы формы существуют только на клиенте. Передавать нужно не элемент, а связанные с ним данные — значение реквизита формы или объекта, которое элемент отображает.
Как передать табличную часть документа в бесконтекстную серверную функцию?
Преобразуйте её на клиенте в массив структур или на сервере в контекстной процедуре выгрузите методом Выгрузить() в таблицу значений. Сам тип ДанныеФормыКоллекция параметром передать нельзя.
Почему изменения, сделанные на сервере, не видны в форме?
Чаще всего после РеквизитФормыВЗначение забыли вызвать ЗначениеВРеквизитФормы для возврата данных в форму. Реже — изменения вносились в отдельный объект по ссылке, который не связан с реквизитом формы.
Когда стоит выносить операцию в фоновое задание вместо обычного серверного вызова?
Когда операция занимает больше нескольких секунд: загрузка файлов, групповая обработка документов, тяжёлые отчёты. Обычный вызов блокирует форму на всё время выполнения, а фоновое задание позволяет показать индикатор и не мешать пользователю.
Можно ли вызвать серверную процедуру общего модуля из формы?
Да, если у общего модуля установлены флаги «Сервер» и «Вызов сервера». Обращение идёт по имени: ИмяМодуля.ИмяФункции(Параметры). Это стандартный способ вынести серверную логику из формы в переиспользуемый код.
Что важно запомнить
Серверные процедуры получают данные только через параметры или контекст формы. Простые значения передавайте параметрами в &НаСервереБезКонтекста, объект целиком — через РеквизитФормыВЗначение с обязательным обратным преобразованием, коллекции — массивами структур. Объединяйте вызовы и проверяйте результат отладчиком.