Почему при программном формировании отчета на СКД не применяются отборы и параметры?

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

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

Разберем подробно причины такого поведения платформы 1С и пошагово выясним, как правильно передавать настройки в СКД.

Причина 1. Сброс настроек в модуле объекта отчета

Самая распространенная ошибка скрывается внутри модуля объекта самого отчета в обработчике события ПриКомпоновкеРезультата. Если разработчик отчета переопределил стандартную обработку формирования и написал следующий код:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // ОШИБКА: берутся базовые настройки из схемы, а не те, что переданы в компоновщик!
    Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    // ... дальнейшая инициализация процессора компоновки ...
КонецПроцедуры

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

Как исправить: в модуле объекта необходимо получать настройки непосредственно из компоновщика настроек отчета с помощью метода ПолучитьНастройки():


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

Причина 2. Замещение настроек пользовательскими настройками

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

Если программно изменить только свойство КомпоновщикНастроек.Настройки, то при формировании или открытии формы старые пользовательские настройки перезапишут переданные значения.

Чтобы гарантированно изменить параметр или отбор, выведенный пользователю, необходимо найти соответствующий элемент в пользовательских настройках по его идентификатору или отключить его использование:


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

Причина 3. Некорректный поиск элемента отбора в коде

Рассмотрим фрагмент кода обхода элементов отбора:


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

Если в схеме компоновки отбор по полю «Номенклатура» не был предварительно добавлен разработчиком, то цикл завершится, условие ни разу не выполнится, и отбор так и не будет установлен.

Разберем надежный алгоритм: ищем существующий отбор, а если он отсутствует — создаем новый элемент программно:


ПолеОтбора = Новый ПолеКомпоновкиДанных("Номенклатура");
НайденныйОтбор = Неопределено;

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

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

НайденныйОтбор.ВидСравнения  = ВидСравненияКомпоновкиДанных.ВСписке;
НайденныйОтбор.ПравоеЗначение = СписокНоменклатуры;
НайденныйОтбор.Использование  = Истина;

Причина 4. Влияние открытия формы и автосохранения настроек

Когда вы вызываете тФорма = текОтчет.ПолучитьФорму(...), а затем тФорма.Открыть(), форма отчета может при инициализации восстанавливать сохраненные настройки пользователя (если у отчета включено свойство автоматического сохранения настроек). Это приводит к тому, что переданные значения затираются сохраненными ранее в базе данных.

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


// Формирование без открытия стандартной формы отчета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
    текОтчет.СхемаКомпоновкиДанных, 
    текОтчет.КомпоновщикНастроек.ПолучитьНастройки(), 
    ДанныеРасшифровки
);

ВнешниеНаборы = Новый Структура;
ВнешниеНаборы.Вставить("ТаблицаДанных", Таблица);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборы, ДанныеРасшифровки, Истина);

ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

ТабДок.Показать("Результат сверки");

Итоговый чек-лист проверки

  1. Проверьте процедуру ПриКомпоновкеРезультата в модуле объекта: макет должен компоноваться через КомпоновщикНастроек.ПолучитьНастройки(), а не через НастройкиПоУмолчанию.
  2. Убедитесь, что переопределяемые параметры и отборы меняются как в Настройки, так и в ПользовательскиеНастройки, если они были вынесены для быстрого доступа.
  3. Проверьте, что имя внешнего набора данных в структуре в точности совпадает с именем набора данных типа «Объект» в схеме СКД.
  4. Предусмотрите добавление нового элемента отбора, если в настройках отчета он еще не был создан.
← На главную