Как выполнить отбор в списке документов по значениям из табличной части бизнес-процесса?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача связать два объекта не по прямой ссылке, а по совпадению данных в их табличных частях. Типичный пример: в бизнес-процессе (БП) указан перечень рисков, и нам необходимо открыть список документов «Оценка значимости риска», которые содержат именно эти риски. Рассмотрим подробно, как реализовать такой механизм, перейдя от простых отборов к работе с динамическими списками и произвольными запросами.

Постановка задачи и анализ ситуации

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

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

Шаг 1. Подготовка данных в форме бизнес-процесса

Прежде всего, нам нужно собрать все риски из табличной части бизнес-процесса в один массив, чтобы передать их открываемой форме. Разберем, как это сделать программно в обработчике команды. Проанализируем код вызова:


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

Шаг 2. Настройка динамического списка в документе

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

  1. Откроем форму списка документа в конфигураторе.
  2. Выберем реквизит Список и в свойствах установим флажок Произвольный запрос.
  3. Нажмем Открыть рядом с настройкой запроса.

В тексте запроса нам нужно использовать условие ГДЕ ... В (&Параметр). Это позволит системе найти документы, в табличной части которых встречается хотя бы один риск из нашего массива. Рассмотрим пример запроса:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ДокументОценка.Ссылка КАК Ссылка,
    ДокументОценка.ПометкаУдаления КАК ПометкаУдаления,
    ДокументОценка.Номер КАК Номер,
    ДокументОценка.Дата КАК Дата,
    ДокументОценка.Проведен КАК Проведен
ИЗ
    Документ.ОценкаЗначимостиРиска КАК ДокументОценка
ГДЕ
    ДокументОценка.Оценка.Риск В (&СписокРисков)

Важный момент: использование ключевого слова РАЗЛИЧНЫЕ обязательно. Поскольку отбор идет по табличной части, один и тот же документ может попасть в выборку столько раз, сколько строк в его табличной части совпало с условием. РАЗЛИЧНЫЕ схлопнет дубли, и мы увидим уникальные ссылки на документы.

Шаг 3. Установка параметров при создании формы

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли наш параметр со списком рисков
    Если Параметры.Свойство("СписокРисков") Тогда
        
        // Устанавливаем значение параметра в динамическом списке
        Список.Параметры.УстановитьЗначениеПараметра("СписокРисков", Параметры.СписокРисков);
        
    Иначе
        
        // Если форма открыта просто так, нужно передать пустой массив или 
        // предусмотреть условие в запросе, чтобы выводились все документы.
        // Для этого в запросе обычно пишут: ГДЕ (&ОтборУстановлен = ЛОЖЬ ИЛИ Риск В (&СписокРисков))
        
        ПустойМассив = Новый Массив;
        Список.Параметры.УстановитьЗначениеПараметра("СписокРисков", ПустойМассив);
        
    КонецЕсли;
    
КонецПроцедуры

Альтернативный метод: Использование компоновщика настроек

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("СписокРисков") Тогда
        
        // Очистим текущие отборы (если нужно)
        Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Очистить();
        
        // Создаем новый элемент отбора
        НовыйОтбор = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        
        // Указываем левое значение — путь к реквизиту табличной части
        НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Оценка.Риск");
        
        // Указываем вид сравнения "В списке"
        НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
        
        // Устанавливаем правое значение — наш массив
        НовыйОтбор.ПравоеЗначение = Параметры.СписокРисков;
        НовыйОтбор.Использование = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Оптимизация и важные рекомендации

Работа с отборами по табличным частям может замедлять систему при больших объемах данных. Разберем, как минимизировать риски падения производительности:

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

← На главную