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

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Для понимания сути проблемы выясним причину, почему данные формы не попадают в базу данных при стандартном вызове метода записи объекта.

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

Проанализируем архитектуру платформы «1С:Предприятие». В ней четко разделены две сущности:

  1. Реквизиты объекта (метаданные): это поля таблиц базы данных. Они создаются в дереве метаданных конфигуратора (реквизиты документа, табличные части). Только они физически сохраняются в СУБД при вызове метода ДокументОбъект.Записать().
  2. Реквизиты формы: это временные переменные, существующие исключительно в оперативной памяти во время открытого окна или жизни контекста формы. Они предназначены для организации интерфейса, промежуточных расчетов и управления элементами управления на экране. При закрытии формы эти значения безвозвратно уничтожаются платформой.

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

Вариант 1. Перенос реквизита в метаданные документа

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

Разберем по шагам, как это реализовать:

  1. Откроем конфигуратор и найдем нужный документ в дереве метаданных.
  2. В ветке Реквизиты создадим новый реквизит нужного типа (число, строка, ссылка и т.д.).
  3. На форме документа свяжем элемент управления с новым реквизитом объекта (через свойство Данные или ПутьКДанным).
  4. В программном коде заполним реквизит напрямую через объект документа без вызова формы:

НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = ВыбраннаяОрганизация;
НовыйДокумент.Контрагент = ВыбранныйКонтрагент;

// Заполняем реквизит объекта напрямую
НовыйДокумент.Комментарий = "Заполнено программно";
НовыйДокумент.СуммаВключаетНДС = Истина;

НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);

Вариант 2. Анализ логики формы и заполнение реального источника данных

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

Посмотрим на типовые сценарии, куда разработчики конфигурации могли перенаправить данные формы:

  1. Табличная часть дополнительных реквизитов (БСП): значение может помещаться в табличную часть ДополнительныеРеквизиты.
  2. Независимый регистр сведений: при записи формы данные записываются в отдельный регистр (например, состояния, статусы, штрихкоды, периодические свойства).
  3. Структура ДополнительныеСвойства объекта: данные из реквизита формы перед записью помещаются в структуру Объект.ДополнительныеСвойства и обрабатываются в модуле объекта в событии ПередЗаписью.

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


// 1. Создаем и записываем документ
НовыйДокумент = Документы.ЗаказПокупателя.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);

// 2. Записываем данные в связанный регистр сведений
МенеджерЗаписи = РегистрыСведений.СтатусыДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Документ = НовыйДокумент.Ссылка;
МенеджерЗаписи.Статус = Справочники.СтатусыЗаказов.Согласован;
МенеджерЗаписи.Период = ТекущаяДата();
МенеджерЗаписи.Записать(Истина);

Вариант 3. Использование механизма дополнительных реквизитов (БСП)

Если форма отображает реквизит из состава подсистемы «Свойства» библиотеки стандартных подсистем, рассмотрим программное заполнение через штатное API БСП.

Посмотрим на пример заполнения дополнительного реквизита объекта без открытия экранных форм:


ДокОбъект = Документы.ЗаказКлиента.СоздатьДокумент();
ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Организация = СсылкаОрганизация;

// Добавляем значение в табличную часть дополнительных реквизитов
СтрокаРеквизита = ДокОбъект.ДополнительныеРеквизиты.Добавить();
СтрокаРеквизита.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("НомерЗаказаНаСайте");
СтрокаРеквизита.Значение = "WEB-98745";

ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Вариант 4. Программная работа с контекстом формы (Обычные формы)

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

Рассмотрим программное взаимодействие с обычной формой:


// Создаем объект документа
НовыйДокумент = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();

// Получаем форму документа
ФормаДокумента = НовыйДокумент.ПолучитьФорму("ФормаДокумента");

// Устанавливаем значение реквизита формы
ФормаДокумента.РеквизитФормыСтрока = "Значение реквизита";

// Вызываем экспортную процедуру пересчета или записи, если она предусмотрена разработчиком формы
ФормаДокумента.ЗаписатьВФорме();

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

Рекомендации по чистой архитектуре 1С

Подведем итог и выделим ключевые правила для надежной разработки:

  1. Не использовать формы для фоновых алгоритмов: программное создание документов, обработка загрузки данных, интеграции и регламентные задания должны работать строго на уровне объектов метаданных (ДокументОбъект), без обращения к методам ПолучитьФорму() и ОткрытьФорму().
  2. Исследовать модуль формы: если функционал работает только из формы, необходимо найти обработчики ПередЗаписью, ПриЗаписи, ПередЗаписьюНаСервере и вынести общую бизнес-логику в общий модуль или модуль менеджера документа для повторного использования.
  3. Проверять признак «Сохраняемые данные»: в управляемых формах для реквизитов формы можно включать флаг СохраняемыеДанные, однако он влияет только на контроль модифицированности формы при закрытии пользователем, но не сохраняет реквизит в базу сам по себе.
← На главную