gifts2017

Кнопка динамического отбора в списке документов/справочнике

Опубликовал Александр Че (chmod660) в раздел Программирование - Работа с интерфейсом

Меню отбора в один клик, заполняющееся возможными значениями из текущей колонки.

Мне давно хотелось иметь возможность не залезать в дебри отбора, а иметь возможность одним лёгким касанием установить отбор по реквизиту, с учетом только возможных вариантов.

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

Для этого нужно на форму добавить одно подменю, а в саму форму - немножечко кода, всего три процедуры, и назначить событию динамического списка ПриАктивизацииКолонки  обработчик кдоДокументСписокПриАктивизацииКолонки.

Код излагаю ниже, а в файле публикации - работающий пример, где фильтр реализован во внешней обработке с динамическим списком документов "Реализация товаров и услуг". (обработка для 8.2, но сам принцип реализуется в любой восьмерке).

UPD 2012-03-13: поправил код и обновил файл с примером. теперь, если мы стоим на колонке, по которой уже отфильтрован список, всё равно меню заполняется всеми значениями из этой колонки (с учетом других отборов). Вследствие этого, не будет "одиноких" меню из одного значения.

 

//будем использовать префикс кдо - "кнопки динамического отбора" для нашей подсистемы
Перем кдоМассивПунктовМеню;
Перем
кдоПодменю;
Перем
кдоДинамическийСписок;


Процедура
кдоДействияФормыИнициализация(Кнопка)
   
//__________________________________________________________________________________________________________________________
    //настройки подсистемки
    //__________________________________________________________________________________________________________________________
    //в принципе, их можно вынести в модуль формы
   
ПредставлениеПустогоЗначения="(не заполнено)";
   
ОграничениеКоличестваПунктовМеню=20;
   
кдоПодменю=ЭлементыФормы.ДействияФормы.Кнопки.Фильтр;

   
кдоЭлементФормыСписок=ЭлементыФормы.Список;
   
кдоДинамическийСписок=ДокументСписок;
   
//__________________________________________________________________________________________________________________________

   
Состояние();

   
кдоПодменю.Кнопки.Очистить();
   
кдоМассивПунктовМеню.Очистить();
   
Действие=Новый Действие("кдоНажатиеНаПунктМенюОтбора");


   
//добавим готовые, установленные уже отборы

   
ТекущаяКолонкаИмя=кдоЭлементФормыСписок.ТекущаяКолонка.Имя;
    Если
кдоДинамическийСписок.Отбор.Найти(ТекущаяКолонкаИмя)=Неопределено Тогда
       
Сообщить("такого отбора нет");
        Возврат;
    КонецЕсли;

   
СчетчикПунктовМеню=0;
   
ВремяНач=ТекущаяДата();
   
ИмяДокумента=кдоЭлементФормыСписок.ТекущаяСтрока.метаданные().Имя;
   
запрос=новый Запрос;

   
СоставнаяЧастьЗапросаОтбор=" ГДЕ     ";
    Для каждого
ЭлементОтбора Из  кдоДинамическийСписок.Отбор Цикл
        Если
ЭлементОтбора.Использование Тогда

            Если
ЭлементОтбора.ПутьКДанным <> ТекущаяКолонкаИмя Тогда
               
СоставнаяЧастьЗапросаОтбор=СоставнаяЧастьЗапросаОтбор+Символы.ПС+" ВыбраннаяТаблица."+ЭлементОтбора.ПутьКДанным +" В(&"+ЭлементОтбора.ПутьКДанным+") И";
            КонецЕсли;



            Если
ТипЗнч(ЭлементОтбора.Значение)<>Тип("СписокЗначений") Тогда
               
ПараметрСписокЗначений=Новый СписокЗначений;
               
ПараметрСписокЗначений.Добавить(ЭлементОтбора.Значение);
            Иначе
               
ПараметрСписокЗначений=ЭлементОтбора.Значение;
            КонецЕсли;

           
запрос.УстановитьПараметр(ЭлементОтбора.ПутьКДанным,ПараметрСписокЗначений);//ЭлементОтбора.Значение);


           
Если Ложь Тогда кдоМассивПунктовМеню=Новый  Массив;КонецЕсли;


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

           
СчетчикПунктовМеню=СчетчикПунктовМеню+1;

       
НоваяКнопка=кдоПодменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
        ?(
ЗначениеЗаполнено(ЭлементОтбора.Имя),строка(ЭлементОтбора.Имя),ПредставлениеПустогоЗначения)
        ,
