При работе с платформой 1С:Предприятие 8.3 в режиме управляемого приложения часто возникает необходимость программно управлять содержимым динамических списков на формах. Например, мы хотим, чтобы при открытии формы список автоматически показывал только определенные элементы справочника или документа, соответствующие заданным критериям. В этой статье мы подробно рассмотрим, как правильно и эффективно установить программный отбор для динамического списка в управляемой форме.
Нашей задачей является создание такого механизма отбора, который будет работать корректно, позволит гибко настраивать условия фильтрации и при этом не будет создавать неудобств для пользователя.
Прежде чем перейти к практическим примерам, давайте вспомним, что такое динамический список в 1С 8.3. Это универсальный механизм отображения данных, который позволяет получать информацию из различных источников (справочников, документов, регистров) с помощью системы компоновки данных (СКД). Он является элементом управляемой формы и обладает собственным набором настроек, которые можно модифицировать как интерактивно пользователем, так и программно.
Ключевым моментом является различие между самим объектом данных ДинамическийСписок, который используется для описания источника данных, и элементом формы, который отображает этот список на экране. Для программного управления отбором на форме нам необходимо взаимодействовать именно с элементом формы.
Часто разработчики-новички или те, кто только осваивает управляемые формы, пытаются установить отбор, обращаясь непосредственно к свойству Отбор у самого объекта ДинамическийСписок (например, Список.Отбор.Элементы.Добавить(...)). Давайте рассмотрим пример такого подхода, который обычно не приносит желаемого результата:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Предположим, что "Список" - это имя реквизита формы типа "ДинамическийСписок"
// Такой код часто встречается при попытке установить отбор,
// но он обычно не работает, как ожидается, для элементов формы.
Отбор = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Код");
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ПравоеЗначение = "00001";
Отбор.Использование = Истина;
КонецПроцедуры
Причина, по которой данный код неэффективен для управляемых форм, заключается в том, что свойство Список.Отбор представляет собой настройки отбора, относящиеся к самому объекту СКД, который лежит в основе динамического списка. В контексте управляемой формы, где динамический список является элементом формы, необходимо обращаться к его визуальным настройкам через коллекцию Элементы формы.
Для корректной работы отбора нам необходимо воздействовать на объект НастройкаОтбора, который принадлежит конкретному элементу формы, отображающему динамический список.
Для успешной программной установки отбора в динамическом списке управляемой формы, мы должны работать с коллекцией Элементы формы и свойством НастройкаОтбора у конкретного элемента, представляющего наш динамический список. Разберем этот процесс по шагам.
Предположим, у нас есть элемент формы с именем СписокКонтрагентов, который отображает динамический список справочника "Контрагенты", и мы хотим отобрать только контрагентов с определенным кодом.
Получаем доступ к настройкам отбора элемента формы. Мы обращаемся к коллекции Элементы формы по имени нашего динамического списка и затем к его свойству НастройкаОтбора. Это свойство возвращает объект типа НастройкиКомпоновкиДанных, содержащий коллекцию Элементы, куда мы и будем добавлять наши условия отбора.
Добавляем новый элемент отбора. В коллекцию Элементы объекта НастройкаОтбора мы добавляем новый элемент, указывая его тип как Тип("ЭлементОтбораКомпоновкиДанных"). Это будет наше конкретное условие фильтрации.
Задаем левое значение. Свойство ЛевоеЗначение нового элемента отбора определяет поле данных, по которому мы будем производить фильтрацию. Мы создаем новый объект ПолеКомпоновкиДанных и указываем в нем имя поля из источника данных динамического списка. Например, для отбора по коду это будет Новый ПолеКомпоновкиДанных("Код").
Указываем вид сравнения. Свойство ВидСравнения определяет, как будут сравниваться левое и правое значения. Например, ВидСравненияКомпоновкиДанных.Равно для точного совпадения, ВидСравненияКомпоновкиДанных.Больше, ВидСравненияКомпоновкиДанных.Содержит и так далее.
Устанавливаем правое значение. Свойство ПравоеЗначение определяет значение, с которым будет сравниваться ЛевоеЗначение. Это может быть строка, число, дата, ссылка на объект и т.д.
Активируем отбор и при необходимости скрываем его от пользователя. Свойство Использование элемента отбора должно быть установлено в Истина, чтобы отбор применялся. Свойство РежимОтображения позволяет нам управлять видимостью элемента отбора для пользователя. Если мы устанавливаем его в РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать, пользователь не увидит этот отбор в окне настроек списка и не сможет его изменить, что часто бывает необходимо для служебных отборов.
Посмотрим на пример кода, который реализует описанный подход:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем доступ к настройкам отбора элемента формы "СписокКонтрагентов"
НастройкаОтбора = Элементы.СписокКонтрагентов.НастройкаОтбора;
// Добавляем новый элемент отбора в коллекцию
ЭлементОтбора = НастройкаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Устанавливаем левое значение - поле "Код" из источника данных списка
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Код");
// Устанавливаем вид сравнения - "Равно"
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// Устанавливаем правое значение - конкретный код контрагента
ЭлементОтбора.ПравоеЗначение = "00001";
// Активируем использование этого отбора
ЭлементОтбора.Использование = Истина;
// Устанавливаем режим отображения, чтобы пользователь не видел и не мог изменить этот отбор
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать;
КонецПроцедуры
В этом примере мы используем процедуру ПриСозданииНаСервере, которая выполняется при создании формы на сервере. Это идеальное место для установки начальных отборов, которые должны действовать сразу после открытия формы.
Давайте подробнее остановимся на каждом свойстве ЭлементОтбораКомпоновкиДанных, чтобы глубже понять их назначение:
ЛевоеЗначение (тип ПолеКомпоновкиДанных): Это поле данных, по которому будет производиться сравнение. Например, "Ссылка", "Наименование", "ПометкаУдаления".ВидСравнения (тип ВидСравненияКомпоновкиДанных): Определяет логику сравнения. Наиболее часто используемые значения:
Равно: Значения равны.НеРавно: Значения не равны.Больше, Меньше, БольшеИлиРавно, МеньшеИлиРавно: Для числовых и датовых сравнений.Содержит, НеСодержит: Для строковых значений, проверяет вхождение подстроки.НачинаетсяС, ЗаканчиваетсяНа: Для строковых значений, проверяет начало/конец строки.ВСписке, НеВСписке: Для отбора по нескольким значениям (см. следующий раздел).ПравоеЗначение: Значение, с которым сравнивается ЛевоеЗначение. Тип этого значения должен соответствовать типу данных поля, указанного в ЛевоеЗначение.Использование (тип Булево): Если Истина, отбор применяется. Если Ложь, отбор игнорируется. Позволяет временно отключать отборы.РежимОтображения (тип РежимОтображенияЭлементаНастройкиКомпоновкиДанных): Управляет видимостью отбора в пользовательских настройках.
Отображать: Отбор виден и доступен для изменения пользователем.НеОтображать: Отбор скрыт от пользователя и не может быть изменен им.БыстрыйДоступ: Отбор отображается в панели быстрого отбора.Часто возникает ситуация, когда нам нужно отобрать элементы динамического списка не по одному конкретному значению, а по нескольким. Например, показать контрагентов с кодами "00001", "00005" и "00010". Для этого мы можем использовать ВидСравненияКомпоновкиДанных.ВСписке, а в качестве ПравоеЗначение передать объект типа СписокЗначений.
Рассмотрим, как это реализовать, а также как можно обновлять существующий отбор, вместо того чтобы каждый раз добавлять новый.
&НаСервере
Процедура УстановитьОтборПоСпискуКодов(СписокКодовДляОтбора)
// Создаем или получаем список значений для отбора
// В реальном сценарии СписокКодовДляОтбора может приходить как параметр
// или формироваться динамически на основе других данных.
// Для примера создадим его здесь:
Если СписокКодовДляОтбора = Неопределено Тогда
СписокКодовДляОтбора = Новый СписокЗначений();
СписокКодовДляОтбора.Добавить("00001");
СписокКодовДляОтбора.Добавить("00002");
СписокКодовДляОтбора.Добавить("00005");
КонецЕсли;
НастройкаОтбора = Элементы.СписокКонтрагентов.НастройкаОтбора;
// Попробуем найти существующий элемент отбора по полю "Код"
// Это позволяет избежать дублирования отборов при повторных вызовах процедуры.
ЭлементОтбора = НастройкаОтбора.Элементы.Найти("Код", "ЛевоеЗначение");
// Если элемент отбора не найден, создаем новый
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = НастройкаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Код");
КонецЕсли;
// Устанавливаем вид сравнения "ВСписке"
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
// В качестве правого значения передаем наш СписокЗначений
ЭлементОтбора.ПравоеЗначение = СписокКодовДляОтбора;
// Активируем отбор
ЭлементОтбора.Использование = Истина;
// Скрываем отбор от пользователя
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать;
КонецПроцедуры
// Пример вызова этой процедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьОтборПоСпискуКодов(Неопределено); // Будет использован список из процедуры
КонецПроцедуры
В этом примере мы демонстрируем несколько важных моментов:
Использование СписокЗначений: Объект СписокЗначений идеально подходит для передачи множественных значений в ПравоеЗначение при использовании видов сравнения ВСписке или НеВСписке.
Поиск существующего отбора: Метод Найти() коллекции Элементы позволяет нам проверить, существует ли уже отбор по заданному полю ("Код" в данном случае), и либо обновить его, либо создать новый. Это предотвращает создание дублирующих элементов отбора, что может привести к непредсказуемому поведению или лишним элементам в настройках списка.
Этот подход делает код более гибким и позволяет легко менять критерии отбора без перезаписи всей структуры.
Выбор места размещения кода для установки отбора зависит от конкретной логики работы вашей формы:
ПриСозданииНаСервере: Как мы уже рассмотрели, это оптимальное место для установки отборов, которые должны применяться при первоначальном открытии формы. Код выполняется один раз на сервере до первого отображения формы клиенту.
Обработчики командных кнопок: Если отбор должен изменяться по действию пользователя (например, после нажатия кнопки "Применить фильтр"), то код установки отбора размещают в обработчике команды (процедура, которая вызывается при нажатии на кнопку). В этом случае после изменения отбора необходимо будет обновить динамический список, вызвав метод Элементы.ИмяДинамическогоСписка.Обновить() или Элементы.ИмяДинамическогоСписка.ОтключитьАвтоОбновление(Ложь) если автообновление было отключено.
ПриОткрытии (клиентская процедура с вызовом на сервер): В некоторых случаях, когда параметры для отбора формируются на клиенте, может потребоваться вызов серверной процедуры из ПриОткрытии для установки отбора. Например:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если МоеУсловиеНаКлиенте Тогда
УстановитьОтборНаСервере();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура УстановитьОтборНаСервере()
// Код установки отбора, как в примерах выше
// ...
КонецПроцедуры
ПриИзменении реквизитов формы: Если отбор зависит от значений других реквизитов формы (например, от выбранного значения в поле ввода), код отбора можно разместить в обработчике события ПриИзменении соответствующего реквизита. После изменения отбора также не забудьте вызвать Обновить() для динамического списка.
Имена полей: Убедитесь, что имена полей, используемые в ПолеКомпоновкиДанных, точно соответствуют именам полей в запросе или источнике данных вашего динамического списка. Ошибки в именах приведут к игнорированию отбора.
Типы данных: Следите за соответствием типов данных ЛевогоЗначения и ПравогоЗначения. Например, если поле "Код" имеет тип "Строка", то и ПравоеЗначение должно быть строкой.
Очистка отборов: Если вам нужно динамически менять отборы, рассмотрите возможность предварительной очистки коллекции НастройкаОтбора.Элементы с помощью метода НастройкаОтбора.Элементы.Очистить() перед добавлением новых элементов, если вы не используете метод Найти().
Производительность: Чрезмерно сложные отборы или отборы по неиндексированным полям могут замедлить работу динамического списка. Старайтесь оптимизировать запросы и используйте индексированные поля для отбора.
Пользовательские настройки: Помните, что программный отбор может конфликтовать с пользовательскими настройками отбора. Использование РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать помогает избежать этого, делая программный отбор "невидимым" для пользователя.
Мы подробно рассмотрели процесс программной установки отбора для динамического списка в управляемой форме 1С 8.3. Мы выяснили, что ключ к успеху лежит во взаимодействии с элементом формы и его свойством НастройкаОтбора, а не с самим объектом ДинамическийСписок напрямую. Мы изучили примеры кода для установки одиночного отбора и отбора по списку значений, а также обсудили, где лучше размещать такой код и какие особенности следует учитывать.
Применяя эти знания и примеры кода, вы сможете эффективно управлять данными, отображаемыми в динамических списках ваших управляемых форм, делая интерфейс более функциональным и адаптированным под нужды пользователей.