Как правильно добавить несколько печатных форм в меню «Печать» и исправить ошибки в модуле менеджера?

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

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

Разбираем структуру модуля менеджера

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

Рассмотрим правильную структуру расположения процедур в модуле:


#Область ПрограммныйИнтерфейс

// Процедура для регистрации команд в интерфейсе
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
    // Здесь описываем параметры команд
КонецПроцедуры

#КонецОбласти

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ПрограммныйИнтерфейс

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

#КонецОбласти

#КонецЕсли

Важный момент: Обратите внимание, что процедура Печать обязательно должна быть обернута в условие #Если Сервер..., так как формирование табличного документа — это серверная операция.

Шаг 1. Регистрация команд в подменю

Для добавления списка макетов в меню «Печать» используется процедура ДобавитьКомандыПечати. Здесь мы создаем структуру команд. Рассмотрим на примере добавления ежемесячных отчетов, как это сделал автор темы.

Проанализируем ключевые параметры команды:

Пример регистрации команд:


Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
    
    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "ФайлОценка_Январь";
    КомандаПечати.Представление = НСтр("ru = 'Файл Оценка (январь)'");
    КомандаПечати.МенеджерПечати = "Документ.ФайлОценка";
    КомандаПечати.Порядок = 1;
    КомандаПечати.ПроверкаПроведенияПередПечатью = Ложь;
    
    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "ФайлОценка_Февраль";
    КомандаПечати.Представление = НСтр("ru = 'Файл Оценка (февраль)'");
    КомандаПечати.МенеджерПечати = "Документ.ФайлОценка";
    КомандаПечати.Порядок = 2;
    
КонецПроцедуры

Совет: Старайтесь использовать латиницу в поле Идентификатор. Это поможет избежать проблем с кодировками и сделает код более устойчивым к изменениям строковых представлений.

Шаг 2. Реализация процедуры Печать

Когда пользователь нажимает на кнопку в меню, БСП вызывает процедуру Печать. Главная задача здесь — правильно определить, какую именно форму запросил пользователь, и заполнить КоллекцияПечатныхФорм.

Выясним причину, по которой часто возникает ошибка Поле объекта не обнаружено (ПолныйПутьКМакету). Это происходит, если мы неверно инициализируем структуру ПечатнаяФорма или используем жесткую индексацию коллекции (например, обращаясь только к первому элементу КоллекцияПечатныхФорм[0]), когда пользователь выбрал несколько форм сразу.

Рассмотрим универсальный и правильный подход:


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

Шаг 3. Решение проблемы «Переполнение стека» в представлениях

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

Почему это происходит? Внутри обработчика представления вы обращаетесь к свойству Данные.Ссылка. Платформа, чтобы показать эту ссылку, снова пытается получить её представление и вызывает тот же самый обработчик. Этот цикл повторяется до падения системы.

Разберем, как сделать правильно. Сначала определим поля в ОбработкаПолученияПолейПредставления:


Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Поля.Добавить("Номер");
    Поля.Добавить("Дата");
КонецПроцедуры

А затем в ОбработкаПолученияПредставления используем только эти поля, не обращаясь к ссылке:


Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Представление = "Документ №" + Данные.Номер + " от " + Формат(Данные.Дата, "ДЛФ=D");
КонецПроцедуры

Шаг 4. Оптимизация формирования макета

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

Рассмотрим эффективный алгоритм:

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

Пример функции формирования:


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

Итог: Основная сложность при работе с подменю печати заключается в строгом соблюдении структуры модулей и правильной передаче идентификаторов между процедурами ДобавитьКомандыПечати и Печать. Используя подход с циклом по коллекции печатных форм и проверкой идентификаторов, вы создадите надежный механизм, который будет корректно работать даже при выборе нескольких макетов одновременно.

← На главную