Как программно передать список значений в параметр отчета СКД?

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает необходимость передать в параметры запроса не одно значение, а целый список (например, массив счетов или номенклатуры), сформированный программно. В этой статье мы подробно разберем, почему стандартные попытки передачи таблицы значений могут не работать, как правильно использовать методы компоновщика настроек и где лучше всего размещать код установки параметров для обеспечения стабильной работы отчета.

Анализ типичной ошибки: Таблица значений против Массива

Рассмотрим ситуацию, с которой сталкиваются многие разработчики: в коде формы выполняется запрос, результат которого выгружается в таблицу значений, а затем эта таблица присваивается параметру СКД. Проанализируем исходный код, который часто приводит к ошибке:


&НаСервереБезКонтекста
Функция ПриОткрытииНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ ПланСчетов.Хозрасчетный ГДЕ Ссылка В ИЕРАРХИИ(&Родитель)";
    Запрос.УстановитьПараметр("Родитель", ПланыСчетов.Хозрасчетный.РасчетыСПокупателямиИЗаказчиками);
    Возврат Запрос.Выполнить().Выгрузить(); // Ошибка здесь: возвращается ТаблицаЗначений
КонецФункции

Основная проблема заключается в том, что параметр СКД, предназначенный для использования в условиях В ИЕРАРХИИ или В СПИСКЕ, ожидает объект типа Массив или СписокЗначений. Платформа 1С не может автоматически преобразовать ТаблицаЗначений в список элементов, даже если в таблице всего одна колонка. Чтобы исправить это, нам необходимо выгрузить конкретную колонку. Разберем правильный подход:


// Вместо Выгрузить() используем ВыгрузитьКолонку()
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
    СчетаМассив = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
    Возврат СчетаМассив;
КонецЕсли;

Метод УстановитьЗначениеПараметра: почему это стандарт?

Вместо ручного поиска элемента в коллекции ПараметрыДанных и установки свойства Значение, рекомендуется использовать встроенный метод УстановитьЗначениеПараметра. Проанализируем преимущества этого метода. Во-первых, он автоматически устанавливает флаг Использование в значение Истина. Во-вторых, он работает быстрее и читается проще. Посмотрим на пример кода:


// Вместо трех строк поиска и установки:
// Элемент = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("Счет");
// Элемент.Использование = Истина;
// Элемент.Значение = Счета;

// Используем одну эффективную строку:
Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Счет", Счета);

Синхронизация с Пользовательскими настройками

В современных конфигурациях на управляемых формах параметры отчета часто выносятся в область пользовательских настроек (шапка отчета). Выясним важный нюанс: если мы программно меняем параметр в КомпоновщикНастроек.Настройки, а этот параметр уже есть в КомпоновщикНастроек.ПользовательскиеНастройки, то визуально на форме значение может не измениться, так как пользовательские настройки имеют приоритет.

Для решения этой проблемы необходимо убедиться, что изменения отражены в обеих коллекциях. Метод УстановитьЗначениеПараметра в последних версиях платформы 8.3 умеет синхронизировать эти данные автоматически, если параметр корректно связан через ИдентификаторПользовательскойНастройки. Однако, если вы работаете со сложными структурами, полезно проверить наличие параметра в пользовательских настройках вручную:


Для Каждого ЭлементНастройки Из Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
    Если ТипЗнч(ЭлементНастройки) = Тип("ЗначениеПараметраКомпоновкиДанных") 
        И ЭлементНастройки.Параметр = Новый ПараметрКомпоновкиДанных("Счет") Тогда
        ЭлементНастройки.Значение = Счета;
        ЭлементНастройки.Использование = Истина;
    КонецЕсли;
КонецЦикла;

Оптимальное место для установки параметров: Модуль объекта

Рассмотрим архитектурный совет: установка параметров в событии ПриОткрытии формы не всегда является лучшим решением. Если отчет будет формироваться программно (например, регламентным заданием или из другой обработки), код формы просто не выполнится. Проанализируем альтернативный вариант — использование модуля объекта отчета и процедуры ПриКомпоновкеРезультата.

Этот метод гарантирует выполнение кода непосредственно перед генерацией отчета, независимо от того, открыта форма или нет. Рассмотрим пример реализации в модуле объекта:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем значение параметра, если оно еще не установлено пользователем
    ПараметрСчет = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("Счет");
    
    Если ПараметрСчет <> Неопределено И Не ПараметрСчет.Использование Тогда
        // Здесь мы можем вызвать серверную функцию для получения списка счетов
        СписокСчетов = ПолучитьСписокСчетовПрограммно(); 
        КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Счет", СписокСчетов);
    КонецЕсли;
    
КонецПроцедуры

Передача параметров в Виртуальные таблицы

Когда мы работаем с планом счетов или регистрами бухгалтерии, крайне важно передавать параметры не просто в условия ГДЕ, а непосредственно в параметры виртуальных таблиц. Это существенно повышает производительность СУБД. Выясним, как это выглядит в тексте запроса СКД:

Неправильно (медленно):


ВЫБРАТЬ * ИЗ РегистрБухгалтерии.Хозрасчетный.Остатки КАК Остатки
ГДЕ Остатки.Счет В ИЕРАРХИИ (&Счет)

Правильно (быстро):


ВЫБРАТЬ * ИЗ РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет В ИЕРАРХИИ (&Счет), , ) КАК Остатки

При таком подходе платформа накладывает фильтр на этапе формирования временных таблиц базы данных, что исключает обработку лишних записей.

Использование выражений в СКД для автоматизации

Разберем еще один эффективный способ, который позволяет избежать написания лишнего кода в модулях. В СКД на закладке "Параметры" есть колонка "Выражение". Здесь можно использовать функции общих модулей или встроенного языка. Например, если вам всегда нужно получать иерархию определенного счета, вы можете прописать в поле выражения:


// В поле "Выражение" для параметра в СКД
ПланыСчетов.Хозрасчетный.РасчетыСПокупателямиИЗаказчиками

Если же требуется более сложная логика (например, получение массива), можно создать функцию в общем модуле с флагом Сервер и вызвать её прямо из выражения параметра СКД: МойОбщийМодуль.ПолучитьСписокСчетовДляОтчета().

Резюме по шагам

Подведем итоги и составим алгоритм действий для надежной передачи параметров в СКД:

  1. Проверьте тип данных: Убедитесь, что вы передаете Массив или СписокЗначений, а не таблицу значений.
  2. Используйте правильный метод: Применяйте КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Имя", Значение) для автоматической активации параметра.
  3. Учитывайте контекст: Если отчет на управляемых формах, проверьте синхронизацию с ПользовательскиеНастройки.
  4. Оптимизируйте место вызова: Старайтесь переносить логику заполнения параметров в модуль объекта (ПриКомпоновкеРезультата) для универсальности.
  5. Настройте видимость: Если параметр устанавливается только программно и пользователь не должен его видеть, установите флаг "Ограничение доступности" на закладке параметров в схеме компоновки.

Следуя этим рекомендациям, вы сможете создавать гибкие и производительные отчеты, которые корректно обрабатывают динамически формируемые фильтры и списки значений.

← На главную