При программном создании документов во внешних обработках разработчики часто сталкиваются с ситуацией, когда некоторые важные реквизиты (например, ТиповаяОперация и связанные с ней параметры) отсутствуют в самом объекте базы данных, а формируются динамически прямо на управляемой форме в событии ПриСозданииНаСервере. В этой статье мы подробно разберем, почему возникает такая ситуация и как правильно программно заполнить документ и связанные с ним документы без интерактивного открытия формы пользователем.
Для понимания логики работы 1С важно четко разделять контекст объекта метаданных и контекст управляемой формы:
ДокументОбъект): создается вызовом метода СоздатьДокумент(). В нем доступны только те реквизиты и табличные части, которые явно добавлены в конфигураторе в состав данного документа. Метод СоздатьДокумент() работает исключительно на сервере и не инициализирует события управляемых форм.СоздатьРеквизиты(), существуют только в памяти конкретного экземпляра формы во время ее работы. Как только форма закрывается, динамические реквизиты прекращают свое существование.В конфигурациях 1С (в частности, в «Бухгалтерии государственного учреждения») параметр ТиповаяОперация на форме отображается как динамический реквизит, но данные о нем в базе данных сохраняются в служебных табличных частях или с помощью дополнительных реквизитов документа. Поэтому попытка обратиться к динамическому реквизиту формы напрямую из объекта ДокументОбъект приведет к ошибке.
Открыть()Рассмотрим способ, когда необходимо выполнить серверную логику формы, включая событие ПриСозданииНаСервере, но без визуального показа формы пользователю. Для этого вызовем метод ПолучитьФорму(), зафиксируем данные и преобразуем их в объект.
Проанализируем пример кода:
ПараметрыФормы = Новый Структура;
ФормаДокумента = ПолучитьФорму("Документ.АктОказанияУслуг.Форма.ФормаДокумента", ПараметрыФормы);
// При вызове ПолучитьФорму отрабатывает событие ПриСозданииНаСервере
// Заполняем реквизиты формы, если требуется
ФормаДокумента.Объект.ВидОперации = Перечисления.ВидыОпераций.ОказаниеУслуг;
// Преобразуем данные формы в объект для последующей записи
ДокументОбъект = ДанныеФормыВЗначение(ФормаДокумента.Объект, Тип("ДокументОбъект.АктОказанияУслуг"));
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
Этот подход позволяет задействовать механизмы формы, однако стоит учитывать, что создание формы создает дополнительную нагрузку на сервер.
Посмотрим на более производительный и архитектурно правильный вариант. Чтобы не завязываться на форму, необходимо изучить, какие именно реквизиты и табличные части объекта заполняются при выборе типовой операции на форме, и повторить этот алгоритм в своей обработке или в процедуре ОбработкаЗаполнения модуля объекта.
Рассмотрим по шагам логику программного заполнения:
ВидОперации или Организация).Заполнить(), передав в него необходимые параметры.Пример программного заполнения документа с использованием метода Заполнить():
НовыйАкт = Документы.АктОказанияУслуг.СоздатьДокумент();
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("ВидОперации", Перечисления.ВидыОпераций.ОказаниеУслуг);
ПараметрыЗаполнения.Вставить("Организация", НашаОрганизация);
ПараметрыЗаполнения.Вставить("Контрагент", НашКонтрагент);
НовыйАкт.Заполнить(ПараметрыЗаполнения);
НовыйАкт.Записать(РежимЗаписиДокумента.Запись);
Разберем ситуацию с созданием подчиненного документа. Чтобы создать документ «Счет-фактура выданный» на основании Акта оказания услуг, платформа 1С использует данные уже записанного документа-основания (его реквизиты шапки и движения), а не визуальные элементы формы.
Схема создания подчиненного документа выглядит следующим образом:
// Сначала создаем и записываем документ-основание
АктОбъект = Документы.АктОказанияУслуг.СоздатьДокумент();
// ... заполнение реквизитов Акта ...
АктОбъект.Записать(РежимЗаписиДокумента.Проведение);
// Затем создаем Счет-фактуру на основании ссылки записанного Акта
СчетФактураОбъект = Документы.СчетФактураВыданный.СоздатьДокумент();
СчетФактураОбъект.Заполнить(АктОбъект.Ссылка);
СчетФактураОбъект.Записать(РежимЗаписиДокумента.Запись);
Важное замечание: Метод Заполнить(СсылкаНаАкт) обращается к процедуре ОбработкаЗаполнения в модуле объекта Счета-фактуры. Если в записанном Акте корректно заполнены реквизиты ВидОперации, организация, контрагент и табличные части, Счет-фактура сформируется без ошибок даже без открытых форм.