К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как объединить строки в таблице значений 1С

Как объединить строки в таблице значений 1С: метод Свернуть(), группировка через запрос, объединение таблиц. Примеры кода, ошибки и проверка результата.

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

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

Важно понимать терминологию: «объединить строки» может означать две разные операции — свёртку внутри одной таблицы (группировку дублей) и слияние двух таблиц в одну. Оба сценария рассмотрены в статье.

Метод Свернуть() — основной способ объединения строк

Метод Свернуть() — встроенный инструмент таблицы значений, который группирует строки по указанным колонкам и суммирует значения в колонках суммирования. Синтаксис: ТаблицаЗначений.Свернуть(КолонкиГруппировки, КолонкиСуммирования), где оба параметра — строки с именами колонок через запятую.

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

ТЗ.Свернуть("Номенклатура", "Количество, Сумма");

После выполнения в таблице останутся только колонки, перечисленные в параметрах: Номенклатура, Количество, Сумма. Все остальные колонки будут удалены без возможности восстановления — это ключевая особенность метода, о которой часто забывают.

Если второй параметр (колонки суммирования) не указать, метод просто удалит дубли строк по колонкам группировки — это удобный способ получить уникальные комбинации значений. Например, ТЗ.Свернуть("Контрагент, Договор") вернёт список уникальных пар «контрагент-договор».

Как сохранить исходные данные при свёртке

Поскольку Свернуть() работает «на месте» и разрушает структуру таблицы, безопасный приём — сворачивать копию. Метод Скопировать() создаёт полную независимую копию таблицы со всеми строками и колонками:

ТЗСвернуто = ТЗ.Скопировать();

ТЗСвернуто.Свернуть("Номенклатура, Склад", "Количество");

Альтернатива — выгрузить только нужные колонки в новую таблицу методом ВыгрузитьКолонку() не подходит, но можно скопировать с отбором колонок: ТЗ.Скопировать(, "Номенклатура, Количество, Сумма"). Второй параметр задаёт список колонок, которые попадут в копию, что сразу отсекает лишнее.

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

ТЗ = ДокументОбъект.Товары.Выгрузить();

ТЗ.Свернуть("Номенклатура", "Количество, Сумма");

Порядок действий
  1. 1
    Определите колонки группировки — по каким полям строки считаются дублями
  2. 2
    Определите колонки суммирования — какие числовые поля нужно сложить
  3. 3
    Сделайте копию таблицы методом Скопировать(), если исходная ещё нужна
  4. 4
    Выполните Свернуть() с двумя параметрами через запятую
  5. 5
    Проверьте результат: количество строк уменьшилось, итоги по суммам совпадают с исходными

Группировка через запрос для сложных сценариев

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

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.Текст =

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ

|ИЗ &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ

| ВТ.Номенклатура,

| СУММА(ВТ.Количество) КАК Количество

|ИЗ ВТ КАК ВТ

|СГРУППИРОВАТЬ ПО ВТ.Номенклатура";

Запрос.УстановитьПараметр("ТЗ", ТЗ);

Результат = Запрос.Выполнить().Выгрузить();

Такой подход оправдан при объёмах от десятков тысяч строк: серверная СУБД выполнит группировку заметно быстрее, чем встроенный язык. Кроме того, запрос позволяет сразу соединить таблицу со справочниками и получить дополнительные поля (артикул, единицу измерения), не делая отдельных обходов.

Ограничение: передача таблицы в запрос требует, чтобы типы колонок были определены однозначно. Колонки с составным типом «произвольного» вида могут вызвать ошибку при помещении во временную таблицу — в этом случае типизируйте колонки при создании таблицы через ОписаниеТипов.

Сравнение вариантов

Свернуть()

Подходит для простой суммовой группировки в памяти. Ограничение: только сумма, удаляет лишние колонки, медленно на очень больших таблицах.

Запрос с СГРУППИРОВАТЬ ПО

Подходит для больших объёмов и нестандартных агрегатов (МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО РАЗЛИЧНЫХ). Требует типизированных колонок и больше кода.

Ручной обход с соответствием

Подходит, когда агрегация нестандартная: склеить строки, собрать массив значений. Гибко, но медленнее и больше кода.

Нестандартная агрегация: склейка строк и сбор значений

Метод Свернуть() умеет только суммировать. Если нужно объединить строки, собрав текстовые значения через запятую (например, список номеров документов по контрагенту), используйте ручной обход с соответствием:

Группы = Новый Соответствие;

Для Каждого Строка Из ТЗ Цикл

Запись = Группы.Получить(Строка.Контрагент);

Если Запись = Неопределено Тогда

Запись = Новый Структура("Документы, Сумма", "", 0);

Группы.Вставить(Строка.Контрагент, Запись);

КонецЕсли;

Запись.Документы = ?(Запись.Документы = "", "", Запись.Документы + ", ") + Строка.НомерДокумента;

Запись.Сумма = Запись.Сумма + Строка.Сумма;

КонецЦикла;

После обхода соответствие можно выгрузить в новую таблицу значений или обработать напрямую. Такой приём универсален: внутри цикла доступна любая логика — конкатенация, подсчёт уникальных значений, сбор массивов.

Для склейки строк в запросе на некоторых СУБД доступны строковые агрегаты, но в языке запросов 1С их нет, поэтому ручной обход остаётся основным решением для текстовой агрегации.

Как объединить две таблицы значений в одну

Вторая трактовка задачи — слить строки двух таблиц в одну. Если структуры колонок совпадают, достаточно цикла:

Для Каждого Строка Из ТЗ2 Цикл

НоваяСтрока = ТЗ1.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);

КонецЦикла;