Действие);
       
НоваяКнопка.Пометка=Истина;


           
//СтруктураЗначенийПунктовМеню;
            //СтруктураЗначенийПунктовМеню.Вставить("_"+Строка(СчетчикПунктовМеню),ТекСтрока[ТекущаяКолонкаИмя]);
        //      НоваяКнопка=Подменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
        //?(ЗначениеЗаполнено(ТекСтрока[ТекущаяКолонкаИмя]),строка(ТекСтрока[ТекущаяКолонкаИмя]),ПредставлениеПустогоЗначения)
        //,Действие);
       
КонецЕсли;
    КонецЦикла;

   
НоваяКнопка=кдоПодменю.Кнопки.Добавить(,ТипКнопкиКоманднойПанели.Разделитель,,);

    Если
Прав(СоставнаяЧастьЗапросаОтбор,1)="И" Тогда
       
СоставнаяЧастьЗапросаОтбор=Лев(СоставнаяЧастьЗапросаОтбор, СтрДлина(СоставнаяЧастьЗапросаОтбор)-1);
    КонецЕсли;
    Если
СтрДлина(СокрЛП(СоставнаяЧастьЗапросаОтбор))=3 Тогда
       
//небыло ни одного условия
       
СоставнаяЧастьЗапросаОтбор=" ";
    КонецЕсли;

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

   
Таблица=запрос.Выполнить().Выгрузить();
   
ВремяКон=ТекущаяДата();
    Для каждого
ТекСтрока Из  Таблица Цикл
       
СчетчикПунктовМеню=СчетчикПунктовМеню+1;

       
НоваяКнопка=кдоПодменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
        ?(
ЗначениеЗаполнено(ТекСтрока[ТекущаяКолонкаИмя]),строка(ТекСтрока[ТекущаяКолонкаИмя]),ПредставлениеПустогоЗначения)
        ,
Действие);


        Если
ТипЗнч(Отбор[ТекущаяКолонкаИмя].Значение)=Тип("СписокЗначений") Тогда
            Если
Отбор[ТекущаяКолонкаИмя].Значение.найтиПоЗначению(ТекСтрока[ТекущаяКолонкаИмя])<>Неопределено Тогда
               
//такое значение есть в списке
               
НоваяКнопка.пометка=Истина;
            КонецЕсли;
        КонецЕсли;

        Если Ложь Тогда
кдоМассивПунктовМеню=Новый  Массив;КонецЕсли;

       
СтруктураУправленияПунктаМеню=Новый Структура;
       
СтруктураУправленияПунктаМеню.Вставить("Действие","Установить");
       
СтруктураУправленияПунктаМеню.Вставить("ИмяОтбора",ТекущаяКолонкаИмя);
       
СтруктураУправленияПунктаМеню.Вставить("Значение",ТекСтрока[ТекущаяКолонкаИмя]);

       
кдоМассивПунктовМеню.Добавить(СтруктураУправленияПунктаМеню);
    КонецЦикла;

КонецПроцедуры


Процедура
кдоНажатиеНаПунктМенюОтбора(Кнопка)

   
НомерЭлемента=Число(Кнопка.Имя)-1;
   
ЗначениеПунктаМеню  = кдоМассивПунктовМеню[НомерЭлемента].Значение;
   
ИмяОтбора           = кдоМассивПунктовМеню[НомерЭлемента].ИмяОтбора;
   
Действие            = кдоМассивПунктовМеню[НомерЭлемента].Действие;

    Если
Действие="Сбросить" Тогда
       
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= ложь;
       
ЗначениеОтбора=кдоДинамическийСписок.Отбор[ИмяОтбора].Значение;
        Если
ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда
           
кдоДинамическийСписок.Отбор[ИмяОтбора].Значение=Новый СписокЗначений;
        КонецЕсли;

       
кдоПодменю.Кнопки.удалить(Кнопка);

    ИначеЕсли
Действие="Установить" Тогда
       
ЗначениеОтбора=кдоДинамическийСписок.Отбор[ИмяОтбора].Значение;

       
кдоДинамическийСписок.Отбор[ИмяОтбора].видСравнения=ВидСравнения.ВСписке;
       
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Истина;

        Если
