Представляю Вашему вниманию расширенные фильтры (отборы) на форме отчета, построенного на СКД.
Предыстория
Ни для кого не секрет, что СКД позволяет размещать свои отборы на форме, установив одну лишь галочку в настройках
После чего на форме отчета получить следующее
Свою функцию отбор выполнит, но с видом сравнения "Равно". СКД позволяет настроить поле отбора:
В этом окне можно указать любой доступный вид сравнения.
Но все это выглядит не очень красиво, особенно если этих отборов больше 6. А пользователю нравится когда удобно, все под рукой и фильтры не занимают пол экрана.
Предлагаю Вашему внимаю программное формирования группы отборов на форме, со всеми возможностями СКД.
Выглядеть это будет так:
При желании количество групп с фильтрами можно увеличить. Также программная обработка отборов позволяет использовать свои собственные условия, подмены значений, обработки выбора, скрытые фильтры и тд. Подобный подход также можно использовать для динамического списка.
В пруфах исходный код
#Область СлужебныеПроцедуры
Процедура ИнициализироватьОтборыНаФорме(Форма) Экспорт
СписокРеквизитов = Новый Структура();
// создадим реквизиты отборов на форме
СоздатьРеквизитыОтборовНаФорме(Форма,СписокРеквизитов);
// расположим элементы на форме
РасположитьЭлементыНаФорме(Форма,СписокРеквизитов);
КонецПроцедуры
Процедура СоздатьРеквизитыОтборовНаФорме(Форма,СписокРеквизитов)
ДобавляемыеРеквизиты = Новый Массив;
Для Каждого ДоступноеПолеОтбора Из ЭтотОбъект.КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.Элементы Цикл
ИмяРеквизита = Строка(ДоступноеПолеОтбора.Поле);
// добавим элемент отбора
ДобавитьЭлементОтбора(ИмяРеквизита);
// добавим реквизит "Использовать"
ДобавитьРеквизитНаФорму(ДобавляемыеРеквизиты,"Использовать_"+ИмяРеквизита,Тип("Булево"));
// добавим реквизит "ВидСравнения"
ДобавитьРеквизитНаФорму(ДобавляемыеРеквизиты,"ВидСравнения_"+ИмяРеквизита,Тип("Неопределено"));
// добавим реквизит "Использовать"
ДобавитьРеквизитНаФорму(ДобавляемыеРеквизиты,"ПравоеЗначение_"+ИмяРеквизита,ДоступноеПолеОтбора.Тип);
// добавим реквизит "Использовать"
ДобавитьРеквизитНаФорму(ДобавляемыеРеквизиты,"ПравоеЗначениеСписок_"+ИмяРеквизита,Тип("СписокЗначений"));
// сохраним данные создаваемго реквизита
СписокРеквизитов.Вставить(ИмяРеквизита,ИмяРеквизита);
КонецЦикла;
Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
КонецПроцедуры
Процедура ДобавитьЭлементОтбора(ИмяРеквизита)
ЭлементОтбора = ЭтотОбъект.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяРеквизита);
ЭлементОтбора.Использование = Ложь;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
ЭлементОтбора.ИдентификаторПользовательскойНастройки = новый УникальныйИдентификатор;
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
КонецПроцедуры
Процедура ДобавитьРеквизитНаФорму(ДобавляемыеРеквизиты,ИмяРеквизита,Тип)
МассивТипов = новый Массив;
МассивТипов.Добавить(Тип);
ОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
Если ТипЗнч(Тип) = ТИП("ОписаниеТипов") Тогда
ОписаниеТипов = Тип;
КонецЕсли;
Реквизит = Новый РеквизитФормы("Отбор_" + ИмяРеквизита, ОписаниеТипов,,, Ложь);
ДобавляемыеРеквизиты.Добавить(Реквизит);
КонецПроцедуры
Процедура РасположитьЭлементыНаФорме(Форма,СписокРеквизитов)
ГруппаФильтра = Форма.Элементы.Добавить("ГруппаФильтр", Тип("ГруппаФормы"));
ГруппаФильтра.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ГруппаФильтра.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
ГруппаФильтра.ОтображатьЗаголовок = Ложь;
ГруппаФильтра.Видимость = Ложь;
ГруппаФильтраЛевая = Форма.Элементы.Добавить("ГруппаФильтрыЛево", Тип("ГруппаФормы"),ГруппаФильтра);
ГруппаФильтраЛевая.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ГруппаФильтраЛевая.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
ГруппаФильтраЛевая.ОтображатьЗаголовок = Ложь;
ГруппаФильтраПравая = Форма.Элементы.Добавить("ГруппаФильтрыПраво", Тип("ГруппаФормы"),ГруппаФильтра);
ГруппаФильтраПравая.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ГруппаФильтраПравая.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
ГруппаФильтраПравая.ОтображатьЗаголовок = Ложь;
Форма.Элементы.Переместить(ГруппаФильтра,Форма,Форма.Элементы.Результат);
ЛеваяГруппа = Истина;
Для Каждого Реквизит Из СписокРеквизитов Цикл
ПолеОтбора = ЭтотОбъект.КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.Элементы.Найти(Реквизит.Значение);
Если ПолеОтбора = Неопределено Тогда
Продолжить;
КонецЕсли;
// Предустановим тип списка значений
Форма["Отбор_ПравоеЗначениеСписок_" + Реквизит.Значение].ТипЗначения = ПолеОтбора.Тип;
Если ЛеваяГруппа Тогда
ЭлементФормыГруппаФильтра = Форма.Элементы.Добавить("Отбор_ГруппаФильтра_" + Реквизит.Значение, Тип("ГруппаФормы"), Форма.Элементы.ГруппаФильтрыЛево);
Иначе
ЭлементФормыГруппаФильтра = Форма.Элементы.Добавить("Отбор_ГруппаФильтра_" + Реквизит.Значение, Тип("ГруппаФормы"), Форма.Элементы.ГруппаФильтрыПраво);
КонецЕсли;
ЛеваяГруппа = НЕ ЛеваяГруппа;
// ГРУППА РАСПОЛОЖЕНИЯ ОТБОРА
ЭлементФормыГруппаФильтра.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ЭлементФормыГруппаФильтра.ОтображатьЗаголовок = Ложь;
ЭлементФормыГруппаФильтра.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
ЭлементФормыГруппаФильтра.Отображение = ОтображениеОбычнойГруппы.Нет;
ЭлементФормыГруппаФильтра.РастягиватьПоГоризонтали = Истина;
ЭлементФормыГруппаФильтра.Объединенная = Ложь;
// ЭЛЕМЕНТ "Использовать"
ЭлементФормы = Форма.Элементы.Добавить("Отбор_Использовать_" + Реквизит.Значение, Тип("ПолеФормы"), ЭлементФормыГруппаФильтра);
ЭлементФормы.ПутьКДанным = "Отбор_Использовать_" + Реквизит.Значение;
ЭлементФормы.Вид = ВидПоляФормы.ПолеФлажка;
ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Право;
ЭлементФормы.ТолькоПросмотр = Ложь;
ЭлементФормы.ВертикальноеПоложениеВГруппе = ВертикальноеПоложениеЭлемента.Центр;
ЭлементФормы.Заголовок = " ";
ЭлементФормы.УстановитьДействие("ПриИзменении","ОтборПриИзменении");
// НАДПИСЬ С НАИМЕНОВАНИЕМ ОТБОРА
НадписьРеквизита = Форма.Элементы.Добавить("Отбор_Наименование_" + Реквизит.Значение, Тип("ДекорацияФормы"), ЭлементФормыГруппаФильтра);
НадписьРеквизита.Заголовок = ПолеОтбора.Заголовок;
НадписьРеквизита.ВертикальноеПоложениеВГруппе = ВертикальноеПоложениеЭлемента.Центр;
НадписьРеквизита.РастягиватьПоГоризонтали = Ложь;
// ЭЛЕМЕНТ "Вид сравнения"
ЭлементФормы = Форма.Элементы.Добавить("Отбор_ВидСравнения_" + Реквизит.Значение, Тип("ПолеФормы"), ЭлементФормыГруппаФильтра);
ЭлементФормы.ПутьКДанным = "Отбор_ВидСравнения_" + Реквизит.Значение;
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ЭлементФормы.ТолькоПросмотр = Ложь;
ЭлементФормы.РежимВыбораИзСписка = Истина;
ЭлементФормы.РедактированиеТекста = Ложь;
ЭлементФормы.Ширина = 10;
ЭлементФормы.Высота = 1;
ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
ЭлементФормы.КнопкаВыбора = Ложь;
ЭлементФормы.УстановитьДействие("ПриИзменении","ОтборПриИзменении");
// заполним доступные виды сравнения
Если ПолеОтбора.ТипЗначения.СодержитТип(ТИП("Число")) Тогда
ЭлементФормы.СписокВыбора.Добавить(ВидСравненияКомпоновкиДанных.Больше);
ЭлементФормы.СписокВыбора.Добавить(ВидСравненияКомпоновкиДанных.Меньше);
ЭлементФормы.СписокВыбора.Добавить(ВидСравненияКомпоновкиДанных.Равно);
Иначе
Для Каждого СтрВидаСравнения Из ПолеОтбора.ДоступныеВидыСравнения Цикл
ЭлементФормы.СписокВыбора.Добавить(СтрВидаСравнения.Значение);
КонецЦикла;
КонецЕсли;
// по умолчанию значение "Равно"
Форма["Отбор_ВидСравнения_" + Реквизит.Значение] = ВидСравненияКомпоновкиДанных.Равно;
// Группа "Правое значение"
ЭлементФормыПраваяГруппа = Форма.Элементы.Добавить("Отбор_ГруппаПравоеЗначение_" + Реквизит.Значение, Тип("ГруппаФормы"), ЭлементФормыГруппаФильтра);
ЭлементФормыПраваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ЭлементФормыПраваяГруппа.ОтображатьЗаголовок = Ложь;
ЭлементФормыПраваяГруппа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
ЭлементФормыПраваяГруппа.Отображение = ОтображениеОбычнойГруппы.Нет;
ЭлементФормыПраваяГруппа.РастягиватьПоГоризонтали = Истина;
// ЭЛЕМЕНТ "Правое значение"
ЭлементФормы = Форма.Элементы.Добавить("Отбор_ПравоеЗначение_" + Реквизит.Значение, Тип("ПолеФормы"), ЭлементФормыПраваяГруппа);
ЭлементФормы.ПутьКДанным = "Отбор_ПравоеЗначение_" + Реквизит.Значение;
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ЭлементФормы.ТолькоПросмотр = Ложь;
ЭлементФормы.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
ЭлементФормы.КнопкаОткрытия = Ложь;
ЭлементФормы.АвтоМаксимальнаяШирина = Ложь;
ЭлементФормы.РастягиватьПоГоризонтали = Истина;
ЭлементФормы.Ширина = 15;
ЭлементФормы.АвтоВыборНезаполненного = Ложь;
ЭлементФормы.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.ПриИзмененииЗначения;
ЭлементФормы.УстановитьДействие("ПриИзменении","ОтборПриИзменении");
ЭлементФормы.УстановитьДействие("НачалоВыбора","ОтборНачалоВыбора");
// ЭЛЕМЕНТ "Правое значение список"
ЭлементФормы = Форма.Элементы.Добавить("Отбор_ПравоеЗначениеСписок_" + Реквизит.Значение, Тип("ПолеФормы"), ЭлементФормыПраваяГруппа);
ЭлементФормы.ПутьКДанным = "Отбор_ПравоеЗначениеСписок_" + Реквизит.Значение;
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ЭлементФормы.ТолькоПросмотр = Ложь;
ЭлементФормы.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
ЭлементФормы.КнопкаОткрытия = Ложь;
ЭлементФормы.Видимость = Ложь;
ЭлементФормы.АвтоМаксимальнаяШирина = Ложь;
ЭлементФормы.РастягиватьПоГоризонтали = Истина;
ЭлементФормы.Ширина = 15;
ЭлементФормы.УстановитьДействие("ПриИзменении","ОтборПриИзменении");
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
ОтчетОбъект.ИнициализироватьОтборыНаФорме(ЭтаФорма);
КонецПроцедуры
#КонецОбласти
#Область ПодключаемыеОбработчикиОтборов
&НаКлиенте
Процедура ПоказатьНастройки(Команда)
Если Элементы.ГруппаФильтр.Видимость Тогда
Элементы.ФормаПоказатьНастройки.Заголовок = "Показать фильтры";
Иначе
Элементы.ФормаПоказатьНастройки.Заголовок = "Скрыть фильтры";
КонецЕсли;
Элементы.ГруппаФильтр.Видимость = Не Элементы.ГруппаФильтр.Видимость;
КонецПроцедуры
&НаКлиенте
Процедура ОтборПриИзменении(Элемент)
ОтборПриИзмененииНаСервере(Строка(Элемент.Имя));
КонецПроцедуры
&НаСервере
Процедура ОтборПриИзмененииНаСервере(Имя)
Если НЕ Найти(Имя,"Отбор") = 0 Тогда
Имя = Сред(Имя,7);
ПоложениеПробела = СтрНайти(Имя,"_");
Если ПоложениеПробела = 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Ошибка применения фильтра";
Сообщение.Сообщить();
Возврат;
КонецЕсли;
ИмяПоля = Сред(Имя,1,ПоложениеПробела-1);
ИмяРеквизита = Сред(Имя,ПоложениеПробела+1);
Если ИмяПоля = "ВидСравнения" Тогда
ТекущееЗначение = ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита];
Если Найти(ВРег(ТекущееЗначение), "СПИС") = 0 Тогда
Элементы["Отбор_ПравоеЗначение_" + ИмяРеквизита].Видимость = Истина;
Элементы["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Видимость = Ложь;
Если Не ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Количество() = 0 Тогда
ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита] = ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита][0].Значение;
ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Очистить();
КонецЕсли;
Иначе
Элементы["Отбор_ПравоеЗначение_" + ИмяРеквизита].Видимость = Ложь;
Элементы["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Видимость = Истина;
Если ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Количество() = 0 И ЗначениеЗаполнено(ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита]) Тогда
ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита].Добавить(ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита]);
ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита] = Неопределено;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ТекущийОтбор = Неопределено;
//Найдем отбор
Для Каждого СтрОтбор Из Отчет.КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если Строка(СтрОтбор.ЛевоеЗначение) = ИмяРеквизита Тогда
ТекущийОтбор = СтрОтбор;
КонецЕсли;
КонецЦикла;
Если Не ТекущийОтбор = Неопределено Тогда
Если Не (ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Ложь И ТекущийОтбор.Использование = Ложь) Тогда
Если Не ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита] = Неопределено Тогда
Попытка
ТекущийОтбор.ВидСравнения = ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита];
ТекЗначениеВидаСравнения = ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита];
Если Найти(ВРег(ТекЗначениеВидаСравнения), "СПИС") = 0 Тогда
ТекущийОтбор.ПравоеЗначение = ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита];
Иначе
ТекущийОтбор.ПравоеЗначение = ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита];
КонецЕсли;
ТекущийОтбор.Использование = ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита];
Исключение
ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Ложь;
КонецПопытки;
Иначе
ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Ложь;
КонецЕсли;
Иначе
ТекЗначениеВидаСравнения = ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита];
Если Найти(ВРег(ТекЗначениеВидаСравнения), "СПИС") = 0 Тогда
Если ЗначениеЗаполнено(ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита]) И ЗначениеЗаполнено(ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита]) Тогда
Если ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Ложь Тогда
ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Истина;
ТекущийОтбор.ВидСравнения = ТекЗначениеВидаСравнения;
ТекущийОтбор.ПравоеЗначение = ЭтаФорма["Отбор_ПравоеЗначение_" + ИмяРеквизита];
ТекущийОтбор.Использование = Истина;
КонецЕсли;
КонецЕсли;
Иначе
Если ЗначениеЗаполнено(ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита])
И ЗначениеЗаполнено(ЭтаФорма["Отбор_ВидСравнения_" + ИмяРеквизита]) Тогда
Если ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Ложь Тогда
ЭтаФорма["Отбор_Использовать_" + ИмяРеквизита] = Истина;
ТекущийОтбор.ВидСравнения = ТекЗначениеВидаСравнения;
ТекущийОтбор.ПравоеЗначение = ЭтаФорма["Отбор_ПравоеЗначениеСписок_" + ИмяРеквизита];
ТекущийОтбор.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
Пример использования программных отборов отчета на СКД тестировался на платформе 8.3.13.1644.
Режим совместимости 8.3.10
Related Posts
- Получение логина и пароля техподдержки 1С из базы
- Класс для вывода отчета в Excel
- Счет-фактура для УПП
- Библиотека классов для создания внешней компоненты 1С на C#
- Акт об оказании услуг (со скидками) — внешняя печатная форма для Управление торговлей 11.1.10.86
- Прайс-лист с артикулом в отдельной колонке
Возможно (скорее всего) я чего не понял, но откуда такая информация, что в СКД форму можно вывести сравнение только на равенство? Вообще-то на форму можно точно так же вывести любое сравнение.
(1)
Можно, и я об этом сказал (3-ий скриншот)
(2) Третий скриншот этотhttps://infostart.ru/upload/iblock/629/6293719cd5ce9620cd007ee5027767ca.jpg ?
Я просто не совсем понял, для чего самому формировать отборы если они формируются автоматически
(3)
Наберусь терпения и скопирую строчку под скриншотом
«Но все это выглядит не очень красиво, особенно если этих отборов больше 6. А пользователю нравится когда удобно, все под рукой и фильтры не занимают пол экрана.»
Дочитайте пожалуйста до конца!
(4) Разумеется я все прочитал. Стандартными средствами отборы рисуются точно так же как Вы нарисовали программно.
https://infostart.ru/upload/iblock/021/021dddfd26cbe92da04ce2ef2acf4f9d.jpg
т.е. вот так
Все, я понял, что Вас не устроило в стандартном формирование (то, что при равенстве оно не отображается на форме, на форме отображаются только другие виды сравнения)
(5) Не совсем так, выбор вида сравнения появляется только когда оно не равно стандартному значению вида сравнения
(6) Именно. Также плюс программного формирования — это контроль того что выбирает пользователь. На практике это бывает очень важным
Код не работает в конфигурациях в режиме совместимости ниже 8.3.10
(9) Прошу прощения. Добавил в описание информацию о режиме совместимости.
В общем можно опустить до 8.2.13 например, но тогда потребуются дополнительные манипуляции с элементами форм (нужно будет добавить кнопку выбора с картинкой, добавить настройку группы элементов по размерам,некоторые события не так работают и тд и тп.).
Я исходил из того, что сейчас уже большинство разработчиков перешло на платформу 8.3.10 и более