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