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