Как получить реквизиты формы из модуля менеджера документа в 1С и избежать ошибки «Поле объекта не обнаружено (ЭлементыФормы)»?

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

При разработке механизмов печати в платформе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью использовать значения различных реквизитов формы. Типичная ошибка начинающих разработчиков — попытка напрямую обратиться к элементам управляемой или обычной формы из модуля менеджера документа. В этой статье мы подробно разберем, почему возникает популярная ошибка «Поле объекта не обнаружено (ЭлементыФормы)», проанализируем архитектуру клиент-серверного взаимодействия и рассмотрим правильные методики решения данной задачи.

Почему возникает ошибка при вызове «ПолучитьФорму» в модуле менеджера?

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


Форма = Документы.АктПриемаПередачи.ПолучитьФорму("ФормаДокумента"); 
Реквизит = Форма.ЭлементыФормы.ПриемПередача.Значение;

В этом фрагменте кода скрыты сразу три критические ошибки, которые делают его неработоспособным:

  1. Разделение контекстов исполнения (Клиент / Сервер). Модуль менеджера документа всегда выполняется на сервере. На сервере нет понятий «экран пользователя», «активное окно» или «текущий сеанс отображения интерфейса». Попытка работать с интерфейсными свойствами в серверном коде противоречит архитектуре управляемого приложения.
  2. Суть метода ПолучитьФорму. Вызов этого метода на сервере инициализирует создание совершенно нового, «чистого» экземпляра формы в оперативной памяти сервера. Эта форма никак не связана с той формой, которую в данный момент видит перед собой пользователь на клиенте. В этой новой форме все реквизиты будут пустыми (или заполненными значениями по умолчанию), а введенные пользователем данные просто не будут существовать.
  3. Различие между обычными и управляемыми формами. Свойство ЭлементыФормы использовалось для обращения к элементам управления исключительно в обычном приложении (толстый клиент). В управляемом приложении коллекция элементов формы называется просто Элементы. Платформа выдает ошибку «Поле объекта не обнаружено», так как у объекта формы в управляемом режиме действительно нет свойства ЭлементыФормы.

Выяснив причины некорректного поведения системы, давайте разберем правильные архитектурные решения.

Решение 1. Получение сохраненных данных через запрос (Рекомендуемый способ)

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

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

Рассмотрим подробный пример реализации такой процедуры в модуле менеджера документа:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

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

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

Этот способ является наиболее оптимальным, быстрым и безопасным с точки зрения производительности системы 1С.

Решение 2. Передача несохраняемых параметров формы через БСП

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

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

Шаг 1. Переопределение обработчика команды печати в модуле формы. Нам нужно перехватить процедуру формирования печати на клиенте и добавить в структуру параметров наши интерфейсные переменные:


&НаКлиенте
Процедура Подключаемый_ВыполнитьКомандуПечати(Команда)
    
    // Создаем структуру параметров печати
    ДополнительныеПараметры = Новый Структура;
    ДополнительныеПараметры.Вставить("ПриемПередача", Объект.ПриемПередача);
    ДополнительныеПараметры.Вставить("Исполнитель", Объект.Исполнитель);
    
    // Запускаем печать БСП с передачей наших параметров
    УправлениеПечатьюКлиент.ВыполнитьПодключаемуюКомандуПечати(Команда, ЭтотОбъект, Объект, ДополнительныеПараметры);
    
КонецПроцедуры

Шаг 2. Считывание параметров в процедуре печати модуля менеджера. В модуле менеджера мы извлекаем переданные значения из входящего параметра ПараметрыПечати:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Проверяем наличие переданных параметров печати
    ПриемПередача = Ложь;
    Исполнитель = Справочники.Сотрудники.ПустаяСсылка();
    
    Если ПараметрыВывода <> Неопределено И ПараметрыВывода.Свойство("ПараметрыПечати") Тогда
        СтруктураПараметров = ПараметрыВывода.ПараметрыПечати;
        Если СтруктураПараметров <> Неопределено Тогда
            СтруктураПараметров.Свойство("ПриемПередача", ПриемПередача);
            СтруктураПараметров.Свойство("Исполнитель", Исполнитель);
        КонецЕсли;
    КонецЕсли;
    
    // Теперь мы можем использовать переменные "ПриемПередача" и "Исполнитель" для алгоритмов макета
    // ...
КонецПроцедуры

Этот подход позволяет гибко управлять печатными формами в зависимости от интерактивного выбора пользователя перед печатью без лишней записи данных в СУБД.

Решение 3. Прямой вызов серверной функции (для самописных конфигураций)

Если ваша конфигурация разработана «с нуля» без использования БСП, вы можете передать любые параметры с формы напрямую в экспортную функцию модуля менеджера или общего модуля. Посмотрим на этот простой пример.

В модуле формы документа описываем клиентский вызов печати:


&НаКлиенте
Процедура ВыполнитьПечать(Команда)
    
    // Передаем значения реквизитов формы напрямую в серверный вызов
    ТабДок = СформироватьПечатнуюФормуНаСервере(Объект.Ссылка, Объект.Исполнитель, Объект.ПриемПередача);
    ТабДок.Показать("Печать акта приема-передачи");
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция СформироватьПечатнуюФормуНаСервере(СсылкаНаДокумент, Исполнитель, ПриемПередача)
    
    // Вызываем процедуру из модуля менеджера, передавая параметры
    Возврат Документы.АктПриемаПередачи.ПечатьВручную(СсылкаНаДокумент, Исполнитель, ПриемПередача);
    
КонецФункции

А в модуле менеджера документа АктПриемаПередачи пишем простую экспортную функцию:


Функция ПечатьВручную(СсылкаНаДокумент, ПереданныйИсполнитель, РежимПриема) Экспорт
    
    ТабДок = Новый ТабличныйДокумент;
    Макет = ПолучитьМакет("Макет");
    Область = Макет.ПолучитьОбласть("Подвал");
    
    // Прямое использование переданных параметров
    Если РежимПриема Тогда
        Область.Параметры.Исполнитель = ПереданныйИсполнитель;
    КонецЕсли;
    
    ТабДок.Вывести(Область);
    Возврат ТабДок;
    
КонецФункции

Подведем итоги

Для успешного решения задач печати и исключения ошибок взаимодействия контекстов всегда помните:

← На главную