Примеры свертки таблицы значений

Примеры свертки таблицы значений на языке программирования 1С:Предприятие. Примеры позволяют быстро разобраться в вопросе и использовать код в своих разработках

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

// Свертка таблицы по ключевым полям с суммированием количественных показателей
Процедура СвернутьТаблицуПоКлючам()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Товар");
    Таблица.Колонки.Добавить("Склад");
    Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    
    // Заполняем тестовыми данными
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[0].Склад = "Основной"; Таблица[0].Количество = 5; Таблица[0].Сумма = 250000;
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[1].Склад = "Основной"; Таблица[1].Количество = 3; Таблица[1].Сумма = 150000;
    Таблица.Добавить().Товар = "Монитор"; Таблица[2].Склад = "Основной"; Таблица[2].Количество = 10; Таблица[2].Сумма = 150000;
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[3].Склад = "Резервный"; Таблица[3].Количество = 2; Таблица[3].Сумма = 100000;
    Таблица.Добавить().Товар = "Монитор"; Таблица[4].Склад = "Резервный"; Таблица[4].Количество = 5; Таблица[4].Сумма = 75000;
    
    Сообщить("Исходная таблица:");
    ВывестиТаблицу(Таблица);
    
    // Свертка по полям "Товар" и "Склад"
    СвернутаяТаблица = Таблица.Свернуть("Товар, Склад", "Количество, Сумма");
    
    Сообщить("Свернутая таблица (по товару и складу):");
    ВывестиТаблицу(СвернутаяТаблица);
    
КонецПроцедуры

Процедура ВывестиТаблицу(Таблица)
    Для Каждого Строка Из Таблица Цикл
        Сообщить(Строка.Товар + " | " + Строка.Склад + " | " + 
                 Строка.Количество + " | " + Строка.Сумма);
    КонецЦикла;
КонецПроцедуры

Свертка с произвольной агрегацией (среднее, минимум, максимум)

