Как настроить отбор документов по значению в их табличной части

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов в 1С часто возникает задача ограничить выбор документов в поле формы не просто по значению в шапке, а по наличию определенной записи в его табличной части. Стандартные механизмы платформы, такие как "Связи параметров выбора", эффективно работают только с реквизитами верхнего уровня (шапки). Если же нам нужно, например, показать только те документы, в которых в списке сотрудников фигурирует конкретное лицо, придется прибегнуть к программным методам. Рассмотрим подробно, как это реализовать наиболее эффективно.

Метод 1. Использование обработчика ОбработкаПолученияДанныхВыбора

Проанализируем самый современный и производительный подход для управляемых форм — использование механизма перехвата данных выбора в модуле менеджера объекта. Этот метод хорош тем, что логика отбора инкапсулирована внутри самого объекта, и она будет срабатывать везде, где используется выбор этого документа (в выпадающих списках, при автоподборе или в формах выбора).

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


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

Обратим внимание на ключевое слово ВЫБРАТЬ РАЗЛИЧНЫЕ в тексте запроса. Это критически важно, так как один и тот же сотрудник может встречаться в табличной части документа несколько раз (например, при различных видах расчетов). Если мы забудем об этом, в списке выбора появятся дублирующиеся строки документов.

Метод 2. Программная установка параметров в событии НачалоВыбора

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

Посмотрим на пример кода, который формирует список ссылок "на лету" и передает его в параметры выбора:


&НаКлиенте
Процедура ДокументНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем массив ссылок, подходящих под условие (выполняется на сервере)
    МассивСсылок = ПолучитьМассивДокументовПоСотруднику(Объект.НужныйСотрудник);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("Ссылка", МассивСсылок));
    
    ОткрытьФорму("Документ.НачислениеЗарплаты.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

В данном примере мы используем СтандартнаяОбработка = Ложь, чтобы самостоятельно управлять процессом открытия формы. Мы заранее подготавливаем массив ссылок через запрос к табличной части и передаем его в структуру отбора по полю Ссылка. Платформа автоматически применит условие В СПИСКЕ, и пользователь увидит только нужные документы.

Метод 3. Работа с составными типами данных

Проанализируем более сложный случай, упомянутый в обсуждении: когда поле имеет составной тип данных, и в одном виде документа сотрудник находится в шапке, а в другом — в табличной части. Здесь возникает проблема с автоматическим определением типа при отключении стандартной обработки.

Для решения этой задачи нам потребуется сначала предложить пользователю выбрать тип документа, а затем применить соответствующий фильтр. Используем метод ПоказатьВыборТипа:


&НаКлиенте
Процедура ПолеДокументаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ОписаниеТиповДокументов = Элементы.ПолеДокумента.ОграничениеТипа;
    
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораТипа", ЭтотОбъект);
    ПоказатьВыборТипа(Оповещение, ОписаниеТиповДокументов);
    
КонецПроцедуры

&НаСервере
Процедура ПослеВыбораТипа(ВыбранныйТип, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныйТип = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Здесь определяем метаданные выбранного типа и открываем соответствующую форму
    // с нужным нам отбором по ТЧ или по шапке.
    
КонецПроцедуры

После того как тип определен, мы можем динамически построить запрос к базе данных. Если выбран тип, где сотрудник в шапке — используем простой отбор. Если выбран тип с сотрудником в ТЧ — используем запрос к табличной части, как мы разбирали выше.

Важные аспекты производительности и индексирования

Выясним причину, по которой поиск по табличным частям может работать медленно. В крупных информационных базах количество строк в таблицах ТЧ может исчисляться миллионами. Чтобы отбор не вызывал зависания системы, необходимо убедиться, что реквизит табличной части, по которому идет поиск (в нашем примере — Сотрудник), проиндексирован.

Посмотрим на настройки в Конфигураторе:

  1. Перейдем к нужному документу.
  2. Откроем вкладку "Табличные части".
  3. Найдем реквизит, по которому планируется отбор.
  4. В свойствах реквизита установим значение "Индексировать" или "Индексировать с дополнительным упорядочиванием".

Без этого шага СУБД будет вынуждена выполнять полное сканирование таблицы (Full Scan), что приведет к значительным задержкам при открытии списка выбора.

Использование критериев отбора

В качестве альтернативы программным запросам, рассмотрим штатный объект метаданных — Критерий отбора. Мы можем создать критерий ДокументыПоСотруднику и на вкладке "Состав" указать все табличные части различных документов, где встречается ссылка на сотрудника.

Преимущества этого метода:

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

← На главную