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