// Свертка таблицы с различными агрегатными функциями
Процедура СверткаСРазличнойАгрегацией()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Товар");
    Таблица.Колонки.Добавить("Месяц");
    Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
    
    // Заполняем данными о продажах по месяцам
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[0].Месяц = "Январь"; Таблица[0].Цена = 50000; Таблица[0].Количество = 10;
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[1].Месяц = "Февраль"; Таблица[1].Цена = 51000; Таблица[1].Количество = 15;
    Таблица.Добавить().Товар = "Ноутбук"; Таблица[2].Месяц = "Март"; Таблица[2].Цена = 52000; Таблица[2].Количество = 12;
    Таблица.Добавить().Товар = "Монитор"; Таблица[3].Месяц = "Январь"; Таблица[3].Цена = 15000; Таблица[3].Количество = 20;
    Таблица.Добавить().Товар = "Монитор"; Таблица[4].Месяц = "Февраль"; Таблица[4].Цена = 15500; Таблица[4].Количество = 25;
    Таблица.Добавить().Товар = "Монитор"; Таблица[5].Месяц = "Март"; Таблица[5].Цена = 16000; Таблица[5].Количество = 18;
    
    Сообщить("Исходная таблица продаж:");
    Для Каждого Строка Из Таблица Цикл
        Сообщить(Строка.Товар + " | " + Строка.Месяц + " | Цена: " + Строка.Цена + " | Кол-во: " + Строка.Количество);
    КонецЦикла;
    
    // Используем свертку через группировку с произвольными агрегациями
    Группировка = Новый ТаблицаЗначений;
    Группировка.Колонки.Добавить("Товар");
    Группировка.Колонки.Добавить("КоличествоПродаж", Новый ОписаниеТипов("Число"));
    Группировка.Колонки.Добавить("СредняяЦена", Новый ОписаниеТипов("Число"));
    Группировка.Колонки.Добавить("МаксЦена", Новый ОписаниеТипов("Число"));
    Группировка.Колонки.Добавить("МинЦена", Новый ОписаниеТипов("Число"));
    Группировка.Колонки.Добавить("ОбщееКоличество", Новый ОписаниеТипов("Число"));
    
    // Формируем массив уникальных товаров
    УникальныеТовары = Новый Массив;
    Для Каждого Строка Из Таблица Цикл
        Если УникальныеТовары.Найти(Строка.Товар) = Неопределено Тогда
            УникальныеТовары.Добавить(Строка.Товар);
        КонецЕсли;
    КонецЦикла;
    
    // Собираем статистику по каждому товару
    Для Каждого Товар Из УникальныеТовары Цикл
        СтрокаГруппы = Группировка.Добавить();
        СтрокаГруппы.Товар = Товар;
        
        ОбщееКоличество = 0;
        ОбщаяСуммаЦен = 0;
        КоличествоМесяцев = 0;
        МаксЦена = 0;
        МинЦена = 999999999;
        
        Для Каждого ИсходнаяСтрока Из Таблица Цикл
            Если ИсходнаяСтрока.Товар = Товар Тогда
                ОбщееКоличество = ОбщееКоличество + ИсходнаяСтрока.Количество;
                ОбщаяСуммаЦен = ОбщаяСуммаЦен + ИсходнаяСтрока.Цена;
                КоличествоМесяцев = КоличествоМесяцев + 1;
                
                Если ИсходнаяСтрока.Цена > МаксЦена Тогда
                    МаксЦена = ИсходнаяСтрока.Цена;
                КонецЕсли;
                
                Если ИсходнаяСтрока.Цена < МинЦена Тогда
                    МинЦена = ИсходнаяСтрока.Цена;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        
        СтрокаГруппы.КоличествоПродаж = КоличествоМесяцев;
        СтрокаГруппы.СредняяЦена = ?(КоличествоМесяцев > 0, ОбщаяСуммаЦен / КоличествоМесяцев, 0);
        СтрокаГруппы.МаксЦена = МаксЦена;
        СтрокаГруппы.МинЦена = МинЦена;
        СтрокаГруппы.ОбщееКоличество = ОбщееКоличество;
    КонецЦикла;
    
    Сообщить("Результат свертки с различной агрегацией:");
    Для Каждого Строка Из Группировка Цикл
        Сообщить(Строка.Товар + 
                 " | Продаж: " + Строка.КоличествоПродаж +
                 " | Ср.цена: " + Строка.СредняяЦена +
                 " | Max: " + Строка.МаксЦена +
                 " | Min: " + Строка.МинЦена +
                 " | Всего: " + Строка.ОбщееКоличество);
    КонецЦикла;
    
КонецПроцедуры

Свертка таблицы через запрос

// Свертка таблицы значений с использованием языка запросов
Процедура СверткаЧерезЗапрос()

    ИсходнаяТаблица = Новый ТаблицаЗначений;
    ИсходнаяТаблица.Колонки.Добавить("Контрагент");
    ИсходнаяТаблица.Колонки.Добавить("Договор");
    ИсходнаяТаблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    ИсходнаяТаблица.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));
    
    ИсходнаяТаблица.Добавить().Контрагент = "ООО Альфа"; ИсходнаяТаблица[0].Договор = "Д-001"; ИсходнаяТаблица[0].Сумма = 10000; ИсходнаяТаблица[0].Дата = '20240115';
    ИсходнаяТаблица.Добавить().Контрагент = "ООО Альфа"; ИсходнаяТаблица[1].Договор = "Д-001"; ИсходнаяТаблица[1].Сумма = 15000; ИсходнаяТаблица[1].Дата = '20240220';
    ИсходнаяТаблица.Добавить().Контрагент = "ООО Бета"; ИсходнаяТаблица[2].Договор = "Д-002"; ИсходнаяТаблица[2].Сумма = 20000; ИсходнаяТаблица[2].Дата = '20240110';
    ИсходнаяТаблица.Добавить().Контрагент = "ООО Бета"; ИсходнаяТаблица[3].Договор = "Д-003"; ИсходнаяТаблица[3].Сумма = 25000; ИсходнаяТаблица[3].Дата = '20240305';
    ИсходнаяТаблица.Добавить().Контрагент = "ООО Альфа"; ИсходнаяТаблица[4].Договор = "Д-001"; ИсходнаяТаблица[4].Сумма = 5000; ИсходнаяТаблица[4].Дата = '20240310';
    
    // Помещаем таблицу во временную таблицу
    Запрос = Новый Запрос;
    Запрос.Текст = "
    |ВЫБРАТЬ
    |   Исходные.Контрагент,
    |   Исходные.Договор,
    |   СУММА(Исходные.Сумма) КАК ОбщаяСумма,
    |   МАКСИМУМ(Исходные.Дата) КАК ПоследняяДата,
    |   МИНИМУМ(Исходные.Дата) КАК ПерваяДата,
    |   КОЛИЧЕСТВО(Исходные.Сумма) КАК КоличествоСделок
    |ПОМЕСТИТЬ ВТ_Свертка
    |ИЗ
    |   &ИсходнаяТаблица КАК Исходные
    |СГРУППИРОВАТЬ ПО
    |   Исходные.Контрагент,
    |   Исходные.Договор";
    
    Запрос.УстановитьПараметр("ИсходнаяТаблица", ИсходнаяТаблица);
    Результат = Запрос.Выполнить().Выгрузить();
    
    Сообщить("Свертка через запрос (по контрагенту и договору):");
    Для Каждого Строка Из Результат Цикл
        Сообщить(Строка.Контрагент + " | " + Строка.Договор + 
                 " | Общая сумма: " + Строка.ОбщаяСумма +
                 " | Сделок: " + Строка.КоличествоСделок +
                 " | Период: " + Формат(Строка.ПерваяДата, "ДФ=dd.MM.yyyy") + 
                 " - " + Формат(Строка.ПоследняяДата, "ДФ=dd.MM.yyyy"));
    КонецЦикла;
    
