При доработке конфигураций 1С через расширения разработчики часто сталкиваются с ошибками инициализации модулей. Особенно часто это происходит при попытке модифицировать алгоритмы печати документов с использованием стандартных механизмов Библиотеки стандартных подсистем (БСП). Рассмотрим подробнее ситуацию, когда при обращении к документу платформа выдает сообщение об ошибке вида: «Переменная не определена (УправлениеПечатью)».
Посмотрим на классический пример. В конфигурации «Бухгалтерия предприятия 3.0» разработчик заимствует в расширение модуль менеджера документа ОтчетОРозничныхПродажах и добавляет процедуру для перехвата печати:
&После("Печать")
Процедура Ант_Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода)
// Проверяем, нужно ли для макета ОтчетККМ формировать табличный документ.
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ООРП_Накладная") Тогда
// Формируем табличный документ и добавляем его в коллекцию печатных форм.
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ООРП_Накладная", "Накладная", ПечатьНакладнойООРП(МассивОбъектов, ОбъектыПечати), , "Документ.ОтчетОРозничныхПродажах.Накладная");
КонецЕсли;
КонецПроцедуры
При запуске базы (особенно в режиме толстого клиента) платформа выдает ошибку инициализации модуля менеджера, указывая, что переменная УправлениеПечатью не определена. Выясним причину такого поведения.
В конфигурациях на базе БСП общий модуль УправлениеПечатью является строго серверным. В его свойствах установлены флажки «Сервер», «Внешнее соединение» и «Толстый клиент (обычное приложение)», но отключен флаг «Толстый клиент (управляемое приложение)» или вызов с клиента. Когда мы пишем код в модуле менеджера расширения без явного указания контекста компиляции, платформа пытается скомпилировать этот код для всех возможных контекстов выполнения (и для клиента, и для сервера). Поскольку на клиенте платформа физически «не видит» серверный модуль, возникает сбой компиляции.
Чтобы избежать ошибки компиляции, весь серверный код в модулях менеджеров (и в самих документах, и в расширениях) должен быть строго изолирован специальными инструкциями препроцессора. Проделаем следующие шаги:
Посмотрим на пример исправленного кода:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
&После("Печать")
Процедура Ант_Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода)
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ООРП_Накладная") Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ООРП_Накладная", "Накладная", ПечатьНакладнойООРП(МассивОбъектов, ОбъектыПечати), , "Документ.ОтчетОРозничныхПродажах.Накладная");
КонецЕсли;
КонецПроцедуры
#КонецЕсли
Заимствовать сам общий модуль УправлениеПечатью в расширение не нужно, если вы не планируете менять его внутреннюю логику. Проблема заключается исключительно в контексте компиляции кода вашего расширения.
Иногда после скрытия кода за директивой разработчики замечают, что процедура просто перестает срабатывать. Директива препроцессора буквально «вырезает» ваш код из сборки для толстого клиента (управляемого приложения) или тонкого клиента. Если механизм печати инициируется пользователем на стороне клиента, вызов попросту пройдет мимо вашего перехватчика.
Для того чтобы процедура корректно отрабатывала, её вызов обязательно должен перенаправляться на сервер. Убедитесь, что команда печати, на которую нажимает пользователь, сначала вызывает клиентскую процедуру (например, обработчик кнопки формы), которая затем делает вызов процедуры &НаСервере или обращается к серверным методам общего модуля, откуда уже маршрутизируется вызов к модулю менеджера.
При добавлении директив препроцессора в расширение платформа иногда продолжает использовать старые закэшированные инструкции компиляции. Если вы добавили директивы #Если Сервер ... Тогда, но ошибка сохраняется, обязательно очистите кэш 1С. В некоторых ситуациях (особенно при тестировании подключаемых команд БСП) изменения вступают в силу только после полной очистки серверного и локального сеансового кэша.
Вместо того чтобы перехватывать метод Печать через аннотацию &После и бороться с директивами, стандартный подход БСП для расширений предполагает использование штатных механизмов добавления команд. Рассмотрим этот вариант.
Рекомендуется добавлять свои печатные формы через метод ДобавитьКомандыПечати в модуле менеджера или использовать функционал УправлениеПечатью.СоздатьКоллекциюКомандПечати. БСП самостоятельно собирает команды и правильно маршрутизирует вызовы (с клиента на сервер), что позволяет изначально избежать проблем с контекстом исполнения и ошибками компиляции.