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

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

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

Разбираем способы записи значения в реквизит формы 1С: обращение через ЭтаФорма, ДанныеФормыВЗначение, работа с реквизитами объекта и табличными частями, типичные ошибки.

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

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

Ниже разобраны рабочие способы записи значений: прямое присваивание в модуле формы, запись в реквизит объекта через «Объект», серверные процедуры с преобразованием ДанныеФормыВЗначение, работа с табличными частями и обращение к форме извне. Для каждого способа указаны условия применения и ограничения.

Различие реквизита формы и реквизита объекта

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

Обращение к реквизиту формы выполняется просто по имени: КонтрагентОтбор = Справочники.Контрагенты.НайтиПоКоду("0001");. Обращение к реквизиту объекта — через точку от основного реквизита: Объект.Комментарий = "Создано обработкой";. Если перепутать и написать Комментарий = "..." для реквизита документа, платформа выдаст ошибку, потому что такого реквизита у формы нет.

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

Прямое присваивание в модуле формы

Базовый способ — присваивание в клиентской или серверной процедуре модуля формы. Значение должно соответствовать типу реквизита, объявленному в редакторе формы. Если реквизит имеет тип «СправочникСсылка.Номенклатура», присвоить ему строку нельзя — нужна ссылка.

Пример клиентской процедуры:

&НаКлиенте

Процедура ЗаполнитьДанные(Команда)

ДатаОтчета = ТекущаяДата();

КоличествоСтрок = Товары.Количество();

ПризнакГотовности = Истина;

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

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

Запись в реквизит объекта через «Объект»

На управляемой форме документа или справочника запись в реквизит объекта выглядит так:

&НаКлиенте

Процедура УстановитьКомментарий(Команда)

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

Объект.Ответственный = ПолучитьТекущегоПользователя();

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

Присвоение значения реквизиту объекта не сохраняет его в базе. Данные попадут в базу только после записи объекта — кнопкой «Записать», «Провести» или программным вызовом Записать(). До этого момента значение существует только в данных формы, и при закрытии формы без записи оно будет потеряно.

Если нужно вызвать метод объекта (например, Заполнить() или проверить заполнение программно), на сервере данные формы преобразуют в объект:

&НаСервере

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

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

ДокОбъект.Заполнить(Неопределено);

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

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

Забытый обратный вызов ЗначениеВРеквизитФормы — частая причина ситуации, когда «в коде всё заполнилось, а на форме пусто». Преобразование работает в обе стороны, и обе строки обязательны.

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

Запись в табличную часть и таблицу значений на форме

Табличная часть объекта доступна через Объект.ИмяТабличнойЧасти. Добавление строки и запись значений в её колонки:

НоваяСтрока = Объект.Товары.Добавить();

НоваяСтрока.Номенклатура = НайденнаяСсылка;

НоваяСтрока.Количество = 2;

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

Для изменения существующей строки используйте индекс или поиск: Объект.Товары[0].Цена = 100;. Помните, что индексация начинается с нуля, а обращение по несуществующему индексу вызовет ошибку — перед записью проверяйте количество строк.

Запись значения из другой формы или извне

Обратиться к реквизиту чужой формы напрямую можно, только имея на неё ссылку. Типовые сценарии: форма открыта с параметрами, форма-владелец, оповещение о выборе. Самый управляемый способ — передать значение через параметры при открытии и обработать его в ПриСозданииНаСервере или ПриОткрытии:

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Свойство("Контрагент") Тогда

ОтборКонтрагент = Параметры.Контрагент;

КонецЕсли;

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

Если форма уже открыта и нужно передать значение в неё из другой формы, используйте Оповестить() с обработчиком ОбработкаОповещения на принимающей стороне. Прямое обращение вида ФормаДокумента.Объект.Комментарий = "..." технически возможно, если ссылка на форму получена, но такой код хрупок: он ломается при закрытии формы и затрудняет сопровождение.

Сравнение способов передачи значения в форму

Параметры при открытии

Подходит для новой формы; значение известно заранее. Не работает для уже открытой формы.

Оповестить / ОбработкаОповещения