КонецПроцедуры

Свертка с объединением строковых полей

// Свертка таблицы с конкатенацией текстовых значений
Процедура СверткаСОбъединениемСтрок()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Заказ");
    Таблица.Колонки.Добавить("Товар");
    Таблица.Колонки.Добавить("Комментарий");
    
    Таблица.Добавить().Заказ = "З-001"; Таблица[0].Товар = "Ноутбук"; Таблица[0].Комментарий = "Срочно";
    Таблица.Добавить().Заказ = "З-001"; Таблица[1].Товар = "Монитор"; Таблица[1].Комментарий = "";
    Таблица.Добавить().Заказ = "З-001"; Таблица[2].Товар = "Мышь"; Таблица[2].Комментарий = "С доставкой";
    Таблица.Добавить().Заказ = "З-002"; Таблица[3].Товар = "Клавиатура"; Таблица[3].Комментарий = "";
    Таблица.Добавить().Заказ = "З-002"; Таблица[4].Товар = "Ноутбук"; Таблица[4].Комментарий = "Premium";
    
    // Группировка с объединением строк
    Группировка = Новый ТаблицаЗначений;
    Группировка.Колонки.Добавить("Заказ");
    Группировка.Колонки.Добавить("СписокТоваров");
    Группировка.Колонки.Добавить("Комментарии");
    Группировка.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
    
    // Формируем уникальные заказы
    УникальныеЗаказы = Новый Массив;
    Для Каждого Строка Из Таблица Цикл
        Если УникальныеЗаказы.Найти(Строка.Заказ) = Неопределено Тогда
            УникальныеЗаказы.Добавить(Строка.Заказ);
        КонецЕсли;
    КонецЦикла;
    
    // Собираем данные по каждому заказу
    Для Каждого Заказ Из УникальныеЗаказы Цикл
        НоваяСтрока = Группировка.Добавить();
        НоваяСтрока.Заказ = Заказ;
        
        СписокТоваров = "";
        СписокКомментариев = "";
        КоличествоТоваров = 0;
        
        Для Каждого ИсходнаяСтрока Из Таблица Цикл
            Если ИсходнаяСтрока.Заказ = Заказ Тогда
                КоличествоТоваров = КоличествоТоваров + 1;
                
                Если СписокТоваров <> "" Тогда
                    СписокТоваров = СписокТоваров + ", ";
                КонецЕсли;
                СписокТоваров = СписокТоваров + ИсходнаяСтрока.Товар;
                
                Если НЕ ПустаяСтрока(ИсходнаяСтрока.Комментарий) Тогда
                    Если СписокКомментариев <> "" Тогда
                        СписокКомментариев = СписокКомментариев + "; ";
                    КонецЕсли;
                    СписокКомментариев = СписокКомментариев + 
                                        ИсходнаяСтрока.Товар + "(" + ИсходнаяСтрока.Комментарий + ")";
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        
        НоваяСтрока.СписокТоваров = СписокТоваров;
        НоваяСтрока.Комментарии = СписокКомментариев;
        НоваяСтрока.Количество = КоличествоТоваров;
    КонецЦикла;
    
    Сообщить("Свертка заказов с объединением товаров:");
    Для Каждого Строка Из Группировка Цикл
        Сообщить("Заказ: " + Строка.Заказ);
        Сообщить("  Товары: " + Строка.СписокТоваров);
        Сообщить("  Комментарии: " + Строка.Комментарии);
        Сообщить("  Всего позиций: " + Строка.Количество);
    КонецЦикла;
    
