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