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