При переводе старых конфигураций (особенно использующих обычные формы и построитель отчетов) на новые релизы платформы «1С:Предприятие», начиная с версии 8.3.14, разработчики часто сталкиваются с неприятной ситуацией. Код, который годами стабильно работал на платформе 8.3.12, внезапно отказывается компилироваться, выдавая ошибку:
{ОбщийМодуль.ОбщегоНазначения.Модуль(4333,32)}: Процедура или функция с указанным именем не определена (ПолучитьМакетОформления)
В этой статье мы подробно разберем, почему возникает эта ошибка, как изменилось поведение платформы в новых релизах и какими способами можно быстро и красиво решить эту проблему.
Для начала проанализируем саму функцию ПолучитьМакетОформления(). Согласно официальной документации и синтакс-помощнику, данный метод принадлежит к глобальному контексту, но имеет жесткое ограничение по доступности:
Почему же в старых версиях платформы (например, 8.3.12) эта ошибка не «выстреливала» при старте системы, а в 8.3.14 стала критичной? Дело в механизмах проверки кода и оптимизации компиляции:
ПолучитьМакетОформления(), физически никогда не вызывалась на сервере, платформа могла игнорировать некорректный вызов при запуске. Начиная с версии 8.3.14, валидация кода под все объявленные в свойствах модуля контексты стала обязательной и более строгой.ОбщегоНазначения). У таких модулей в свойствах практически всегда взведен флаг «Сервер». При обновлении платформы система пытается скомпилировать этот модуль для сервера, натыкается на сугубо клиентскую функцию ПолучитьМакетОформления() и прерывает работу с ошибкой.Перейдем к практическим вариантам решения этой проблемы.
Если код, содержащий вызов макета оформления, должен выполняться исключительно на клиенте (в толстом клиенте), самым простым и правильным решением будет явное указание платформе инструкций препроцессора. Мы должны «скрыть» этот участок кода от серверного компилятора.
Рассмотрим подробнее, как переписать проблемный участок кода. Вместо исходного варианта:
ПострПечать.МакетОформления = ПолучитьМакетОформления(?(Оформление = Неопределено, СтандартноеОформление.Интерфейс, Оформление));
Используем конструкцию с директивами препроцессора:
#Если ТолстыйКлиентОбычноеПриложение Или ТолстыйКлиентУправляемоеПриложение Тогда
ПострПечать.МакетОформления = ПолучитьМакетОформления(?(Оформление = Неопределено, СтандартноеОформление.Интерфейс, Оформление));
#Иначе
// Если код компилируется на сервере или в тонком клиенте,
// мы можем либо ничего не делать, либо задать альтернативное поведение.
ПострПечать.МакетОформления = Неопределено;
#КонецЕсли
Этот нехитрый прием полностью решает проблему компиляции общего модуля. Серверный компилятор просто проигнорирует строку внутри условия препроцессора, а толстый клиент успешно выполнит её во время работы пользователя.
Что делать, если построитель отчета инициализируется на стороне сервера (например, в регламентном задании, которое генерирует отчет и отправляет его по электронной почте)? В этом случае директивы препроцессора нам не помогут, так как на сервере функция ПолучитьМакетОформления() физически не может быть выполнена.
Для таких ситуаций мы можем применить изящный обходной путь:
.mxl):
Макет = ПолучитьМакетОформления(СтандартноеОформление.Интерфейс);
Макет.Записать("C:\temp\MyInterfaceTemplate.mxl");
МакетОформленияИнтерфейс.MyInterfaceTemplate.mxl.ПолучитьМакетОформления() и заменить его на обращение к общему макету, который прекрасно работает в любом контексте (и на клиенте, и на сервере):
// Этот код абсолютно безопасен и будет успешно работать на сервере
ПострПечать.МакетОформления = ПолучитьОбщийМакет("МакетОформленияИнтерфейс");
Данный подход гарантирует одинаковый внешний вид отчетов независимо от того, где они формируются.
Если вы столкнулись с этой ошибкой, рекомендуем также проанализировать структуру ваших общих модулей. Зачастую разработчики помещают клиентские процедуры (работающие с формами, интерфейсом или макетами оформления) в универсальные общие модули, у которых включены все галочки компиляции.
Выполните следующие шаги для аудита:
ОбщегоНазначенияКлиент (без флага «Сервер») и ОбщегоНазначенияСервер. Перенесите вызовы работы с макетами оформления в клиентский модуль.Разделение логики по контекстам выполнения — это стандарт хорошего тона при разработке на платформе 1С, который убережет вашу конфигурацию от подобных ошибок при любых последующих обновлениях платформы.