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

Наверное, многие сталкивались с проблемой поиска похожих значений в наименованиях и реквизитах справочников. А те, кто не сталкивался - еще столкнутся. ;)

Каждый изобретал велосипед своей собственной конструкции, а ведь все уже давно придумано. Для тех, кто использует базы данных SQL, есть очень простой вариант решения этого вопроса. Причем, так как осуществляется все средствами SQL сервера, то и работает очень быстро. Настолько быстро, что в прилагаемой обработке больше время тратится на заполнение визуальных форм, чем на получение данных из базы данных.

Автор приводимой обработки AndrewKa.

Обработка позволяет выбрать элементы любого справочника в любой конфигурации 1C Предприятие 7.7 в соответствии с заданным фильтром по любому реквизиту типа «Строка» или «Число».

В принципе это демострация возможностей использования ODBCQuery, хотя и является полноценным продуктом. Для работы необходимо наличие библиотеки rainbow.dll в папке ИБ, которую можно взять здесь.

Поиск производится по текущему (в списке значений) справочнику. Результат поиска выводится в СЗ, который удобно использовать в конструкции запроса
|Значение в СЗ; для построения различных отчетов отчетов.

ВНИМАНИЕ: Пока не поддерживается поиск по периодическим реквизитам и по реквизитам типа "Строка неограниченной длины"!!!

Описание служебных символов:

% - Обозначает строку из любых символов и любой длины (в том числе и пустую).

_ - знак подчеркивания. Обозначает любой одиночный символ.

[] - Интервальный метасимвол. Обозначает любой одиночный символ в пределах заданного интервала или множества, например [m-p] или [mnop] обознает любой из символов m,n,o или p.

[^] - Метасимвол "вне интервала". Обозначает любой одиночный символ, находящийся вне заданного интервала или множества, например [^m-p] или [^mnop] означает любой символ, отличный от m,n,o или p.

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

Форма обработки

Ниже приведен код модуля формы обработки:

Перем ТекСправочник,MDW,RBS,ТЗНомераРеквизитов;

Процедура Сформировать()
    Перем Ном;
    Список.УдалитьСтроки();
    Ном=0;
    ВнутрИД="SC"+MDW.GetRefID(Справочники.ТекущаяСтрока()-1);
    ТипаТекЗнач=Реквизиты.ПолучитьЗначение(Реквизиты.ТекущаяСтрока());
    Если ТипаТекЗнач="Код" тогда
        ИДПоля="CODE";
    ИначеЕсли ТипаТекЗнач="Наименование" тогда
        ИДПоля="DESCR";
    Иначе
        ТЗНомераРеквизитов.НайтиЗначение(Реквизиты.ПолучитьЗначение(Реквизиты.Текущаястрока()),Ном,1);
        ИДПоля="SP"+MDW.GetRefFieldID(Справочники.ТекущаяСтрока()-1,ТЗНомераРеквизитов.ПолучитьЗначение(Ном,2)-1);
    КонецЕсли;
    Query = СоздатьОбъект("ODBCQuery");
    ТекстSELECT="SELECT ID,"+ИДПоля+"
    | FROM "+ВнутрИД+"
    | WHERE (RTRIM(CONVERT(char(100), "+ИДПоля+", 112)) LIKE '"+СокрЛП(Стр)+"')";
    Если Query.Prepare(ТекстSELECT,1,1)=1 Тогда
        Если Query.Open()=1 Тогда
            Query.GotoNext();
            Пока Query.IsOK()=1 Цикл
                Список.Новаястрока();
                Список.Наименование=RBS.ValueFromDBString(11,Строка(MDW.GetRefID(Справочники.ТекущаяСтрока()-1)),Query.GetString(Query.FindField("ID")));
                Список.Значение=Query.GetString(Query.FindField(ИДПоля));
                Query.GotoNext();
            КонецЦикла;
            Query.Close();
        Иначе
            Предупреждение("Ошибка Query.Open");
        КонецЕсли;
        Query.Reset();
    Иначе
        Предупреждение("Ошибка Query.Prepare");
    КонецЕсли;
КонецПроцедуры

