Как правильно свернуть строки табличной части документа в 1С:Предприятие 8

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

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

Разбор ошибки: Значение не является значением объектного типа (Материалы)

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


Таблица = Объект.Материалы.Выгрузить(); 
Таблица.Свернуть("Наименование", "Количество"); 
Объект.Материалы.Загрузить(Таблица);

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

Исправленный вариант для модуля объекта (который можно привести к каноническому виду через Code formatter) будет выглядеть так:


// Прямое обращение к табличной части
Таблица = Материалы.Выгрузить(); 
Таблица.Свернуть("Номенклатура", "Количество"); 
Материалы.Загрузить(Таблица);

Метод Свернуть: синтаксис и правила использования

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

Свернуть(КолонкиГруппировки, КолонкиСуммирования)

Важные правила, которые необходимо запомнить:

  1. КолонкиГруппировки: Строка с именами колонок, разделенных запятыми, по которым будет происходить поиск дублей. Если значения во всех этих колонках совпадают, строки будут объединены.
  2. КолонкиСуммирования: Строка с именами колонок, значения которых будут суммироваться при объединении.
  3. Удаление данных: Это самый важный нюанс. Все колонки, которые не указаны ни в первом, ни во втором параметре, будут удалены из таблицы. Если вы забыли указать колонку "Цена" или "ЕдиницаИзмерения", после выполнения метода эти данные исчезнут.

Посмотрим на пример из практики, когда нужно свернуть табличную часть "Материалы" по номенклатуре и цене, просуммировав количество и сумму:


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

Как сохранить все колонки при свертке?

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

Однако, если колонок десятки, перечислять их вручную неудобно и опасно (при добавлении нового реквизита в конфигураторе код придется переписывать). Разберем, как сделать это динамически с помощью метаданных:


КолонкиГруппировки = "";
КолонкиСуммирования = "Количество, Сумма"; // Указываем только те, что суммируем

// Получаем метаданные нашей табличной части
МетаТЧ = Метаданные.Документы.Приходная.ТабличныеЧасти.Материалы;

Для Каждого РеквизитТЧ Из МетаТЧ.Реквизиты Цикл
    ИмяРеквизита = РеквизитТЧ.Имя;
    
    // Если реквизит не входит в список суммируемых, добавляем его в группировку
    Если Найти(КолонкиСуммирования, ИмяРеквизита) = 0 Тогда
        КолонкиГруппировки = КолонкиГруппировки + ИмяРеквизита + ",";
    КонецЕсли;
КонецЦикла;

// Удаляем последнюю запятую
Если Лев(КолонкиГруппировки, 1) <> "" Тогда
    КолонкиГруппировки = Лев(КолонкиГруппировки, СтрДлина(КолонкиГруппировки) - 1);
КонецЕсли;

Материалы.Свернуть(КолонкиГруппировки, КолонкиСуммирования);

Особенности работы на управляемых формах

Если вам нужно свернуть табличную часть прямо в интерфейсе (в модуле формы), ситуация меняется. На форме мы работаем не с объектом ТабличнаяЧасть, а с типом ДанныеФормыКоллекция. У этого типа нет метода Свернуть.

Рассмотрим по шагам, как решить эту задачу на сервере в контексте управляемой формы:

  1. Преобразуем данные формы в объект документа или в таблицу значений.
  2. Выполняем свертку.
  3. Загружаем результат обратно в данные формы.

Пример кода на сервере:


&НаСервере
Процедура СвернутьНаСервере()
    // Преобразуем ТЧ формы в ТаблицуЗначений
    ТЗ = Объект.Материалы.Выгрузить();
    
    // Выполняем свертку
    ТЗ.Свернуть("Номенклатура", "Количество");
    
    // Загружаем обратно в реквизит формы
    Объект.Материалы.Загрузить(ТЗ);
КонецПроцедуры

Внимание: При использовании метода Загрузить() в табличной части полностью обновляются строки. Это означает, что идентификаторы строк изменятся. Если у вас есть связанные данные (например, другая табличная часть, ссылающаяся на номер строки первой), эти связи могут быть нарушены.

Использование запросов для сложных задач

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

Алгоритм действий будет следующим:

  1. Выгружаем табличную часть в ТаблицаЗначений.
  2. Помещаем эту таблицу во временную таблицу в запросе.
  3. В запросе выполняем СГРУППИРОВАТЬ ПО с любыми агрегатными функциями (СУММА, МАКСИМУМ, СРЕДНЕЕ).
  4. Выгружаем результат запроса обратно в табличную часть.

Этот способ работает медленнее на маленьких объемах данных, но он гораздо мощнее и позволяет избежать ручного перебора колонок.

Таким образом, мы проанализировали основные способы группировки строк. Для простых задач идеально подходит метод Свернуть, а для универсальных решений лучше использовать обход метаданных или запросы. Главное — всегда помнить о контексте (Модуль объекта или Модуль формы) и не забывать, что Свернуть удаляет неуказанные колонки.

← На главную