Кнопка.Пометка Тогда
           
//нужно удалять
           
Если ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда

               
ИскомыйЭлемент=ЗначениеОтбора.найтиПоЗначению(ЗначениеПунктаМеню);
                Если
ИскомыйЭлемент<>Неопределено Тогда
                   
ЗначениеОтбора.удалить(ИскомыйЭлемент);

                    Если
ЗначениеОтбора.Количество()=0 Тогда
                       
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Ложь;
                    Иначе
                       
массив=ЗначениеОтбора.ВыгрузитьЗначения();
                       
ЗначениеОтбора.ЗагрузитьЗначения(массив);
                       
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Ложь;
                       
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Истина;
                    КонецЕсли;
                КонецЕсли;
            Иначе
               
кдоДинамическийСписок.Отбор[ИмяОтбора].Использование=Ложь;
            КонецЕсли;

        Иначе
            Если
ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда
               
ЗначениеОтбора.Добавить(ЗначениеПунктаМеню);
            Иначе
               
СписокЗначений=Новый СписокЗначений;
               
СписокЗначений.Добавить(ЗначениеПунктаМеню);
               
кдоДинамическийСписок.Отбор[ИмяОтбора].Значение=СписокЗначений;
            КонецЕсли;

        КонецЕсли;

       
Состояние();

    КонецЕсли;
   
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= не ДокументСписок.Отбор[ИмяОтбора].использование;
   
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= не ДокументСписок.Отбор[ИмяОтбора].использование;


   
Кнопка.пометка=не Кнопка.пометка;

   
кдоДействияФормыИнициализация(Неопределено);
КонецПроцедуры


Процедура
кдоДокументСписокПриАктивизацииКолонки(Элемент)
   
кдоДействияФормыИнициализация(Неопределено);
КонецПроцедуры

//нам не нужен строковый идентификатор, поэтому используем массив
кдоМассивПунктовМеню=Новый Массив;

Скачать файлы

Наименование Файл Версия Размер
Обработка с примером динамического фильтра 76
.epf 24,43Kb
13.03.12
76
.epf 24,43Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

0. Александр Че (chmod660) 29.02.12 01:18
Меню отбора в один клик, заполняющееся возможными значениями из текущей колонки.

Перейти к публикации

1. Александр Хоменко (scape) 29.02.12 01:18
Хорошая идея! Но как всегда, сделаю все по своему... :D
2. ta44ik (ta44ik) 29.02.12 04:28
Идея хорошая) Но красивше было бы дерево сделать, так и сделаю) Ну типо конрагенты - подстроки соответственно значения, отмеченные - вверх, ну и все такое)
3. Андрей К. (andrei.k) 29.02.12 08:13
Отличная идея, спасибо. В любом случает все делается под себя. Спасибо.
4. Сергей Смирнов (milanse) 29.02.12 08:44
5. Олег (OLEG4120) 29.02.12 09:06
У Вас есть небольшие ошибки в коде, приведенном в публикации.
Например отсутствие определения переменных
кдоПодменю;
кдоДинамическийСписок;
кдоМассивПунктовМеню;

массив вообще-то есть, но
Если Ложь Тогда кдоМассивПунктовМеню=Новый  Массив;КонецЕсли;

а так +
7. Александр Че (chmod660) 29.02.12 12:18
(1), (2), (3) - спасибо за отзыв!
Переработка и использование приветствуется, особенно с фидбеком ))
Есть мнение, что на большом массиве данных заполнение дерева возможных вариантов отбора будет небыстрым.
Но, тем не менее, интересно будет посмотреть реализацию.


(4) Для управляемых небыло необходимости, но при возможности гляну.
8. Александр Че (chmod660) 29.02.12 12:29
(5) Благодарю!
Поправил публикацию. (в обработке эти определения есть)
Процитированный вами код - это уловка, чтобы конфигуратор видел нужный тип переменной и добавлял контекстную подсказку.
9. Олег (OLEG4120) 29.02.12 14:04
10. Александр Иванов (dkprim) 29.02.12 16:47
Идея очень хорошая! Буду адаптировать под свои потребности. Автору спасибо )
11. Ruslan (rus128) 29.02.12 18:23
Классная идея!
Странно, что это до сих пор не реализовано в платформе и в типовых...
12. Михаил Гомбоев (yoyoman) 01.03.12 05:35
Ой и правда, юзабилити очень высокое)
13. Андрей Якшин (YakshinAnd) 01.03.12 10:00
Начинаю пользоваться. Часто приходится тестить разные отборы, а тут такое счастье, которое облегчит жизнь и сэкономит много времени. Спасибо огромное)!
14. Fomix (fomix) 01.03.12 10:20
Спасибо автору за идею и реализацию. Однако руки чешутся сделать подменю фильтра не выборочно для конкретного вида документа, а для всех списков...
15. Александр Че (chmod660) 01.03.12 10:54
всем спасибо за положительные отзывы, очень приятно.

