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

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

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

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

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

Причина возникновения проблемы в кросс-таблицах

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

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

Способ 1. Рекурсивный сбор отбора в структуру

Рассмотрим первый вариант решения — создание рекурсивной функции, которая обходит всех родителей элемента расшифровки и заполняет структуру значениями найденных полей.

Проанализируем пример функции, принимающей идентификатор расшифровки и возвращающей структуру с именами и значениями полей:


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

Важное замечание: При использовании объекта Структура стоит учитывать, что имена полей компоновки данных, содержащие точку (например, Контрагент.ГоловнойКонтрагент), не могут быть использованы в качестве ключей структуры. Если в отчете используются реквизиты через точку, вместо структуры рекомендуется применять Соответствие или ТаблицаЗначений.

Способ 2. Обход родителей с сохранением в таблицу значений

Разберем еще один подход, применяемый в типовых конфигурациях 1С (например, в «Управление торговлей» или «Бухгалтерия предприятия»). В этом варианте данные собираются в таблицу значений, что исключает ошибки при работе с составными именами полей и исключает дублирование записей.

Посмотрим на реализацию алгоритма:


Функция ПолучитьТаблицуПолейРасшифровки(ИдентификаторРасшифровки, ДанныеРасшифровки)

    ПроверкаПолей = Новый ТаблицаЗначений;
    ПроверкаПолей.Колонки.Добавить("ИмяПоля", Новый ОписаниеТипов("Строка"));
    ПроверкаПолей.Колонки.Добавить("Значение");
    
    ЭлементРасшифровки = ДанныеРасшифровки.Элементы[ИдентификаторРасшифровки];
    ЗаполнитьРодителейРекурсивно(ЭлементРасшифровки, ПроверкаПолей);

    Возврат ПроверкаПолей;

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

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

        КонецЦикла;
    КонецЕсли;

    Для каждого Родитель Из ЭлементРасшифровки.ПолучитьРодителей() Цикл
        ЗаполнитьРодителейРекурсивно(Родитель, ПроверкаПолей);
    КонецЦикла;
    
КонецПроцедуры

Альтернативный подход: Использование программной обработки расшифровки

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

Порядок действий при таком подходе выглядит следующим образом:

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

Подводные камни и рекомендации

При работе с расшифровкой таблицы СКД следует учитывать следующие особенности:

← На главную