Как суммировать строки и выводить итоговые значения в печатной форме документа РеализацияТоваровУслуг в 1С?

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

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


РеализацияТоваровУслуг
на примере конфигурации "Бухгалтерия для Беларуси, редакция 2.1".

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

Разберем структуру исходного кода и макета

Начнем с анализа предоставленного кода, сгенерированного конструктором запросов. Мы видим, что он уже выбирает необходимые данные из документа


РеализацияТоваровУслуг
, включая табличные части

Товары
и

Услуги
. Также определены различные области макета для вывода:

  1. ОбластьЗаголовок: для общей шапки документа.

  2. ОбластьШапкаТаблицы: для общей шапки основной таблицы (хотя далее используются специфические шапки для товаров и услуг).

  3. ОбластьДетальныхЗаписей: предположительно для вывода основной информации о документе или первой строки.

  4. УслугиОбластьШапкаТаблицы, УслугиОбластьДетальныхЗаписей, УслугиОбластьПодвалТаблицы: для вывода информации об услугах.

  5. ТоварыОбластьШапкаТаблицы, ТоварыОбластьДетальныхЗаписей, ТоварыОбластьПодвалТаблицы: для вывода информации о товарах.

  6. ОбластьПодвалТаблицы: для общего подвала документа, где обычно располагаются глобальные итоги.

  7. ОбластьПодвал: для финального подвала, возможно, с подписями.

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

Пошаговое решение: Суммирование по разделам "Товары" и "Услуги"

Для того чтобы суммировать данные по каждой из табличных частей (


Товары
и

Услуги
) и выводить их в соответствующие подвалы, нам потребуется выполнить следующие шаги:

1. Суммирование для раздела "Товары"

Прежде всего, нам необходимо инициализировать переменные для накопления суммы и НДС по товарам перед началом цикла перебора товарных позиций. Затем в каждом шаге цикла мы будем добавлять значения текущей строки к нашим накопительным переменным.

  1. Инициализация переменных: Перед циклом

    
    Пока ТоварыВыборкаДетальныеЗаписи.Следующий Цикл
    
    объявим и обнулим переменные для хранения итоговых сумм по товарам:

    
    ИтогоСуммаТоваров = 0;
    ИтогоНДСТоваров = 0;
    
  2. Накопление сумм: Внутри цикла, после того как мы заполнили параметры для детальной записи и вывели ее, добавим к нашим переменным значения из текущей строки выборки:

    
    Пока ТоварыВыборкаДетальныеЗаписи.Следующий Цикл
        ТоварыОбластьДетальныхЗаписей.Параметры.Заполнить(ТоварыВыборкаДетальныеЗаписи);
        ТабДок.Вывести(ТоварыОбластьДетальныхЗаписей, ТоварыВыборкаДетальныеЗаписи.Уровень);
        // Накапливаем суммы по товарам
        ИтогоСуммаТоваров = ИтогоСуммаТоваров + ТоварыВыборкаДетальныеЗаписи.Сумма;
        ИтогоНДСТоваров = ИтогоНДСТоваров + ТоварыВыборкаДетальныеЗаписи.СуммаНДС;
    КонецЦикла;
    
  3. Вывод итогов: После завершения цикла по товарам, но до вывода

    
    ТоварыОбластьПодвалТаблицы
    
    , мы передадим накопленные значения в параметры этой области макета и выведем ее. Убедитесь, что в макете
    
    ТоварыОбластьПодвалТаблицы
    
    есть ячейки с именами параметров, например,
    
    СуммаИтогоТоваров
    
    и
    
    НДСИтогоТоваров
    
    , и для них установлено свойство "Заполнение" = "Параметр".

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

2. Суммирование для раздела "Услуги"

