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

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

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

Как программно записать реквизит формы в 1С: ЭтаФорма, Элементы, ПриСозданииНаСервере, ПараметрыФормы. Примеры кода, типичные ошибки и проверка результата.

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

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

В статье разобраны основные приёмы записи реквизитов формы: прямое присваивание, заполнение при открытии через параметры, работа с динамическими списками и таблицами значений на форме, а также типичные ошибки, из-за которых значение «не сохраняется» или форма ведёт себя неожиданно.

Что такое реквизит формы и чем он отличается от реквизита объекта

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

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

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

Прямое присваивание значения реквизиту формы

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

&НаКлиенте

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

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

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

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

Для реквизита объекта через основной реквизит формы синтаксис такой:

&НаСервере

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

Объект.Наименование = "Сформировано обработкой";

Объект.ДатаИзменения = ТекущаяДатаСеанса();

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

После такого присваивания форма помечается как модифицированная, и при закрытии платформа спросит о сохранении. Чтобы зафиксировать данные без участия пользователя, вызовите Записать() в коде формы или ОбъектДанных.Записать() при работе через объектное API.

1c
&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Запись простого реквизита формы
    СтатусОбработки = "Новая";
    // Запись реквизита объекта через основной реквизит формы
    Объект.Ответственный = ПользователиКлиент.ТекущийПользователь();
КонецПроцедуры

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

Частый сценарий — открыть форму и сразу заполнить её реквизиты из вызывающего кода. Для этого используется структура параметров, передаваемая в метод ОткрытьФорму(), и обработчик ПриСозданииНаСервере в открываемой форме.

// В вызывающем коде

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Контрагент", ВыбранныйКонтрагент);

ПараметрыФормы.Вставить("СуммаДокумента", 15000);

ОткрытьФорму("Обработка.ОформлениеЗаявки.Форма.ФормаЗаявки", ПараметрыФормы);

// В форме обработки

&НаСервере

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

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

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

КонецЕсли;

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

СуммаДокумента = Параметры.СуммаДокумента;

КонецЕсли;

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

Обратите внимание на проверку Параметры.Свойство(): без неё обращение к несуществующему параметру вызовет ошибку, если форму открыли другим способом — например, из меню, без параметров. Это стандартная защитная практика.

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

Порядок передачи значения через параметры
  1. 1
    Сформируйте структуру с нужными значениями в вызывающем коде
  2. 2
    Передайте структуру вторым аргументом в ОткрытьФорму()
  3. 3
    В обработчике ПриСозданииНаСервере проверьте наличие параметра через Свойство()
  4. 4
    Присвойте значение реквизиту формы
  5. 5
    Откройте форму и убедитесь, что поля заполнены

Запись реквизита объекта с сохранением в базу данных

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

&НаКлиенте

Процедура ЗаписатьИЗакрыть(Команда)

Объект.Комментарий = КомментарийКОбработке;

Записать();

Закрыть();

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

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

СпрОбъект = СсылкаНаЭлемент.ПолучитьОбъект();

СпрОбъект.Наименование = "Обновлено обработкой";

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

Важное ограничение: если форма элемента уже открыта у пользователя, а вы изменили объект программно через ПолучитьОбъект(), в открытой форме останутся старые данные, и при её записи ваши изменения будут перезаписаны. Координируйте такие операции: либо закрывайте формы, либо используйте ЗаблокироватьДанныеДляРедактирования().

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

Табличная часть объекта на форме доступна как коллекция: Объект.Товары. Записать в неё данные программно означает добавить или изменить строки:

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

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

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

НоваяСтрока.Цена = 500;

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

&НаСервере

Процедура ЗагрузитьТаблицуНаСервере()

ТЗ = ПолучитьТаблицуИзЗапроса(); // произвольный источник

ЗначениеВРеквизитФормы(ТЗ, "ТаблицаРезультатов");

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

Обратное преобразование выполняется методом РеквизитФормыВЗначение(). Эта пара методов — стандартный способ обмена данными между серверными процедурами и реквизитами формы сложных типов.

Программное добавление реквизита формы

Иногда реквизит нужно создать не в конфигураторе, а в момент выполнения — например, в универсальной обработке, где состав полей заранее неизвестен. Для этого служит метод ИзменитьРеквизиты():

&НаСервере

Процедура ДобавитьРеквизитНаСервере()

Добавляемые = Новый Массив;

Описание = Новый РеквизитФормы("ДинамическоеПоле",

Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100)),

"", "Динамическое поле", Ложь);

Добавляемые.Добавить(Описание);

ИзменитьРеквизиты(Добавляемые);

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

После добавления реквизит доступен по имени как обычный: ДинамическоеПоле = "Значение". Чтобы пользователь его увидел, нужно программно создать и элемент формы через Элементы.Добавить() с указанием пути к данным.

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

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

Большинство проблем при программной записи реквизитов сводится к нескольким повторяющимся сценариям. Знание их экономит часы отладки.

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

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

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

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

Значение на форме
Норма

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

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

Поле пустое или со старым значением — обработчик не выполнился или изменён другой реквизит

Данные в базе
Норма

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

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

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

Модифицированность формы
Норма

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

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

Форма не считает себя изменённой — изменён реквизит формы, а не объекта

FAQ

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

Используйте оповещения: в первой форме вызовите Оповестить("ИмяСобытия", Параметр), а во второй обработайте событие в ОбработкаОповещения() и присвойте значение реквизиту. Альтернатива — получить форму через ПолучитьФорму() с владельцем и обратиться к экспортной процедуре формы.

Почему значение реквизита пропадает при переходе между вкладками формы?

Само по себе переключение вкладок значения не очищает. Чаще причина в том, что реквизит перезаполняется в обработчиках ПриАктивизацииСтраницы или в серверных вызовах, которые пересоздают данные формы. Проверьте, нет ли кода, сбрасывающего значение.

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

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

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

Через параметры передаются только сериализуемые типы. Сложные объекты передают через временное хранилище: поместите значение методом ПоместитьВоВременноеХранилище(), передайте в параметрах адрес, а в ПриСозданииНаСервере извлеките данные по адресу.

Чем отличается ЭтаФорма.Реквизит от простого обращения по имени?

В большинстве случаев оба варианта работают одинаково — обращение по имени идёт через контекст формы неявно. Явное ЭтаФорма.ИмяРеквизита повышает читаемость и помогает отличать реквизиты от локальных переменных в длинных процедурах.

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

Реквизиты формы списка заполняются так же, по имени. Для отбора динамического списка изменяйте не реквизит, а коллекцию Список.Отбор.Элементы или параметры запроса через Список.Параметры.УстановитьЗначениеПараметра().

Итог

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

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