Как исправить ошибку «Неверные параметры "ПолучитьНавигационнуюСсылку"» в отчетах СКД при обновлении платформы 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При обновлении платформы «1С:Предприятие» до версий 8.3.14, 8.3.15 и выше программисты часто сталкиваются с тем, что ранее стабильно работавшие отчеты на базе Системы компоновки данных (СКД) начинают аварийно завершать работу. Ошибка локализуется в модуле объекта отчета, внутри предопределенной процедуры ПриКомпоновкеРезультата, на строке выполнения компоновщика макета: МакетКомпоновки = КомпоновщикМакета.Выполнить(...).

В этой статье мы подробно разберем, почему возникает ошибка «Неверные параметры "ПолучитьНавигационнуюСсылку"», проанализируем внутренние механизмы платформы, вызвавшие это изменение, и рассмотрим три надежных практических способа устранения этой проблемы.

Выясняем причину: почему отчеты «посыпались» на новой платформе?

Главная причина кроется в изменении поведения платформы «1С:Предприятие» при работе с глобальными функциями и отключении устаревших режимов совместимости (в частности, совместимости с версией 8.3.8).

Давайте сопоставим поведение платформы в разных режимах:

  1. В режиме совместимости с 8.3.8 и ниже: Если в функцию ПолучитьНавигационнуюСсылку() передавалось значение, для которого невозможно получить ссылку (например, NULL, Неопределено, пустая ссылка или тип, не поддерживающий получение навигационных ссылок), платформа не генерировала критическую ошибку. Она «молча» возвращала пустую строку, и построение отчета продолжалось в штатном режиме.
  2. В новых версиях платформы (без режима совместимости): Поведение системы было строго унифицировано. Теперь при попытке передать некорректный тип данных или пустое значение в функцию ПолучитьНавигационнуюСсылку() платформа незамедлительно генерирует исключение «Неверные параметры», что приводит к аварийному прерыванию расчета макета компоновки данных.

Но почему это происходит именно в СКД, ведь разработчик может быть абсолютно уверен, что в исходной таблице базы данных все поля заполнены корректно? Разберем этот тонкий момент подробнее.

Дело в том, что СКД рассчитывает вычисляемые поля не только для детальных записей отчета, но и для группировок, а также для общих итогов. На уровне группировки или общего итога детальное ссылочное поле (например, ссылка на справочник) по умолчанию принимает значение NULL или Неопределено. Как только СКД пытается рассчитать макет и обращается к вычисляемому полю на уровне итогов, функция ПолучитьНавигационнуюСсылку() принимает этот самый NULL и моментально вызывает критический сбой всей компоновки.

Также не стоит забывать про левые соединения (Left Join) в запросах СКД. Если в результате соединения для какой-то строки не нашлось соответствия, поле гарантированно вернет NULL, спровоцировав падение отчета.

---

Способ 1. Использование безопасного выражения ВЫБОР в схеме компоновки данных

Самый простой и быстрый способ, не требующий написания программного кода в общих модулях, — это добавление условий проверки непосредственно в выражение вычисляемого поля СКД.

Допустим, в вашем отчете используется следующее выражение вычисляемого поля, которое вызывает ошибку:


СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "")

Для того чтобы обезопасить расчет, заменим его конструкцией ВЫБОР. Мы должны явно указать платформе, что расчет ссылки нужно производить только тогда, когда наше поле заполнено и не является пустым.

Рассмотрим более надежный вариант выражения:


ВЫБОР 
    КОГДА Запрос ЕСТЬ NULL ИЛИ Запрос = НЕОПРЕДЕЛЕНО ИЛИ Запрос = ЗНАЧЕНИЕ(Справочник.Запросы.ПустаяСсылка) 
        ТОГДА "" 
    ИНАЧЕ СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "") 
КОНЕЦ

Если в вашей конфигурации на уровне вычисления выражений СКД доступна функция ЗначениеЗаполнено(), выражение можно сократить до лаконичного вида:


