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

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

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

Проблема: Лишние строки при обычном добавлении

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


// Ошибочный подход
Для каждого Стр Из ТЗ Исходная Цикл
    НоваяСтрока = ТЗ_Результат.Добавить();
    Если Стр.Цвет = "Зелёный" Тогда
        НоваяСтрока.Авто1 = Стр.Автомобиль;
    ИначеЕсли Стр.Цвет = "Синий" Тогда
        НоваяСтрока.Авто2 = Стр.Автомобиль;
    КонецЕсли;
КонецЦикла;

В данном случае для каждого цвета создается отдельный объект строки. Чтобы объединить данные, нам нужно либо найти уже созданную строку, либо заранее подготовить структуру результата.

Решение 1: Использование метода Найти() для сопоставления строк

Рассмотрим по шагам более надежный способ. Если мы знаем, что данные должны объединяться по какому-то ключевому полю (например, Владелец или НомерЗаказа), мы можем проверять наличие строки в новой таблице перед её созданием. Посмотрим на пример кода:


Для каждого СтрИзИсточника Из ТЗ_Исходная Цикл
    // Ищем, не создавали ли мы уже строку для этого объекта (например, по марке автомобиля)
    СтрокаРезультата = ТЗ_Результат.Найти(СтрИзИсточника.Марка, "Марка");
    
    // Если не нашли — создаем новую
    Если СтрокаРезультата = Неопределено Тогда
        СтрокаРезультата = ТЗ_Результат.Добавить();
        СтрокаРезультата.Марка = СтрИзИсточника.Марка;
    КонецЕсли;
    
    // Теперь записываем данные в нужную колонку в зависимости от условия
    Если СтрИзИсточника.Цвет = "Зелёный" Тогда
        СтрокаРезультата.Авто1 = СтрИзИсточника.Автомобиль;
        СтрокаРезультата.Класс1 = СтрИзИсточника.Класс;
    ИначеЕсли СтрИзИсточника.Цвет = "Синий" Тогда
        СтрокаРезультата.Авто2 = СтрИзИсточника.Автомобиль;
        СтрокаРезультата.Класс2 = СтрИзИсточника.Класс;
    КонецЕсли;
КонецЦикла;

Этот метод гарантирует, что данные «склеятся» в одну строку. Однако помните, что метод Найти() работает перебором, и на таблицах в десятки тысяч строк он может работать медленно.

Решение 2: Оптимизация через Соответствие (Map)

Для ускорения процесса, особенно если исходная таблица большая, проанализируем использование объекта Соответствие. Это позволит нам мгновенно получать нужную строку без поиска по всей таблице.


КэшСтрок = Новый Соответствие;

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

Решение 3: Динамическое создание колонок

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

  1. Получим уникальный список атрибутов: создадим временную таблицу со списком всех цветов, которые есть в исходных данных.
  2. Создадим колонки: пройдемся по этому списку и добавим в ТЗ_Результат колонки с именами этих цветов.
  3. Заполним данные: используя объектную модель, обратимся к колонкам по имени.

Пример динамического создания структуры:


// Сначала создаем колонки на основе уникальных значений
УникальныеЦвета = ТЗ_Исходная.Скопировать();
УникальныеЦвета.Свернуть("Цвет");

Для каждого СтрЦвет Из УникальныеЦвета Цикл
    ИмяКолонки = "Цвет_" + СтрЦвет.Цвет; // Важно: имя должно соответствовать правилам имен 1С
    ТЗ_Результат.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("Строка"), СтрЦвет.Цвет);
КонецЦикла;

// Теперь заполняем
Для каждого Стр Из ТЗ_Исходная Цикл
    СтрокаРезультата = // ... поиск или получение из соответствия ...
    ИмяКолонки = "Цвет_" + Стр.Цвет;
    СтрокаРезультата[ИмяКолонки] = Стр.Автомобиль;
КонецЦикла;

Решение 4: Использование механизмов СКД (Система компоновки данных)

Если ваша задача — просто показать эту таблицу пользователю в отчете или на форме, рассмотрите использование СКД. В СКД задача «разворота» решается штатными средствами настройки кросс-таблицы (тип «Таблица»).

В настройках компоновки вы указываете:

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

Важные нюансы типизации

При программном создании колонок через ТЗ_Результат.Колонки.Добавить() всегда старайтесь указывать второй параметр — ОписаниеТипов. Помните: если колонка будет иметь неопределенный тип, это может привести к невозможности ее использования в итогах, а также к проблемам при отображении в табличном поле на форме.

Подведем итог: для простых задач с двумя-тремя фиксированными условиями подойдет обычный цикл с предварительным поиском строки через Найти() или Соответствие. Для сложных, масштабируемых систем выбирайте динамическое создание колонок или мощные инструменты платформы, такие как СКД или запросы с конструкциями ВЫБОР КОГДА....

← На главную