Критерии отбора



Статья посвящена объекту конфигурации — критерий отбора. Поговорим о сущности этого объекта и о методах работы с ним.

В составе метаданных 1С:Предприятия 8 существует объект Критерий отбора. 

Этот объект, в отличие от большинства прикладных объектов конфигурации, не описывает каких-либо самостоятельных данных, которые будут храниться в информационной базе 1С:Предприятия. Критерий отбора предназначен для того, чтобы описать условия отбора по некоторым объектам. Например, можно указать, что критерий отбора строится по типу данных СправочникСсылка.Номенклатура, и в этот критерий входят документы «ПоступлениеТоваровУслуг» и «РеализацияТоваровУслуг». Конечно, все отборы мы можем делать с помощью запроса.

Особенностью (преимуществом) критерия отбора является то, что он может строиться в том числе по реквизирам табличных частей. Таким образом мы можем очень просто настроить отбор так, чтобы в его результат попадали лишь те документы, в табличной части которых есть интересующий нас элемент справочника «Номенклатура».

Критерий отбора является прикладным объектом, для него, в частности, можно создать форму, которая будет отображаться в пользовательском режиме. Однако находится он в ветке «Общие» из-за того, что имеет узкоспециализированное назначение. Особенностью Критерия отбора является то, что он не входит в глобальный командный интерфейс.


     

Рассмотрим особенности критерия отбора на примере. Создадим новый критерий отбора «Документы с номенклатурой». Настроим закладки «Данные» и «Состав». На закладке «Данные» указывается тот тип данных, по которому будет осуществляться отбор. Причем тип данных может быть составным. Итак, выберем тип данных — СправочникСсылка.Номенклатура. На закладке состав мы выбираем объекты, которые будут являться результатом выполнения нашего отбора. Система предлагает нам отметить флажками интересующие нас объекты из списка, в который она включает все объекты, содержащие ссылку на справочник «Номенклатура». На закладке формы мы можем для критерия отбора указать ФормуСписка, которая будет содержать динамический список объектов, удовлетворяющих нашему критерию. Кроме того, на закладке Права мы можем настроить «Просмотр» для определенных ролей. Следует отметить, что в пользовательском интерфейсе существует возможность просмотра результата отбора, т.е. ФормыСписка критерия отбора. В нашем случае это будет форма справочника «Номенклатура», но, чтобы это работало, необходимо перейти в командный интерфейс ФормыЭлемента справочника «Номенклатура» и поставить флаг в колонке «Видимость» напротив «Документы с номенклатурой (Объект.Ссылка).


     

Рассмотрим, как критерий отбора хранится в базе данных. Если мы в нашей Базе данных создадим запрос, то мы увидим таблицу, которая соответствует критерию отбора. Однако данная таблица является «виртуальной«. В процессе отладки мы можем вызвать метод ПолучитьСтруктуруХраненияБазыДанных(), и мы также не найдем таблиц, соответствующих критерию отбора. Таким образом, нет физической таблицы, соответствующей критерию отбора, но есть таблица виртуальная, к которой мы можем обратиться. Например, создав запрос и выгрузив результатЗапроса:

Запрос.Текст =
"ВЫБРАТЬ
| ДокументыСНоменклатурой.Ссылка
|ИЗ
| КритерийОтбора.ДокументыСНоменклатурой(&Номенклатура) КАК ДокументыСНоменклатурой";

Запрос.УстановитьПараметр("Номенклатура", Номенклатура);

РезультатЗапроса = Запрос.Выполнить();

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

Также следует отметить, что, несмотря на то, что при включении в конфигурацию критерия отбора система не создает никаких таблиц, однако для оптимизации поиска создается индекс по каждому реквизиту, который указан в составе критериев отбора. Индексы будут использоваться для оптимизации получения выборки при использовании критерия отбора. Таким образом, при описании критерия отбора нужно учитывать, что система будет тратить дополнительные ресурсы на поддержание необходимых индексов. Кстати, процесс «заполнения индекса поиска» можно увидеть, если мы просто переименуем созданный ранее критерий отбора. Сам процесс длится около минуты. А далее система выдает сообщение «Код модулей содержит возможные использования ссылки на изменяемый объект. Продолжить операцию переименования?» И если мы соглашаемся, то выдает нам ссылки на код, где встречаются упоминания нашего критерия отбора. Причем рядом с каждой ссылкой появляется команда «заменить», при нажатии на которую автоматически происходит замена старого наименования критерия отбора на новое.

