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