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

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

При разработке внешних печатных форм для документов, таких как РеализацияТоваровУслуг, программисты часто сталкиваются с ситуацией, когда в табличной части товара одна и та же номенклатура указана несколько раз. Это может быть связано с особенностями складского учета, разными сериями или просто человеческим фактором. Однако в печатной форме (например, в накладной или счете) заказчик часто хочет видеть «схлопнутые» строки, где одинаковые товары объединены в одну позицию с суммированным количеством и суммой.

В этой статье мы разберем, как правильно реализовать группировку строк в запросе и альтернативные способы объединения данных в коде 1С.

Способ 1: Использование конструкции СГРУППИРОВАТЬ ПО в запросе

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

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


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

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

Важные нюансы этого решения:

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

Способ 2: Программное объединение через таблицу значений (метод Свернуть)

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

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

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

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

// Сворачиваем таблицу
// Первый параметр - список полей, которые должны быть уникальными (группировка)
// Второй параметр - список числовых полей, которые нужно просуммировать
ТаблицаТоваров.Свернуть("Номенклатура, Артикул, Цена, ЕдиницаИзмерения", "КоличествоУпаковок, Сумма");

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

Этот метод часто оказывается нагляднее и проще для отладки, так как в отладчике можно сразу увидеть состояние таблицы до и после выполнения метода Свернуть.

Способ 3: Использование ИТОГИ ПО (для иерархического вывода)

Рассмотрим ситуацию, когда нам нужно вывести и сгруппированную строку, и детализацию под ней. В этом случае используется конструкция ИТОГИ. Однако помните: если вы используете итоги, обход выборки должен быть иерархическим.


Запрос.Текст = "... ИТОГИ СУММА(КоличествоУпаковок) ПО Артикул";
ВыборкаПоАртикулу = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

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

Проблема расчета НДС при группировке

Выясним важную причину, по которой итоги могут «не сходиться» на копейку. В документах 1С НДС часто рассчитывается построчно. Если мы просто сложим суммы НДС из разных строк, итог может отличаться от НДС, рассчитанного от общей (сгруппированной) суммы.

Рекомендация: Для печатных форм, имеющих юридическую значимость, всегда суммируйте значения СуммаНДС непосредственно из строк документа. Это гарантирует, что итоговая сумма НДС в печатной форме совпадет с итогом в самом документе 1С, даже если математически расчет от общей суммы дал бы другой результат.

Учет характеристик и серий

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

Аналогично следует поступать с полями СтавкаНДС и Склад, если они выводятся в печатную форму. Правило простое: все данные, которые делают строку уникальной, должны участвовать в группировке.

Заключение

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

← На главную