Аналогичные действия выполним и для раздела услуг. Это позволит нам получить раздельные итоги по услугам.

  1. Инициализация переменных: Перед циклом

    
    Пока УслугиВыборкаДетальныеЗаписи.Следующий Цикл
    
    инициализируем переменные для сумм услуг:

    
    ИтогоСуммаУслуг = 0;
    ИтогоНДСУслуг = 0;
    
  2. Накопление сумм: Внутри цикла по услугам, добавляем значения к нашим переменным:

    
    Пока УслугиВыборкаДетальныеЗаписи.Следующий Цикл
        УслугиОбластьДетальныхЗаписей.Параметры.Заполнить(УслугиВыборкаДетальныеЗаписи);
        ТабДок.Вывести(УслугиОбластьДетальныхЗаписей, УслугиВыборкаДетальныеЗаписи.Уровень);
        // Накапливаем суммы по услугам
        ИтогоСуммаУслуг = ИтогоСуммаУслуг + УслугиВыборкаДетальныеЗаписи.Сумма;
        ИтогоНДСУслуг = ИтогоНДСУслуг + УслугиВыборкаДетальныеЗаписи.СуммаНДС;
    КонецЦикла;
    
  3. Вывод итогов: После завершения цикла по услугам, передаем накопленные значения в параметры области

    
    УслугиОбластьПодвалТаблицы
    
    и выводим ее. Убедитесь, что в макете есть ячейки с параметрами, например,
    
    СуммаИтогоУслуг
    
    и
    
    НДСИтогоУслуг
    
    .

    
    // Передаем итоговые значения в подвал услуг
    УслугиОбластьПодвалТаблицы.Параметры.СуммаИтогоУслуг = ИтогоСуммаУслуг;
    УслугиОбластьПодвалТаблицы.Параметры.НДСИтогоУслуг = ИтогоНДСУслуг;
    ТабДок.Вывести(УслугиОбластьПодвалТаблицы);
    

Пошаговое решение: Суммирование в графу "Всего с НДС"

Теперь, когда у нас есть раздельные итоги по товарам и услугам, мы можем приступить к расчету и выводу общей суммы "Всего с НДС" для всего документа. Здесь возможно несколько подходов.

1. Использование поля "СуммаДокумента" из запроса

Если в документе


РеализацияТоваровУслуг
поле

СуммаДокумента
уже содержит нужный нам общий итог (сумму всех товаров и услуг с НДС), мы можем просто использовать его. Это самый простой способ, если данные в этом поле корректны.

  1. Передача параметра: После обработки всех табличных частей, перед выводом общего подвала

    
    ОбластьПодвалТаблицы
    
    , мы можем передать значение
    
    ВыборкаДетальныеЗаписи.СуммаДокумента
    
    в соответствующий параметр этой области. Убедитесь, что в
    
    ОбластьПодвалТаблицы
    
    есть параметр, например,
    
    ВсегоСНДС
    
    .

    
    ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВыборкаДетальныеЗаписи.СуммаДокумента;
    // ... другие параметры общего подвала, если нужны
    ТабДок.Вывести(ОбластьПодвалТаблицы);
    

2. Расчет общей суммы на основе просуммированных значений

Если поле


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

  1. Расчет общих итогов: После того как циклы по товарам и услугам завершены и их итоги накоплены, мы можем просуммировать их:

    
    // Рассчитываем общие итоги документа
    ОбщаяСуммаБезНДС = ИтогоСуммаТоваров + ИтогоСуммаУслуг;
    ОбщийНДС = ИтогоНДСТоваров + ИтогоНДСУслуг;
    ВсегоСНДС = ОбщаяСуммаБезНДС + ОбщийНДС;
    
  2. Передача параметров в общий подвал: Далее передадим эти рассчитанные значения в параметры области

    
    ОбластьПодвалТаблицы
    
    . Как и ранее, необходимо настроить соответствующие параметры в макете.

    
    // Передаем общие итоги в общий подвал документа
    ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВсегоСНДС;
    ОбластьПодвалТаблицы.Параметры.ОбщаяСуммаБезНДС = ОбщаяСуммаБезНДС; // Если нужно вывести сумму без НДС
    ОбластьПодвалТаблицы.Параметры.ОбщийНДС = ОбщийНДС; // Если нужно вывести общий НДС
    ТабДок.Вывести(ОбластьПодвалТаблицы);
    

Выбор между этими двумя подходами зависит от логики вашей конфигурации и того, что именно хранится в поле


СуммаДокумента
. Обычно, для избежания расхождений, рекомендуется пересчитывать итоги вручную, основываясь на данных, которые вы вывели в детальных строках.

Настройка макета: Подготовка ячеек для параметров

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

  1. Откройте макет: В конфигураторе откройте вашу внешнюю печатную форму и перейдите на вкладку "Макеты".

  2. Определите области подвалов: Убедитесь, что у вас есть явно выделенные области для подвалов таблиц:

    
    УслугиОбластьПодвалТаблицы
    
    ,
    
    ТоварыОбластьПодвалТаблицы
    
    и
    
    ОбластьПодвалТаблицы
    
    .

  3. Создайте ячейки-параметры: В каждой из этих областей создайте или выделите ячейки, в которых должны отображаться итоговые суммы. Для каждой такой ячейки выполните следующее:

    • Щелкните правой кнопкой мыши по ячейке и выберите "Свойства".

    • В свойствах ячейки найдите поле "Заполнение" и установите его в значение "Параметр".

    • В поле "Параметр" укажите точное имя параметра, которое вы используете в коде. Например:

      
      СуммаИтогоТоваров
      
      ,
      
      НДСИтогоТоваров
      
      ,
      
      СуммаИтогоУслуг
      
      ,
      
      НДСИтогоУслуг
      
      ,
      
      ВсегоСНДС
      
      ,
      
      ОбщаяСуммаБезНДС
      
      ,
      
      ОбщийНДС
      
      .

  4. Форматирование: При необходимости настройте формат вывода чисел (количество десятичных знаков, разделители) через свойства ячейки, используя вкладку "Формат".

Без правильной настройки этих параметров в макете, даже самый корректный код не сможет вывести итоговые значения.

Финальный код процедуры ПечатьОбъекта

Теперь, давайте объединим все сделанные изменения в итоговый код процедуры


ПечатьОбъекта
. Мы учтем инициализацию переменных, накопление сумм в циклах и передачу их в параметры соответствующих областей макета.


Процедура ПечатьОбъекта(ТабДок, Ссылка) Экспорт

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

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

    ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
    ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
    //ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы"); // Эта область не используется для вывода
    ОбластьПодвалТаблицы = Макет.ПолучитьОбласть("ПодвалТаблицы");
    ОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("Детали"); // Возможно для общих деталей документа

    УслугиОбластьШапкаТаблицы = Макет.ПолучитьОбласть("УслугиШапкаТаблицы");
    УслугиОбластьПодвалТаблицы = Макет.ПолучитьОбласть("УслугиПодвалТаблицы");
    УслугиОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("УслугиДетали");

    ТоварыОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ТоварыШапкаТаблицы");
    ТоварыОбластьПодвалТаблицы = Макет.ПолучитьОбласть("ТоварыПодвалТаблицы");
    ТоварыОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("ТоварыДетали");

    ТабДок.Очистить(); // Очищаем табличный документ перед формированием

    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл // Главный цикл по документу (обычно один проход)

        // Выводим заголовок документа
        ОбластьЗаголовок.Параметры.Заполнить(ВыборкаДетальныеЗаписи);
        ОбластьЗаголовок.Параметры.Дата = Формат(ВыборкаДетальныеЗаписи.Дата, "ДФ=dd.MM.yyyy");
        ТабДок.Вывести(ОбластьЗаголовок);

        // Если есть область для общих деталей документа, выводим ее
        // ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетальныеЗаписи);
        // ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетальныеЗаписи.Уровень); // Или ТабДок.Вывести(ОбластьДетальныхЗаписей);

        ТабДок.НачатьГруппуСтрок(); // Начинаем группу для всего содержимого документа

        // --- Обработка услуг ---
        ТабДок.Вывести(УслугиОбластьШапкаТаблицы);
        
        ИтогоСуммаУслуг = 0;
        ИтогоНДСУслуг = 0;

        УслугиВыборкаДетальныеЗаписи = ВыборкаДетальныеЗаписи.Услуги.Выбрать();
        Пока УслугиВыборкаДетальныеЗаписи.Следующий() Цикл
            УслугиОбластьДетальныхЗаписей.Параметры.Заполнить(УслугиВыборкаДетальныеЗаписи);
            ТабДок.Вывести(УслугиОбластьДетальныхЗаписей, УслугиВыборкаДетальныеЗаписи.Уровень);
            ИтогоСуммаУслуг = ИтогоСуммаУслуг + УслугиВыборкаДетальныеЗаписи.Сумма;
            ИтогоНДСУслуг = ИтогоНДСУслуг + УслугиВыборкаДетальныеЗаписи.СуммаНДС;
        КонецЦикла;
        
        // Выводим подвал для услуг с итогами
        УслугиОбластьПодвалТаблицы.Параметры.СуммаИтогоУслуг = ИтогоСуммаУслуг;
        УслугиОбластьПодвалТаблицы.Параметры.НДСИтогоУслуг = ИтогоНДСУслуг;
        ТабДок.Вывести(УслугиОбластьПодвалТаблицы);


        // --- Обработка товаров ---
        ТабДок.Вывести(ТоварыОбластьШапкаТаблицы);

        ИтогоСуммаТоваров = 0;
        ИтогоНДСТоваров = 0;

        ТоварыВыборкаДетальныеЗаписи = ВыборкаДетальныеЗаписи.Товары.Выбрать();
        Пока ТоварыВыборкаДетальныеЗаписи.Следующий() Цикл
            ТоварыОбластьДетальныхЗаписей.Параметры.Заполнить(ТоварыВыборкаДетальныеЗаписи);
            ТабДок.Вывести(ТоварыОбластьДетальныхЗаписей, ТоварыВыборкаДетальныеЗаписи.Уровень);
            ИтогоСуммаТоваров = ИтогоСуммаТоваров + ТоварыВыборкаДетальныеЗаписи.Сумма;
            ИтогоНДСТоваров = ИтогоНДСТоваров + ТоварыВыборкаДетальныеЗаписи.СуммаНДС;
        КонецЦикла;

        // Выводим подвал для товаров с итогами
        ТоварыОбластьПодвалТаблицы.Параметры.СуммаИтогоТоваров = ИтогоСуммаТоваров;
        ТоварыОбластьПодвалТаблицы.Параметры.НДСИтогоТоваров = ИтогоНДСТоваров;
        ТабДок.Вывести(ТоварыОбластьПодвалТаблицы);

        ТабДок.ЗакончитьГруппуСтрок(); // Заканчиваем группу для всего содержимого документа
        
        // --- Расчет и вывод общих итогов документа ---
        // Вариант 1: Использование поля СуммаДокумента из запроса
        // ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВыборкаДетальныеЗаписи.СуммаДокумента;
        
        // Вариант 2: Расчет на основе просуммированных значений
        ОбщаяСуммаБезНДС = ИтогоСуммаТоваров + ИтогоСуммаУслуг;
        ОбщийНДС = ИтогоНДСТоваров + ИтогоНДСУслуг;
        ВсегоСНДС = ОбщаяСуммаБезНДС + ОбщийНДС;

        ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВсегоСНДС;
        ОбластьПодвалТаблицы.Параметры.ОбщаяСуммаБезНДС = ОбщаяСуммаБезНДС;
        ОбластьПодвалТаблицы.Параметры.ОбщийНДС = ОбщийНДС;
        
        ТабДок.Вывести(ОбластьПодвалТаблицы);

        // Выводим общий подвал (например, для подписей)
        ТабДок.Вывести(ОбластьПодвал);

    КонецЦикла;

