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

Программист Управленческий учет Торговля и дистрибуция
← На главную

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

Разбор проблемы: почему обычный запрос не всегда подходит

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

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

Шаг 1: Подготовка основного запроса

Выясним причину, по которой стандартные подходы могут не работать. Часто разработчики пытаются обернуть всё соединение в фигурные скобки. Однако, как показывает практика, для стабильной работы отбора по табличной части лучше оставить само соединение «жестким» (без скобок), а в фигурные скобки вынести только условие ГДЕ.

Рассмотрим пример правильной структуры запроса для динамического списка:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ЗаказыПокупателей.Ссылка КАК Ссылка,
    ЗаказыПокупателей.Дата КАК Дата,
    ЗаказыПокупателей.Номер КАК Номер,
    ЗаказыПокупателей.Контрагент КАК Контрагент
ИЗ
    Документ.ЗаказПокупателя КАК ЗаказыПокупателей
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя.Услуги КАК ЗаказПокупателяУслуги
    ПО ЗаказыПокупателей.Ссылка = ЗаказПокупателяУслуги.Ссылка
{ГДЕ
    ЗаказПокупателяУслуги.Поставщик.* КАК ПоставщикУслуги}

Важные моменты в этом коде:

  1. Использование ключевого слова РАЗЛИЧНЫЕ обязательно. Это гарантирует, что в списке не будет дублей документов, если условию отбора удовлетворяют сразу несколько строк в табличной части одного документа.
  2. Секция {ГДЕ ...} описывает поле, которое появится в окне «Настройка списка» у пользователя.
  3. Конструкция Поставщик.* позволяет обращаться к полям реквизита (если это справочник), а КАК ПоставщикУслуги задает понятное имя для этого поля в интерфейсе настроек.

Шаг 2: Почему отбор может не работать в консоли запросов

Многие программисты пытаются тестировать подобные запросы в консолях. Проанализируем, почему это часто приводит к неверным выводам. Обычная консоль запросов выполняет текст запроса через объект Запрос. Объект Запрос полностью игнорирует всё, что написано в фигурных скобках {}. Эти инструкции предназначены исключительно для механизмов Построителя или СКД.

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

Шаг 3: Оптимизация списка доступных полей

Рассмотрим следующую проблему: после добавления соединений в динамическом списке может появиться огромное количество «лишних» полей для отбора (все измерения регистров, все реквизиты присоединенных таблиц). Это «замусоривает» интерфейс и путает пользователя.

Чтобы оставить пользователю только нужные поля (например, только реквизиты документа и наш новый отбор по поставщику), выполним следующие действия:

  1. Откроем свойства динамического списка.
  2. Найдем флаг Автозаполнение доступных полей. Если версия платформы выше 8.3.10 и режим совместимости позволяет, снимем этот флаг.
  3. Если флаг недоступен (как в старых версиях или при режиме совместимости 8.2), перейдем в Конструктор запроса на закладку Компоновка данных.

На закладке Компоновка данных мы можем детально управлять тем, что видит пользователь:

Например, если мы хотим явно ограничить список доступных полей через текст запроса, мы можем использовать секции {ВЫБРАТЬ...}:


ВЫБРАТЬ
    ЗаказыПокупателей.Ссылка,
    ЗаказыПокупателей.Дата
ИЗ
    Документ.ЗаказПокупателя КАК ЗаказыПокупателей
{ВЫБРАТЬ
    Ссылка.*,
    Дата,
    ЗаказПокупателяУслуги.Поставщик.* КАК ПоставщикУслуги}
{ГДЕ
    ЗаказыПокупателей.Ссылка.*,
    ЗаказПокупателяУслуги.Поставщик.* КАК ПоставщикУслуги}

Шаг 4: Программная настройка доступности полей

Если визуальные средства настройки не помогают (например, из-за специфических ограничений конфигурации), мы можем прибегнуть к программному управлению в модуле формы. Проанализируем пример кода в процедуре ПриСозданииНаСервере:


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

Этот метод позволяет жестко контролировать интерфейс настройки списка, оставляя пользователю только необходимые инструменты для работы.

Резюме

Для корректной фильтрации динамического списка по табличной части необходимо использовать ЛЕВОЕ СОЕДИНЕНИЕ с обязательным указанием РАЗЛИЧНЫЕ в секции ВЫБРАТЬ. Инструкции отбора должны быть заключены в фигурные скобки {ГДЕ ...}. Помните, что динамический список — это объект, работающий по принципам компоновки данных, поэтому управление составом полей лучше всего выполнять на закладке Компоновка данных в конструкторе запроса.

← На главную