Работа с управляемыми формами в 1С подразумевает частое использование объекта ДинамическийСписок. Это мощный инструмент для отображения данных из таблиц базы данных или результатов запросов. Однако, одна из самых распространенных задач, с которой мы сталкиваемся при разработке, — это необходимость отфильтровать этот список при открытии формы или по нажатию кнопки, основываясь на каких-то конкретных условиях. Рассмотрим подробно, как мы можем программно управлять отборами, разберем структуру настроек компоновки данных и проанализируем лучшие практики решения этой задачи.
Прежде чем мы перейдем к написанию кода, давайте разберемся, с чем именно нам предстоит работать. У реквизита формы типа ДинамическийСписок есть свойство КомпоновщикНастроек. Именно через него происходит управление тем, как данные будут выводиться пользователю. Глубокое понимание программной работы с компоновщиком настроек в 1С 8.3 позволяет четко разграничить области ответственности различных коллекций — для быстрой отладки этих параметров есть консоль настройки компоновщика и отладки запросов СКД. Внутри компоновщика нас интересуют две основные коллекции:
Важно понимать разницу. Если мы изменим отбор только в Настройках, пользователь может этого не увидеть в интерфейсе "Еще - Настроить список", хотя фильтрация сработает. Если же мы хотим, чтобы отбор отобразился у пользователя и он мог его снять, нам нужно работать с ПользовательскимиНастройками или связывать их.
Давайте рассмотрим несколько способов решения задачи: от "классического" метода с использованием чистого API платформы до более современного подхода с использованием Библиотеки Стандартных Подсистем (БСП).
Если ваша конфигурация построена на базе БСП (а это большинство современных типовых решений: 1С:ERP, 1С:Бухгалтерия, 1С:УТ и т.д.), то наиболее правильным и быстрым путем будет использование БСП для управления динамическими списками. Это сэкономит время и избавит от написания громоздких конструкций. Чтобы лучше ориентироваться в доступном функционале библиотеки, полезно изучить справочник по методам БСП с примерами использования.
Для работы с отборами динамического списка в БСП существует общий модуль ОбщегоНазначенияКлиентСервер. Рассмотрим, как мы можем применить функцию УстановитьЭлементОтбораДинамическогоСписка.
Предположим, у нас есть список документов, и нам нужно при открытии формы показать только документы за текущий день. Разберем код, который мы поместим в процедуру ПриСозданииНаСервере:
// Определяем параметры отбора
ПолеОтбора = Новый ПолеКомпоновкиДанных("Дата");
ЗначениеОтбора = НачалоДня(ТекущаяДата());
ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
// Вызываем метод БСП
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
ПолеОтбора,
ЗначениеОтбора,
ВидСравнения,
"Период (с текущей даты)", // Представление отбора
Истина // Использовать отбор
);
Разберем параметры, которые мы передали:
Список — это реквизит нашей формы (сам динамический список).ПолеОтбора — имя поля, по которому фильтруем. Обратите внимание, что мы инициализируем объект ПолеКомпоновкиДанных.ЗначениеОтбора — то значение, с которым будем сравнивать.ВидСравнения — условие (Равно, Больше, ВСписке и т.д.).Представление — заголовок отбора, который увидит пользователь.Истина — флаг, включающий использование отбора сразу после установки.Этот метод удобен тем, что он автоматически ищет существующий элемент отбора с таким же полем. Если находит — обновляет его, если нет — создает новый. Это избавляет нас от дублирования отборов при повторном вызове кода.
Теперь представим ситуацию, что мы пишем "с нуля" или в конфигурации нет БСП. В этом случае нам придется работать напрямую с объектной моделью Схемы Компоновки Данных (СКД). Этот процесс более трудоемкий, но позволяет глубже понять механику платформы. Чтобы значительно сократить объем рутинного кода в таких задачах, можно использовать СКДБилдер, который упрощает программное создание СКД.
Давайте проанализируем, как создать элемент отбора вручную:
// 1. Получаем доступ к коллекции элементов отбора
ЭлементыОтбора = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы;
// 2. Создаем новый элемент отбора
НовыйОтбор = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// 3. Указываем левое значение (Поле)
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
// 4. Указываем вид сравнения
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// 5. Указываем правое значение (Значение фильтра)
НовыйОтбор.ПравоеЗначение = Объект.СсылкаНаКонтрагента;
// 6. Включаем использование
НовыйОтбор.Использование = Истина;
// 7. Опционально: режим отображения
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
Давайте подробно разберем важные нюансы этого кода.
Во-первых, свойство ЛевоеЗначение всегда ожидает объект типа ПолеКомпоновкиДанных. Передача просто строки приведет к ошибке или некорректной работе.
Во-вторых, свойство РежимОтображения. Если мы хотим, чтобы пользователь увидел этот отбор над списком и мог его отключить "галочкой", мы устанавливаем РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ. Если же это "технический" отбор, который пользователю менять нельзя, выбираем Недоступный.
Иногда нам нужно установить жесткий отбор, который пользователь вообще не должен видеть в настройках и не должен иметь возможности отключить. Для таких целей идеально подходят фиксированные настройки и параметры запроса динамического списка. Подобные механизмы часто применяются, когда реализуется настройка видимости объектов пользователями в списке базы 1С.
Рассмотрим ситуацию: мы открываем форму выбора номенклатуры, и нам нужно показать только услуги. Пользователь может накладывать свои фильтры поверх, но товары он видеть не должен ни при каких обстоятельствах.
// Создаем новый элемент отбора
ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ВидНоменклатуры");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Перечисления.ВидыНоменклатуры.Услуга;
ЭлементОтбора.Использование = Истина;
Отличие этого кода только в том, что мы обращаемся к Список.КомпоновщикНастроек.ФиксированныеНастройки. Все, что попадает сюда, применяется к запросу динамического списка через логическое "И" с основными настройками, но скрыто от глаз пользователя в стандартном окне настроек.
Часто возникают задачи сложнее, чем просто "Поле = Значение". Например, нам нужно отобрать документы, где "Ответственный = Иванов" ИЛИ "Ответственный = Петров". Для реализации такой логики полезно изучить тему о сложных условиях в динамических списках. В некоторых случаях могут потребоваться дополнительные отборы по диапазону значений или списку соответствий шаблону.
Давайте посмотрим, как создать логическую структуру "ИЛИ":
// 1. Создаем группу с типом "ГруппаИли"
ГруппаИли = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
// 2. Добавляем элементы ВНУТРЬ этой группы
Элемент1 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ответственный");
Элемент1.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент1.ПравоеЗначение = Ответственный1;
Элемент1.Использование = Истина;
Элемент2 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ответственный");
Элемент2.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент2.ПравоеЗначение = Ответственный2;
Элемент2.Использование = Истина;
Создавая ГруппаЭлементовОтбораКомпоновкиДанных, мы можем строить сложные логические деревья условий, комбинируя И, ИЛИ и НЕ. Например, для расширенных возможностей фильтрации по строкам удобно использовать механизм подобно в списке для отборов на соответствие шаблону.
При программной работе с отборами есть риск накопления дублей. Если ваш код выполняется, например, при нажатии кнопки на форме, каждый клик может добавлять новый элемент в коллекцию Элементы. Это приведет к тому, что запрос станет перегруженным и нечитаемым.
Поэтому хорошей практикой считается предварительная очистка или поиск существующего элемента. Разберем функцию для безопасного добавления отбора:
Процедура УстановитьОтборБезопасно(ИмяПоля, Значение)
КоллекцияЭлементов = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы;
// Попытаемся найти существующий отбор
НайденныйЭлемент = Неопределено;
Для Каждого Элемент Из КоллекцияЭлементов Цикл
// Проверяем, что это именно ЭлементОтбора, а не Группа
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
// Сравниваем строковое представление поля
Если Строка(Элемент.ЛевоеЗначение) = ИмяПоля Тогда
НайденныйЭлемент = Элемент;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Если не нашли - создаем, если нашли - обновляем
Если НайденныйЭлемент = Неопределено Тогда
НайденныйЭлемент = КоллекцияЭлементов.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НайденныйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля);
КонецЕсли;
НайденныйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НайденныйЭлемент.ПравоеЗначение = Значение;
НайденныйЭлемент.Использование = Истина;
КонецПроцедуры
Стоит упомянуть важный альтернативный подход. Если ваш ДинамическийСписок построен на основе Произвольного запроса, то часто эффективнее использовать параметры запроса динамического списка, а не отборы СКД.
Например, если в тексте запроса списка написано:
ВЫБРАТЬ
Заказ.Ссылка,
Заказ.Дата,
Заказ.Клиент
ИЗ
Документ.ЗаказКлиента КАК Заказ
ГДЕ
Заказ.Статус = &Статус
То вместо добавления элемента отбора через компоновщик, мы должны установить значение параметра. Делается это следующим образом:
Список.Параметры.УстановитьЗначениеПараметра("Статус", Перечисления.СтатусыЗаказов.ВРаботе);
Разберем преимущества этого метода:
ГДЕ в тексте запроса через интерфейс настроек.Однако, этот метод подходит только для условий, которые должны применяться всегда или логика которых заложена в структуре запроса жестко.
Подводя итог, можно выделить несколько правил для работы с отборами динамического списка:
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка. Это стандарт де-факто.ФиксированныеНастройки.Применяя эти подходы, вы сможете создавать гибкие и удобные интерфейсы, внедряя при необходимости дополнительные элементы управления, такие как флажок в динамическом списке в 1С 8.3, которые корректно реагируют на контекст работы пользователя и не вызывают проблем с производительностью.