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

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

Как получить реквизиты формы на сервере 1С

Как получить реквизиты формы на сервере 1С: РеквизитФормыВЗначение, ДанныеФормыВЗначение, контекст сервера, типичные ошибки и примеры кода.

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

Ключевые инструменты для этого — методы РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы(), а также работа с коллекцией Элементы и реквизитами формы через ЭтаФорма. Неправильное использование этих механизмов приводит к ошибкам «Объект не найден», потере данных формы или лишним серверным вызовам.

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

Как устроены данные формы и почему нельзя обратиться к объекту напрямую

В управляемой форме данные хранятся не как прикладные объекты, а как специальные типы данных формы: ДанныеФормыСтруктура, ДанныеФормыКоллекция, ДанныеФормыДерево. Это сделано для сериализации данных между клиентом и сервером. Пока данные находятся в формате формы, с ними нельзя работать методами прикладных объектов — например, вызвать Записать() или обратиться к менеджеру объекта.

На клиенте в серверном контексте недоступны даже сами типы прикладных объектов. Поэтому любая операция, требующая записи в базу, запроса или вызова объектных методов, выполняется в процедуре с директивой &НаСервере, куда данные передаются из формы.

Получение основного реквизита формы через РеквизитФормыВЗначение

У формы документа, справочника или задачи основной реквизит обычно называется «Объект». Чтобы получить настоящий прикладной объект на сервере, используется метод формы РеквизитФормыВЗначение():

&НаСервере

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

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

ДокОбъект.Комментарий = "Заполнен программно";

ДокОбъект.Записать();

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

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

Обратите внимание на пару методов: РеквизитФормыВЗначение() преобразует данные формы в прикладной объект, а ЗначениеВРеквизитФормы() выполняет обратное преобразование. Если после изменений не вернуть объект в форму, пользователь не увидит обновлённые данные на экране, хотя в базе они сохранятся.

Метод РеквизитФормыВЗначение() работает только в серверном контексте формы. Вызов его на клиенте приведёт к ошибке компиляции или выполнения, потому что типы прикладных объектов там недоступны.

Чтение простых реквизитов формы без преобразования

Если реквизит формы имеет примитивный тип (строка, число, дата, булево) или является ссылкой, преобразование не требуется — значение читается напрямую на сервере через ЭтаФорма:

&НаСервере

Процедура РассчитатьНаСервере()

Ставка = ЭтаФорма.СтавкаНДС; // число

Контрагент = ЭтаФорма.Контрагент; // ссылка

Итог = ЭтаФорма.Объект.СуммаДокумента; // реквизит объекта через данные формы

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

Чтение реквизитов самого объекта (например, ЭтаФорма.Объект.Номер) тоже допустимо без преобразования — платформа обращается к данным формы. Преобразование в объект нужно только тогда, когда требуются объектные методы: Записать(), ПроверитьЗаполнение(), обращение к движениям или модулю объекта.

Ссылки (например, реквизит типа «СправочникСсылка») можно использовать на сервере для запросов и получения объектов через ПолучитьОбъект(). Но помните: получение объекта по ссылке — это обращение к базе данных, и в цикле такие вызовы следует заменять запросом.

Работа с табличными частями и коллекциями формы

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

&НаСервере

Процедура ОбработатьТоварыНаСервере()

ТЗ = ЭтаФорма.Объект.Товары.Выгрузить();

Для Каждого Строка Из ТЗ Цикл

// работа с таблицей значений

КонецЦикла;

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

Если табличная часть является отдельным реквизитом формы типа «ТаблицаЗначений», для преобразования используется тот же механизм: РеквизитФормыВЗначение("ИмяТаблицы") вернёт таблицу значений, а ЗначениеВРеквизитФормы(ТЗ, "ИмяТаблицы") — загрузит её обратно.

Для динамических списков и деревьев значений действуют аналогичные правила, но у дерева есть особенность: после ЗначениеВРеквизитФормы() теряются идентификаторы строк, поэтому позицию текущей строки нужно сохранять заранее и восстанавливать через НайтиПоИдентификатору().

Порядок действий
  1. 1
    Определите, какие данные нужны на сервере: объект целиком, отдельные реквизиты или табличная часть
  2. 2
    Создайте процедуру с директивой &НаСервере
  3. 3
    Получите объект через РеквизитФормыВЗначение("Объект") или прочитайте реквизиты через ЭтаФорма.Имя
  4. 4
    Выполните серверную логику: запись, запрос, расчёт
  5. 5
    Верните изменённый объект через ЗначениеВРеквизитФормы()
  6. 6
    Вызовите серверную процедуру из клиентской и проверьте отображение данных в форме

