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