ЗаполнитьЗначенияСвойств() переносит значения по совпадающим именам колонок, поэтому лишние колонки во второй таблице не вызовут ошибку — они просто не перенесутся. Если колонки называются по-разному, присваивайте значения явно.

Для больших таблиц быстрее объединение через запрос с конструкцией ОБЪЕДИНИТЬ ВСЕ: обе таблицы передаются как параметры, помещаются во временные таблицы и объединяются одним запросом. Вариант ОБЪЕДИНИТЬ (без ВСЕ) дополнительно удалит полные дубли строк.

Перед объединением проверяйте типы колонок: если в одной таблице колонка Сумма имеет тип Число(15,2), а в другой Число(10,0), итоговая точность может отличаться от ожидаемой. Приведите описания типов к единому виду при создании таблиц.
ПЗ
Практическое замечание

Проверка результата и типичные ошибки

После свёртки или объединения результат стоит проверить, прежде чем передавать его дальше — в документ, отчёт или печатную форму. Контрольные точки: сумма по итоговой колонке до и после свёртки должна совпадать, количество строк не должно быть больше исходного, а все ключевые комбинации — присутствовать.

СуммаДо = ТЗ.Итог("Сумма");

ТЗКопия = ТЗ.Скопировать();

ТЗКопия.Свернуть("Номенклатура", "Сумма");

Если ТЗКопия.Итог("Сумма") <> СуммаДо Тогда

ВызватьИсключение "Итоги не совпадают после свёртки";

КонецЕсли;

Типичные ошибки
01
Свёртка исходной таблицы без копии — теряются колонки и детальные строки, которые нужны дальше по коду
02
Перечисление в колонках суммирования нечислового поля — значения обнуляются или дают непредсказуемый итог
03
Сравнение строковых ключей с лишними пробелами — дубли не объединяются, потому что 'Товар ' и 'Товар' считаются разными значениями
04
Использование ОБЪЕДИНИТЬ вместо ОБЪЕДИНИТЬ ВСЕ — теряются одинаковые строки, которые должны были сохраниться
05
Забытый второй параметр Свернуть() — таблица очищается от дублей, но все суммы пропадают вместе с колонками
Контрольные точки

Как проверить результат

Итог по суммовой колонке
Норма

Совпадает с итогом до свёртки

Тревожный признак

Итог изменился — возможно, часть строк потеряна или колонка не числовая

Количество строк
Норма

Строк стало меньше или столько же, каждая комбинация ключей уникальна

Тревожный признак

Остались дубли по ключевым полям — проверьте пробелы и регистр в строковых значениях

Состав колонок
Норма

В таблице только колонки группировки и суммирования, этого достаточно для дальнейшей логики

Тревожный признак

Нужные дальше колонки пропали — свёртку выполняли не на копии

Производительность и ограничения

На таблицах до нескольких тысяч строк разница между Свернуть() и запросом практически незаметна. На десятках и сотнях тысяч строк запрос с временной таблицей обычно выигрывает, особенно в клиент-серверном варианте, где группировка выполняется на стороне СУБД без перекачки данных.

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

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

Маршрут решения

Как выбрать действие

Нужно просуммировать числовые колонки по дублям ключейИспользуйте Свернуть() на копии таблицы
Нужны МИНИМУМ, МАКСИМУМ или количество различных, либо строк очень многоПередайте таблицу в запрос и используйте СГРУППИРОВАТЬ ПО
Нужно склеить текстовые значения или собрать списокВыполните ручной обход с соответствием
Нужно слить две таблицы с одинаковой структуройЦикл с ЗаполнитьЗначенияСвойств или запрос с ОБЪЕДИНИТЬ ВСЕ

Частые вопросы

Можно ли свернуть таблицу, не удаляя остальные колонки?

Штатно нет: Свернуть() оставляет только указанные колонки. Обходной путь — свернуть копию, а затем при необходимости соединить результат с исходными данными через запрос или поиск по ключу.

Почему после Свернуть() остались дубли по номенклатуре?

Чаще всего причина в разных значениях, которые выглядят одинаково: лишние пробелы, разный регистр в строках или разные ссылки на элементы с одинаковым наименованием. Проверьте значения через СокрЛП() и сравнение ссылок.

Как свернуть табличную часть документа, не меняя сам документ?

Вызовите ДокументОбъект.Товары.Выгрузить() — получите независимую таблицу значений. Все операции с ней, включая Свернуть(), не затрагивают данные объекта до явной загрузки обратно методом Загрузить().

Что быстрее: Свернуть() или запрос?

На малых объёмах разницы нет, и Свернуть() проще в коде. На больших таблицах в клиент-серверной базе запрос с временной таблицей обычно быстрее, так как группировку выполняет СУБД.

Как объединить строки и посчитать количество сгруппированных строк?

Свернуть() этого не умеет. Используйте запрос с агрегатом КОЛИЧЕСТВО(*) либо ручной обход со счётчиком в структуре значения соответствия.

Можно ли свернуть по дате без времени?

Напрямую нет — группировка идёт по точному значению, а даты с разным временем считаются разными. Добавьте в таблицу колонку с усечённой датой (НачалоДня(Дата)) и сворачивайте по ней.

Итог

Что важно запомнить

Основной инструмент объединения строк — метод Свернуть(КолонкиГруппировки, КолонкиСуммирования), выполняемый на копии таблицы. Для нестандартных агрегатов и больших объёмов используйте запрос с СГРУППИРОВАТЬ ПО, для склейки текстов — обход с соответствием, а для слияния таблиц — цикл с ЗаполнитьЗначенияСвойств или ОБЪЕДИНИТЬ ВСЕ. После операции сверяйте итоги по суммовым колонкам с исходными.