(14) fomix, не знаю, как программно добавить менюшку прям сразу ко всем формам. всё равно править код придется. Процедуру инициализации меню можно доработать и вынести во внешний модуль (чтобы осталась одна), но код её вызова всё равно в форму надо добавлять.
А так - специально делал настраиваемым, чтобы для любой формы подходило, лишь правильно надо указать 3 (три) переменных. Ну и немножко доделаю, чтобы и для справочников работало.
16. Fomix (fomix) 01.03.12 11:41
18. Vladimir (Boroda) 05.03.12 00:35
Судя по количеству положительных отзывов - очень неплохая вещица! Думаю, будет работать в любых конфигурациях. Спасибо за интересное решение.
19. Алексей Ромашов (krund) 10.03.12 13:37
Решение интересное. Жаль, что сделана под себя.
20. Александр Че (chmod660) 12.03.12 13:16
(19) krund, почему жаль?
Вроде пытался сделать универсальной, можно брать и пользоваться, а можно - дорабатывать.
21. olga pt (pt_olga) 12.03.12 22:11
спасибо автору, быстро, удобно, красиво :)
22. Игорь Дзеса (Kamikadze) 12.03.12 22:24
23. Игорь Дзеса (Kamikadze) 15.03.12 17:15
В строке ИмяДокумента=кдоЭлементФормыСписок.ТекущаяСтрока.метаданные().Имя;

должно быть так: ИмяДокумента=кдоЭлементФормыСписок.ТекущаяСтрока.метаданные().Данные.

и строки неограниченой длинны фильтр не отрабатывает.
24. Александр Че (chmod660) 15.03.12 18:01
(23) Kamikadze, спасибо!
Я буду накапливать исправления, чтобы не изменять по чайной ложке и не нагружать модератора. Но все уведомления и предложения приветствуются.
25. Валерий Дубовой (Valerich) 27.03.12 16:19
я бы предложил основной функционал сделать универсальным:
- добавление подменю на панель при открытии (в типовых такую процедуру можно вызывать из процедур, всегда отрабатывающих при открытии)
- формирование подменю (достаточно передавать правильный набор параметров, чтобы этой процедуре было "фиолетово" откуда ее вызвали.

тогда ценность публикации вырастет в разы

А вообще идея отличная, за что и + автору
26. uno dos (unoDosTres) 30.05.12 12:06
когда слишком большой список в меню фильтра он весь не помещается, добавить бы полосу прокрутки внизу и вверху, и еще когда реквизит незаполнен, стоит добавить исключение, а то ошибка на доедает выскакивать )
а вообще идея отличная ПЛЮСУЮ
27. Александр Че (chmod660) 30.05.12 12:48
(26) unoDosTres, список ограничен параметром ОграничениеКоличестваПунктовМеню.
Можно переделать запрос (убрав "ПЕРВЫЕ "+ОграничениеКоличестваПунктовМеню+"), тогда 1С сама будет дорисовывать стрелки прокрутки. Мне это показалось неудобным, да и небыстрым.
про ошибку: не видел, напишите, как воспроизвести - исправим.
28. uno dos (unoDosTres) 31.05.12 10:38
(27) chmod660,
оказалось, что ошибка связана не с незаполненностью реквизита, я проверял на УТ, реквизит адрес доставки,а как сказал kamikadze в (23) строки неограниченной длинны фильтр не отрабатывает, так что оказалось что об этом вы уже знаете
29. Игорь Дзеса (Kamikadze) 31.05.12 11:21
я подсистему внедрил - пользователм понравилась, такая себе юзабилюшка, не особо важно, но приятно :)
32. Алекс Фергюсон (Foxux) 03.04.13 18:52
глюк какой то в предыдущем посте, сорри
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа