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

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

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

В этой статье мы подробно разберем, как программно выгрузить результат такого отчета в Таблицу Значений (ТЗ), сохранив при этом ссылки на объекты базы данных, которые "спрятаны" в механизме расшифровки, а не просто получить текстовое представление ячеек.

Суть проблемы

Часто программисты используют метод конвертации табличного документа в таблицу значений через объект ПостроительОтчета. Код обычно выглядит так:


// Пример того, как часто делают (и теряют ссылки)
ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДокумент.Область());
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = ИсточникДанных;
Построитель.Выполнить();
ТаблицаЗначений = Построитель.Результат.Выгрузить();

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

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

Решение 1: Извлечение данных из готового Табличного документа

Если отчет уже сформирован (например, мы находимся в форме отчета и хотим по кнопке обработать результат), то нам нужно работать с парой: ТабличныйДокумент и ДанныеРасшифровки.

Механизм следующий:

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

Посмотрим на алгоритм реализации функции, которая обходит табличный документ и извлекает реальные значения.


// Функция для получения значения расшифровки из ячейки
// ТабДок - сам табличный документ
// ДанныеРасшифровки - объект ДанныеРасшифровкиКомпоновкиДанных (хранится во временном хранилище или реквизите формы)
// ИмяПоля - имя поля СКД, значение которого мы хотим найти (например, "Ссылка")

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

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

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

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

Решение 2: Прямой вывод в Коллекцию Значений

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

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

Разберем этот метод, так как он архитектурно более верный для обработки данных.


// СхемаКомпоновкиДанных - ваша схема
// Настройки - настройки отчета

// 1. Создаем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

// 2. Создаем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

// 3. Создаем процессор вывода НЕ в табличный документ, а в коллекцию
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);

// 4. Выводим
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// Теперь ТаблицаРезультат содержит типизированные колонки.
// Если в СКД было поле "Ссылка", то в ТЗ это будет колонка типа ДокументСсылка.

Этот способ предпочтительнее, если вам не нужно отображать отчет пользователю перед обработкой. Он исключает ошибки парсинга и работает быстрее, так как не тратит ресурсы на отрисовку макета.

Решение 3: "Хитрость" с невидимой колонкой

Иногда требуется компромисс: нужно использовать ПостроительОтчета (как в исходном вопросе автора) для парсинга, но ссылки теряются. Можно применить "костыльный", но рабочий метод на уровне настройки СКД.

Если вы хотите, чтобы ссылка попала в результат парсинга табличного документа:

  1. В выбранные поля отчета добавьте поле "Ссылка".
  2. В настройках "Условного оформления" для этого поля установите цвет текста равным цвету фона (белый на белом).
  3. Или установите минимальную ширину колонки, чтобы она не мешала визуально.

Тогда физически в ячейке будет текст (представление ссылки), и ПостроительОтчета сможет его считать, но это все равно будет строка, которую потом придется искать методом НайтиПоНаименованию или НайтиПоНомеру, что ненадежно. Поэтому мы рекомендуем использовать Решение 1 или Решение 2.

Резюме

Давайте подведем итог. При работе с результатом отчета на СКД:

← На главную