Мне давно хотелось иметь возможность не залезать в дебри отбора, а иметь возможность одним лёгким касанием установить отбор по реквизиту, с учетом только возможных вариантов.
Тоесть не лазить по всему справочнику контрагентов, а выбрать из перечня реально встречающихся в текущем списке документов, причем еще и желательно с учетом уже установленных по прочим реквизитам этих документов.
Для этого нужно на форму добавить одно подменю, а в саму форму - немножечко кода, всего три процедуры, и назначить событию динамического списка ПриАктивизацииКолонки обработчик кдоДокументСписокПриАктивизацииКолонки.
Код излагаю ниже, а в файле публикации - работающий пример, где фильтр реализован во внешней обработке с динамическим списком документов "Реализация товаров и услуг". (обработка для 8.2, но сам принцип реализуется в любой восьмерке).
UPD 2012-03-13: поправил код и обновил файл с примером. теперь, если мы стоим на колонке, по которой уже отфильтрован список, всё равно меню заполняется всеми значениями из этой колонки (с учетом других отборов). Вследствие этого, не будет "одиноких" меню из одного значения.
//будем использовать префикс кдо - "кнопки динамического отбора" для нашей подсистемы
Перем кдоМассивПунктовМеню;
Перем кдоПодменю;
Перем кдоДинамическийСписок;
Процедура кдоДействияФормыИнициализация(Кнопка)
//__________________________________________________________________________________________________________________________
//настройки подсистемки
//__________________________________________________________________________________________________________________________
//в принципе, их можно вынести в модуль формы
ПредставлениеПустогоЗначения="(не заполнено)";
ОграничениеКоличестваПунктовМеню=20;
кдоПодменю=ЭлементыФормы.ДействияФормы.Кнопки.Фильтр;
кдоЭлементФормыСписок=ЭлементыФормы.Список;
кдоДинамическийСписок=ДокументСписок;
//__________________________________________________________________________________________________________________________
Состояние();
кдоПодменю.Кнопки.Очистить();
кдоМассивПунктовМеню.Очистить();
Действие=Новый Действие("кдоНажатиеНаПунктМенюОтбора");
//добавим готовые, установленные уже отборы
ТекущаяКолонкаИмя=кдоЭлементФормыСписок.ТекущаяКолонка.Имя;
Если кдоДинамическийСписок.Отбор.Найти(ТекущаяКолонкаИмя)=Неопределено Тогда
Сообщить("такого отбора нет");
Возврат;
КонецЕсли;
СчетчикПунктовМеню=0;
ВремяНач=ТекущаяДата();
ИмяДокумента=кдоЭлементФормыСписок.ТекущаяСтрока.метаданные().Имя;
запрос=новый Запрос;
СоставнаяЧастьЗапросаОтбор=" ГДЕ ";
Для каждого ЭлементОтбора Из кдоДинамическийСписок.Отбор Цикл
Если ЭлементОтбора.Использование Тогда
Если ЭлементОтбора.ПутьКДанным <> ТекущаяКолонкаИмя Тогда
СоставнаяЧастьЗапросаОтбор=СоставнаяЧастьЗапросаОтбор+Символы.ПС+" ВыбраннаяТаблица."+ЭлементОтбора.ПутьКДанным +" В(&"+ЭлементОтбора.ПутьКДанным+") И";
КонецЕсли;
Если ТипЗнч(ЭлементОтбора.Значение)<>Тип("СписокЗначений") Тогда
ПараметрСписокЗначений=Новый СписокЗначений;
ПараметрСписокЗначений.Добавить(ЭлементОтбора.Значение);
Иначе
ПараметрСписокЗначений=ЭлементОтбора.Значение;
КонецЕсли;
запрос.УстановитьПараметр(ЭлементОтбора.ПутьКДанным,ПараметрСписокЗначений);//ЭлементОтбора.Значение);
Если Ложь Тогда кдоМассивПунктовМеню=Новый Массив;КонецЕсли;
СтруктураУправленияПунктаМеню=Новый Структура;
СтруктураУправленияПунктаМеню.Вставить("Действие","Сбросить");
СтруктураУправленияПунктаМеню.Вставить("ИмяОтбора",ЭлементОтбора.Имя);
СтруктураУправленияПунктаМеню.Вставить("Значение",Неопределено);
кдоМассивПунктовМеню.Добавить(СтруктураУправленияПунктаМеню);
СчетчикПунктовМеню=СчетчикПунктовМеню+1;
НоваяКнопка=кдоПодменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
?(ЗначениеЗаполнено(ЭлементОтбора.Имя),строка(ЭлементОтбора.Имя),ПредставлениеПустогоЗначения)
,Действие);
НоваяКнопка.Пометка=Истина;
//СтруктураЗначенийПунктовМеню;
//СтруктураЗначенийПунктовМеню.Вставить("_"+Строка(СчетчикПунктовМеню),ТекСтрока[ТекущаяКолонкаИмя]);
// НоваяКнопка=Подменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
//?(ЗначениеЗаполнено(ТекСтрока[ТекущаяКолонкаИмя]),строка(ТекСтрока[ТекущаяКолонкаИмя]),ПредставлениеПустогоЗначения)
//,Действие);
КонецЕсли;
КонецЦикла;
НоваяКнопка=кдоПодменю.Кнопки.Добавить(,ТипКнопкиКоманднойПанели.Разделитель,,);
Если Прав(СоставнаяЧастьЗапросаОтбор,1)="И" Тогда
СоставнаяЧастьЗапросаОтбор=Лев(СоставнаяЧастьЗапросаОтбор, СтрДлина(СоставнаяЧастьЗапросаОтбор)-1);
КонецЕсли;
Если СтрДлина(СокрЛП(СоставнаяЧастьЗапросаОтбор))=3 Тогда
//небыло ни одного условия
СоставнаяЧастьЗапросаОтбор=" ";
КонецЕсли;
Запрос.Текст=
"ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ "+ОграничениеКоличестваПунктовМеню+"
| ВыбраннаяТаблица."+ТекущаяКолонкаИмя+"
|ИЗ
| Документ."+ИмяДокумента+" КАК ВыбраннаяТаблица
|" +СоставнаяЧастьЗапросаОтбор+"
|УПОРЯДОЧИТЬ ПО
| "+ТекущаяКолонкаИмя;
Таблица=запрос.Выполнить().Выгрузить();
ВремяКон=ТекущаяДата();
Для каждого ТекСтрока Из Таблица Цикл
СчетчикПунктовМеню=СчетчикПунктовМеню+1;
НоваяКнопка=кдоПодменю.Кнопки.Добавить(СчетчикПунктовМеню,ТипКнопкиКоманднойПанели.Действие,
?(ЗначениеЗаполнено(ТекСтрока[ТекущаяКолонкаИмя]),строка(ТекСтрока[ТекущаяКолонкаИмя]),ПредставлениеПустогоЗначения)
,Действие);
Если ТипЗнч(Отбор[ТекущаяКолонкаИмя].Значение)=Тип("СписокЗначений") Тогда
Если Отбор[ТекущаяКолонкаИмя].Значение.найтиПоЗначению(ТекСтрока[ТекущаяКолонкаИмя])<>Неопределено Тогда
//такое значение есть в списке
НоваяКнопка.пометка=Истина;
КонецЕсли;
КонецЕсли;
Если Ложь Тогда кдоМассивПунктовМеню=Новый Массив;КонецЕсли;
СтруктураУправленияПунктаМеню=Новый Структура;
СтруктураУправленияПунктаМеню.Вставить("Действие","Установить");
СтруктураУправленияПунктаМеню.Вставить("ИмяОтбора",ТекущаяКолонкаИмя);
СтруктураУправленияПунктаМеню.Вставить("Значение",ТекСтрока[ТекущаяКолонкаИмя]);
кдоМассивПунктовМеню.Добавить(СтруктураУправленияПунктаМеню);
КонецЦикла;
КонецПроцедуры
Процедура кдоНажатиеНаПунктМенюОтбора(Кнопка)
НомерЭлемента=Число(Кнопка.Имя)-1;
ЗначениеПунктаМеню = кдоМассивПунктовМеню[НомерЭлемента].Значение;
ИмяОтбора = кдоМассивПунктовМеню[НомерЭлемента].ИмяОтбора;
Действие = кдоМассивПунктовМеню[НомерЭлемента].Действие;
Если Действие="Сбросить" Тогда
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= ложь;
ЗначениеОтбора=кдоДинамическийСписок.Отбор[ИмяОтбора].Значение;
Если ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда
кдоДинамическийСписок.Отбор[ИмяОтбора].Значение=Новый СписокЗначений;
КонецЕсли;
кдоПодменю.Кнопки.удалить(Кнопка);
ИначеЕсли Действие="Установить" Тогда
ЗначениеОтбора=кдоДинамическийСписок.Отбор[ИмяОтбора].Значение;
кдоДинамическийСписок.Отбор[ИмяОтбора].видСравнения=ВидСравнения.ВСписке;
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Истина;
Если Кнопка.Пометка Тогда
//нужно удалять
Если ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда
ИскомыйЭлемент=ЗначениеОтбора.найтиПоЗначению(ЗначениеПунктаМеню);
Если ИскомыйЭлемент<>Неопределено Тогда
ЗначениеОтбора.удалить(ИскомыйЭлемент);
Если ЗначениеОтбора.Количество()=0 Тогда
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Ложь;
Иначе
массив=ЗначениеОтбора.ВыгрузитьЗначения();
ЗначениеОтбора.ЗагрузитьЗначения(массив);
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Ложь;
кдоДинамическийСписок.Отбор[ИмяОтбора].использование=Истина;
КонецЕсли;
КонецЕсли;
Иначе
кдоДинамическийСписок.Отбор[ИмяОтбора].Использование=Ложь;
КонецЕсли;
Иначе
Если ТипЗнч(ЗначениеОтбора)=Тип("СписокЗначений") Тогда
ЗначениеОтбора.Добавить(ЗначениеПунктаМеню);
Иначе
СписокЗначений=Новый СписокЗначений;
СписокЗначений.Добавить(ЗначениеПунктаМеню);
кдоДинамическийСписок.Отбор[ИмяОтбора].Значение=СписокЗначений;
КонецЕсли;
КонецЕсли;
Состояние();
КонецЕсли;
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= не ДокументСписок.Отбор[ИмяОтбора].использование;
кдоДинамическийСписок.Отбор[ИмяОтбора].использование= не ДокументСписок.Отбор[ИмяОтбора].использование;
Кнопка.пометка=не Кнопка.пометка;
кдоДействияФормыИнициализация(Неопределено);
КонецПроцедуры
Процедура кдоДокументСписокПриАктивизацииКолонки(Элемент)
кдоДействияФормыИнициализация(Неопределено);
КонецПроцедуры
//нам не нужен строковый идентификатор, поэтому используем массив
кдоМассивПунктовМеню=Новый Массив;