Как правильно свернуть табличную часть в 1С и избежать удаления колонок

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

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

В этой статье мы подробно разберем, как правильно использовать механизм сворачивания данных, почему стандартный метод Свернуть() часто вызывает ошибку «Поле объекта не обнаружено» и как грамотно организовать этот процесс без изменения данных самого документа.

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

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

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

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


// Выгружаем данные табличной части в таблицу значений
ТаблицаТоваров = Выборка.Ссылка.Товары.Выгрузить();

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

Исчезновение колонок после сворачивания: почему возникает ошибка «Поле объекта не обнаружено»

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

ТаблицаТоваров.Свернуть("НомерЧека", "Сумма");

При последующем обходе полученной таблицы в цикле для заполнения параметров макета печатной формы:


Для Каждого СтрокаТЗ Из ТаблицаТоваров Цикл
    ОбластьМакета.Параметры.ДокументДата = СтрокаТЗ.ДатаЧека; // Ошибка!
КонецЦикла;

Система аварийно завершила работу с ошибкой: «Поле объекта ДатаЧека не обнаружено». Почему так произошло?

Обратимся к синтаксису метода Свернуть():

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

Важное правило платформы 1С: любые колонки таблицы значений, которые не были явно указаны в качестве колонок группировки (первый параметр) или колонок суммирования (второй параметр), после выполнения метода физически удаляются из таблицы значений для экономии оперативной памяти.

В примере автора колонка ДатаЧека не была передана ни в один из параметров метода Свернуть(). В результате выполнения операции платформа оставила в таблице только две колонки — НомерЧека и Сумма, а колонку ДатаЧека удалила. Последующее обращение к ней в цикле закономерно вызвало ошибку.

Разберем по шагам правильное сворачивание таблицы значений

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

Рассмотрим правильный пример кода для группировки табличной части перед выводом в макет:


// 1. Выгружаем табличную часть во временную таблицу значений
ТаблицаТоваров = Выборка.Ссылка.Товары.Выгрузить();

// 2. Сворачиваем таблицу, сохраняя все аналитические разрезы и суммируя показатели
// Все колонки, которые должны быть выведены в печатную форму, указываем в первом параметре
ТаблицаТоваров.Свернуть("НомерЧека,ДатаЧека", "Сумма");

// 3. Обходим свернутую таблицу в цикле и заполняем макет
НомерСтроки = 0;
ИтогоПоОтчету = 0;

Для Каждого Стр1 Из ТаблицаТоваров Цикл
    
    // Теперь ошибки не возникнет, так как колонка ДатаЧека сохранена
    ОбластьМакета.Параметры.ДокументДата = Стр1.ДатаЧека;
    ОбластьМакета.Параметры.ДокументНомер = Стр1.НомерЧека;
    ОбластьМакета.Параметры.НаименованиеРасхода = "Чек";
    ОбластьМакета.Параметры.ПоОтчету = Стр1.Сумма;
    ОбластьМакета.Параметры.ПоУчету = Стр1.Сумма;
    
    НомерСтроки = НомерСтроки + 1;
    ИтогоПоОтчету = ИтогоПоОтчету + Стр1.Сумма;
    
    ОбластьМакета.Параметры.НомерСтроки = НомерСтроки;
    ТабличныйДокумент.Вывести(ОбластьМакета);
    
КонецЦикла;

Альтернативный и более производительный подход: Группировка в запросе

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

Правильный архитектурный подход — группировать данные еще на этапе получения их из базы данных с помощью запроса и конструкции СГРУППИРОВАТЬ ПО. Посмотрим на пример такого запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Товары.НомерЧека КАК НомерЧека,
    |	Товары.ДатаЧека КАК ДатаЧека,
    |	СУММА(Товары.Сумма) КАК Сумма
    |ИЗ
    |	Документ.РасходныйКассовыйОрдер.Товары КАК Товары
    |ГДЕ
    |	Товары.Ссылка = &Ссылка
    |
    |СГРУППИРОВАТЬ ПО
    |	Товары.НомерЧека,
    |	Товары.ДатаЧека";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    // Заполнение параметров макета напрямую из выборки запроса
    ОбластьМакета.Параметры.ДокументДата = ВыборкаДетальныеЗаписи.ДатаЧека;
    ОбластьМакета.Параметры.ДокументНомер = ВыборкаДетальныеЗаписи.НомерЧека;
    ОбластьМакета.Параметры.ПоОтчету = ВыборкаДетальныеЗаписи.Сумма;
    // ...
КонецЦикла;

Почему группировка в запросе предпочтительнее сворачивания в коде?

  1. Снижение нагрузки на сеть и ОЗУ: На сервер приложений (или клиентский компьютер) передается уже сжатый и сгруппированный сервером СУБД массив данных, а не вся детальная табличная часть целиком.
  2. Оптимизация СУБД: Системы управления базами данных (MS SQL, PostgreSQL и др.) аппаратно оптимизированы для выполнения операций группировки и делают это значительно быстрее, чем внутренние механизмы платформы 1С при обработке таблиц значений в оперативной памяти.
  3. Расширенные возможности агрегации: В запросе, помимо простого суммирования, мы можем использовать функции получения максимума, минимума, среднего значения или количества уникальных записей, что невозможно сделать стандартным методом Свернуть().

Важные технические нюансы работы с методом Свернуть()

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

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

← На главную