Как перенести данные из одной табличной части в другую с группировкой и суммированием в 1С?

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

В процессе разработки бизнес-процессов и документов в 1С часто возникает задача агрегирования данных прямо на форме. Типичный пример: пользователь заполняет подробную табличную часть (например, со спецификацией товаров, поставщиками и суммами), а для проведения документа или выполнения задачи БП требуется сформировать сводную таблицу по контрагентам с общими суммами обязательств. В этой статье мы подробно разберем, как реализовать этот механизм на управляемых формах 1С 8.3.

Особенности клиент-серверного взаимодействия (Клиент и Сервер)

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

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

Способ 1. Использование встроенных методов таблицы значений (Рекомендуемый)

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

Разберем этот алгоритм по шагам:

  1. Выгрузим исходную табличную часть во временную таблицу значений с помощью метода Выгрузить().
  2. Приведем имена колонок к общему знаменателю. Если в первой ТЧ колонка называется Поставщик, а во второй — Контрагент, мы переименуем колонку во временной таблице через свойство Имя коллекции колонок.
  3. Применим метод Свернуть(). При этом все лишние колонки (например, Номенклатура), которые не участвуют в группировке и суммировании, автоматически удалятся платформой.
  4. Очистим табличную часть-приемник и загрузим в нее подготовленные данные методом Загрузить().

Посмотрим на пример реализации кода:


&НаКлиенте
Процедура ПеренестиДанныеКнопка(Команда)
    // Вызываем серверную процедуру для обработки данных
    ПеренестиДанныеНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПеренестиДанныеНаСервере()
    // Шаг 1: Выгружаем данные первой ТЧ во временную таблицу значений
    ВременнаяТЗ = Объект.ТЧПервая.Выгрузить();
    
    // Шаг 2: Приводим имя колонки "Поставщик" к имени "Контрагент"
    Если ВременнаяТЗ.Колонки.Найти("Поставщик") <> Неопределено Тогда
        ВременнаяТЗ.Колонки.Поставщик.Имя = "Контрагент";
    КонецЕсли;
    
    // Шаг 3: Сворачиваем таблицу. 
    // Первый параметр — колонки группировки, второй — колонки суммирования.
    // Все остальные колонки (например, "Номенклатура") будут автоматически удалены из ТЗ.
    ВременнаяТЗ.Свернуть("Контрагент", "Сумма");
    
    // Шаг 4: Загружаем свернутые данные в ТЧВторая
    Объект.ТЧВторая.Загрузить(ВременнаяТЗ);
КонецПроцедуры

Способ 2. Обработка данных с помощью запроса

Иногда требуется не просто сгруппировать данные формы, но и соединить их с информацией из базы данных (например, получить актуальные остатки по взаиморасчетам с контрагентами, их ИНН или проверить договоры). В этом случае идеально подойдет использование механизма запросов.

Мы можем передать выгруженную таблицу значений в качестве параметра запроса. Платформа временно поместит эти данные в базу данных, где СУБД выполнит их группировку средствами SQL.

Рассмотрим пример реализации:


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

Важное примечание: Использование запроса оправдано только тогда, когда вам действительно нужно связать данные формы с физическими таблицами базы данных. Если нужно просто сложить числа из ТЧ, используйте Способ 1, так как пересылка временных таблиц на СУБД для маленьких объемов данных работает медленнее, чем обработка в оперативной памяти сервера 1С.

Способ 3. Построчное добавление слиянием (без полной перезаписи)

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

В этом случае логика работы будет выглядеть следующим образом:


&НаСервере
Процедура ОбъединитьИГруппироватьНаСервере()
    // 1. Выгружаем уже существующие данные из ТЧВторая
    СводнаяТЗ = Объект.ТЧВторая.Выгрузить(); 
    
    // 2. Выгружаем новые данные из ТЧПервая
    НовыеДанныеТЗ = Объект.ТЧПервая.Выгрузить();
    
    // 3. Согласуем наименования колонок
    НовыеДанныеТЗ.Колонки.Поставщик.Имя = "Контрагент";
    
    // 4. Построчно добавляем новые строки в общую таблицу
    Для Каждого СтрокаНовая Из НовыеДанныеТЗ Цикл
        ЗаполнитьЗначенияСвойств(СводнаяТЗ.Добавить(), СтрокаНовая);
    КонецЦикла;
    
    // 5. Сворачиваем объединенную таблицу (суммы по дублирующимся контрагентам сложатся)
    СводнаяТЗ.Свернуть("Контрагент", "Сумма");
    
    // 6. Загружаем итоговый результат обратно в форму
    Объект.ТЧВторая.Загрузить(СводнаяТЗ);
КонецПроцедуры

Анализ возможных ошибок и полезные советы

← На главную