Почему в отчете СКД УТ 11 возникает ошибка «Значение не является значением объектного типа (свойства)» при незаполненной стране в адресе?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

«Значение не является значением объектного типа (свойства)»

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

Рассмотрим эту проблему по шагам и проанализируем причины ее возникновения.

Выясним причину: почему запрос работает в консоли, но падает в СКД?

Для начала проанализируем поведение консоли запросов и СКД. Консоль запросов — это инструмент для получения «сырых» данных из базы данных. Когда мы выполняем ЛЕВОЕ СОЕДИНЕНИЕ с табличной частью контактной информации, для партнеров без адреса или без заполненной страны СУБД возвращает стандартное значение NULL. Консоль запросов просто выводит пустую ячейку (или текст "Null") и завершает работу без ошибок.

Однако СКД работает иначе. Она не просто выводит данные, но и выполняет их постобработку:

  1. Автоматическое получение представлений: СКД пытается определить типы связей и автоматически получить текстовые представления для всех ссылочных полей. Если поле связи содержит NULL или некорректно приведенный тип, встроенные функции форматирования могут дать сбой при обращении к свойствам объекта.
  2. Программная обработка в модуле отчета: Во многих типовых отчетах УТ 11 в модуле объекта (в обработчике события ПриКомпоновкеРезультата) или в общих модулях вызывается стандартный код БСП для разбора контактной информации. Этот код перебирает строки результата компоновки и пытается разобрать XML или JSON-строку из поля ЗначенияПолей. Если поле Страна пустое (имеет значение NULL или Неопределено), алгоритм пытается обратиться к свойству этой пустой переменной через точку (например, получить код или наименование страны), что мгновенно приводит к аварийному завершению работы системы.

Рассмотрим пример ошибочного кода в запросе, который предоставил автор темы:


ВЫБОР 
    КОГДА ТабПродаж.Country = "" ТОГДА 0 
    ИНАЧЕ ТабПродаж.Country 
КОНЕЦ КАК Country

В этой конструкции кроется серьезная методическая ошибка. Попытка заменить пустую строку на числовой ноль (0) приводит к конфликту типов в СКД. Платформа ожидает в поле Country ссылку на справочник СтраныМира, а получает число или пустую строку. При попытке СКД обратиться к свойствам этого поля (например, для вывода представления кода страны) возникает ошибка объектного типа.

Устаревание функции «АдресВФорматеКЛАДР» и переход на JSON

Проанализируем ситуацию с функциями разбора адресов в современных релизах УТ 11. В старых версиях конфигураций для преобразования адресов использовалась функция АдресВФорматеКЛАДР. В современных версиях БСП (3.x) эта функция признана устаревшей и полностью удалена из общего модуля РаботаСАдресами.

Это связано с глобальным переходом адресного классификатора РФ с КЛАДР на ФИАС (муниципальное деление) и изменением структуры хранения контактной информации:

Если в вашем отчете (или в кодовой части ПриКомпоновкеРезультата) происходит попытка распарсить современную JSON-строку старыми XML-методами, система не находит нужных тегов. Если при этом у партнера не заполнена страна, парсер возвращает пустое значение Неопределено. Последующий вызов свойств этого значения (например, попытка получить наименование региона или города) вызывает ошибку: «Значение не является значением объектного типа (свойства)».

Решение проблемы: правильная обработка пустых значений в запросе СКД

Чтобы гарантированно победить эту ошибку на уровне запроса и СКД, выполним несколько обязательных шагов.

Шаг 1. Использование ЕСТЬNULL с пустой ссылкой справочника

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

Рассмотрим правильный пример написания этого участка запроса:


ЕСТЬNULL(ПартнерыКонтактнаяИнформация.Страна, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)) КАК Страна

При таком подходе СКД всегда будет видеть в поле Страна объектный тип (пустую ссылку справочника). У пустой ссылки можно без ошибок запрашивать любые реквизиты (код, наименование, предопределенный статус) — платформа вернет пустые значения, но программа не упадет с критической ошибкой.

Шаг 2. Оптимизация запроса с использованием временных таблиц

Использование тяжелых левых соединений с вложенными запросами и виртуальными таблицами в СКД часто приводит к построению неоптимальных планов запросов на СУБД и замедлению работы отчета в десятки раз. Рекомендуется сначала выбирать контактную информацию во временную таблицу (ВТ), предварительно отфильтровав ее по нужному виду контактной информации.

