При разработке конфигураций на платформе 1С часто возникает задача объединения (свертки) дублирующихся строк в табличной части документа. Например, если пользователь несколько раз добавил один и тот же товар, и нам нужно просуммировать его количество в одну строку. В процессе решения этой задачи начинающие разработчики часто сталкиваются с типовыми ошибками, избежать которых поможет консоль кода с ИИ-помощником — для этого есть консоль кода и запросов с ИИ-помощником. В этой статье мы подробно разберем, как реализовать этот механизм правильно, какие подводные камни существуют и как сделать код универсальным.
Рассмотрим ситуацию, когда при попытке выгрузить табличную часть в модуле объекта документа возникает ошибка. Подобный анализ конфигурации на наличие ошибок позволяет быстро найти причину сбоя — поможет пошаговая отладка кода 1С в режиме Предприятия. Проанализируем типичный ошибочный код:
Таблица = Объект.Материалы.Выгрузить();
Таблица.Свернуть("Наименование", "Количество");
Объект.Материалы.Загрузить(Таблица);
Выясним причину этой ошибки. Проблема заключается в контексте исполнения кода. В 1С переменная Объект доступна в модуле формы (она ссылается на данные формы). Однако, если вы пишете код непосредственно в модуле объекта документа (например, в процедуре ПередЗаписью), переменная Объект там не определена. Для обращения к данным текущего объекта в его собственном модуле следует использовать ключевое слово ЭтотОбъект или обращаться к реквизитам напрямую по их имени.
Исправленный вариант для модуля объекта (который можно привести к каноническому виду через Code formatter) будет выглядеть так:
// Прямое обращение к табличной части
Таблица = Материалы.Выгрузить();
Таблица.Свернуть("Номенклатура", "Количество");
Материалы.Загрузить(Таблица);
Метод Свернуть является встроенным методом объекта ТаблицаЗначений, но он также доступен и непосредственно для объекта ТабличнаяЧасть (разобраться в доступных свойствах поможет информер по метаданным) — для этого подойдёт нейросеть для поиска метаданных и написания кода. Рассмотрим подробнее его синтаксис:
Свернуть(КолонкиГруппировки, КолонкиСуммирования)
Важные правила, которые необходимо запомнить:
Посмотрим на пример из практики, когда нужно свернуть табличную часть "Материалы" по номенклатуре и цене, просуммировав количество и сумму:
Материалы.Свернуть("Номенклатура, Цена", "Количество, Сумма");
Проанализируем ситуацию: в табличной части много реквизитов, и вы хотите свернуть строки только по "Номенклатуре", сохранив при этом остальные данные. Как мы выяснили выше, метод Свернуть просто удалит лишние колонки. Чтобы этого не произошло, необходимо перечислить все колонки, которые не суммируются, в первом параметре (группировка).
Однако, если колонок десятки, перечислять их вручную неудобно и опасно (при добавлении нового реквизита в конфигураторе код придется переписывать). Разберем, как сделать это динамически с помощью метаданных:
КолонкиГруппировки = "";
КолонкиСуммирования = "Количество, Сумма"; // Указываем только те, что суммируем
// Получаем метаданные нашей табличной части
МетаТЧ = Метаданные.Документы.Приходная.ТабличныеЧасти.Материалы;
Для Каждого РеквизитТЧ Из МетаТЧ.Реквизиты Цикл
ИмяРеквизита = РеквизитТЧ.Имя;
// Если реквизит не входит в список суммируемых, добавляем его в группировку
Если Найти(КолонкиСуммирования, ИмяРеквизита) = 0 Тогда
КолонкиГруппировки = КолонкиГруппировки + ИмяРеквизита + ",";
КонецЕсли;
КонецЦикла;
// Удаляем последнюю запятую
Если Лев(КолонкиГруппировки, 1) <> "" Тогда
КолонкиГруппировки = Лев(КолонкиГруппировки, СтрДлина(КолонкиГруппировки) - 1);
КонецЕсли;
Материалы.Свернуть(КолонкиГруппировки, КолонкиСуммирования);
Если вам нужно свернуть табличную часть прямо в интерфейсе (в модуле формы), ситуация меняется. На форме мы работаем не с объектом ТабличнаяЧасть, а с типом ДанныеФормыКоллекция. У этого типа нет метода Свернуть.
Рассмотрим по шагам, как решить эту задачу на сервере в контексте управляемой формы:
Пример кода на сервере:
&НаСервере
Процедура СвернутьНаСервере()
// Преобразуем ТЧ формы в ТаблицуЗначений
ТЗ = Объект.Материалы.Выгрузить();
// Выполняем свертку
ТЗ.Свернуть("Номенклатура", "Количество");
// Загружаем обратно в реквизит формы
Объект.Материалы.Загрузить(ТЗ);
КонецПроцедуры
Внимание: При использовании метода Загрузить() в табличной части полностью обновляются строки. Это означает, что идентификаторы строк изменятся. Если у вас есть связанные данные (например, другая табличная часть, ссылающаяся на номер строки первой), эти связи могут быть нарушены.
Иногда метод Свернуть оказывается недостаточно гибким. Например, если вам нужно получить не сумму, а среднее значение или максимальную цену. В таких случаях мы рекомендуем использовать механизм запросов.
Алгоритм действий будет следующим:
ТаблицаЗначений.СГРУППИРОВАТЬ ПО с любыми агрегатными функциями (СУММА, МАКСИМУМ, СРЕДНЕЕ).Этот способ работает медленнее на маленьких объемах данных, но он гораздо мощнее и позволяет избежать ручного перебора колонок.
Таким образом, мы проанализировали основные способы группировки строк. Для простых задач идеально подходит метод Свернуть, а для универсальных решений лучше использовать обход метаданных или запросы. Главное — всегда помнить о контексте (Модуль объекта или Модуль формы) и не забывать, что Свернуть удаляет неуказанные колонки.