Как в запросе 1С вывести строки в колонки (создать кросс-таблицу)?

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

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

Метод 1. Использование Системы компоновки данных (СКД)

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

  1. Создадим набор данных — запрос. В самом запросе мы пишем обычный плоский выбор: ВЫБРАТЬ Товар, ТипЦены, Цена ИЗ РегистрСведений.Цены.СрезПоследних.
  2. Перейдем на вкладку «Настройки».
  3. Вместо обычной группировки добавим в структуру отчета элемент «Таблица».
  4. В строки таблицы добавим поле Товар.
  5. В колонки таблицы добавим поле ТипЦены.
  6. В выбранные поля (ресурсы) добавим поле Цена.

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

Метод 2. Механизм характеристик в Динамических списках

Если задача стоит не в создании отчета, а в выводе данных на форму списка (например, в справочнике Номенклатура), то программное построение запроса может быть избыточным. Рассмотрим современный платформенный механизм — Характеристики.

Этот метод позволяет «подмешивать» данные из регистра сведений к основному объекту. Чтобы это заработало, выполним следующие действия:

  1. В свойствах объекта метаданных (или в настройках динамического списка) укажем источник характеристик.
  2. В качестве видов характеристик выберем справочник ТипыЦен.
  3. В качестве значений характеристик укажем регистр сведений Цены.
  4. В настройках динамического списка на форме появится возможность вытащить эти характеристики как отдельные колонки.

Проанализируем ситуацию: пользователь сможет сам через меню «Изменить форму» добавлять или скрывать колонки с типами цен, а платформа сама будет оптимизировать запрос к базе данных.

Метод 3. Динамическое формирование текста запроса

Бывают случаи, когда использование СКД невозможно (например, нам нужно программно обработать таблицу значений или вывести данные в специфический интерфейс). Тогда мы прибегаем к динамическому формированию текста запроса. Разберем по шагам, как это реализовать.

Суть метода заключается в использовании конструкции ВЫБОР КОГДА ... ТОГДА для каждого типа цены. Посмотрим на пример алгоритма:


// 1. Сначала получим все доступные типы цен
ЗапросТипы = Новый Запрос("ВЫБРАТЬ Ссылка, Наименование ИЗ Справочник.ТипыЦен");
ВыборкаТипов = ЗапросТипы.Выполнить().Выбрать();

// 2. Начнем формировать текст основного запроса
ТекстЗапроса = "ВЫБРАТЬ Товар,";

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

// Убираем лишнюю запятую и добавляем условия
ТекстЗапроса = Лев(ТекстЗапроса, СтрДлина(ТекстЗапроса) - 1) + "
|ИЗ РегистрСведений.Цены.СрезПоследних
|СГРУППИРОВАТЬ ПО Товар";

Важно помнить: при таком подходе обязательно использование функции МАКСИМУМ (или другой агрегатной функции) и группировки по основному объекту (Товар). Это позволяет «схлопнуть» несколько строк регистра в одну строку результата, где значения распределятся по разным колонкам.

Метод 4. Транспонирование Таблицы Значений

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

  1. Создадим новую ТаблицаЗначений.
  2. Добавим в нее колонку Товар.
  3. Обойдем исходные данные и для каждого уникального значения ТипЦены добавим новую колонку в созданную ТЗ с помощью метода Колонки.Добавить().
  4. Заполним таблицу данными. Для ускорения процесса рекомендуется предварительно индексировать исходную таблицу по полям Товар и ТипЦены.

Проанализируем пример заполнения:


// Предположим, ТЗ_Результат - это наша новая широкая таблица
Для Каждого СтрокаДанных Из ТЗ_Исходная Цикл
    НоваяСтрока = ТЗ_Результат.Найти(СтрокаДанных.Товар, "Товар");
    Если НоваяСтрока = Неопределено Тогда
        НоваяСтрока = ТЗ_Результат.Добавить();
        НоваяСтрока.Товар = СтрокаДанных.Товар;
    КонецЕсли;
    
    // Имя колонки должно соответствовать идентификатору типа цены
    ИмяКолонки = "Тип_" + СтрокаДанных.ТипЦены.УникальныйИдентификатор();
    НоваяСтрока[ИмяКолонки] = СтрокаДанных.Цена;
КонецЦикла;

Метод 5. Построитель отчета

Хотя ПостроительОтчета считается предшественником СКД, он до сих пор встречается в старых конфигурациях и удобен для быстрой генерации кросс-таблиц в коде. Выясним, в чем его особенность: у него есть свойство РазмещатьИзмеренияВКолонках.

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

Подведем итоги

Мы рассмотрели несколько способов превращения строк в колонки. Выбор конкретного метода зависит от вашей конечной цели:

Каждый из этих методов позволяет автоматизировать процесс: при добавлении новых типов цен или категорий система сама «дорисует» нужные колонки, не требуя вмешательства программиста в код запроса при каждом изменении справочников. Для оптимизации вывода можно применять механизм скрытия столбцов при отсутствии в них данных.

← На главную