ВЫБОР 
    КОГДА ЗначениеЗаполнено(Запрос) 
        ТОГДА СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("""", ПолучитьНавигационнуюСсылку(Запрос), "") 
    ИНАЧЕ "" 
КОНЕЦ

Этот способ прекрасно подходит для простых отчетов, так как все изменения производятся исключительно внутри конструктора схемы компоновки данных.

---

Способ 2. Создание функции-обертки в общем модуле (Рекомендуемый)

Если вы разрабатываете сложную систему или один и тот же отчет используется в разных вариациях, дублировать громоздкие конструкции ВЫБОР в схемах СКД становится неудобно. Гораздо профессиональнее вынести логику получения ссылки в специальную прокси-функцию серверного общего модуля.

Выполним это решение по шагам:

Шаг 1. Создайте или откройте существующий общий модуль. Обратите внимание на его свойства: у модуля должны быть установлены флаги «Сервер» и «Вызов сервера» (например, модуль ОбщегоНазначенияСервер).

Шаг 2. Напишем экспортную функцию-обертку, которая будет проверять входящий параметр на тип данных и заполненность перед вызовом системного метода:


Функция ПолучитьБезопаснуюНавигационнуюСсылку(Знач СсылкаНаОбъект) Экспорт

    // Проверяем на самые распространенные пустые значения
    Если СсылкаНаОбъект = Неопределено 
        Или СсылкаНаОбъект = NULL 
        Или СсылкаНаОбъект.Пустая() Тогда
        Возврат "";
    КонецЕсли;
    
    // Выполняем строгую проверку типа. Навигационную ссылку можно получить только от ссылочных типов.
    // Проверим, относится ли переданный объект к справочникам или документам.
    ТипОбъекта = ТипЗнч(СсылкаНаОбъект);
    Если Не Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта) 
        И Не Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
        // При необходимости расширьте этот список планами видов характеристик, бизнес-процессами и т.д.
        Возврат "";
    КонецЕсли;

    // Дополнительно страхуем выполнение блоком Попытка...Исключение
    Попытка
        Возврат ПолучитьНавигационнуюСсылку(СсылкаНаОбъект);
    Исключение
        Возврат "";
    КонецПопытки;

КонецФункции

Шаг 3. Перейдите в схему компоновки данных вашего отчета, откройте вкладку «Вычисляемые поля» и замените выражение вызова системной функции на созданную вами безопасную обертку:

ОбщегоНазначенияСервер.ПолучитьБезопаснуюНавигационнуюСсылку(Запрос)

Преимущество этого метода очевидно: код централизован, защищен от любых непредвиденных типов данных (включая ошибочно переданные строки или числа) и гарантирует стабильную работу отчета при любых настройках группировок СКД.

---

Способ 3. Предотвращение появления пустых значений на уровне запроса

Если ваше вычисляемое поле выводится строго в детальных записях (без использования итогов по этому полю), вы можете подстраховать себя еще на уровне написания SQL-запроса в СКД.

Для этого при соединении таблиц или выборке данных всегда используйте функцию ЕСТЬNULL, заменяя потенциальный NULL на пустую ссылку соответствующего справочника или документа.

Рассмотрим пример секции выборки в запросе:


ВЫБРАТЬ
    ЕСТЬNULL(ТаблицаПродаж.ДокументСсылка, ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка)) КАК СсылкаНаДокумент
ИЗ
    РегистрНакопления.Продажи КАК ТаблицаПродаж

Важное предупреждение: этот способ является вспомогательным. Он решает проблему появления NULL в строках детальных записей, но не спасет от генерации ошибки, если поле СсылкаНаДокумент попадет в расчет итогов группировки более высокого уровня в СКД. Поэтому настоятельно рекомендуется совмещать его со Способом 1 или Способом 2.

Резюме

Переход на новые платформы 1С (начиная с 8.3.14) требует от разработчиков более аккуратного написания выражений. Использование безопасной функции-обертки в общем модуле — наиболее надежный и промышленный стандарт решения проблемы с ПолучитьНавигационнуюСсылку. Применение этого подхода позволит вам навсегда забыть о непредвиденных сбоях при формировании сложных аналитических отчетов.

← На главную