При сопровождении и доработке конфигураций 1С перед разработчиком часто встает задача изменения печатных форм. Традиционный подход с созданием Внешней печатной формы (ВПФ) имеет свои недостатки: необходимость постоянного обновления кода при изменении структуры метаданных, неудобство отладки и дополнительные сложности при работе в безопасном режиме. С развитием механизма расширений в платформе 1С:Предприятие 8.3 появился более элегантный и надежный способ — доработка типового макета и логики его формирования непосредственно в расширении. Это позволяет оставить основную конфигурацию на полной поддержке и упростить дальнейшие обновления.
В этой статье мы подробно и по шагам разберем, как доработать типовую печатную форму (на примере документа «Акт сверки взаимных расчетов»), добавив в нее собственные данные и изменив макет, используя только возможности расширений.
Прежде чем перейти к практической реализации, проанализируем, почему доработка через расширение во многих случаях предпочтительнее создания ВПФ:
Рассмотрим детально процесс доработки типовой печатной формы на примере добавления контактных данных ответственного менеджера в подвал Акта сверки взаимных расчетов.
Для начала создадим новое расширение (или откроем существующее) и заимствуем в него необходимые объекты:
Документ.АктСверкиВзаимныхРасчетов).ПФ_MXL_АктСверкиВзаимныхРасчетов).После переноса макета в расширение мы можем открыть его интерактивно и добавить новую область или отредактировать существующие параметры. В нашем примере мы добавим новый параметр КонтактыМенеджера в область подвала макета.
Если нам необходимо добавить новую команду печати или переопределить поведение существующей, мы можем использовать предопределенные процедуры БСП в модуле менеджера документа. Используем директиву &После для перехвата процедуры добавления команд печати.
Рассмотрим пример добавления новой команды в список печати:
&После("ДобавитьКомандыПечати")
Процедура зсп_ДобавитьКомандыПечати(КомандыПечати) Экспорт
// Создаем новую команду печати для нашего измененного акта сверки
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.Идентификатор = "АктСверкиСКонтактами";
КомандаПечати.Представление = НСтр("ru = 'Акт сверки (с контактами менеджера)'");
КомандаПечати.Обработчик = "УправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати";
КомандаПечати.СписокФорм = "ФормаСписка,ФормаВыбора,ФормаДокумента";
КомандаПечати.Порядок = 1; // Устанавливаем команду в самый верх списка
КонецПроцедуры
Использование директивы &После позволяет нам не замещать типовой код, а лишь дополнять коллекцию команд печати своими значениями, что гарантирует стабильную работу механизма при обновлениях.
В обсуждениях часто возникает вопрос: как правильно перехватить формирование печатной формы, если весь код сосредоточен в одной функции, возвращающей табличный документ? В платформе 1С для функций нельзя эффективно использовать аннотации &Перед или &После, если требуется изменить возвращаемый результат. В таких ситуациях единственным верным решением является использование директивы &Вместо совместно с вызовом ПродолжитьВызов().
Выясним причину: вызов оригинальной функции через метод ПродолжитьВызов() позволяет получить уже сформированный типовой результат (например, структуру настроек запроса или готовый табличный документ), после чего мы можем программно модифицировать его и вернуть в вызывающий код. Это избавляет нас от необходимости копировать сотни строк типового сложного запроса в расширение.
Разберем конкретный пример модификации структуры настроек печати в модуле менеджера документа:
&Вместо("ВыборкаДанныхДокумента")
Функция зсп_ВыборкаДанныхДокумента(МассивОбъектов, НастройкиПечати)
// Вызываем оригинальный алгоритм для первоначального заполнения настроек
РезультатНастроек = ПродолжитьВызов(МассивОбъектов, НастройкиПечати);
// Добавляем в структуру настроек путь к нужным нам данным
// В данном случае указываем поле получения контактов менеджера
НастройкиПечати.Вставить("КонтактыМенеджера", "ДокументСверки.Ответственный.ФизическоеЛицо.КонтактнаяИнформация.Представление");
Возврат РезультатНастроек;
КонецФункции
Часто данные для печатной формы собираются сложным динамическим запросом. Переписывать его полностью — плохая практика, так как при обновлении конфигурации структура таблиц может измениться. Оптимальный вариант — использовать замену текста запроса «на лету» с помощью функции СтрЗаменить().
Проанализируем пример доработки функции формирования текста запроса:
&Вместо("ТекстЗапросаДанныеДокумента")
Функция зсп_ТекстЗапросаДанныеДокумента(НастройкиПечати)
// Получаем исходный текст типового запроса
ИсходныйТекстЗапроса = ПродолжитьВызов(НастройкиПечати);
// Модифицируем выборку полей в запросе, добавляя новые контакты
НовыйТекстЗапроса = СтрЗаменить(
ИсходныйТекстЗапроса,
"ДокументСверки.ФИОРуководителяКонтрагента КАК ФИОРуководителяКонтрагента,",
"ДокументСверки.ФИОРуководителяКонтрагента КАК ФИОРуководителяКонтрагента,"
+ Символы.ПС + " " + НастройкиПечати.КонтактыМенеджера + " КАК КонтактыМенеджера,"
);
// Добавляем наше поле в секцию группировки, если запрос содержит группировку данных
НовыйТекстЗапроса = СтрЗаменить(
НовыйТекстЗапроса,
"МАКСИМУМ(ДолжностьРуководителяКонтрагента),",
"МАКСИМУМ(ДолжностьРуководителяКонтрагента),"
+ Символы.ПС + " МАКСИМУМ(КонтактыМенеджера),"
);
Возврат НовыйТекстЗапроса;
КонецФункции
Важный момент: при использовании СтрЗаменить() для модификации запросов будьте предельно внимательны к форматированию типового кода (наличию пробелов, переносов строк, запятых). Старайтесь выбирать наиболее уникальные фрагменты текста запроса для замены, чтобы избежать ошибочного позиционирования.
Если вам не хочется перехватывать запросы и менять логику их формирования, существует альтернативный способ доработки макета через расширение. Мы можем перехватить саму процедуру вывода печатной формы, вызвать типовое формирование табличного документа, а затем программно модифицировать полученный результат перед выводом на экран.
Этот подход особенно удобен, когда нужно просто дописать несколько строк в подвал документа или прикрепить дополнительную небольшую область.
Рассмотрим пример реализации такого алгоритма:
&После("Печать")
Процедура зсп_Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, нужно ли выводить нашу измененную форму
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "АктСверкиСКонтактами") Тогда
// Получаем имя макета для формирования
СтруктураТиповойПечати = КоллекцияПечатныхФорм.Найти("АктСверкиСКонтактами");
Если СтруктураТиповойПечати <> Неопределено Тогда
// Получаем готовый сформированный табличный документ из типового механизма
ТабличныйДокумент = СтруктураТиповойПечати.ТабличныйДокумент;
// Получаем макет из нашего расширения, в который мы добавили свою область
МакетРасширения = ПолучитьМакет("ПФ_MXL_МойДополнительныйПодвал");
ОбластьКонтактов = МакетРасширения.ПолучитьОбласть("Контакты");
// Заполняем параметры области данными из объектов печати
Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
ОбластьКонтактов.Параметры.МенеджерКонтакты = СсылкаНаДокумент.Ответственный.ФизическоеЛицо.КонтактнаяИнформация.Представление;
// Выводим область в конец готового табличного документа
ТабличныйДокумент.Вывести(ОбластьКонтактов);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой подход делает наше решение максимально устойчивым к обновлениям: основной макет и алгоритм получения данных остаются полностью на поддержке поставщика, а мы лишь дополняем готовый табличный документ своей областью из изолированного макета расширения.
Мы детально разобрали, как с помощью расширений можно гибко управлять выводом печатных форм в системе 1С. В зависимости от архитектуры конфигурации и сложности задачи, вы можете выбрать один из двух путей:
Использование расширений для изменения печатных форм сокращает время разработки, упрощает процесс обновления программного продукта и делает систему более удобной в поддержке для администраторов и программистов.