Вызов сервера из клиента и передача параметров

Клиентская процедура не может напрямую обратиться к объекту, но может вызвать серверную процедуру формы. Данные при этом сериализуются автоматически: весь контекст формы передаётся на сервер и обратно. Чтобы уменьшить трафик, для тяжёлых операций используют процедуры &НаСервереБезКонтекста — туда данные формы не передаются, поэтому и РеквизитФормыВЗначение() там недоступен.

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

Сравнение вариантов

&НаСервере с контекстом

Полный доступ к реквизитам формы и РеквизитФормыВЗначение. Подходит для работы с объектом формы, но передаёт все данные формы по сети.

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

Быстрее и легче, данные передаются параметрами. Нет доступа к реквизитам формы — подходит для независимых расчётов и запросов.

Общий серверный модуль

Централизованная логика, вызывается из любой формы. Данные формы нужно передавать параметрами, объект из формы туда не передаётся.

Типичные ошибки и их диагностика

Самая частая ошибка — попытка вызвать РеквизитФормыВЗначение() на клиенте или в процедуре &НаСервереБезКонтекста. В первом случае компилятор сообщит о недоступности метода, во втором возникнет ошибка выполнения, так как у формы без контекста нет реквизитов.

Вторая распространённая проблема — изменение объекта без обратного преобразования. Разработчик получает объект, меняет его, записывает, но забывает ЗначениеВРеквизитФормы(). Итог: в базе данные новые, на экране — старые, а при повторной записи из формы свежие изменения затираются старой версией объекта.

Третья группа ошибок связана с именами реквизитов: метод принимает строковое имя, и опечатка обнаруживается только в runtime. Для основного реквизита имя можно узнать в редакторе формы — в панели реквизитов у основного реквизита стоит признак «Основной».

Типичные ошибки
01
Вызов РеквизитФормыВЗначение на клиенте — ошибка компиляции, метод доступен только на сервере
02
Изменение объекта без ЗначениеВРеквизитФормы — форма показывает устаревшие данные и затирает изменения при записи
03
Опечатка в строковом имени реквизита — ошибка выполнения «Реквизит не найден» только в момент вызова
04
Многократное преобразование объекта в цикле — резкое падение производительности из-за полного копирования данных
05
Использование серверного вызова с контекстом ради одного значения — лишняя передача всей формы по сети

Проверка результата и отладка

Чтобы убедиться, что данные получены корректно, используйте отладчик: поставьте точку останова в серверной процедуре и проверьте тип полученного значения. После РеквизитФормыВЗначение("Объект") в табло должно отображаться, например, «ДокументОбъект.РеализацияТоваровУслуг», а не «ДанныеФормыСтруктура».

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

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

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

Тип значения после преобразования
Норма

ДокументОбъект или СправочникОбъект

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

ДанныеФормыСтруктура — преобразование не выполнено

Ссылка полученного объекта
Норма

Совпадает со ссылкой редактируемого элемента

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

Пустая ссылка у существующего объекта

Отображение после изменений
Норма

Форма показывает обновлённые данные

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

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

FAQ

Можно ли получить реквизиты формы в процедуре &НаСервереБезКонтекста?

Нет. В такой процедуре контекст формы недоступен, поэтому ни ЭтаФорма, ни РеквизитФормыВЗначение использовать нельзя. Передайте нужные значения параметрами — ссылки, структуры или примитивные типы.

Чем РеквизитФормыВЗначение отличается от ДанныеФормыВЗначение?

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

Почему после изменения объекта на сервере форма показывает старые данные?

Потому что пропущен обратный вызов ЗначениеВРеквизитФормы(Объект, "Объект"). Преобразование в объект создаёт копию данных, и изменения копии автоматически в форму не возвращаются.

Как получить значение реквизита формы, созданного программно?

Так же, как обычного: через ЭтаФорма.ИмяРеквизита. Программно добавленные реквизиты (метод ИзменитьРеквизиты) ничем не отличаются от созданных в конфигураторе, главное — обращаться по точному имени, заданному при добавлении.

Что делать, если объект большой и серверный вызов работает медленно?

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

Итог

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

Основной объект формы на сервере получают через РеквизитФормыВЗначение("Объект"), простые реквизиты читают через ЭтаФорма напрямую. После изменений обязательно возвращайте объект в форму методом ЗначениеВРеквизитФормы. Для лёгких операций без доступа к форме используйте процедуры &НаСервереБезКонтекста с передачей данных параметрами.