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