КонецПроцедуры

Свертка с условным суммированием

// Свертка с суммированием только при выполнении условия
Процедура СверткаСУсловнымСуммированием()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Менеджер");
    Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Статус");
    
    Таблица.Добавить().Менеджер = "Иванов"; Таблица[0].Сумма = 100000; Таблица[0].Статус = "Оплачен";
    Таблица.Добавить().Менеджер = "Иванов"; Таблица[1].Сумма = 50000; Таблица[1].Статус = "В работе";
    Таблица.Добавить().Менеджер = "Петров"; Таблица[2].Сумма = 200000; Таблица[2].Статус = "Оплачен";
    Таблица.Добавить().Менеджер = "Петров"; Таблица[3].Сумма = 30000; Таблица[3].Статус = "Отменен";
    Таблица.Добавить().Менеджер = "Иванов"; Таблица[4].Сумма = 75000; Таблица[4].Статус = "Оплачен";
    Таблица.Добавить().Менеджер = "Сидоров"; Таблица[5].Сумма = 150000; Таблица[5].Статус = "Оплачен";
    
    // Группировка с разделением по статусам
    Результат = Новый ТаблицаЗначений;
    Результат.Колонки.Добавить("Менеджер");
    Результат.Колонки.Добавить("СуммаОплаченных", Новый ОписаниеТипов("Число"));
    Результат.Колонки.Добавить("СуммаВРаботе", Новый ОписаниеТипов("Число"));
    Результат.Колонки.Добавить("СуммаОтмененных", Новый ОписаниеТипов("Число"));
    Результат.Колонки.Добавить("ОбщаяСумма", Новый ОписаниеТипов("Число"));
    Результат.Колонки.Добавить("КоличествоСделок", Новый ОписаниеТипов("Число"));
    
    УникальныеМенеджеры = Новый Массив;
    Для Каждого Строка Из Таблица Цикл
        Если УникальныеМенеджеры.Найти(Строка.Менеджер) = Неопределено Тогда
            УникальныеМенеджеры.Добавить(Строка.Менеджер);
        КонецЕсли;
    КонецЦикла;
    
    Для Каждого Менеджер Из УникальныеМенеджеры Цикл
        НоваяСтрока = Результат.Добавить();
        НоваяСтрока.Менеджер = Менеджер;
        
        СуммаОплаченных = 0;
        СуммаВРаботе = 0;
        СуммаОтмененных = 0;
        КоличествоСделок = 0;
        
        Для Каждого ИсходнаяСтрока Из Таблица Цикл
            Если ИсходнаяСтрока.Менеджер = Менеджер Тогда
                КоличествоСделок = КоличествоСделок + 1;
                
                Если ИсходнаяСтрока.Статус = "Оплачен" Тогда
                    СуммаОплаченных = СуммаОплаченных + ИсходнаяСтрока.Сумма;
                ИначеЕсли ИсходнаяСтрока.Статус = "В работе" Тогда
                    СуммаВРаботе = СуммаВРаботе + ИсходнаяСтрока.Сумма;
                ИначеЕсли ИсходнаяСтрока.Статус = "Отменен" Тогда
                    СуммаОтмененных = СуммаОтмененных + ИсходнаяСтрока.Сумма;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        
        НоваяСтрока.СуммаОплаченных = СуммаОплаченных;
        НоваяСтрока.СуммаВРаботе = СуммаВРаботе;
        НоваяСтрока.СуммаОтмененных = СуммаОтмененных;
        НоваяСтрока.ОбщаяСумма = СуммаОплаченных + СуммаВРаботе;
        НоваяСтрока.КоличествоСделок = КоличествоСделок;
    КонецЦикла;
    
    Сообщить("Свертка с разделением по статусам:");
    Для Каждого Строка Из Результат Цикл
        Сообщить(Строка.Менеджер + 
                 " | Оплачено: " + Строка.СуммаОплаченных +
                 " | В работе: " + Строка.СуммаВРаботе +
                 " | Отменено: " + Строка.СуммаОтмененных +
                 " | Итого: " + Строка.ОбщаяСумма +
                 " | Сделок: " + Строка.КоличествоСделок);
    КонецЦикла;
    