Каким же образом система получает искомый результат? Дело в том, что она формирует запрос для поиска объектов, которые включают искомое значение, и формирует выборку, состоящую из найденных ссылок на объекты. Формируемый запрос представляет собой объединение запросов по каждой таблице, в которой нужно осуществить поиск. Запросы формируются только к тем данным (таблицам), из числа описанных в критерии отбора, у которых в реквизите может быть значение того типа, значение которого в данный момент ищется. Например, критерий отбора включает ссылки на справочник физических лиц и справочник организаций, а в конкретном реквизите конкретного документа может быть ссылка только на справочник физических лиц. Тогда запрос по этому документу будет выполняться, только если в данный момент поиск выполняется по физическому лицу. Важно учитывать, что критерий отбора всегда выбирает все искомые данные. Ни в списке, ни в других режимах не поддерживается динамическая выборка, так как информация выбирается путем объединения данных из разных таблиц. Формируемый для критерия отбора индекс позволяет сделать это достаточно быстро, но если данных в выборке окажется очень много, то выборка не будет формироваться эффективно. Поэтому целесообразно создавать критерии отбора по данным, имеющим большой разброс значений, чтобы выборки получались не очень большие.  В противном случае теряется смысл такого отбора и снижается его эффективность.

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

     Поговорим о программной работе с критерием отбора. В синтакс-помощнике в ветке «Прикладные объекты» находится ветка «Критерии отбора». Мы видим, что количество типов данных здесь не очень большое. Во-первых, это менеджер критериев отбора — КритерииОтбораМенеджер (FilterCriteriaManager). Это свойство глобального контекста, которое позволяет через точку обратиться к конкретному критерию отбора. Далее мы получаем КритерийОтбораМенеджер.<Имя критерия> (FilterCriterionManager.<Имя критерия>), у которого есть два метода — Найти(<ЗначениеПоиска>) и ПолучитьФорму(<Форма>, <Владелец>, <КлючУникальности>). И еще один тип данных — КритерийОтбораСписок.<Имя критерия> (FilterCriterionList.<Имя критерия>). Он предназначен для управления списком отобранных документов и/или элементов справочников, отображаемых в табличном поле (списком критерия отбора). Как видим, методов для програмной работы не очень много, поэтому гораздо удобнее работать с критерием отбора при помощи запроса.
     Рассмотрим на примере, как отобразить результат работы критерия отбора в форме. Для этого можно создать обработку.

Итак, создаем обработку и управляемую форму для неё. У формы будет два реквизита. Это «Номенклатура» — СправочникСсылка.Номенклатуры и «Список», тип которого — «ДинамическийСписок«. В свойствах реквизита «Список» заполним «ОсновнаяТаблица» значением — «КритерийОтбора.ДокументыСНоменклатурой». Перетаскиваем оба реквизита на форму. Кроме того, нам необходимо установить параметр «Значение» для нашего динамического списка. У динамического списка есть свойство «Параметры», тип значения которого: ЗначенияПараметровДанныхКомпоновкиДанных. У которого в свою очередь есть метод: УстановитьЗначениеПараметра(<Параметр>, <Значение>). Итак, в модуле формы у нас будет следующий код:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("Значение",Номенклатура);
КонецПроцедуры

&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
Список.Параметры.УстановитьЗначениеПараметра("Значение",Номенклатура);
КонецПроцедуры

Сохраняем обработку и запускаем в пользовательском режиме.

     Рассмотрим еще один пример работы с критерием отбора. На этот раз поработаем с ФормойСписка критерия отбора. Дело в том, что интерактивно открыть её пользователь не может. Попробуем открыть её программным образом. В нашей обработке создадим команду «ОткрытьФ», перетащим её в форму нашей обработки, и создадим процедуру для нашей команды:

 &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("Значение",Номенклатура);
КонецПроцедуры

&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
Список.Параметры.УстановитьЗначениеПараметра("Значение",Номенклатура);
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьФ(Команда)
ОткрытьФорму("КритерийОтбора.ДокументыПоДоговоруКонтрагента.ФормаСписка");
КонецПроцедуры

Сохраняем нашу обработку, в пользовательском режиме нажимаем на кнопку «ОткрытьФ», наша ФормаСписка открывается, но система при этом выдает ошибку. Дело в том, что система не может понять, по какому объекту ей нужно сделать отбор. Нам необходимо заполнить параметр Значение нашего динамического списка. В принципе, мы можем сделать это интерактивно. Для этого перейдем в ФормуСписка нашего критерия отбора, раскроем ветку «Список», найдем там «Параметры» и перетащим их на нашу ФормуСписка критерия отбора. Теперь в пользовательском режиме мы можем поставить флажок перед параметром «Значение» в истину, ну и, собственно, заполнить и сам параметр «Значение». Но лучше это сделать программно при открытии ФормыСписка критерия отбора. Программную установку мы будем делать в процедуре «ПриСозданииНаСервере()«. Если мы поставим точку останова в этой процедуре, то при отладке мы увидим: в параметрах нашего динамического списка есть коллекция «Элементы», и у элемента «Использование» стоит значение «Ложь». Чтобы установить его в истину, можно использовать следующий код, поскольку «Элементы» — это коллекция значений:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.Элементы[0].Использование = Истина;
КонецПроцедуры

     Мы можем также использовать обращение по имени параметра. Для этого мы можем использовать метод «Найти()»:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.Элементы.Найти("Значение").Использование = Истина;
КонецПроцедуры

      Также мы можем передать в ФормуСписка критерия отбора значение «Номенклатуры» из формы вызывающей, т.е. нашей обработки. Для этого передадим из формы нашей обработки значение «Номенклатура»:

 

&НаКлиенте
Процедура ОткрытьФ(Команда)
ОткрытьФорму("КритерийОтбора.ДокументыСНоменклатурой.ФормаСписка", новый Структура("Номенклатура", Номенклатура);
КонецПроцедуры

     А в ФормеСписка критерия отбора воспользуемся переданным значением:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.Элементы.Найти("Значение").Использование = Истина;
Список.Параметры.Элементы.Найти("Значение").Значение = Параметры.Номенклатура;
КонецПроцедуры

     Далее запускаем нашу обработку в пользовательском режиме, заполняем реквизит «Номенклатура» и нажимаем кнопку «ОткрытьФ». В результате откроется ФормаСписка критерия отбора с переданным значением «Номенклатуры» из формы вызывающей, а также сформируется результат отбора.

     На этом заканчиваем, надеюсь, материал будет полезен для понимания сути объекта «Критерий отбора». Всем пока и удачи)

