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