Как объединить одинаковые строки с номенклатурой в печатной форме 1С

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет
← На главную

При разработке печатных форм, особенно в конфигурациях типа "Бухгалтерия государственного учреждения" (БГУ) или "ERP", часто возникает задача объединения (группировки) строк. Например, если один и тот же товар списывается разными документами или из разных партий, в печатной форме "Акт списания" он должен отображаться одной строкой с общим количеством и суммой. В этой статье мы подробно разберем, как реализовать такое сложение строк, проанализируем ошибки в программном коде и рассмотрим оптимальные методы решения задачи.

Метод 1. Группировка данных на уровне запроса

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

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

Рассмотрим пример правильного построения запроса:


ВЫБРАТЬ
    Материалы.Номенклатура КАК Номенклатура,
    Материалы.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
    СУММА(Материалы.Количество) КАК Количество,
    СУММА(Материалы.Сумма) КАК Сумма
ИЗ
    Документ.АктСписания.Материалы КАК Материалы
ГДЕ
    Материалы.Ссылка В(&МассивДокументов)
СГРУППИРОВАТЬ ПО
    Материалы.Номенклатура,
    Материалы.ЕдиницаИзмерения

Важный нюанс: Если в вашей таблице есть поле Цена, его нельзя просто добавить в группировку, так как у одной и той же номенклатуры в разных строках цена может незначительно отличаться (например, из-за округлений). В таком случае строки не схлопнутся. Правильный подход — суммировать количество и сумму, а цену рассчитывать уже в коде при выводе области макета.

Метод 2. Использование метода Свернуть() для таблицы значений

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

Рассмотрим алгоритм действий по шагам:

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

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


// Выгружаем данные в таблицу
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// Сворачиваем таблицу по Номенклатуре и Счету учета, суммируя Количество и Сумму
ТаблицаДанных.Свернуть("Номенклатура, СчетУчета, КПС", "Количество, Сумма");

// Теперь обходим свернутую таблицу для вывода на печать
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    ОбластьМакетаСтрока.Параметры.Заполнить(СтрокаДанных);
    
    // Рассчитываем цену для вывода, чтобы избежать ошибок округления
    Если СтрокаДанных.Количество <> 0 Тогда
        ОбластьМакетаСтрока.Параметры.Цена = СтрокаДанных.Сумма / СтрокаДанных.Количество;
    Иначе
        ОбластьМакетаСтрока.Параметры.Цена = 0;
    КонецЕсли;
    
    ТабДокумент.Вывести(ОбластьМакетаСтрока);
КонецЦикла;

Метод 3. Группировка с помощью объекта Соответствие (Map)

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

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


ГруппировкаДанных = Новый Соответствие;

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

// Затем выводим данные из соответствия в печатную форму

Разбор типичных ошибок при группировке

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

СтруктураОтбора.Количество = ВыборкаМатериалы.Количество;

Когда вы включаете Количество в структуру поиска для объединения строк, метод НайтиСтроки ищет полное совпадение. Если в одной строке было 2 шт., а в другой 5 шт., поиск по значению "2" никогда не найдет строку со значением "5". Для успешного объединения из условий поиска нужно исключать количественные и суммовые показатели, оставляя только аналитику (Номенклатура, Характеристика, Склад).

Также важно помнить особенности учета в бюджетных учреждениях (БГУ). При списании материалов нельзя слепо складывать одну и ту же номенклатуру, если у нее разные КБК (КПС) или разные счета учета. По правилам формирования Акта списания (форма 0504230), такие данные должны идти разными строками, так как они отражаются по разным аналитическим счетам в бухгалтерии. Поэтому при использовании метода Свернуть или СГРУППИРОВАТЬ ПО, обязательно включайте КПС, КФО и СчетУчета в список группировочных полей.

Расчет цены и итогов

При суммировании строк часто возникает вопрос: какую цену выводить в печатную форму? Если товары поступали по разным ценам, средняя цена может получиться с большим количеством знаков после запятой. Рекомендуем всегда рассчитывать цену как Сумма / Количество непосредственно перед выводом строки в табличный документ, предварительно округляя результат до нужной точности функцией Окр().

Итоговый совет: Если вы работаете с типовыми механизмами печати 1С, старайтесь подготовить все данные в одном запросе с использованием временных таблиц. Это сделает ваш код чище, а печать — быстрее.

← На главную