Приветствую Вас ГостьСуббота, 04.05.2024, 18:51

Каталог статей


Отбор по подчиненным элементам динамического списка в виде дерева или обратная иерархия.

В базе есть иерархический справочник с иерархией групп и элементов. На одной из форм расположен динамический список в виде дерева. Требуется разместить организовать отбор по значению реквизита с отображением полной иерархии.

Основная проблема в том, что у родительских элементов и групп реквизит может быть не заполнен или одна группа может содержать подгруппы с разными значениями данного реквизита. Так как надо отображать полную иерархию, то эти родительские группы тоже надо выводить.

Схематическая структура данных:

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

Но нам это не подходит.

В интернете я нашел 2 подхода к решению задачи:

1. Формировать запрос, в котором связывать таблицу справочника с самой собой по значению реквизита Родитель с отбором по значению требуемого реквизита. Рассмотрение похожей задаче можно посмотреть здесь. Запрос можно как формировать динамически с учетом определенного уровня вложения, так и сразу написать, с учетом возможного количества вложения уровней. В нашем случае количество уровней не ограничено и список реквизитов в выводимом динамическом списке довольно большой, что сделает текст запроса трудно читабельным.

2. Установить отбор "В ИЕРАРХИИ" с предварительным определением списка требуемых групп.

Анализ данных показал, что данные в справочнике структурированы и количество групп для определенного значения реквизита невелико.

Описание реализации.

На форме располагаем реквизит с типом значения нужного реквизита и на его события "ПриИзменении" и "ПриОчистке" повесили метод программной установки отбора динамического списка.

Чтобы вывести список всех групп использовали запрос с выводом итогов "ТОЛЬКО ИЕРАРХИЯ":

Функция ПолучитьСписокРодителей(ЗначениеРеквизита)
    
    Перем Результат;
    Результат = Новый Массив();    
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗЛИЧНЫЕ
        |    МойСправчоник.Родитель КАК Родитель
        |ИЗ
        |    Справочник.МойСправчоник КАК МойСправчоник
        |ГДЕ
        |    МойСправчоник.Реквизит= &ЗначениеРеквизита
        |ИТОГИ ПО
        |    Родитель ТОЛЬКО ИЕРАРХИЯ";
    
    Запрос.УстановитьПараметр("ЗначениеРеквизита", ЗначениеРеквизита);
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        Если ЗначениеЗаполнено(Выборка.Родитель) Тогда
            Результат.Добавить(Выборка.Родитель);
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

В результате получим список всех групп, в которых есть элементы с с нужным значением реквизита.

Как всегда не обошлось без нюансов: в одной из групп (Группа 2) у нас хранятся элементы с разными значениями реквизита, поэтому отбирать только по родителю будет неправильно. Надо добавить условие отбора по самому значению реквизита. Чтобы не отсечь группы без заполненного реквизита надо добавить в отбор группу условий, объединенных по "ИЛИ", в которой указать 2 условия: реквизит = Значение ИЛИ ЭтоГруппа.

Таким образом общее условие выглядит так:

Ссылка В ИЕРАРХИИ (&СписокГрупп) И (Реквизит = &Значение или ЭтоГруппа)

В программой установке отбора динамического списка прежде всего надо очистить предыдущие элемента отбора. Чтобы случайно не удалить отбор, установленный пользователем, было решено использовать "Представления" элементов отбора и удалять только те элементы, которые соответствуют заданными нами представлениям. Далее, если установлено значение отбора, то устанавливаем отбор.

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

    ОбщегоНазначенияКлиентСервер.УдалитьЭлементыГруппыОтбораДинамическогоСписка(Список,,"ОтборПоСсылке");     // отбор по родителю
    ОбщегоНазначенияКлиентСервер.УдалитьЭлементыГруппыОтбораДинамическогоСписка(Список,,"ГруппаОтбора"); //группа ИЛИ
    Если ЗначениеЗаполнено(ЗначениеРеквизита) Тогда

МассивРодителей = ПолучитьСписокРодителейДляСети(ЗначениеРеквизита);        
КомпоновкаКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Ссылка",МассивРодителей, ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии,"ОтборПоСсылке", ,РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);    
        
ГруппаОтбора = КомпоновкаКлиентСервер.СоздатьГруппуЭлементовОтбора(Список.Отбор.Элементы,"ГруппаОтбора",ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли);        
КомпоновкаКлиентСервер.УстановитьЭлементОтбора(ГруппаОтбора, "Реквизит",ЗначениеРеквизита, ВидСравненияКомпоновкиДанных.Равно,,,РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);    

КомпоновкаКлиентСервер.УстановитьЭлементОтбора(ГруппаОтбора, "ЭтоГруппа",Истина, ВидСравненияКомпоновкиДанных.Равно,,,РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);    

    КонецЕсли;


Несколько комментариев:

Было очень полезно, до программной установки определить условия отбора в клиенте через "Настроить список"

Режим отображения условий "Недоступный" было сделано для того, чтобы пользователи не сломали отбор, своими настройками. Как оказалось, это вполне возможно.

Из определения списка групп были исключены пустые значения, так как на верхнем уровне были только папки. Если на верхнем уровне заведены еще и элементы, то для них родителем будет ПустаяСсылка и тогда надо добавить дополнительные условия. Оставить в списке родителей ПустуюСсылку просто так тоже нельзя, так как в этом случае будут выводится все папки.

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

Категория: Формы | Добавил: leshic (27.12.2023)
Просмотров: 78 | Рейтинг: 0.0/0
Всего комментариев: 0
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [40]
Администрирование [34]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0