Универсальный фильтр справочников средствами 1C

Находясь под впечатлением обработки по фильтрации справочников средствами SQL, решил написать свою версию обработки с использованием только стандартных средств 1С для работы с любыми базами.

Материал опубликован на сайте компании "СофтПоинт"/

Находясь под впечатлением обработки по фильтрации справочников средствами SQL, решил написать свою версию обработки с использованием только стандартных средств 1С для работы с любыми базами.

Для простоты решил отказаться от диапазонов. Осталось только два шаблона * и ?, так что реализовать оказалось несложно. Зато добавилась опция поиска с учетом либо без учета регистра символов.

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

Вот как выглядит форма обработки:

А вот вторая закладка (результат):

Вот код модуля:
Перем ТекСправочник,ТЗ;
Перем Последний;
Процедура ОбрТабл()
Если Список.КоличествоСтрок()>0 Тогда
Предупреждение(Список.Реквизит);
КонецЕсли;
КонецПроцедуры
//________________________________________________________
Функция ПроверкаСтроки(ПармСтрока)
Перем ВремСтрока, Результат;
ВремСтрока=ПармСтрока;
ТЗ.ВыбратьСтроки();
Результат=1;
Пока ТЗ.ПолучитьСтроку()=1 Цикл
Если СтрДлина(ВремСтрока)=0 Тогда
Результат=0;
КонецЕсли;
ТекПропуск=ТЗ.Пропуск;
ТекТекст=ТЗ.Текст;
ТекДлина=ТЗ.Длина;
Если ТекПропуск>0 Тогда
//обрезаем
ВремСтрока=Сред(ВремСтрока,1+ТекПропуск);
КонецЕсли;
Если ТекПропуск<0 Тогда
ТекПозиция=Найти(ВремСтрока,ТекТекст);
Если ТекПозиция>0 Тогда
ВремСтрока=Сред(ВремСтрока,ТекПозиция+ТекДлина);
Иначе
Результат=0;
Прервать;
КонецЕсли;
Иначе
//=0
Если Лев(ВремСтрока,ТекДлина)=ТекТекст Тогда
ВремСтрока=Сред(ВремСтрока,1+ТекДлина);
Иначе
Результат=0;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если (Последний=1) И (СтрДлина(ВремСтрока)>0) Тогда
Результат=0;
КонецЕсли;
Возврат Результат;
КонецФункции
//________________________________________________________
Процедура ШаблонистыйШаблон()
Состояние("Создание правил");
ТекШаблон=СокрП(Стр);
Если РегистрСимволов=0 Тогда
ТекШаблон=Врег(ТекШаблон);
КонецЕсли;
ТекПропуск=0;
Накопитель="";
Если ТипЗначениястр(ТЗ)="ТаблицаЗначений" Тогда
ТЗ.УдалитьСтроки();
Иначе
ТЗ=СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Пропуск","Число");
ТЗ.НоваяКолонка("Текст","Строка");
ТЗ.НоваяКолонка("Длина","Число",);
КонецЕсли;
Последний=0;
Для к=1 по СтрДлина(ТекШаблон) Цикл
Символ=Лев(ТекШаблон,1);
ТекШаблон=Сред(ТекШаблон,2);
Если Символ="*" Тогда
Если СтрДлина(Накопитель)>0 Тогда
ТЗ.НоваяСтрока();
ТЗ.Пропуск=ТекПропуск;
ТЗ.Текст=Накопитель;
ТЗ.Длина=СтрДлина(Накопитель);
ТекПропуск=0;
Накопитель="";
КонецЕсли;
ТекПропуск=?(ТекПропуск>0,ТекПропуск,-1);
ИначеЕсли Символ="?" Тогда
Если СтрДлина(Накопитель)>0 Тогда
ТЗ.НоваяСтрока();
ТЗ.Пропуск=ТекПропуск;
ТЗ.Текст=Накопитель;
ТЗ.Длина=СтрДлина(Накопитель);
ТекПропуск=0;
Накопитель="";
КонецЕсли;
ТекПропуск=?(ТекПропуск>0,ТекПропуск+1,1);
Иначе
Накопитель=Накопитель+Символ;
КонецЕсли;
КонецЦикла;
Если СтрДлина(Накопитель)>0 Тогда
ТЗ.НоваяСтрока();
ТЗ.Пропуск=ТекПропуск;
ТЗ.Текст=Накопитель;
ТЗ.Длина=СтрДлина(Накопитель);
Последний=1;
КонецЕсли;
КонецПроцедуры
//________________________________________________________
Процедура Сформировать()
Перем Спр, ТекАтрибут;
Перем ТекРезультатПроверки;
Список.УдалитьСтроки();
ШаблонистыйШаблон();
ТекЭлемент=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока());
ТекРеквизит=Реквизиты.ПолучитьЗначение(Реквизиты.ТекущаяСтрока());
Запрос=СоздатьОбъект("Запрос");
ТекстЗапроса="ЗапЭлемент = Справочник."+ТекЭлемент+".ТекущийЭлемент;
|ЗапРеквизит = Справочник."+ТекЭлемент+"."+ТекРеквизит+";
|Группировка ЗапЭлемент без упорядочивания;";
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Не выполнился запрос!");
Возврат;
КонецЕсли;
Состояние("Проверка соответствия");
Пока Запрос.Группировка(1)=1 Цикл
ТекЗначение=СокрП(Запрос.ЗапРеквизит);
Если РегистрСимволов=1 Тогда
//1-учитывать регистр
ТекРезультатПроверки=ПроверкаСтроки(ТекЗначение);
Иначе
//0- не учитывать регистр
ТекРезультатПроверки=ПроверкаСтроки(Врег(ТекЗначение));
КонецЕсли;
Если ТекРезультатПроверки = 1 Тогда
Список.НоваяСтрока();
Список.Элемент=Запрос.ЗапЭлемент;
Список.Реквизит=ТекЗначение;
КонецЕсли;
КонецЦикла;
Запрос=0;
КонецПроцедуры
//________________________________________________________
Процедура приОткрытии()
// Пример строки для фильтрации
Для х=1 По Метаданные.Справочник() Цикл // перебор справочников
Справочники.ДобавитьЗначение(МетаДанные.Справочник(х).Идентификатор);
Если х=1 тогда // Для первого справочника. Остальные при навигации
Реквизиты.ДобавитьЗначение("Код");
Реквизиты.ДобавитьЗначение("Наименование");
Для хх=1 По Метаданные.Справочник(х).Реквизит() Цикл
Если Метаданные.Справочник(х).Реквизит(хх).Тип="Строка" тогда
Если Метаданные.Справочник(х).Реквизит(хх).Длина=0 тогда
Продолжить;
КонецЕсли;
Если Метаданные.Справочник(х).Реквизит(хх).Периодический=1 тогда
Продолжить;
КонецЕсли;
Реквизиты.ДобавитьЗначение(МетаДанные.Справочник(х).Реквизит(хх).Идентификатор );
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
ТекСправочник=Справочники.ПолучитьЗначение(1);
Форма.ИспользоватьСлой("Источник,Общий");
КонецПроцедуры
//________________________________________________________
Функция Пересчет()
Если НЕ(ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока())) Тогда
ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока());
Реквизиты.УдалитьВсе();
Если Метаданные.Справочник(ТекСправочник).ДлинаКода>0 Тогда
Реквизиты.ДобавитьЗначение("Код");
КонецЕсли;
Если Метаданные.Справочник(ТекСправочник).ДлинаНаименования>0 Тогда
Реквизиты.ДобавитьЗначение("Наименование");
КонецЕсли;
Для хх=1 По Метаданные.Справочник(ТекСправочник).Реквизит() Цикл
ТекТип=Метаданные.Справочник(ТекСправочник).Реквизит(хх).Тип;
Если (ТекТип="Строка") Или (ТекТип="Число") тогда
Если Метаданные.Справочник(ТекСправочник).Реквизит(хх).Длина=0 тогда
Продолжить;
КонецЕсли;
Если Метаданные.Справочник(ТекСправочник).Реквизит(хх).Периодический=1 тогда
Продолжить;
КонецЕсли;
Реквизиты.ДобавитьЗначение(МетаДанные.Справочник(ТекСправочник).Реквизит(хх).Идентификатор);
КонецЕсли;
КонецЦикла;
ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока());
Реквизиты.Текущаястрока(2);
КонецЕсли;
КонецФункции
//________________________________________________________
Процедура ПриВыбореЗакладки(ТекНомер)
Если ТекНомер=1 Тогда
Форма.ИспользоватьСлой("Источник,Общий");
Иначе
Форма.ИспользоватьСлой("Основной,Общий");
КонецЕсли;
КонецПроцедуры
//________________________________________________________
Форма.ИспользоватьЗакладки(1);
Форма.Закладки.ДобавитьЗначение(1,"Данные");
Форма.Закладки.ДобавитьЗначение(2,"Результат");
Список.НоваяКолонка("Элемент");
Список.НоваяКолонка("Реквизит");

Эту обработку можно загрузить в разделе "Скачать".

Автор статьи: Антон Гусев

Начать дискуссию