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