При разработке отчетов в «1С:Управление торговлей 11» (УТ 11) на базе Системы компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда сложный запрос без проблем выполняется в консоли запросов, но при интеграции в схему компоновки данных выдает фатальную ошибку:
«Значение не является значением объектного типа (свойства)»
Особенно часто это происходит при работе с контактной информацией (адресами, телефонами) партнеров или контрагентов, если у некоторых из них не заполнено поле Страна. В этой статье мы подробно разберем, почему возникает данная проблема, как ведут себя механизмы БСП (Библиотеки стандартных подсистем) и СКД при обработке пустых адресов, и как правильно оптимизировать и переписать запрос, чтобы отчет работал быстро и без сбоев.
Рассмотрим эту проблему по шагам и проанализируем причины ее возникновения.
Для начала проанализируем поведение консоли запросов и СКД. Консоль запросов — это инструмент для получения «сырых» данных из базы данных. Когда мы выполняем ЛЕВОЕ СОЕДИНЕНИЕ с табличной частью контактной информации, для партнеров без адреса или без заполненной страны СУБД возвращает стандартное значение NULL. Консоль запросов просто выводит пустую ячейку (или текст "Null") и завершает работу без ошибок.
Однако СКД работает иначе. Она не просто выводит данные, но и выполняет их постобработку:
NULL или некорректно приведенный тип, встроенные функции форматирования могут дать сбой при обращении к свойствам объекта.ПриКомпоновкеРезультата) или в общих модулях вызывается стандартный код БСП для разбора контактной информации. Этот код перебирает строки результата компоновки и пытается разобрать XML или JSON-строку из поля ЗначенияПолей. Если поле Страна пустое (имеет значение NULL или Неопределено), алгоритм пытается обратиться к свойству этой пустой переменной через точку (например, получить код или наименование страны), что мгновенно приводит к аварийному завершению работы системы.Рассмотрим пример ошибочного кода в запросе, который предоставил автор темы:
ВЫБОР
КОГДА ТабПродаж.Country = "" ТОГДА 0
ИНАЧЕ ТабПродаж.Country
КОНЕЦ КАК Country
В этой конструкции кроется серьезная методическая ошибка. Попытка заменить пустую строку на числовой ноль (0) приводит к конфликту типов в СКД. Платформа ожидает в поле Country ссылку на справочник СтраныМира, а получает число или пустую строку. При попытке СКД обратиться к свойствам этого поля (например, для вывода представления кода страны) возникает ошибка объектного типа.
Проанализируем ситуацию с функциями разбора адресов в современных релизах УТ 11. В старых версиях конфигураций для преобразования адресов использовалась функция АдресВФорматеКЛАДР. В современных версиях БСП (3.x) эта функция признана устаревшей и полностью удалена из общего модуля РаботаСАдресами.
Это связано с глобальным переходом адресного классификатора РФ с КЛАДР на ФИАС (муниципальное деление) и изменением структуры хранения контактной информации:
ЗначенияПолей) хранилась в формате XML.Если в вашем отчете (или в кодовой части ПриКомпоновкеРезультата) происходит попытка распарсить современную JSON-строку старыми XML-методами, система не находит нужных тегов. Если при этом у партнера не заполнена страна, парсер возвращает пустое значение Неопределено. Последующий вызов свойств этого значения (например, попытка получить наименование региона или города) вызывает ошибку: «Значение не является значением объектного типа (свойства)».
Чтобы гарантированно победить эту ошибку на уровне запроса и СКД, выполним несколько обязательных шагов.
Ни в коем случае нельзя заменять NULL в ссылочных полях на пустые строки ("") или нули (0). Вместо этого в запросе при левом соединении с табличной частью контактной информации необходимо заменять NULL на пустую ссылку соответствующего справочника. Для поля Страна это справочник СтраныМира.
Рассмотрим правильный пример написания этого участка запроса:
ЕСТЬNULL(ПартнерыКонтактнаяИнформация.Страна, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)) КАК Страна
При таком подходе СКД всегда будет видеть в поле Страна объектный тип (пустую ссылку справочника). У пустой ссылки можно без ошибок запрашивать любые реквизиты (код, наименование, предопределенный статус) — платформа вернет пустые значения, но программа не упадет с критической ошибкой.
Использование тяжелых левых соединений с вложенными запросами и виртуальными таблицами в СКД часто приводит к построению неоптимальных планов запросов на СУБД и замедлению работы отчета в десятки раз. Рекомендуется сначала выбирать контактную информацию во временную таблицу (ВТ), предварительно отфильтровав ее по нужному виду контактной информации.
Рассмотрим правильную структуру построения пакета запросов:
// Помещаем контактную информацию во временную таблицу
ВЫБРАТЬ РАЗРЕШЕННЫЕ
ПартнерыКонтактнаяИнформация.Ссылка КАК Партнер,
ЕСТЬNULL(ПартнерыКонтактнаяИнформация.Страна, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)) КАК Страна,
ПартнерыКонтактнаяИнформация.Город КАК Город,
ПартнерыКонтактнаяИнформация.Регион КАК Регион,
ПартнерыКонтактнаяИнформация.Представление КАК Представление,
ВЫРАЗИТЬ(ПартнерыКонтактнаяИнформация.ЗначенияПолей КАК СТРОКА(1000)) КАК ЗначениеПолей
ПОМЕСТИТЬ ВТ_Контакты
ИЗ
Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
ГДЕ
ПартнерыКонтактнаяИнформация.Вид = &Вид
;
////////////////////////////////////////////////////////////////////////////////
// Основной запрос продаж с левым соединением к ВТ_Контакты
ВЫБРАТЬ
РеализацияТовары.Ссылка КАК Ссылка,
РеализацияТовары.Номенклатура КАК Номенклатура,
РеализацияТовары.Ссылка.Партнер КАК Партнер,
ВТ_Контакты.Представление КАК Address,
ВТ_Контакты.Страна КАК Country,
ВТ_Контакты.Город КАК TownCity,
ВТ_Контакты.Регион КАК Region
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Контакты КАК ВТ_Контакты
ПО РеализацияТовары.Ссылка.Партнер = ВТ_Контакты.Partner
Помещение контактной информации в ВТ_Контакты с предварительным отбором по виду контактной информации (&Вид) позволяет СУБД мгновенно сопоставить данные при левом соединении с табличной частью товаров документа.
Вместо того чтобы вручную разбирать поле ЗначенияПолей (которое в новых версиях хранится в формате JSON) в модуле отчета через устаревшие процедуры, переложим эту задачу на вычисляемые поля СКД.
В системе СКД перейдем на вкладку «Вычисляемые поля» и добавим новое поле:
ПредставлениеАдресаУправлениеКонтактнойИнформациейКлиентСервер.ПредставлениеКонтактнойИнформации(ЗначенияПолей)Использование этого выражения гарантирует, что разбор адреса выполнится силами стандартных, оптимизированных и всегда актуальных функций БСП вашей конфигурации. Этот метод автоматически обработает пустые строки, отсутствие страны или региона, сформировав красивое представление адреса в зависимости от того, отечественный это адрес или иностранный.
Давайте сравним два подхода к решению этой проблемы: программный разбор в ПриКомпоновкеРезультата и обработку непосредственно в запросе СКД.
| Критерий сравнения | Программный разбор (в модуле) | Обработка в запросе и вычисляемых полях СКД |
|---|---|---|
| Производительность | Низкая. Построчный обход выборки в коде сильно замедляет формирование отчета на больших объемах данных. | Высокая. СУБД быстро обрабатывает временные таблицы, а СКД оптимизирует вывод данных. |
| Стабильность при пустых полях | Частые ошибки типа «Значение не является значением объектного типа», если не предусмотрены многоуровневые проверки на NULL и Неопределено. |
Абсолютная. Функция ЕСТЬNULL гарантирует передачу типизированного значения (пустой ссылки) в систему компоновки. |
| Зависимость от обновлений 1С | Высокая. При обновлении БСП устаревшие функции (например, АдресВФорматеКЛАДР) удаляются, ломая код отчета. |
Низкая. Вызовы общих модулей в вычисляемых полях СКД легко адаптировать под актуальный программный интерфейс. |
Для того чтобы отчет в СКД работал стабильно и быстро при получении контактной информации партнеров, придерживайтесь следующих правил:
ЕСТЬNULL, приводя их к пустой ссылке соответствующего типа (например, ЗНАЧЕНИЕ(Справочник.СтраныМира.ПустаяСсылка)).Эти несложные правила позволят вам избежать досадных ошибок и кратно ускорить формирование ваших отчетов в «1С:Управление торговлей 11».