28/02/2019
ВІДБОРИ В ДЕРЕВІ ЗНАЧЕНЬ
Потрібно відібрати якісь дані в ієрархічній структурі? Наочне та просте рішення для відборів у дереві значень. Приклади коду з картинками можна знайти тут.
Працюючи з конфігураціями на керованому додатку, часто доводиться стикатися з елементом управління Дерево значень. З одного боку – це дуже зручний інструмент для відображення ієрархічних списків, з іншого – цей елемент має деякі обмеження щодо налаштування зовнішнього вигляду та користувальницької роботи з ним.
Дерево значень часто використовують у довідниках Номенклатура, Контрагенти; у документах Встановлення цін номенклатури.
Дерево значень у розгорнутому вигляді може бути дуже довгим і часом знайти там якусь інформацію для користувача перетворюється на цілу проблему. На жаль, стандартні механізми платформи не дозволяють зробити відбори у дереві значень. Але цю проблему можна вирішити знаючи структуру вашого дерева та конкретні умови відбору.
Розглянемо на прикладі відбір у документі Встановлення цін номенклатури. Нам потрібно вибрати номенклатуру, яка не змінила нову ціну стосовно старої; а також вибрати номенклатуру, яка не має нової ціни. Заздалегідь хочу помітити, що ми не очищатимемо дерево значень, ми лише приховуватимемо непотрібні нам рядки.
Для початку додамо на форму документа меню Відбори та три кнопки «Без нової ціни», «Немає змін ціни», «Без відборів». Остання кнопка використовуватиметься для відключення всіх відборів. Застосовувати одночасно кілька відборів не передбачено. Створимо дві булевих змінних ВідбірПоЦеніНуль та ВідбірНемаєЗміниЦіни. У дерево цін додамо реквізит «Відбір» тип число, безпосередньо для встановлення відбору цього реквізиту.
&НаКлиенте
Процедура ОтборБезНовойЦены(Команда)
// Отключение всех отборов
ОтключитьОтборы(“ОтборПоЦенеНоль”);
ОтборПоЦенеНоль = не ОтборПоЦенеНоль;
ЭлементыДерева = ДеревоЦен.ПолучитьЭлементы();
// Обработка дерева значений
ОбойтиДеревоРекурсивно(ЭлементыДерева,“НетНовойЦены”,Истина,не ОтборПоЦенеНоль);
ОтборУстановитьНаСервере(не ОтборПоЦенеНоль);
// Установка картинки у кнопки для отображения включен отбор или нет Если ОтборПоЦенеНоль Тогда
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборБезНовойЦены.Картинка
= БиблиотекаКартинок.ВыполненоУспешно;
Иначе
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборБезНовойЦены.Картинка
= БиблиотекаКартинок.ПустаяКартинка;
КонецЕсли;
КонецПроцедуры;
&НаКлиенте
Процедура ОтключитьОтборы(ТекущийОтбор = “”)
Отключать = Ложь;
Если ОтборПоЦенеНоль и ТекущийОтбор <> “ОтборПоЦенеНоль” Тогда
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборБезНовойЦены.Картинка
= БиблиотекаКартинок.ПустаяКартинка;
Отключать = Истина;
ОтборПоЦенеНоль = Ложь;
КонецЕсли;
Если ОтборНетИзмененияЦены и ТекущийОтбор <> “ОтборНетИзмененияЦены” Тогда
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборНетИзмененияЦены.Картинка
= БиблиотекаКартинок.ПустаяКартинка;
Отключать = Истина;
ОтборНетИзмененияЦены = Ложь;
КонецЕсли;
Если Отключать Тогда
ЭлементыДерева = ДеревоЦен.ПолучитьЭлементы();
ОбойтиДеревоРекурсивно(ЭлементыДерева,“”,Истина,Истина);
ОтборУстановитьНаСервере(Истина);
КонецЕсли;
КонецПроцедуры;
Процедура ОбойтиДеревоРекурсивно використовується для визначення елементів, які будуть показані за заданою умовою.
&НаКлиенте
Процедура ОбойтиДеревоРекурсивно(ЭлементыДерева,УсловиеОтбора,СкрыватьРодителя,ОтключитьОтбор)
Для Каждого ЭлементДерева Из ЭлементыДерева Цикл
Если ЭлементДерева.ИндексКартинки = 2 Тогда // Это Подчиненные Для каждого ВидЦены Из ВыбранныеЦены Цикл
// Обходим все виды цен, которые выбраны в документе
Если не ВидЦены.Выбрана Тогда
Продолжить;
КонецЕсли;
Если УсловиеОтбора = “НетНовойЦены” Тогда
// проверяем, что в колонке Новая цена стоит 0.
Если (ЭлементДерева[ВидЦены.ИмяКолонки] = 0 или ЭлементДерева.Отбор = 1)
и не ОтключитьОтбор Тогда
ЭлементДерева.Отбор = 1;
СкрыватьРодителя = Ложь;
Иначе
ЭлементДерева.Отбор = 0;
КонецЕсли;
ИначеЕсли УсловиеОтбора = “НетИзмененияЦены” Тогда
// проверяем что колонках Новая цена
// и Старая цена одинаковые значения
Если (ЭлементДерева[ВидЦены.ИмяКолонки]
= ЭлементДерева[“СтараяЦена” + ВидЦены.ИмяКолонки]
или ЭлементДерева.Отбор = 1)
и не ОтключитьОтбор Тогда
ЭлементДерева.Отбор = 1;
СкрыватьРодителя = Ложь;
Иначе
ЭлементДерева.Отбор = 0;
КонецЕсли;
// Эта ветка для отключения отборов
ИначеЕсли УсловиеОтбора = “” Тогда
ЭлементДерева.Отбор = 0;
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Рекурсивно вызываем эту процедуру для обхода всей иерархии ОбойтиДеревоРекурсивно(ЭлементДерева.ПолучитьЭлементы(),
УсловиеОтбора,СкрыватьРодителя,ОтключитьОтбор);
// Для самого верхнего элемента.
// Если хоть один из подчиненных элементов будет показан при отборе,
// тогда будет показан и родитель
Если ЭлементДерева.ИндексКартинки = 0 Тогда
Если не СкрыватьРодителя и не ОтключитьОтбор Тогда
ЭлементДерева.Отбор = 1;
СкрыватьРодителя = Истина;
Иначе
ЭлементДерева.Отбор = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры;
Процедура ОтборУстановитьНаСервере необхідна безпосередньо для встановлення видимості вибраних рядків за допомогою умовного оформлення.
&НаСервере
Процедура ОтборУстановитьНаСервере(ОтключитьОтбор)
Для каждого текЭлементУО Из УсловноеОформление.Элементы Цикл
//проверяем, что элемент УО – это установка видимости строки Если Найти(текЭлементУО.Представление, “ДеревоЦенВидимостьСтрок”) > 0 Тогда
текЭлементФормы = Элементы[“ДеревоЦен”];
текЭлементУО.Поля.Элементы.Очистить();
ДобавитьПодчиненныеЭлементыДляУО(текЭлементФормы, текЭлементУО);
текЭлементУО.Отбор.Элементы.Очистить();
ОтборЭлемента = текЭлементУО.Отбор.Элементы.Добавить
(Тип(“ЭлементОтбораКомпоновкиДанных”));
ОтборЭлемента.ЛевоеЗначение
= Новый ПолеКомпоновкиДанных(“ДеревоЦен.Отбор”);
ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборЭлемента.ПравоеЗначение = 0;
текЭлементУО.Использование = не ОтключитьОтбор;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ДобавитьПодчиненныеЭлементыДляУО(ЭлементФормы, ЭлементУО)
Попытка
Для каждого текПодчиненныйЭлемент Из ЭлементФормы.ПодчиненныеЭлементы Цикл
ДобавитьПодчиненныеЭлементыДляУО(текПодчиненныйЭлемент, ЭлементУО);
КонецЦикла;
Исключение
Если ЭлементФормы.Видимость Тогда
ОформляемоеПоле = ЭлементУО.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных(ЭлементФормы.Имя);
КонецЕсли;
КонецПопытки;
КонецПроцедуры
За аналогією додамо обробники подій для кнопок «Немає змін ціни», «Без відборів».
&НаКлиенте
Процедура ОтборНетИзмененияЦены(Команда)
ОтключитьОтборы(“ОтборНетИзмененияЦены”);
ОтборНетИзмененияЦены = не ОтборНетИзмененияЦены;
ЭлементыДерева = ДеревоЦен.ПолучитьЭлементы();
ОбойтиДеревоРекурсивно(ЭлементыДерева,“НетИзмененияЦены”, Истина,
не ОтборНетИзмененияЦены);
ОтборУстановитьНаСервере(не ОтборНетИзмененияЦены);
Если ОтборНетИзмененияЦены Тогда
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборНетИзмененияЦены.Картинка
= БиблиотекаКартинок.ВыполненоУспешно;
Иначе
Элементы.ДеревоЦенКоманднаяПанель.ПодчиненныеЭлементы.ГруппаОтборы.
ПодчиненныеЭлементы.ДеревоЦенОтборНетИзмененияЦены.Картинка
= БиблиотекаКартинок.ПустаяКартинка;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура БезОтбора(Команда)
ОтключитьОтборы();
КонецПроцедуры