13 Comments

  1. gradi

    Спасибо за подробный разбор темы.

    Reply
  2. DrAku1a
    А далее система выдает сообщение «Код модулей содержит возможные использования ссылки на изменяемый объект. Продолжить операцию переименования?» И если мы соглашаемся, то выдает нам ссылки на код, где встречаются упоминания нашего критерия отбора. Причем рядом с каждой ссылкой появляется команда «заменить», при нажатии на которую автоматически происходит замена старого наименования критерия отбора на новое.

    Это стандартное поведение новой платформы (8.3) при переименовании объектов конфигурации (Справочники, Документы, Регистры). Прямого отношения к критериям отбора не имеет.

    Reply
  3. Sardukar

    В подготовительных материалах к «1С Профессионал» говорится — «В управляемых формах с реквизитом типа «динамический список» правило отбора настраивается через настройки списка в режимах Конфигуратор и 1С:Предприятие. Поля реквизитов табличных частей доступны в правилах отбора динамических списков без необходимости создания произвольного запроса». Я к тому, что может быть более подходящим для демонстрации критериев отбора мог быть пример на обычной форме, а не управляемой. При всем уважении к автору.

    Reply
  4. Поручик

    А недостатком (большим) критерия отбора является то, что в запросе ему невозможно передать список или массив ссылок для построения выборки. А иногда надо. Приходится извращаться. Несколько раз сталкивался.

    Reply
  5. echo77

    (4) В итоге, как вы решили эту задачу? Можете поделиться?

    Я решал подобную задачу: переписывал форму структуры подчиненности на СКД — запрос из кучи объединений писал сам

    Reply
  6. Поручик

    (5) Вы никому не говорите. Запрос к критерию отбора в цикле. Одно из творчеств буду переписывать, уж очень тормозно.

    Reply
  7. pavlo

    (6) Ну к сожалению механизм хороший, но не имение возможности передать список часто просто убивает пользу. В итоге и остается имхо только или не слабый свой запрос из объединений или цикл 🙁

    Reply
  8. German_Tagil

    Вопрос — как передать критерий обора из документа к примеру «Заказ поставщику» отбор по значению в текущей колонке

    в отбор списка документов

    критерий отбора в списке по номенклатуре доделан.

    хотелось бы сразу отбор из документа по списку делать

    Reply
  9. German_Tagil

    в общем так

    не могу понять как проверить отбор по товарам — те была ли нажата кнопочка

    а так напрашивается

    ДокументСписок.Отбор.Номенклатура.Значение = ДанныеСтроки.Номенклатура;
    ДокументСписок.Отбор.Номенклатура.Использование = Истина;
    ДокументСписок.Обновить();
    Reply
  10. German_Tagil

    (6) А можно поподробнее?

    Запрос к критерию отбора в цикле.

    Сделал как мог — в ЗаказеПоставщику в Форме списка

    Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ПараметрОтборПоЗначению=эТАФОРМА.Отбор.Номенклатура.Значение;
    
    Если типЗнч(ПараметрОтборПоЗначению)= тип («Строка») Тогда
    
    
    
    
    
    //{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
    // Данный фрагмент построен конструктором.
    // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    |    Номенклатура.Наименование,
    |    Номенклатура.Ссылка,
    |    Номенклатура.НаименованиеПолное
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.НаименованиеПолное ПОДОБНО   &НаименованиеПолное   «;
    
    Запрос.УстановитьПараметр(«НаименованиеПолное», «%»+ ПараметрОтборПоЗначению + «%»);
    
    Результат = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = Результат.Выбрать();
    
    Номенклатура = Новый СписокЗначений;
    
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    Номенклатура.Добавить(ВыборкаДетальныеЗаписи.ссылка);
    сообщить(«ВыборкаДетальныеЗаписи » + ВыборкаДетальныеЗаписи.ссылка);
    // Вставить обработку выборки ВыборкаДетальныеЗаписи
    КонецЦикла;
    
    
    
    ЭтаФорма.Отбор.Номенклатура.ВидСравнения = ВидСравнения.ВСписке;
    
    ЭтаФорма.Отбор.Номенклатура.Значение = Номенклатура;
    ЭтаФорма.Отбор.Номенклатура.Использование=Истина;
    
    //}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
    
    
    
    КонецЕсли;
    
    
    
    
    
    // Вставить содержимое обработчика.
    КонецПроцедуры

    Показать

    Reply
  11. dj_tol

    А можно как нибудь со списком поработать чет я не могу ни как сообразить. Есть запрос который перебирает последние поступления по товару, так вот в этом запросе как сделать выборку по подчиненным документам.

    ВЫБРАТЬ
    Закупки.ИсточникГФУНоменклатуры КАК ИсточникГФУНоменклатуры,
    Закупки.Регистратор КАК Регистратор,
    СУММА(ВременнаяТаблицаТоваров.ВНаличииОстаток) КАК ВНаличииОстаток,
    СУММА(ВЫРАЗИТЬ(Закупки.Сумма / Закупки.Количество КАК ЧИСЛО(15, 2))) КАК Цена,
    СвязанныеДокументы.Ссылка КАК СвязанныеДокументы
    ИЗ
    РегистрНакопления.Закупки КАК Закупки
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблицаПоследних КАК ВременнаяТаблицаПоследних
    ПО (ВременнаяТаблицаПоследних.Ссылка = Закупки.Регистратор)
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблицаТоваров КАК ВременнаяТаблицаТоваров
    ПО (ВременнаяТаблицаТоваров.Номенклатура.Ссылка = Закупки.ИсточникГФУНоменклатуры)
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ КритерийОтбора.СвязанныеДокументы() КАК СвязанныеДокументы
    ПО Закупки.Регистратор.Ссылка = СвязанныеДокументы.Ссылка
    
    СГРУППИРОВАТЬ ПО
    Закупки.ИсточникГФУНоменклатуры,
    Закупки.Регистратор,
    СвязанныеДокументы.Ссылка

    Показать

    Reply
  12. СергейК

    (11) Подскажите, не получилось вставить КритерийОтбора в СОЕДИНЕНИЕ ?

    Reply
  13. Stanislav1993

    Крутая статья! Спасибо, добрый человек! =)

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *