Как программно получить текстовое представление отбора в СКД

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

В процессе разработки отчетов на базе Системы компоновки данных (СКД) часто возникает необходимость программно получить ту самую строку, которую платформа автоматически выводит в шапке отчета. Например: ЦФО Получателя Равно "Армавир". Казалось бы, задача тривиальная, но стандартный метод Строка() для одиночного элемента отбора возвращает лишь тип объекта — "ЭлементОтбораКомпоновкиДанных". В этой статье мы подробно разберем, как обойти это ограничение и получить читаемое представление отбора различными способами.

Разбор проблемы: почему Строка() не работает напрямую

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

Способ 1: Использование приведения типов для всей коллекции

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

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


// Создаем временную коллекцию отборов
ВременныйОтбор = Новый ОтборКомпоновкиДанных;

// Копируем нужный нам элемент во временную коллекцию
НовыйЭлемент = ВременныйОтбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЗаполнитьЗначенияСвойств(НовыйЭлемент, ТекущийЭлементОтбора);

// Получаем представление
ТекстОтбора = Строка(ВременныйОтбор);

Этот метод хорош тем, что он полностью полагается на механизмы платформы. Он правильно обработает системные представления видов сравнения («Равно», «В списке» и т.д.) и корректно выведет значения ссылочных типов.

Способ 2: Ручная сборка строки представления

Иногда требуется сформировать представление в особом формате, который отличается от стандартного платформенного. В этом случае нам придется перебирать свойства элемента отбора. Разберем по шагам, как это реализовать, учитывая заголовки полей.

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


Функция ПолучитьТекстЭлементаОтбора(ЭлементОтбора, КомпоновщикНастроек)
    
    // Если у элемента уже заполнено пользовательское представление, используем его
    Если ЗначениеЗаполнено(ЭлементОтбора.Представление) Тогда
        Возврат ЭлементОтбора.Представление;
    КонецЕсли;
    
    // Ищем заголовок поля в доступных полях отбора
    ИмяПоля = Строка(ЭлементОтбора.ЛевоеЗначение);
    ЗаголовокПоля = ИмяПоля;
    
    ПолеОтбора = КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.Элементы.Найти(ИмяПоля);
    Если ПолеОтбора <> Неопределено Тогда
        ЗаголовокПоля = ПолеОтбора.Заголовок;
    КонецЕсли;
    
    // Формируем строку. Внимание: для разных видов сравнения логика может отличаться!
    Текст = СтрШаблон("%1 %2 %3", 
        ЗаголовокПоля, 
        Строка(ЭлементОтбора.ВидСравнения), 
        Строка(ЭлементОтбора.ПравоеЗначение));
        
    Возврат Текст;
    
КонецФункции

Важное замечание: При ручной сборке необходимо отдельно обрабатывать вид сравнения В списке. Если ПравоеЗначение — это СписокЗначений, то простой вызов Строка() вернет системную надпись «Список значений» вместо перечисления элементов. В таких случаях нужно обходить список в цикле и соединять элементы через запятую.

Способ 3: Использование механизмов БСП

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

Рассмотрим использование функции ПредставлениеОтбора. Этот метод учитывает иерархию (группы «И», «ИЛИ»), сложные типы данных и локализацию видов сравнения. Как правило, вызов выглядит следующим образом:


// Пример для БСП
ТекстОтбора = ОтчетыКлиентСервер.ПредставлениеОтбора(КомпоновщикНастроек.Настройки.Отбор);

Использование БСП — это наиболее правильный путь для типовых конфигураций (БП 3.0, УТ 11, ERP), так как код там уже оптимизирован и протестирован на различных версиях платформы.

Способ 4: Сериализация в XML (метод для продвинутых)

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


Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
СериализаторXDTO.ЗаписатьXML(Запись, Настройки);

// После записи можно анализировать XML-структуру или 
// использовать Строка(Настройки.Отбор) для получения текста.
Представление = Строка(Настройки.Отбор);

Хотя сам XML не дает нам прямого текста, процесс получения настроек через компоновщик актуализирует внутренние представления объектов, что иногда помогает корректно отработать функции Строка().

Решение проблемы с ошибкой «Совпадают значения параметра»

В ходе обсуждения (сообщения 6-7) была затронута важная проблема: при программной установке отборов и открытии формы отчета часто возникает ошибка "Невозможно применить фиксированные настройки. Совпадают значения параметра". Выясним причину этого поведения.

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

Рассмотрим правильный алгоритм программного открытия отчета с отбором:

  1. Выясним, где именно мы хотим установить отбор. Если мы хотим, чтобы пользователь мог его изменить, используйте ПользовательскиеНастройки.
  2. Если мы передаем структуру отбора через параметры формы, платформа сама пытается сопоставить их. Чтобы избежать конфликта, перед загрузкой новых настроек рекомендуется очистить текущие пользовательские настройки.
  3. В современных конфигурациях вместо прямой передачи структуры Отбор лучше использовать параметр формы ПользовательскиеНастройки, предварительно сконструировав объект ПользовательскиеНастройкиКомпоновкиДанных.

Пример корректной передачи параметров:


ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);

// Вместо прямой вставки "Отбор", лучше подготовить настройки
Настройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
// ... здесь программно меняем Настройки.Отбор ...

ПараметрыФормы.Вставить("ФиксированныеНастройки", Настройки);
ОткрытьФорму("Отчет.ИмяОтчета.Форма", ПараметрыФормы);

Подведем итоги

Для получения программного представления отбора в СКД мы рекомендуем придерживаться следующей иерархии решений:

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

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

← На главную