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