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