При разработке отчетов на системе компоновки данных (СКД) в среде 1С:Предприятие на обычных формах (например, в УПП или КА 1.1) программисты часто сталкиваются с досадной проблемой. Если открыть отчет стандартным способом через Файл — Открыть, то ссылки в итоговой таблице работают корректно: двойной клик по заказу или номенклатуре открывает соответствующую форму объекта. Однако стоит реализовать программный вызов этого же отчета из другой формы или обработки, как расшифровка «ломается» — вместо открытия документа система воспринимает ячейку как обычный текст.
В этой статье мы подробно разберем, почему так происходит, изучим внутренние механизмы расшифровки СКД и научимся правильно инициализировать отчет программно, чтобы сохранить интерактивность ссылок.
Для начала проанализируем ситуацию. Когда мы работаем с табличным документом, сформированным через СКД, ссылка в ячейке — это не просто значение типа ДокументСсылка. Это сложная структура. В свойстве Расшифровка конкретной ячейки хранится числовой идентификатор (индекс).
Чтобы при нажатии на это число платформа поняла, какой именно объект нужно открыть, ей нужна «карта соответствия». Эта карта хранится в специальном объекте ДанныеРасшифровкиКомпоновкиДанных. Если мы открываем отчет интерактивно, платформа берет создание этого объекта на себя. Но при программном вызове метода СкомпоноватьРезультат, если не указать второй параметр, данные расшифровки просто не формируются. В итоге в таблице есть визуальный текст, есть даже индекс в ячейке, но нет хранилища, где этот индекс расшифровывается в реальную ссылку.
Рассмотрим ситуацию, когда нам нужно открыть внешний отчет из конфигурации или другого файла и передать в него настройки (например, отбор по номенклатуре). Типичная ошибка — вызвать компоновку без передачи контейнера для расшифровки.
Давайте пошагово разберем, как должен выглядеть код, чтобы всё «залетало». Нам необходимо не только создать форму, но и подготовить объект для хранения данных расшифровки, а затем связать его с формой отчета.
Шаг 1: Подготовка внешнего объекта
Сначала мы получаем форму внешнего отчета. Проанализируем пример кода для обычных форм:
// Получаем ссылку на внешнюю обработку/отчет из справочника (или из файла)
СсылкаНаОбъект = Справочники.ВнешниеОбработки.НайтиПоКоду("000000072");
ИмяФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанные = СсылкаНаОбъект.ХранилищеВнешнейОбработки.Получить();
ДвоичныеДанные.Записать(ИмяФайла);
// Получаем форму отчета
Форма = ВнешниеОтчеты.ПолучитьФорму(ИмяФайла);
Шаг 2: Установка настроек и инициализация расшифровки
Теперь самое важное. Мы должны создать объект ДанныеРасшифровкиКомпоновкиДанных. Без этого шага двойной клик по ячейке будет выдавать лишь текстовое представление ссылки.
Если Не Форма = Неопределено Тогда
// 1. Устанавливаем необходимые отборы
НастройкиКД = Форма.КомпоновщикНастроек.ПолучитьНастройки();
// (Здесь идет код добавления отборов, например, по Номенклатуре)
// ...
Форма.КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиКД);
// 2. КЛЮЧЕВОЙ МОМЕНТ: Создаем объект для данных расшифровки
ДанныеРасшифровкиОбъект = Новый ДанныеРасшифровкиКомпоновкиДанных;
// 3. Компонуем результат, передавая объект расшифровки вторым параметром
// ЭлементыФормы.Результат — это ПолеТабличногоДокумента на форме отчета
Форма.СкомпоноватьРезультат(Форма.ЭлементыФормы.Результат, ДанныеРасшифровкиОбъект);
// 4. Связываем полученные данные с реквизитом формы
// В обычных формах СКД у формы должен быть реквизит ДанныеРасшифровки
Форма.ДанныеРасшифровки = ДанныеРасшифровкиОбъект;
// 5. Открываем форму
Форма.Открыть();
КонецЕсли;
Разберем подробнее, что произошло в методе СкомпоноватьРезультат(ТабДок, ДанныеРасшифровки). Когда СКД обходит записи запроса и выводит их в ТабДок, она заполняет переданный объект ДанныеРасшифровки. В нем создается иерархическая структура: какие поля группировок были выведены, какие значения полей детальных записей там находятся и какие значения параметров использовались.
Когда вы присваиваете Форма.ДанныеРасшифровки = ДанныеРасшифровкиОбъект, вы сообщаете обработчику событий формы: «Если пользователь кликнет по таблице, ищи значения здесь». Теперь платформа, видя индекс в ячейке, обращается к этому объекту, находит там ДокументСсылка.ЗаказПокупателя и выполняет стандартное действие — открытие формы документа.
Иногда даже при наличии правильного кода расшифровка не срабатывает. Проанализируем возможные причины, связанные с настройками самого элемента Результат (Поле табличного документа):
Истина. Если ячейка доступна для редактирования текста, платформа при двойном клике просто предложит вам изменить текст, вместо того чтобы вызвать механизм расшифровки.ДанныеРасшифровки. В стандартных отчетах на СКД он создается автоматически, но при ручном создании формы его можно забыть.Если вам нужно не просто открыть документ, а, например, выполнить специфическое действие (открыть другой отчет или изменить текущий), вы можете переопределить процедуру РезультатОбработкаРасшифровки. Посмотрим, как извлечь саму ссылку в коде:
Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка)
Перем ВыполненноеДействие;
// Если мы хотим программно получить ссылку из ячейки:
ТекущиеДанные = ДанныеРасшифровки.Элементы[Расшифровка];
Если ТипЗнч(ТекущиеДанные) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
Поля = ТекущиеДанные.ПолучитьПоля();
Для Каждого Поле Из Поля Цикл
Если Поле.Поле = "Заказ" Тогда
СсылкаНаЗаказ = Поле.Значение;
// Теперь со ссылкой можно работать
Сообщить("Выбран документ: " + СсылкаНаЗаказ);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Использование этого подхода позволяет полностью контролировать поведение отчета, сохраняя при этом все преимущества компоновки данных. Главное помнить: без передачи объекта расшифровки при компоновке, параметр "Расшифровка" в обработчике будет бесполезен, так как он будет ссылаться на несуществующие данные.
Таким образом, мы выяснили, что секрет «оживления» ссылок в программно открытых отчетах СКД заключается в явном создании и связывании объекта ДанныеРасшифровкиКомпоновкиДанных. Это гарантирует, что ваши отчеты будут удобными и функциональными для конечного пользователя.