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