КонецПроцедуры

Свертка с вычислением процентного соотношения

// Свертка с расчетом доли каждого элемента в общем итоге
Процедура СверткаСПроцентнымСоотношением()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Категория");
    Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    
    Таблица.Добавить().Категория = "Электроника"; Таблица[0].Сумма = 500000;
    Таблица.Добавить().Категория = "Электроника"; Таблица[1].Сумма = 300000;
    Таблица.Добавить().Категория = "Мебель"; Таблица[2].Сумма = 200000;
    Таблица.Добавить().Категория = "Одежда"; Таблица[3].Сумма = 150000;
    Таблица.Добавить().Категория = "Одежда"; Таблица[4].Сумма = 100000;
    Таблица.Добавить().Категория = "Электроника"; Таблица[5].Сумма = 200000;
    Таблица.Добавить().Категория = "Мебель"; Таблица[6].Сумма = 100000;
    
    // Сначала свернем по категориям
    Свернутая = Таблица.Свернуть("Категория", "Сумма");
    
    // Вычисляем общую сумму
    ОбщаяСумма = 0;
    Для Каждого Строка Из Свернутая Цикл
        ОбщаяСумма = ОбщаяСумма + Строка.Сумма;
    КонецЦикла;
    
    // Добавляем колонку с процентом
    Свернутая.Колонки.Добавить("Доля", Новый ОписаниеТипов("Число"));
    Свернутая.Колонки.Добавить("Процент", Новый ОписаниеТипов("Строка"));
    
    Для Каждого Строка Из Свернутая Цикл
        Строка.Доля = ?(ОбщаяСумма > 0, Строка.Сумма / ОбщаяСумма, 0);
        Строка.Процент = Формат(Строка.Доля * 100, "ЧЦ=2; ЧРД=") + "%";
    КонецЦикла;
    
    // Сортируем по убыванию доли
    Свернутая.Сортировать("Сумма УБЫВ");
    
    Сообщить("Структура продаж по категориям:");
    Для Каждого Строка Из Свернутая Цикл
        Сообщить(Строка.Категория + " | Сумма: " + Строка.Сумма + 
                 " | Доля: " + Строка.Процент);
    КонецЦикла;
    
    Сообщить("Общая сумма: " + ОбщаяСумма);
    
КонецПроцедуры

Многоуровневая свертка (иерархическая группировка)

