При работе с коллекцией ТаблицаЗначений разработчики часто сталкиваются с необходимостью объединить дублирующиеся строки и просуммировать числовые показатели. Для этого в платформе 1С предусмотрен встроенный метод Свернуть(). Однако его некорректный вызов может привести к непредвиденному удалению данных или аварийному завершению работы алгоритма с ошибкой времени выполнения.
Проанализируем типичную ситуацию: в исходной таблице присутствуют колонки Номенклатура, Характеристика, ВНаличииОстаток, НоменклатураНаименование и ХарактеристикаНаименование. Выясним причину ошибок при вызове метода, разберем состав результирующих колонок и рассмотрим правильные варианты реализации группировки.
Посмотрим на пример ошибочного вызова метода:
ТзХР.Свернуть("Номенклатура", СтрТч.Номенклатура);
В данном примере во второй параметр вместо имени числовой колонки передано значение конкретного поля строки (СтрТч.Номенклатура). Платформа ожидает в качестве параметров исключительно строковые значения с именами существующих колонок таблицы.
Если во второй параметр передается объект ссылки, число или имя несуществующего поля, платформа генерирует исключение «Поле не найдено» или «Неверное значение параметров».
Разберем по шагам ключевые особенности функционирования метода:
КолонкиГруппировок и КолонкиСуммирования. Имена колонок перечисляются через запятую в виде обычной строки.Свернуть() не возвращает новую таблицу, а изменяет исходный объект.Рассмотрим правильный синтаксис вызова метода, когда необходимо сгруппировать данные по номенклатуре и характеристике с суммированием остатка:
// Создаем копию, если исходная таблица с полным набором полей нужна дальше
ТзСвернутая = ТзХР.Скопировать();
// Сворачиваем таблицу по колонкам группировки и суммирования
ТзСвернутая.Свернуть("Номенклатура, Характеристика", "ВНаличииОстаток");
// В результате в таблице ТзСвернутая останутся только 3 колонки:
// Номенклатура, Характеристика, ВНаличииОстаток
Если требуется получить только уникальные комбинации без суммирования числовых полей, второй параметр можно опустить:
ТзУникальныеПозиции = ТзХР.Скопировать();
ТзУникальныеПозиции.Свернуть("Номенклатура, Характеристика");
Рассмотрим ситуации, когда возможностей стандартного метода Свернуть() недостаточно (например, требуется вычислить максимум, минимум или сохранить текстовые описания без их включения в ключ группировки).
Передача таблицы значений в запрос позволяет использовать всю мощь агрегатных функций языка 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИсходнаяТЗ.Номенклатура КАК Номенклатура,
| ИсходнаяТЗ.Характеристика КАК Характеристика,
| МАКСИМУМ(ИсходнаяТЗ.НоменклатураНаименование) КАК НоменклатураНаименование,
| МАКСИМУМ(ИсходнаяТЗ.ХарактеристикаНаименование) КАК ХарактеристикаНаименование,
| СУММА(ИсходнаяТЗ.ВНаличииОстаток) КАК ВНаличииОстаток
|ПОМЕСТИТЬ ВТ_Свернутая
|ИЗ
| &ТаблицаИсточника КАК ИсходнаяТЗ
|СГРУППИРОВАТЬ ПО
| ИсходнаяТЗ.Номенклатура,
| ИсходнаяТЗ.Характеристика
|;
|ВЫБРАТЬ * ИЗ ВТ_Свернутая КАК ВТ_Свернутая";
Запрос.УстановитьПараметр("ТаблицаИсточника", ТзХР);
ТзРезультат = Запрос.Выполнить().Выгрузить();
Для сложных алгоритмов или нестандартных правил агрегации данных можно применить обход строк через объект Соответствие:
ТаблицаИтогов = Новый Соответствие;
Для Каждого СтрТЗ Из ТзХР Цикл
Ключ = Новый Структура("Номенклатура, Характеристика", СтрТЗ.Номенклатура, СтрТЗ.Характеристика);
ТекущийОстаток = ТаблицаИтогов[Ключ];
Если ТекущийОстаток = Неопределено Тогда
ТаблицаИтогов.Вставить(Ключ, СтрТЗ.ВНаличииОстаток);
Иначе
ТаблицаИтогов.Вставить(Ключ, ТекущийОстаток + СтрТЗ.ВНаличииОстаток);
КонецЕсли;
КонецЦикла;
Таким образом, метод Свернуть() является быстрым инструментом для базовой группировки, однако всегда требует передачи строковых имен колонок и удаляет из таблицы все неперечисленные поля.