Как программно заполнять документы в 1С 8.3, если в процедурах общего модуля требуется параметр Форма?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

Попытка вызвать такую процедуру при пакетной или регламентной генерации документов вызывает логичный вопрос: как получить и передать форму на сервере, если мы создаем документ чисто программно? Разберем архитектурные причины этих изменений и рассмотрим правильные способы решения задачи.

Почему возникает ошибка?

Проанализируем архитектуру управляемого приложения. В типовых конфигурациях 1С действует жесткое разделение логики:

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

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

Способ 1. Использование штатного метода Заполнить() модуля объекта

Рассмотрим основной и самый правильный подход к программному формированию документов в 1С. Для инициализации реквизитов не нужно вызывать методы, предназначенные для экранных форм. Вся бизнес-логика начального заполнения по стандарту закладывается в событие ОбработкаЗаполнения модуля самого документа.

Посмотрим на пример правильного создания и заполнения документа:


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

// Формируем структуру с данными для инициализации
ДанныеЗаполнения = Новый Структура;
ДанныеЗаполнения.Вставить("Организация", ВыбраннаяОрганизация);
ДанныеЗаполнения.Вставить("Контрагент",  ВыбранныйКонтрагент);
ДанныеЗаполнения.Вставить("ДоговорКонтрагента", ВыбранныйДоговор);

// Вызываем штатную логику заполнения объекта
НовыйДокумент.Заполнить(ДанныеЗаполнения);

// При необходимости дозаполняем табличные части и специфичные реквизиты
// ...

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

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

Способ 2. Поиск серверных аналогов в модуле менеджера или общих модулях

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

Вместо процедур управления формой следует искать методы, принимающие сам ДокументОбъект, ссылку или структуру значений. Например, алгоритмы расчета налогов и счетов обычно располагаются в модулях подсистем бухгалтерского и налогового учета и имеют экспортные методы вида ЗаполнитьСчетаУчета(...), не привязанные к визуальным элементам.

Способ 3. Программная эмуляция структуры формы (обходной путь)

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

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

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

Посмотрим на пример реализации данного обхода:


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

// 1. Создаем структуру данных формы
ДанныеФормы = Новый ДанныеФормыСтруктура;

// 2. Преобразуем реальный объект в данные формы
ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);

// 3. Формируем контекст-заглушку формы
КонтекстФормы = Новый Структура;
КонтекстФормы.Вставить("Объект", ДанныеФормы);

// При необходимости можно добавить параметры, если их ожидает процедура
КонтекстФормы.Вставить("Параметры", Новый Структура);

// 4. Вызываем типовую процедуру общего модуля
УчетУСН.ПараметрыФормыДокументаДляУСН(КонтекстФормы);

// 5. Возвращаем обновленные данные обратно в прикладной объект
ДанныеФормыВЗначение(КонтекстФормы.Объект, ДокОбъект);

// 6. Записываем объект в информационную базу
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

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

← На главную