// Свертка с группировкой на нескольких уровнях
Процедура МногоуровневаяСвертка()

    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Год", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Квартал", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Месяц", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    
    // Заполняем данными
    Таблица.Добавить().Год = 2024; Таблица[0].Квартал = 1; Таблица[0].Месяц = 1; Таблица[0].Сумма = 1000;
    Таблица.Добавить().Год = 2024; Таблица[1].Квартал = 1; Таблица[1].Месяц = 1; Таблица[1].Сумма = 1500;
    Таблица.Добавить().Год = 2024; Таблица[2].Квартал = 1; Таблица[2].Месяц = 2; Таблица[2].Сумма = 2000;
    Таблица.Добавить().Год = 2024; Таблица[3].Квартал = 2; Таблица[3].Месяц = 4; Таблица[3].Сумма = 3000;
    Таблица.Добавить().Год = 2024; Таблица[4].Квартал = 2; Таблица[4].Месяц = 5; Таблица[4].Сумма = 2500;
    Таблица.Добавить().Год = 2024; Таблица[5].Квартал = 2; Таблица[5].Месяц = 5; Таблица[5].Сумма = 1000;
    Таблица.Добавить().Год = 2024; Таблица[6].Квартал = 3; Таблица[6].Месяц = 7; Таблица[6].Сумма = 1800;
    
    // Уровень 1: свертка по месяцам
    ПоМесяцам = Таблица.Свернуть("Год, Квартал, Месяц", "Сумма");
    
    // Уровень 2: свертка по кварталам
    ПоКварталам = ПоМесяцам.Свернуть("Год, Квартал", "Сумма");
    
    // Уровень 3: свертка по годам
    ПоГодам = ПоКварталам.Свернуть("Год", "Сумма");
    
    // Формируем иерархический отчет
    Сообщить("=== ИЕРАРХИЧЕСКИЙ ОТЧЕТ ПО ПРОДАЖАМ ===");
    
    Для Каждого ГодСтрока Из ПоГодам Цикл
        Сообщить("Итого за " + Строка(ГодСтрока.Год) + " год: " + ГодСтрока.Сумма);
        
        // Выводим кварталы этого года
        Для Каждого КварталСтрока Из ПоКварталам Цикл
            Если КварталСтрока.Год = ГодСтрока.Год Тогда
                Сообщить("  Квартал " + Строка(КварталСтрока.Квартал) + ": " + КварталСтрока.Сумма);
                
                // Выводим месяцы этого квартала
                Для Каждого МесяцСтрока Из ПоМесяцам Цикл
                    Если МесяцСтрока.Год = КварталСтрока.Год И 
                       МесяцСтрока.Квартал = КварталСтрока.Квартал Тогда
                        Сообщить("    Месяц " + Строка(МесяцСтрока.Месяц) + ": " + МесяцСтрока.Сумма);
                    КонецЕсли;
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
        
    КонецЦикла;
    
КонецПроцедуры

Свертка с использованием словаря (максимальная производительность)

// Высокопроизводительная свертка через Соответствие
Функция СвернутьТаблицуБыстро(Таблица, МассивКлючей, МассивЗначений)

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

Процедура ТестБыстройСвертки()

    // Создаем большую тестовую таблицу
    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Группа");
    Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
    Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
    
    Для Инд = 1 По 10000 Цикл
        Строка = Таблица.Добавить();
        Строка.Группа = "Группа " + Строка(Инд % 100);
        Строка.Количество = Инд;
        Строка.Сумма = Инд * 10;
    КонецЦикла;
    
    МассивКлючей = Новый Массив;
    МассивКлючей.Добавить("Группа");
    
    МассивЗначений = Новый Массив;
    МассивЗначений.Добавить("Количество");
    МассивЗначений.Добавить("Сумма");
    
    Замер = Новый ЗамерВремени;
    Результат = СвернутьТаблицуБыстро(Таблица, МассивКлючей, МассивЗначений);
    Время = Замер.Закончить();
    
    Сообщить("Быстрая свертка: " + Строка(Время) + " мс");
    Сообщить("Результат: " + Строка(Результат.Количество()) + " групп");
    
КонецПроцедуры

Примечания

// Важные особенности свертки таблицы значений:
// 1. Метод Свернуть(КлючевыеПоля, СуммируемыеПоля) - самый простой способ
// 2. Свертка изменяет исходную таблицу, при необходимости сделайте копию
// 3. Для сложной агрегации (среднее, максимум, минимум) используйте группировку через цикл
// 4. При свертке больших таблиц (10к+ строк) эффективнее использовать запрос или словарь
// 5. Ключевые поля указываются через запятую: "Поле1, Поле2"
// 6. Суммируемые поля также указываются через запятую
// 7. Метод Свернуть работает только с числовыми полями для суммирования
// 8. Для конкатенации строковых полей используйте ручную группировку
// 9. При свертке теряются все неключевые и несуммируемые поля
// 10. Для иерархической свертки выполняйте последовательную свертку
// 11. Перед сверткой рекомендуется отсортировать таблицу по ключевым полям
// 12. Для подсчета количества записей в группе используйте дополнительное числовое поле со значением 1

Поделиться с друзьями
Smirnov code
Добавить комментарий