Разработка и модификация внешних печатных форм — одна из самых частых задач для программиста 1С. Однако нередко возникает классическая проблема: разработчик вносит изменения в макет или код внешней печатной формы, сохраняет файл, подключает его через механизм «Дополнительные отчеты и обработки», но при нажатии на кнопку печати в документе система продолжает выводить старый, неизмененный вариант. При этом, если запустить ту же самую обработку через стандартное меню Файл — Открыть и выбрать документ-основание, изменения отображаются корректно.
В этой статье мы подробно проанализируем, почему возникает подобное поведение платформы и Библиотеки стандартных подсистем (БСП), разберем ключевые причины этой проблемы и пошагово рассмотрим способы её решения.
Это самая распространенная и неочевидная ошибка, с которой сталкиваются даже опытные разработчики при адаптации стандартных печатных форм (таких как УПД, Торг-12, Счет-фактура) под внешние обработки. Выясним причину этой проблемы подробнее.
Когда мы берем за основу типовую печатную форму, её процедура Печать в модуле объекта часто копируется из конфигурации «как есть». Рассмотрим пример такого кода, который предоставил автор темы:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
СчетаФактуры = ПолучитьСчетФактуры(МассивОбъектов);
Если НЕ ЗначениеЗаполнено(СчетаФактуры) тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не выписана счет фактура";
Сообщение.Сообщить();
Возврат;
КонецЕсли;
ДокументСчф = СчетаФактуры[0];
ДатаДок = ДокументСчф.Дата;
Если ДатаДок < Дата("20170701") тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "УПДСтатус1_981", "УПД (статус 1)",
ПечатьУниверсальныхПередаточныхДокументов(СчетаФактуры, ОбъектыПечати,
ТекстЗапросаПечатьСчетовФактур(Истина, Истина, Ложь)),,
"ПФ_MXL_УниверсальныйПередаточныйДокумент");
ИначеЕсли ДатаДок >= Дата("20170701") И ДатаДок < Дата("20171001") тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "УПДСтатус1_981", "УПД (статус 1)",
ПечатьУниверсальныхПередаточныхДокументов(СчетаФактуры, ОбъектыПечати,
ТекстЗапросаПечатьСчетовФактур(Истина, Истина, Ложь)),,
"ПФ_MXL_УниверсальныйПередаточныйДокумент");
ИначеЕсли ДатаДок >= Дата("20171001") тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "УПДСтатус1_981", "УПД (статус 1)",
УчетНДС.ПечатьУниверсальныхПередаточныхДокументов981(СчетаФактуры, ОбъектыПечати,
ТекстЗапросаПечатьСчетовФактур(Истина, Истина, Истина)),,
"ПФ_MXL_УниверсальныйПередаточныйДокумент981");
КонецЕсли;
КонецПроцедуры
Обратим внимание на условие, когда дата документа больше или равна 01.10.2017. В этом ветвлении система вызывает метод общего модуля конфигурации: УчетНДС.ПечатьУниверсальныхПередаточныхДокументов981(...).
Проанализируем ситуацию: общий модуль конфигурации УчетНДС ничего не знает о существовании вашей внешней печатной формы и её локальных макетов. Он обращается к стандартному макету, который жестко прописан в метаданных самой конфигурации 1С. Когда вы запускаете обработку через Файл — Открыть, могут отрабатывать другие ветки кода (например, если дата тестового документа попадает под первое или второе условие, где вызываются локальные функции обработки ПечатьУниверсальныхПередаточныхДокументов, а не общий модуль).
Для решения этой проблемы выполним следующие шаги:
ПечатьУниверсальныхПередаточныхДокументов981 из общего модуля конфигурации УчетНДС в модуль объекта вашей внешней печатной формы.ЛокальнаяПечатьУниверсальныхПередаточныхДокументов981.
// Вместо получения макета из конфигурации:
// Макет = УправлениеПечатью.МакетПечатнойФормы("ОбщийМакет.ПФ_MXL_УниверсальныйПередаточныйДокумент981");
// Пишем получение макета из нашей внешней обработки:
Макет = ЭтотОбъект.ПолучитьМакет("ПФ_MXL_УниверсальныйПередаточныйДокумент981");
Печать заменим вызов метода общего модуля на нашу новую локальную функцию:
ИначеЕсли ДатаДок >= Дата("20171001") тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "УПДСтатус1_981", "УПД (статус 1)",
ЛокальнаяПечатьУниверсальныхПередаточныхДокументов981(СчетаФактуры, ОбъектыПечати,
ТекстЗапросаПечатьСчетовФактур(Истина, Истина, Истина)),,
"ПФ_MXL_УниверсальныйПередаточныйДокумент981");
Этот шаг позволяет полностью изолировать логику формирования печатной формы внутри файла .epf, гарантируя, что система будет использовать именно ваш измененный макет.
Посмотрим на то, как платформа 1С работает с механизмом дополнительных отчетов и обработок. Когда вы открываете внешнюю обработку через меню Файл — Открыть, платформа считывает актуальный файл напрямую с диска вашего компьютера. Любые изменения макета видны сразу.
Однако при регистрации формы в справочнике «Дополнительные отчеты и обработки» происходит иное: двоичные данные файла обработки записываются непосредственно в базу данных 1С. При нажатии кнопки печати в документе БСП извлекает сохраненный бинарный файл из базы данных, помещает его во временный каталог на сервере и запускает оттуда.
Если вы внесли изменения в макет на диске через Конфигуратор, но не обновили файл в справочнике 1С:Предприятия, система продолжит использовать старый файл из базы данных. Разберем по шагам, как правильно обновлять печатную форму:
.epf с актуальными изменениями.После выполнения этих действий старый кэш в базе данных перезапишется новой версией файла.
В современных конфигурациях 1С на базе БСП реализован удобный механизм кастомизации печатных форм силами пользователей прямо в режиме «1С:Предприятие». Пользователь может зайти в специальную форму, отредактировать шрифт, добавить логотип или изменить текст ячейки стандартного макета.
Проанализируем важный нюанс: измененные пользователем макеты сохраняются в специальном системном регистре сведений ПользовательскиеМакетыПечати. При формировании печатной формы БСП проверяет этот регистр. Если в нем зарегистрирован измененный макет для данного документа (например, для УПД), система принудительно подставит его, проигнорировав как встроенный макет конфигурации, так и макет вашей новой внешней печатной формы.
Посмотрим, как исправить эту ситуацию и вернуть приоритет вашей разработке:
После сброса пользовательских настроек система вернется к стандартному алгоритму выбора макета, прописанному в кодовой базе вашей внешней обработки.
При регистрации внешней обработки в процедуре СведенияОВнешнейОбработке разработчик указывает параметры её запуска. Одним из таких параметров является БезопасныйРежим. Рассмотрим пример заполнения параметров:
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
ПараметрыРегистрации.Версия = "1";
ПараметрыРегистрации.БезопасныйРежим = Истина; // или Ложь
Если для параметра БезопасныйРежим установлено значение Истина, платформа накладывает жесткие ограничения на исполнение кода внешней обработки. В безопасном режиме запрещены:
Если ваша печатная форма обращается к специфическим функциям конфигурации (например, для формирования штрихкодов, работы со внешними компонентами или вызова недоступных в безопасном режиме методов), выполнение кода может прерываться ошибкой, либо система может некорректно инициализировать макет. Если логика вашей формы сложна и требует расширенных прав, измените этот параметр на Ложь в функции СведенияОВнешнейОбработке() и заново обновите обработку в справочнике информационной базы.
Для того чтобы ваши изменения во внешней печатной форме всегда отображались корректно при печати из документов, рекомендуем придерживаться следующего чек-листа:
ЭтотОбъект.ПолучитьМакет().