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