Как получить значение "ТекущаяСтраница" управляемой формы в модуле менеджера при печати в 1С

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

При разработке печатных форм в среде «1С:Предприятие 8.3» программисты часто сталкиваются с необходимостью изменить логику формирования печатного листа в зависимости от того, на какой вкладке (странице) документа сейчас находится пользователь. Типичный пример: если открыта вкладка «Спецодежда» — выводим в печатной форме ответственное физлицо, во всех остальных случаях оставляем поле пустым.

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

Почему нельзя получить «Текущую страницу» напрямую в модуле менеджера?

Для понимания сути проблемы проанализируем архитектуру клиент-серверного взаимодействия платформы «1С:Предприятие». Управляемая форма и её элементы (кнопки, панели, вкладки, текущие страницы) существуют исключительно в клиентском контексте в оперативной памяти компьютера пользователя.

В то же время модуль менеджера выполняется строго на сервере и не имеет состояния (он является stateless-объектом). Серверный код модуля менеджера ничего не знает о визуальном отображении: открыта ли форма вообще (ведь печать может запускаться групповым способом из формы списка документов, где формы объектов вообще не создаются), какая вкладка активна и какие промежуточные данные ввел пользователь.

Попытка обратиться из модуля менеджера к объекту ЭтаФорма или получить значение типа Элементы.ГруппаСтраницы.ТекущаяСтраница невозможна физически — сервер не имеет доступа к интерфейсной части клиента.

Решение проблемы: Передача контекста формы через параметры печати БСП

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

Шаг 1. Перехват и подготовка параметров на клиенте (Модуль формы документа)

Нам необходимо определить активную страницу панели формы непосредственно перед отправкой документа на печать. Для этого мы переопределяем или дополняем процедуру обработки команды печати в модуле управляемой формы.

Проанализируем следующий пример кода:


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

В этом коде мы считываем значение свойства ТекущаяСтраница, сопоставляем его с элементами формы и упаковываем текстовый маркер во вспомогательную структуру. Эта структура без потерь преодолеет границу «клиент-сервер» и будет доставлена в модуль менеджера.

Шаг 2. Чтение переданных параметров на сервере (Модуль менеджера документа)

Теперь переместимся в модуль менеджера документа. Нам нужно принять переданный параметр внутри экспортной процедуры Печать и использовать его для управления логикой вывода данных.

Рассмотрим, как это выглядит на практике:


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

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

Оптимизация работы с данными: убираем небезопасные обращения «через точку»

Обратим внимание на критическую ошибку, часто совершаемую начинающими разработчиками:

СтрокаТабл.Параметры.ФизЛицо = ДокументыДляПечати.Ссылка.Спецодежда[0].ФизЛицо;

Данный подход таит в себе сразу две серьезные угрозы для стабильности и производительности конфигурации:

  1. Индекс находится за границами диапазона. Если пользователь не заполнил табличную часть «Спецодежда» и она осталась пустой, обращение к индексу [0] мгновенно вызовет ошибку и прервет процесс печати для пользователя.
  2. Катастрофическое падение производительности (N+1 запрос). Обращение «через точку» от ссылки к табличным частям (Ссылка.Спецодежда) заставляет СУБД выполнять неявные, тяжелые запросы в цикле. При печати пакета документов система будет отправлять отдельные запросы к БД по каждому объекту, что перегрузит сервер.

Выясним, как решить эту задачу производительно и безопасно. Проанализируем правильный паттерн извлечения первой строки табличной части с помощью запроса по массиву объектов:


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

Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
РезультатЗапроса = Запрос.Выполнить();

При таком подходе база данных вернет ровно столько строк, сколько документов содержат заполненную ТЧ. Если строк в документе нет — запрос просто проигнорирует его, исключая любые критические ошибки падения кода по индексу. Всю выборку мы получаем за одно-единственное обращение к СУБД, что отвечает высоким стандартам разработки фирмы «1С».

Проблема модифицированности формы (печать несохраненных данных)

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

Как с этим бороться в БСП?

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

Если же вы используете кастомные механизмы печати в обход БСП, то на клиенте перед отправкой данных на печать вам необходимо принудительно вызвать метод Записать() или получить актуальные данные формы через вызов серверной функции контекста формы и конвертацию данных:


// Пример получения актуальных данных формы на сервере без записи в БД
&НаСервере
Функция ПолучитьДанныеФормыДляПечати()
    ТекущийОбъект = РеквизитФормыВЗначение("Объект");
    // Теперь переменная ТекущийОбъект содержит актуальные несохраненные данные из интерфейса
    Возврат ТекущийОбъект.Спецодежда.Выгрузить();
КонецФункции

Использование связки параметров БСП для проброса контекста активной страницы и получение данных через оптимизированные запросы гарантирует быструю, стабильную и безотказную работу ваших печатных форм в любых конфигурациях 1С.

← На главную