При обновлении платформы «1С:Предприятие» до версий 8.3.14, 8.3.15 и выше программисты часто сталкиваются с тем, что ранее стабильно работавшие отчеты на базе Системы компоновки данных (СКД) начинают аварийно завершать работу. Ошибка локализуется в модуле объекта отчета, внутри предопределенной процедуры ПриКомпоновкеРезультата, на строке выполнения компоновщика макета: МакетКомпоновки = КомпоновщикМакета.Выполнить(...).
В этой статье мы подробно разберем, почему возникает ошибка «Неверные параметры "ПолучитьНавигационнуюСсылку"», проанализируем внутренние механизмы платформы, вызвавшие это изменение, и рассмотрим три надежных практических способа устранения этой проблемы.
Главная причина кроется в изменении поведения платформы «1С:Предприятие» при работе с глобальными функциями и отключении устаревших режимов совместимости (в частности, совместимости с версией 8.3.8).
Давайте сопоставим поведение платформы в разных режимах:
ПолучитьНавигационнуюСсылку() передавалось значение, для которого невозможно получить ссылку (например, NULL, Неопределено, пустая ссылка или тип, не поддерживающий получение навигационных ссылок), платформа не генерировала критическую ошибку. Она «молча» возвращала пустую строку, и построение отчета продолжалось в штатном режиме.ПолучитьНавигационнуюСсылку() платформа незамедлительно генерирует исключение «Неверные параметры», что приводит к аварийному прерыванию расчета макета компоновки данных.Но почему это происходит именно в СКД, ведь разработчик может быть абсолютно уверен, что в исходной таблице базы данных все поля заполнены корректно? Разберем этот тонкий момент подробнее.
Дело в том, что СКД рассчитывает вычисляемые поля не только для детальных записей отчета, но и для группировок, а также для общих итогов. На уровне группировки или общего итога детальное ссылочное поле (например, ссылка на справочник) по умолчанию принимает значение NULL или Неопределено. Как только СКД пытается рассчитать макет и обращается к вычисляемому полю на уровне итогов, функция ПолучитьНавигационнуюСсылку() принимает этот самый NULL и моментально вызывает критический сбой всей компоновки.
Также не стоит забывать про левые соединения (Left Join) в запросах СКД. Если в результате соединения для какой-то строки не нашлось соответствия, поле гарантированно вернет NULL, спровоцировав падение отчета.
---
Самый простой и быстрый способ, не требующий написания программного кода в общих модулях, — это добавление условий проверки непосредственно в выражение вычисляемого поля СКД.
Допустим, в вашем отчете используется следующее выражение вычисляемого поля, которое вызывает ошибку:
СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "")
Для того чтобы обезопасить расчет, заменим его конструкцией ВЫБОР. Мы должны явно указать платформе, что расчет ссылки нужно производить только тогда, когда наше поле заполнено и не является пустым.
Рассмотрим более надежный вариант выражения:
ВЫБОР
КОГДА Запрос ЕСТЬ NULL ИЛИ Запрос = НЕОПРЕДЕЛЕНО ИЛИ Запрос = ЗНАЧЕНИЕ(Справочник.Запросы.ПустаяСсылка)
ТОГДА ""
ИНАЧЕ СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "")
КОНЕЦ
Если в вашей конфигурации на уровне вычисления выражений СКД доступна функция ЗначениеЗаполнено(), выражение можно сократить до лаконичного вида:
ВЫБОР
КОГДА ЗначениеЗаполнено(Запрос)
ТОГДА СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "")
ИНАЧЕ ""
КОНЕЦ
Этот способ прекрасно подходит для простых отчетов, так как все изменения производятся исключительно внутри конструктора схемы компоновки данных.
---
Если вы разрабатываете сложную систему или один и тот же отчет используется в разных вариациях, дублировать громоздкие конструкции ВЫБОР в схемах СКД становится неудобно. Гораздо профессиональнее вынести логику получения ссылки в специальную прокси-функцию серверного общего модуля.
Выполним это решение по шагам:
Шаг 1. Создайте или откройте существующий общий модуль. Обратите внимание на его свойства: у модуля должны быть установлены флаги «Сервер» и «Вызов сервера» (например, модуль ОбщегоНазначенияСервер).
Шаг 2. Напишем экспортную функцию-обертку, которая будет проверять входящий параметр на тип данных и заполненность перед вызовом системного метода:
Функция ПолучитьБезопаснуюНавигационнуюСсылку(Знач СсылкаНаОбъект) Экспорт
// Проверяем на самые распространенные пустые значения
Если СсылкаНаОбъект = Неопределено
Или СсылкаНаОбъект = NULL
Или СсылкаНаОбъект.Пустая() Тогда
Возврат "";
КонецЕсли;
// Выполняем строгую проверку типа. Навигационную ссылку можно получить только от ссылочных типов.
// Проверим, относится ли переданный объект к справочникам или документам.
ТипОбъекта = ТипЗнч(СсылкаНаОбъект);
Если Не Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта)
И Не Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
// При необходимости расширьте этот список планами видов характеристик, бизнес-процессами и т.д.
Возврат "";
КонецЕсли;
// Дополнительно страхуем выполнение блоком Попытка...Исключение
Попытка
Возврат ПолучитьНавигационнуюСсылку(СсылкаНаОбъект);
Исключение
Возврат "";
КонецПопытки;
КонецФункции
Шаг 3. Перейдите в схему компоновки данных вашего отчета, откройте вкладку «Вычисляемые поля» и замените выражение вызова системной функции на созданную вами безопасную обертку:
ОбщегоНазначенияСервер.ПолучитьБезопаснуюНавигационнуюСсылку(Запрос)
Преимущество этого метода очевидно: код централизован, защищен от любых непредвиденных типов данных (включая ошибочно переданные строки или числа) и гарантирует стабильную работу отчета при любых настройках группировок СКД.
---
Если ваше вычисляемое поле выводится строго в детальных записях (без использования итогов по этому полю), вы можете подстраховать себя еще на уровне написания SQL-запроса в СКД.
Для этого при соединении таблиц или выборке данных всегда используйте функцию ЕСТЬNULL, заменяя потенциальный NULL на пустую ссылку соответствующего справочника или документа.
Рассмотрим пример секции выборки в запросе:
ВЫБРАТЬ
ЕСТЬNULL(ТаблицаПродаж.ДокументСсылка, ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка)) КАК СсылкаНаДокумент
ИЗ
РегистрНакопления.Продажи КАК ТаблицаПродаж
Важное предупреждение: этот способ является вспомогательным. Он решает проблему появления NULL в строках детальных записей, но не спасет от генерации ошибки, если поле СсылкаНаДокумент попадет в расчет итогов группировки более высокого уровня в СКД. Поэтому настоятельно рекомендуется совмещать его со Способом 1 или Способом 2.
Переход на новые платформы 1С (начиная с 8.3.14) требует от разработчиков более аккуратного написания выражений. Использование безопасной функции-обертки в общем модуле — наиболее надежный и промышленный стандарт решения проблемы с ПолучитьНавигационнуюСсылку. Применение этого подхода позволит вам навсегда забыть о непредвиденных сбоях при формировании сложных аналитических отчетов.