Рассмотрим правильную структуру построения пакета запросов:


// Помещаем контактную информацию во временную таблицу
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ПартнерыКонтактнаяИнформация.Ссылка КАК Партнер,
    ЕСТЬNULL(ПартнерыКонтактнаяИнформация.Страна, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)) КАК Страна,
    ПартнерыКонтактнаяИнформация.Город КАК Город,
    ПартнерыКонтактнаяИнформация.Регион КАК Регион,
    ПартнерыКонтактнаяИнформация.Представление КАК Представление,
    ВЫРАЗИТЬ(ПартнерыКонтактнаяИнформация.ЗначенияПолей КАК СТРОКА(1000)) КАК ЗначениеПолей
ПОМЕСТИТЬ ВТ_Контакты
ИЗ
    Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
ГДЕ
    ПартнерыКонтактнаяИнформация.Вид = &Вид
;

////////////////////////////////////////////////////////////////////////////////
// Основной запрос продаж с левым соединением к ВТ_Контакты
ВЫБРАТЬ
    РеализацияТовары.Ссылка КАК Ссылка,
    РеализацияТовары.Номенклатура КАК Номенклатура,
    РеализацияТовары.Ссылка.Партнер КАК Партнер,
    ВТ_Контакты.Представление КАК Address,
    ВТ_Контакты.Страна КАК Country,
    ВТ_Контакты.Город КАК TownCity,
    ВТ_Контакты.Регион КАК Region
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Контакты КАК ВТ_Контакты
        ПО РеализацияТовары.Ссылка.Партнер = ВТ_Контакты.Partner

Помещение контактной информации в ВТ_Контакты с предварительным отбором по виду контактной информации (&Вид) позволяет СУБД мгновенно сопоставить данные при левом соединении с табличной частью товаров документа.

Шаг 3. Использование современных функций БСП в вычисляемых полях СКД

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

В системе СКД перейдем на вкладку «Вычисляемые поля» и добавим новое поле:

Использование этого выражения гарантирует, что разбор адреса выполнится силами стандартных, оптимизированных и всегда актуальных функций БСП вашей конфигурации. Этот метод автоматически обработает пустые строки, отсутствие страны или региона, сформировав красивое представление адреса в зависимости от того, отечественный это адрес или иностранный.

Сравнительный анализ подходов

Давайте сравним два подхода к решению этой проблемы: программный разбор в ПриКомпоновкеРезультата и обработку непосредственно в запросе СКД.

Критерий сравнения Программный разбор (в модуле) Обработка в запросе и вычисляемых полях СКД
Производительность Низкая. Построчный обход выборки в коде сильно замедляет формирование отчета на больших объемах данных. Высокая. СУБД быстро обрабатывает временные таблицы, а СКД оптимизирует вывод данных.
Стабильность при пустых полях Частые ошибки типа «Значение не является значением объектного типа», если не предусмотрены многоуровневые проверки на NULL и Неопределено. Абсолютная. Функция ЕСТЬNULL гарантирует передачу типизированного значения (пустой ссылки) в систему компоновки.
Зависимость от обновлений 1С Высокая. При обновлении БСП устаревшие функции (например, АдресВФорматеКЛАДР) удаляются, ломая код отчета. Низкая. Вызовы общих модулей в вычисляемых полях СКД легко адаптировать под актуальный программный интерфейс.

Подведем итоги

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

  1. Всегда обрабатывайте поля левого соединения, которые могут вернуть пустые значения, с помощью функции ЕСТЬNULL, приводя их к пустой ссылке соответствующего типа (например, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)).
  2. Не используйте вложенные запросы в левых соединениях основного пакета. Сначала собирайте контактную информацию во временную таблицу с фильтрацией по виду адреса, а затем соединяйте ее с основными данными.
  3. Откажитесь от устаревших процедур ручного разбора XML/JSON-строк адреса (таких как КЛАДР-функции) в модуле отчета. Пользуйтесь современным программным интерфейсом БСП через вычисляемые поля СКД.

Эти несложные правила позволят вам избежать досадных ошибок и кратно ускорить формирование ваших отчетов в «1С:Управление торговлей 11».

← На главную