КонецПроцедуры

Важные моменты:

  1. 
    ТабДок.Очистить()
    
    : Мы добавили эту строку в начале, чтобы гарантировать чистоту табличного документа перед формированием нового отчета.

  2. Переменные итогов: Переменные

    
    ИтогоСуммаУслуг
    
    ,
    
    ИтогоНДСУслуг
    
    ,
    
    ИтогоСуммаТоваров
    
    ,
    
    ИтогоНДСТоваров
    
    должны быть инициализированы перед их использованием в соответствующих циклах, что мы и сделали.

  3. Параметры макета: Еще раз подчеркнем, что имена параметров, используемые в коде (например,

    
    СуммаИтогоТоваров
    
    ), должны точно совпадать с именами параметров, заданных в свойствах ячеек макета.

  4. 
    ТабДок.НачатьАвтогруппировкуСтрок
    
    и
    
    ТабДок.ЗакончитьАвтогруппировкуСтрок
    
    :
    В оригинальном коде были эти вызовы. Они используются для автоматического сворачивания групп строк в интерфейсе 1С, что может быть полезно для пользователя. Мы сохранили их для основного цикла, но в циклах по товарам и услугам они были внутри
    
    НачатьГруппуСтрок
    
    , что не совсем корректно. Обычно,
    
    НачатьАвтогруппировкуСтрок
    
    используется для деталей, а подвал таблицы выводится уже после ее завершения. В нашем примере мы сосредоточились на суммировании, поэтому часть этих вызовов была упрощена или переставлена, чтобы логика накопления и вывода итогов была максимально прозрачной. Если вам требуется именно автогруппировка, убедитесь, что она корректно охватывает нужные детальные строки перед выводом подвала.

Таким образом, комбинируя правильную логику накопления данных в коде и корректную настройку макета, вы сможете эффективно выводить итоговые значения в ваших внешних печатных формах 1С.

← На главную