Подходит для уже открытых форм и подбора. Требует аккуратной проверки имени события.

Прямое обращение к форме

Быстро, но хрупко: ломается при закрытии формы, усложняет поддержку. Использовать в крайнем случае.

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

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

Вторая группа проблем — контекст выполнения. Код в процедуре &НаКлиенте пытается выполнить запрос к базе, или процедура &НаСервереБезКонтекста обращается к реквизиту формы. В обоих случаях решение — изменить директиву или перенести логику: получить данные на сервере с контекстом, записать в реквизит, а клиенту оставить только отображение.

Третья типичная ситуация — значение присваивается, но на форме не отображается. Причины: элемент формы не связан с реквизитом (проверьте свойство «ПутьКДанным» у элемента), значение присвоено локальной переменной с тем же именем, а не реквизиту, либо после РеквизитФормыВЗначение не выполнен обратный ЗначениеВРеквизитФормы.

Типичные ошибки
01
Обращение к реквизиту документа без префикса Объект. — ошибка «Поле объекта не обнаружено»
02
Забытый ЗначениеВРеквизитФормы после изменений на сервере — форма остаётся со старыми данными
03
Присваивание значения несовместимого типа — ошибка преобразования или пустое поле
04
Использование &БезКонтекста при необходимости писать в реквизиты формы — реквизиты недоступны
05
Запись в Объект без последующего Записать() — данные теряются при закрытии формы

Проверка результата и ограничения

После записи убедитесь, что значение реально попало в реквизит: выведите его через Сообщить() или проверьте в отладчике, поставив точку останова после присваивания. Для реквизитов объекта дополнительно проверьте запись в базе: откройте объект заново после Записать() и убедитесь, что значение сохранилось.

Учитывайте ограничения платформы: реквизиты формы недоступны вне контекста формы, сериализация данных формы при серверных вызовах имеет накладные расходы (не тащите на сервер огромные таблицы без необходимости), а обращение к элементам формы возможно только на клиенте. Запись значений выполняйте в данных, а не в элементах формы — элемент только отображает реквизит.

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

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

Значение в реквизите формы
Норма

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

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

Значение Неопределено или старое — присваивание не выполнилось

Отображение на форме
Норма

Поле ввода показывает новое значение

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

Поле пустое — проверьте ПутьКДанным элемента

Сохранение в базе
Норма

После Записать() и повторного открытия значение на месте

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

Значение пропало — запись объекта не выполнялась

Итог

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

Реквизит формы заполняется прямым присваиванием по имени, реквизит объекта — через Объект.Имя. На сервере для методов объекта используйте пару РеквизитФормыВЗначение / ЗначениеВРеквизитФормы. Значение попадёт в базу только после Записать(), а извне данные в форму передавайте через параметры или оповещения.

Частые вопросы

Почему возникает ошибка «Поле объекта не обнаружено» при записи?

Чаще всего имя указано неверно или реквизит относится не к тому уровню. Если это реквизит документа, обращайтесь через Объект.ИмяРеквизита. Если реквизит формы — проверьте, что он добавлен в редакторе формы и имя в коде совпадает с именем в дереве реквизитов с точностью до символа.

Можно ли записать значение в реквизит формы из общего модуля?

Напрямую — нет, общий модуль не имеет контекста формы. Передайте форму или нужные данные параметром в процедуру общего модуля, получите вычисленное значение обратно и присвойте его реквизиту уже в модуле формы.

Почему значение присвоено, но поле на форме пустое?

Проверьте свойство «ПутьКДанным» у элемента формы — оно должно указывать на ваш реквизит. Также убедитесь, что присваивание выполнилось до отображения и что после серверного преобразования РеквизитФормыВЗначение выполнен обратный ЗначениеВРеквизитФормы.

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

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

Как записать значение в реквизит формы списка?

У динамического списка нет редактируемых реквизитов строк — изменять нужно данные самих объектов через запись в базу. Реквизиты формы списка (отборы, параметры) заполняются обычным присваиванием в модуле формы, а для отбора списка удобнее использовать ЭлементыОтбора или параметры компоновки данных.

Сохранится ли значение реквизита формы после закрытия?

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