Почему возникает ошибка «Значение не является значением объектного типа (Элементы)» в расшифровке СКД и как ее исправить

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

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

Причина ошибки и правильный контекст выполнения

Выясним причину возникновения ошибки «Значение не является значением объектного типа (Элементы)». В управляемом приложении параметр ДанныеРасшифровки, передаваемый в клиентские события (например, при обработке ячейки табличного документа), содержит не сам объект ДанныеРасшифровкиКомпоновкиДанных, а лишь строковый адрес временного хранилища.

При попытке напрямую обратиться к свойству ДанныеРасшифровки.Элементы на клиенте платформа выдает ошибку, так как у строки нет свойства Элементы. Чтобы получить объект расшифровки, его необходимо выгрузить из временного хранилища на сервере.

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

  1. Передаем строковый адрес ДанныеРасшифровки и числовой идентификатор Расшифровка с клиента на сервер.
  2. На сервере вызываем функцию ПолучитьИзВременногоХранилища() для восстановления объекта ДанныеРасшифровкиКомпоновкиДанных.
  3. Обращаемся к коллекции Элементы полученного объекта.

Рассмотрим пример реализации на языке 1С:


&НаСервере
Функция ПолучитьЗначениеПоляРасшифровки(Знач АдресДанныхРасшифровки, Знач ИдентификаторРасшифровки, ИмяИскомогоПоля)
    
    ДанныеРасшифровкиОбъект = ПолучитьИзВременногоХранилища(АдресДанныхРасшифровки);
    Если ДанныеРасшифровкиОбъект = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    Элемент = ДанныеРасшифровкиОбъект.Элементы.Получить(ИдентификаторРасшифровки);
    Если Элемент = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    // Проверяем поля текущего элемента
    Если ТипЗнч(Элемент) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
        Для Каждого ПолеИзРасшифровки Из Элемент.ПолучитьПоля() Цикл
            Если ПолеИзРасшифровки.Поле = ИмяИскомогоПоля Тогда
                Возврат ПолеИзРасшифровки.Значение;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Почему метод ПолучитьПоля() возвращает NULL

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

  1. Обращение к ресурсным полям: В объекте ДанныеРасшифровкиКомпоновкиДанных по умолчанию не сохраняются значения ресурсов (вычисляемых итогов и сумм). При вызове ПолучитьПоля() для ресурса значение свойства Значение будет равно NULL, даже если в ячейке отчета отображается число.
  2. Иерархия группировок: Искомое поле группировки может находиться выше по дереву отчета (в родительских группировках). В текущем элементе кликнутой ячейки значение этого поля может отсутствовать.
  3. Тип элемента расшифровки: Выбранная ячейка может относиться к типу ЭлементРасшифровкиКомпоновкиДанныхГруппировка, а не к детальным полям.

Способы решения и обход иерархии

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


&НаСервере
Функция НайтиЗначениеПоляСУчетомРодителей(ДанныеРасшифровкиОбъект, ИдентификаторЭлемента, ИмяПоля)
    
    ТекущийИдентификатор = ИдентификаторЭлемента;
    
    Пока ТекущийИдентификатор <> Неопределено Цикл
        Элемент = ДанныеРасшифровкиОбъект.Элементы.Получить(ТекущийИдентификатор);
        Если Элемент = Неопределено Тогда
            Прервать;
        КонецЕсли;
        
        Если ТипЗнч(Элемент) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
            Для Каждого ПолеИзРасшифровки Из Элемент.ПолучитьПоля() Цикл
                Если ПолеИзРасшифровки.Поле = ИмяПоля Тогда
                    Возврат ПолеИзРасшифровки.Значение;
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
        
        // Переходим к родительским элементам
        Родители = Элемент.ПолучитьРодителей();
        Если Родители.Количество() > 0 Тогда
            ТекущийИдентификатор = Родители[0].Идентификатор;
        Иначе
            ТекущийИдентификатор = Неопределено;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Неопределено;
КонецФункции

Для работы со значениями ресурсных полей (когда СКД возвращает NULL) рекомендуются следующие подходы:

← На главную