Почему не работают изменения варианта отчета (сортировка, отборы) при программном выводе СКД?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

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

Разбор типовой ситуации и ошибки в коде

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


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

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

Решение проблемы: Слияние настроек

Чтобы отчет «увидел» то, что пользователь настроил на форме, необходимо выполнить слияние основных настроек варианта и пользовательских изменений. Для этого в объекте КомпоновщикНастроек существует специальный метод.

Давайте выясним причину, почему это важно. В СКД настройки разделены на уровни. Первый уровень — это сам вариант отчета (структура группировок, выбранные поля). Второй уровень — пользовательские настройки (те, что вынесены в шапку отчета или доступны через кнопку «Настройки»). Метод ПолучитьНастройки() собирает их воедино, создавая результирующий объект настроек, который и должен быть передан в генератор макета.

Исправим наш код. Вместо обращения к схеме напрямую, используем компоновщик настроек отчета:


// Правильный способ получения настроек
НастройкиДляМакета = КомпоновщикНастроек.ПолучитьНастройки();

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

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

Особенности работы с внешними наборами данных

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

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

Проанализируем ситуацию, если сортировка все равно не работает даже после исправления кода:

  1. Проверьте типы полей в СКД: Зайдите в конструктор схемы, на закладку «Наборы данных». Убедитесь, что для полей внешнего набора данных четко указаны типы (например, Число, СправочникСсылка.Номенклатура). Если стоит Любая ссылка или тип не указан, механизм сравнения значений при сортировке может давать сбои.
  2. Имена полей: Убедитесь, что имена колонок в вашей таблице значений (ТЗ) на 100% совпадают с именами полей в наборе данных СКД. Регистр важен.
  3. Использование параметров: Если пользователь меняет параметры (например, дату), убедитесь, что в коде формирования ТЗ вы берете значения не из переменных формы, а из КомпоновщикНастроек.Настройки.ПараметрыДанных.

Полный пример корректного формирования отчета

Сведем все знания воедино и напишем эталонный обработчик ПриКомпоновкеРезультата, который учитывает все пользовательские настройки и корректно работает с внешними данными.


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

Дополнительные рекомендации

Рассмотрим еще один важный момент — оптимизацию. Если ваш отчет работает с огромными объемами данных, расчет всей таблицы значений может занимать много времени. Поскольку мы получили доступ к объекту Настройки в начале процедуры, мы можем проанализировать коллекцию Настройки.Отбор.

Если пользователь установил отбор по конкретной организации или складу, нет смысла выбирать из базы данных все записи. Мы можем программно прочитать эти отборы и подставить их в параметры нашего запроса, который наполняет ТЗ. Это значительно ускорит формирование отчета, сохранив при этом стандартный интерфейс фильтрации СКД для пользователя.

Также помните про Условное оформление. Оно также хранится в пользовательских настройках. Если вы не используете ПолучитьНастройки(), то раскраска строк, выделение жирным шрифтом и другие визуальные эффекты, настроенные пользователем «на лету», не попадут в финальный табличный документ.

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

← На главную