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