При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача отображения данных из табличных частей документов непосредственно в списке (форме списка). Типичный пример: в документе есть табличная часть «Параметры», где хранятся записи в формате «Ключ — Значение» (например, «Марка — Audi», «Модель — A3»). Если просто выбрать эти данные в запросе динамического списка, система выведет несколько строк для одного документа, что делает список нечитаемым.
В этой статье мы подробно разберем, как «развернуть» (транспонировать) строки табличной части в колонки, чтобы в динамическом списке была одна строка на один документ с заполненными реквизитами в разных столбцах.
Рассмотрим ситуацию, которую описал автор вопроса. При использовании конструкции ВЫБОР КОГДА в простом запросе к табличной части, система перебирает каждую строку ТЧ по отдельности. Если в документе две строки (Марка и Модель), то запрос сформирует две записи. В первой записи будет заполнена только «Марка», а «Модель» будет пустой строкой. Во второй — наоборот. В результате в динамическом списке один и тот же документ продублируется столько раз, сколько строк в его табличной части.
Для решения этой задачи нам необходимо объединить эти данные «по горизонтали». Проанализируем три основных способа реализации.
Это самый гибкий и понятный способ для динамического списка. Суть заключается в том, что мы берем основную таблицу документов и последовательно присоединяем к ней таблицу её же табличной части столько раз, сколько колонок нам нужно вынести в список.
Рассмотрим по шагам, как составить такой запрос:
Документ.ЗапросКотировок).ЛЕВОЕ СОЕДИНЕНИЕ с таблицей Документ.ЗапросКотировок.ПараметрыЗапросаКотировок.Пример реализации запроса:
ВЫБРАТЬ
ЗапросКотировок.Ссылка КАК Ссылка,
ЗапросКотировок.Дата КАК Дата,
ЗапросКотировок.Номер КАК Номер,
ЕСТЬNULL(ТЧ_Марка.Значение, "") КАК Марка,
ЕСТЬNULL(ТЧ_Модель.Значение, "") КАК Модель
ИЗ
Документ.ЗапросКотировок КАК ЗапросКотировок
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗапросКотировок.ПараметрыЗапросаКотировок КАК ТЧ_Марка
ПО ЗапросКотировок.Ссылка = ТЧ_Марка.Ссылка
И ТЧ_Марка.Идентификатор = "Марка"
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗапросКотировок.ПараметрыЗапросаКотировок КАК ТЧ_Модель
ПО ЗапросКотировок.Ссылка = ТЧ_Модель.Ссылка
И ТЧ_Модель.Идентификатор = "Модель"
Важный момент: Мы используем ЕСТЬNULL, чтобы в случае отсутствия записи в табличной части в списке отображалась пустая строка, а не системное значение NULL, которое может мешать поиску и сортировке.
Проанализируем ситуацию, когда параметров много и плодить десятки соединений не хочется. В этом случае можно использовать механизм СГРУППИРОВАТЬ ПО и агрегатную функцию МАКСИМУМ. Этот метод позволяет «схлопнуть» несколько строк в одну.
Разберем логику работы такого запроса:
ВЫБРАТЬ
ЗапросКотировок.Ссылка КАК Ссылка,
МАКСИМУМ(ВЫБОР
КОГДА ТЧ.Идентификатор = "Марка"
ТОГДА ТЧ.Значение
ИНАЧЕ ""
КОНЕЦ) КАК Марка,
МАКСИМУМ(ВЫБОР
КОГДА ТЧ.Идентификатор = "Модель"
ТОГДА ТЧ.Значение
ИНАЧЕ ""
КОНЕЦ) КАК Модель
ИЗ
Документ.ЗапросКотировок КАК ЗапросКотировок
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗапросКотировок.ПараметрыЗапросаКотировок КАК ТЧ
ПО ЗапросКотировок.Ссылка = ТЧ.Ссылка
ГДЕ
ТЧ.Идентификатор В ("Марка", "Модель")
СГРУППИРОВАТЬ ПО
ЗапросКотировок.Ссылка
Выясним причину использования МАКСИМУМ: так как для каждой строки ТЧ все поля ВЫБОР, кроме одного, будут пустыми, функция МАКСИМУМ выберет именно то единственное заполненное значение для каждой колонки и объединит их в рамках одной строки по ссылке документа.
Если ваша конфигурация использует План видов характеристик (ПВХ) для определения параметров, то 1С предоставляет встроенный инструмент. В настройках динамического списка на вкладке «Характеристики» можно указать источник данных для дополнительных реквизитов.
Преимущества этого подхода:
Нужно учитывать, что динамический список выполняет запрос при каждом скроллинге или поиске. Проанализируем возможные проблемы при работе с большими объемами данных:
ЛЕВОЕ СОЕДИНЕНИЕ может значительно замедлить открытие формы списка.Идентификатор и Ссылка в табличной части должны быть индексированы, иначе СУБД будет выполнять полное сканирование таблицы.Таким образом, для простых задач идеально подходит Способ 1 с левыми соединениями. Он нагляден, легко отлаживается и позволяет быстро получить требуемый результат в одной строке динамического списка.