При разработке собственных документов в конфигурациях на базе БСП (Библиотеки Стандартных Подсистем), таких как 1С:Бухгалтерия 3.0, разработчики часто сталкиваются с неожиданными ошибками компиляции. Одна из наиболее коварных проблем — появление ошибки «Переменная не определена (УправлениеПечатью)» в модуле менеджера документа при записи или проведении, хотя при непосредственном выводе на печать всё работает исправно. Давайте подробно разберем эту ситуацию, проанализируем причины ее возникновения и найдем надежное решение в соответствии со стандартами разработки фирмы «1С».
Рассмотрим типовой сценарий. В самописном документе (например, СопроводительноПисьмоДляПодтверждения0СтавкиНДС) реализована функция печати с использованием механизмов БСП. При попытке записать или провести документ интерактивно через стандартные кнопки формы система аварийно завершает работу и выдает следующую ошибку:
Ошибка инициализации модуля: Документ.СопроводительноПисьмоДляПодтверждения0СтавкиНДС.МодульМенеджера
по причине:
{Документ.СопроводительноПисьмоДляПодтверждения0СтавкиНДС.МодульМенеджера(34,7)}: Переменная не определена (УправлениеПечатью)
Если <<?>>УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СопроводительноПисьмоДляПодтверждения0СтавкиНДС") Тогда
{Документ.СопроводительноПисьмоДляПодтверждения0СтавкиНДС.МодульМенеджера(35,3)}: Переменная не определена (УправлениеПечатью)
<<?>>УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
При этом примечательно, что:
Выясним причину такого избирательного поведения платформы «1С:Предприятие».
Для того чтобы понять природу ошибки, проанализируем, как платформа работает с модулями менеджеров в разных режимах запуска:
В режиме Тонкого клиента модули менеджеров объектов (МодульМенеджера) компилируются и выполняются исключительно на сервере. Тонкий клиент физически не загружает в себя код этого модуля. Соответственно, если в коде модуля менеджера идет обращение к серверному общему модулю УправлениеПечатью (у которого в свойствах стоит флаг «Сервер» и снят флаг «Клиент (управляемое приложение)»), никаких проблем не возникает. Сервер видит серверные модули, и компиляция проходит успешно.
В режиме Толстого клиента (управляемое приложение) архитектура работы иная. Платформа для обеспечения интерактивных функций компилирует модули менеджеров как на сервере, так и на стороне клиента. В момент компиляции модуля менеджера на стороне толстого клиента система пытается разрешить все ссылки на внешние объекты и модули. Дойдя до строчки с обращением к УправлениеПечатью, клиентский компилятор обнаруживает, что этот общий модуль недоступен в контексте клиента. Из-за отсутствия флага клиентской доступности у общего модуля платформа считает имя УправлениеПечатью неопределенной переменной, что и приводит к критической ошибке компиляции всего модуля менеджера.
Возникает логичный вопрос: почему ошибка не проявляется сразу при открытии формы, а «выстреливает» именно при нажатии кнопок «Записать» или «Провести»?
Дело в механизмах БСП. При записи или проведении документа система инициализирует обновление командного интерфейса формы. Чтобы динамически определить состав доступных команд печати, платформа неявно обращается к метаданным и менеджеру объекта на клиенте. Это обращение инициирует принудительную компиляцию МодуляМенеджера в контексте толстого клиента. В этот момент и происходит сбой.
Для устранения этой ошибки нам необходимо явно указать платформе, что код внутри модуля менеджера не должен компилироваться на стороне клиента. Разберем по шагам, как это сделать:
Шаг 1. Откройте конфигуратор вашей базы данных и перейдите к модулю менеджера проблемного документа (Документ.СопроводительноПисьмоДляПодтверждения0СтавкиНДС.МодульМенеджера).
Шаг 2. Оберните все процедуры и функции модуля менеджера (включая обработчики печати) в специальные инструкции препроцессора. Код должен начинаться с проверки контекста выполнения:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Здесь располагается весь существующий код модуля менеджера, например:
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
// Формирование команд печати БСП
КонецПроцедуры
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СопроводительноПисьмоДляПодтверждения0СтавкиНДС") Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"СопроводительноПисьмоДляПодтверждения0СтавкиНДС",
"Сопроводительное письмо для подтверждения 0 ставки НДС",
СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
);
КонецЕсли;
КонецПроцедуры
#КонецЕсли
Шаг 3. Сохраните изменения и обновите конфигурацию базы данных. Данная инструкция препроцессора гарантирует, что при запуске управляемого приложения в толстом клиенте весь этот код будет просто проигнорирован клиентским компилятором, предотвращая возникновение синтаксической ошибки.
Использование директивы #Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда для модулей объектов и менеджеров является обязательным стандартом разработки фирмы «1С» для любых конфигураций, использующих БСП.
Однако при написании кода следует помнить о важном исключении. Если в модуле менеджера переопределены стандартные обработчики получения представления, такие как:
ОбработкаПолученияПредставленияОбработкаПолученияПолейПредставленияЭти обработчики могут вызываться платформой непосредственно на клиенте (например, при быстром вводе или отображении ссылок в полях ввода). Если обернуть их в общую директиву #Если Сервер..., то при работе в толстом клиенте они перестанут функционировать.
Поэтому правильная структура модуля менеджера должна выглядеть следующим образом:
// 1. Секция кода, которая должна выполняться везде (и на клиенте, и на сервере)
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
// Внутри этой процедуры ЗАПРЕЩЕНО использовать вызовы серверных общих модулей типа УправлениеПечатью
// Код должен быть максимально легковесным и использовать только переданную структуру "Данные"
КонецПроцедуры
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// 2. Основной серверный код модуля менеджера (Экспортные процедуры БСП, печать, выборки данных)
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Безопасный вызов УправлениеПечатью на сервере
КонецПроцедуры
#КонецЕсли
Чтобы не сталкиваться с подобными «сюрпризами» на этапе промышленной эксплуатации, когда пользователи заходят в систему под разными клиентами, настоятельно рекомендуется использовать встроенный механизм проверки конфигурации:
Система автоматически проанализирует все модули конфигурации и выведет список мест, где происходят некорректные вызовы некомпилируемых в данном контексте общих модулей. Это позволит вам оперативно исправить код еще на этапе разработки.