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