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