Процедура приОткрытии()
    // Пример строки для фильтрации
    Стр="%пиво%";
    // Выведет все элементы (включая группы) в которых содержится слово "пиво"
    Для х=1 По Метаданные.Справочник() Цикл // перебор справочников
        Справочники.ДобавитьЗначение(МетаДанные.Справочник(х).Идентификатор);
        Если х=1 тогда // Для первого справочника. Остальные при навигации
            Реквизиты.ДобавитьЗначение("Код");
            Реквизиты.ДобавитьЗначение("Наименование");
            Для хх=1 По Метаданные.Справочник(х).Реквизит() Цикл
                Если Метаданные.Справочник(х).Реквизит(хх).Тип="Строка" тогда
                    Если Метаданные.Справочник(х).Реквизит(хх).Длина=0 тогда
                        Продолжить;
                    КонецЕсли;
                    Если Метаданные.Справочник(х).Реквизит(хх).Периодический=1 тогда
                        Продолжить;
                    КонецЕсли;
                    Реквизиты.ДобавитьЗначение(МетаДанные.Справочник(х).Реквизит(хх).Идентификатор );
                    ТЗНомераРеквизитов.НоваяСтрока();
                    ТЗНомераРеквизитов.Реквизит=МетаДанные.Справочник(х).Реквизит(хх).Идентификатор;
                    ТЗНомераРеквизитов.Номер=хх;
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    ТекСправочник=Справочники.ПолучитьЗначение(1);
    Форма.ИспользоватьСлой("Источник,Общий");
Конецпроцедуры

Функция Пересчет()
    Если НЕ(ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока())) Тогда
        ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока());
        Реквизиты.УдалитьВсе();
        ТЗНомераРеквизитов.УдалитьСтроки();
        Если Метаданные.Справочник(ТекСправочник).ДлинаКода>0 Тогда
            Реквизиты.ДобавитьЗначение("Код");
        КонецЕсли;
        Если Метаданные.Справочник(ТекСправочник).ДлинаНаименования>0 Тогда
            Реквизиты.ДобавитьЗначение("Наименование");
        КонецЕсли;
        Для хх=1 По Метаданные.Справочник(ТекСправочник).Реквизит() Цикл
            ТекТип=Метаданные.Справочник(ТекСправочник).Реквизит(хх).Тип;
            Если (ТекТип="Строка") Или (ТекТип="Число") тогда
                Если Метаданные.Справочник(ТекСправочник).Реквизит(хх).Длина=0 тогда
                    Продолжить;
                КонецЕсли;
                Если Метаданные.Справочник(ТекСправочник).Реквизит(хх).Периодический=1 тогда
                    Продолжить;
                КонецЕсли;
                Реквизиты.ДобавитьЗначение(МетаДанные.Справочник(ТекСправочник).Реквизит(хх).Идентификатор);
                ТЗНомераРеквизитов.НоваяСтрока();
                ТЗНомераРеквизитов.Реквизит=МетаДанные.Справочник(ТекСправочник).Реквизит(хх).Идентификатор;
                ТЗНомераРеквизитов.Номер=хх;
            КонецЕсли;
        КонецЦикла;
        ТекСправочник=Справочники.ПолучитьЗначение(Справочники.ТекущаяСтрока());
        Реквизиты.Текущаястрока(2);
    КонецЕсли;
КонецФункции

Процедура ПриВыбореЗакладки(ТекНомер)
    Если ТекНомер=1 Тогда
        Форма.ИспользоватьСлой("Источник,Общий");
    Иначе
        Форма.ИспользоватьСлой("Основной,Общий");
    КонецЕсли;
КонецПроцедуры
Форма.ИспользоватьЗакладки(1);
Форма.Закладки.ДобавитьЗначение(1,"Данные");
Форма.Закладки.ДобавитьЗначение(2,"Результат");
ЗагрузитьВнешнююКомпоненту("rainbow.dll");
MDW=СоздатьОбъект("MetaDataWork");
RBS=СоздатьОбъект("RainBowService");
список.НоваяКолонка("Наименование");
список.НоваяКолонка("Значение");
ТЗНомераРеквизитов=СоздатьОбъект("ТаблицаЗначений");
ТЗНомераРеквизитов.НоваяКолонка("Реквизит");
ТЗНомераРеквизитов.НоваяКолонка("Номер");

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

Вот здесь можно посмотреть, как улучшить пользовательский интерфейс путем вставки быстрого поиска в справочник товаров. А здесь можно посмотреть на быстрый поиск встроенными средствами -Предприятия.

 


 

Перепечатка, воспроизведение в любой форме, распространение, в том числе в переводе, любых материалов с сайта www.softpoint.ru возможны только с письменного разрешения компании "СофтПоинт". Это правило действует для всех без исключения случаев, кроме тех, когда в материале прямо указано разрешение на копирование (основание: Закон Российской Федерации "Об авторском праве и смежных правах").