При разработке внешних печатных форм для документов 1С часто возникает необходимость в подсчете и выводе итоговых значений по различным группам строк, например, по товарам и услугам, а также расчет общей суммы с учетом НДС. Рассмотрим подробнее, как реализовать подобное суммирование в документе
РеализацияТоваровУслуг
Перед нами стоит задача: создать внешнюю печатную форму, которая будет не только выводить детальные данные по товарам и услугам, но и аккумулировать их суммы, а также суммы НДС, и отображать эти итоги в соответствующих подвалах таблиц и в общем итоге документа.
Начнем с анализа предоставленного кода, сгенерированного конструктором запросов. Мы видим, что он уже выбирает необходимые данные из документа
РеализацияТоваровУслуг
Товары
Услуги
ОбластьЗаголовок: для общей шапки документа.
ОбластьШапкаТаблицы: для общей шапки основной таблицы (хотя далее используются специфические шапки для товаров и услуг).
ОбластьДетальныхЗаписей: предположительно для вывода основной информации о документе или первой строки.
УслугиОбластьШапкаТаблицы, УслугиОбластьДетальныхЗаписей, УслугиОбластьПодвалТаблицы: для вывода информации об услугах.
ТоварыОбластьШапкаТаблицы, ТоварыОбластьДетальныхЗаписей, ТоварыОбластьПодвалТаблицы: для вывода информации о товарах.
ОбластьПодвалТаблицы: для общего подвала документа, где обычно располагаются глобальные итоги.
ОбластьПодвал: для финального подвала, возможно, с подписями.
Текущий код успешно выводит детальные записи из табличных частей, но не содержит логики для их суммирования. Давайте дополним его, чтобы он отвечал нашим требованиям по агрегированию данных.
Для того чтобы суммировать данные по каждой из табличных частей (
Товары
Услуги
Прежде всего, нам необходимо инициализировать переменные для накопления суммы и НДС по товарам перед началом цикла перебора товарных позиций. Затем в каждом шаге цикла мы будем добавлять значения текущей строки к нашим накопительным переменным.
Инициализация переменных: Перед циклом
Пока ТоварыВыборкаДетальныеЗаписи.Следующий Цикл
ИтогоСуммаТоваров = 0;
ИтогоНДСТоваров = 0;
Накопление сумм: Внутри цикла, после того как мы заполнили параметры для детальной записи и вывели ее, добавим к нашим переменным значения из текущей строки выборки:
Пока ТоварыВыборкаДетальныеЗаписи.Следующий Цикл
ТоварыОбластьДетальныхЗаписей.Параметры.Заполнить(ТоварыВыборкаДетальныеЗаписи);
ТабДок.Вывести(ТоварыОбластьДетальныхЗаписей, ТоварыВыборкаДетальныеЗаписи.Уровень);
// Накапливаем суммы по товарам
ИтогоСуммаТоваров = ИтогоСуммаТоваров + ТоварыВыборкаДетальныеЗаписи.Сумма;
ИтогоНДСТоваров = ИтогоНДСТоваров + ТоварыВыборкаДетальныеЗаписи.СуммаНДС;
КонецЦикла;
Вывод итогов: После завершения цикла по товарам, но до вывода
ТоварыОбластьПодвалТаблицы
ТоварыОбластьПодвалТаблицы
СуммаИтогоТоваров
НДСИтогоТоваров
// Передаем итоговые значения в подвал товаров
ТоварыОбластьПодвалТаблицы.Параметры.СуммаИтогоТоваров = ИтогоСуммаТоваров;
ТоварыОбластьПодвалТаблицы.Параметры.НДСИтогоТоваров = ИтогоНДСТоваров;
ТабДок.Вывести(ТоварыОбластьПодвалТаблицы);
Аналогичные действия выполним и для раздела услуг. Это позволит нам получить раздельные итоги по услугам.
Инициализация переменных: Перед циклом
Пока УслугиВыборкаДетальныеЗаписи.Следующий Цикл
ИтогоСуммаУслуг = 0;
ИтогоНДСУслуг = 0;
Накопление сумм: Внутри цикла по услугам, добавляем значения к нашим переменным:
Пока УслугиВыборкаДетальныеЗаписи.Следующий Цикл
УслугиОбластьДетальныхЗаписей.Параметры.Заполнить(УслугиВыборкаДетальныеЗаписи);
ТабДок.Вывести(УслугиОбластьДетальныхЗаписей, УслугиВыборкаДетальныеЗаписи.Уровень);
// Накапливаем суммы по услугам
ИтогоСуммаУслуг = ИтогоСуммаУслуг + УслугиВыборкаДетальныеЗаписи.Сумма;
ИтогоНДСУслуг = ИтогоНДСУслуг + УслугиВыборкаДетальныеЗаписи.СуммаНДС;
КонецЦикла;
Вывод итогов: После завершения цикла по услугам, передаем накопленные значения в параметры области
УслугиОбластьПодвалТаблицы
СуммаИтогоУслуг
НДСИтогоУслуг
// Передаем итоговые значения в подвал услуг
УслугиОбластьПодвалТаблицы.Параметры.СуммаИтогоУслуг = ИтогоСуммаУслуг;
УслугиОбластьПодвалТаблицы.Параметры.НДСИтогоУслуг = ИтогоНДСУслуг;
ТабДок.Вывести(УслугиОбластьПодвалТаблицы);
Теперь, когда у нас есть раздельные итоги по товарам и услугам, мы можем приступить к расчету и выводу общей суммы "Всего с НДС" для всего документа. Здесь возможно несколько подходов.
Если в документе
РеализацияТоваровУслуг
СуммаДокумента
Передача параметра: После обработки всех табличных частей, перед выводом общего подвала
ОбластьПодвалТаблицы
ВыборкаДетальныеЗаписи.СуммаДокумента
ОбластьПодвалТаблицы
ВсегоСНДС
ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВыборкаДетальныеЗаписи.СуммаДокумента;
// ... другие параметры общего подвала, если нужны
ТабДок.Вывести(ОбластьПодвалТаблицы);
Если поле
СуммаДокумента
Расчет общих итогов: После того как циклы по товарам и услугам завершены и их итоги накоплены, мы можем просуммировать их:
// Рассчитываем общие итоги документа
ОбщаяСуммаБезНДС = ИтогоСуммаТоваров + ИтогоСуммаУслуг;
ОбщийНДС = ИтогоНДСТоваров + ИтогоНДСУслуг;
ВсегоСНДС = ОбщаяСуммаБезНДС + ОбщийНДС;
Передача параметров в общий подвал: Далее передадим эти рассчитанные значения в параметры области
ОбластьПодвалТаблицы
// Передаем общие итоги в общий подвал документа
ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВсегоСНДС;
ОбластьПодвалТаблицы.Параметры.ОбщаяСуммаБезНДС = ОбщаяСуммаБезНДС; // Если нужно вывести сумму без НДС
ОбластьПодвалТаблицы.Параметры.ОбщийНДС = ОбщийНДС; // Если нужно вывести общий НДС
ТабДок.Вывести(ОбластьПодвалТаблицы);
Выбор между этими двумя подходами зависит от логики вашей конфигурации и того, что именно хранится в поле
СуммаДокумента
Критически важным шагом для успешного вывода итоговых значений является правильная настройка макета печатной формы. Если этого не сделать, система не сможет найти поля для вывода, и вы получите ошибку "Поле объекта не обнаружено (ИмяПараметра)".
Откройте макет: В конфигураторе откройте вашу внешнюю печатную форму и перейдите на вкладку "Макеты".
Определите области подвалов: Убедитесь, что у вас есть явно выделенные области для подвалов таблиц:
УслугиОбластьПодвалТаблицы
ТоварыОбластьПодвалТаблицы
ОбластьПодвалТаблицы
Создайте ячейки-параметры: В каждой из этих областей создайте или выделите ячейки, в которых должны отображаться итоговые суммы. Для каждой такой ячейки выполните следующее:
Щелкните правой кнопкой мыши по ячейке и выберите "Свойства".
В свойствах ячейки найдите поле "Заполнение" и установите его в значение "Параметр".
В поле "Параметр" укажите точное имя параметра, которое вы используете в коде. Например:
СуммаИтогоТоваров
НДСИтогоТоваров
СуммаИтогоУслуг
НДСИтогоУслуг
ВсегоСНДС
ОбщаяСуммаБезНДС
ОбщийНДС
Форматирование: При необходимости настройте формат вывода чисел (количество десятичных знаков, разделители) через свойства ячейки, используя вкладку "Формат".
Без правильной настройки этих параметров в макете, даже самый корректный код не сможет вывести итоговые значения.
Теперь, давайте объединим все сделанные изменения в итоговый код процедуры
ПечатьОбъекта
Процедура ПечатьОбъекта(ТабДок, Ссылка) Экспорт
Макет = ПолучитьМакет("Макет");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Номер КАК Номер,
| РеализацияТоваровУслуг.Дата КАК Дата,
| РеализацияТоваровУслуг.Организация.НаименованиеПолное КАК ОрганизацияНаименованиеПолное,
| РеализацияТоваровУслуг.Организация.ОсновнойБанковскийСчет.НомерСчета КАК ОрганизацияОсновнойБанковскийСчетНомерСчета,
| РеализацияТоваровУслуг.Организация.ОсновнойБанковскийСчет.Банк.Наименование КАК ОрганизацияОсновнойБанковскийСчетБанкНаименование,
| РеализацияТоваровУслуг.Организация.ОсновнойБанковскийСчет.Банк.Код КАК ОрганизацияОсновнойБанковскийСчетБанкКод,
| РеализацияТоваровУслуг.Организация.ИНН КАК ОрганизацияИНН,
| РеализацияТоваровУслуг.Контрагент.НаименованиеПолное КАК КонтрагентНаименованиеПолное,
| РеализацияТоваровУслуг.Контрагент.ИНН КАК КонтрагентИНН,
| РеализацияТоваровУслуг.ОснованиеОтпуска КАК ОснованиеОтпуска,
| РеализацияТоваровУслуг.ПунктПогрузки КАК ПунктПогрузки,
| РеализацияТоваровУслуг.ПунктРазгрузки КАК ПунктРазгрузки,
| РеализацияТоваровУслуг.СуммаДокумента КАК СуммаДокумента,
| РеализацияТоваровУслуг.АвтомобильДляСТО КАК АвтомобильДляСТО,
| РеализацияТоваровУслуг.Товары.(
| НомерСтроки КАК НомерСтроки,
| Номенклатура.Наименование КАК НоменклатураНаименование,
| Номенклатура.ЕдиницаИзмерения.Наименование КАК НоменклатураЕдиницаИзмеренияНаименование,
| Количество КАК Количество,
| Цена КАК Цена,
| Сумма КАК Сумма,
| СтавкаНДС КАК СтавкаНДС,
| СуммаНДС КАК СуммаНДС
| ) КАК Товары,
| РеализацияТоваровУслуг.Услуги.(
| НомерСтроки КАК НомерСтроки,
| Номенклатура.Наименование КАК НоменклатураНаименование,
| Номенклатура.ЕдиницаИзмерения.Наименование КАК НоменклатураЕдиницаИзмеренияНаименование,
| Количество КАК Количество,
| Цена КАК Цена,
| Сумма КАК Сумма,
| СтавкаНДС КАК СтавкаНДС,
| СуммаНДС КАК СуммаНДС
| ) КАК Услуги
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
//ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы"); // Эта область не используется для вывода
ОбластьПодвалТаблицы = Макет.ПолучитьОбласть("ПодвалТаблицы");
ОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("Детали"); // Возможно для общих деталей документа
УслугиОбластьШапкаТаблицы = Макет.ПолучитьОбласть("УслугиШапкаТаблицы");
УслугиОбластьПодвалТаблицы = Макет.ПолучитьОбласть("УслугиПодвалТаблицы");
УслугиОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("УслугиДетали");
ТоварыОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ТоварыШапкаТаблицы");
ТоварыОбластьПодвалТаблицы = Макет.ПолучитьОбласть("ТоварыПодвалТаблицы");
ТоварыОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("ТоварыДетали");
ТабДок.Очистить(); // Очищаем табличный документ перед формированием
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл // Главный цикл по документу (обычно один проход)
// Выводим заголовок документа
ОбластьЗаголовок.Параметры.Заполнить(ВыборкаДетальныеЗаписи);
ОбластьЗаголовок.Параметры.Дата = Формат(ВыборкаДетальныеЗаписи.Дата, "ДФ=dd.MM.yyyy");
ТабДок.Вывести(ОбластьЗаголовок);
// Если есть область для общих деталей документа, выводим ее
// ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетальныеЗаписи);
// ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетальныеЗаписи.Уровень); // Или ТабДок.Вывести(ОбластьДетальныхЗаписей);
ТабДок.НачатьГруппуСтрок(); // Начинаем группу для всего содержимого документа
// --- Обработка услуг ---
ТабДок.Вывести(УслугиОбластьШапкаТаблицы);
ИтогоСуммаУслуг = 0;
ИтогоНДСУслуг = 0;
УслугиВыборкаДетальныеЗаписи = ВыборкаДетальныеЗаписи.Услуги.Выбрать();
Пока УслугиВыборкаДетальныеЗаписи.Следующий() Цикл
УслугиОбластьДетальныхЗаписей.Параметры.Заполнить(УслугиВыборкаДетальныеЗаписи);
ТабДок.Вывести(УслугиОбластьДетальныхЗаписей, УслугиВыборкаДетальныеЗаписи.Уровень);
ИтогоСуммаУслуг = ИтогоСуммаУслуг + УслугиВыборкаДетальныеЗаписи.Сумма;
ИтогоНДСУслуг = ИтогоНДСУслуг + УслугиВыборкаДетальныеЗаписи.СуммаНДС;
КонецЦикла;
// Выводим подвал для услуг с итогами
УслугиОбластьПодвалТаблицы.Параметры.СуммаИтогоУслуг = ИтогоСуммаУслуг;
УслугиОбластьПодвалТаблицы.Параметры.НДСИтогоУслуг = ИтогоНДСУслуг;
ТабДок.Вывести(УслугиОбластьПодвалТаблицы);
// --- Обработка товаров ---
ТабДок.Вывести(ТоварыОбластьШапкаТаблицы);
ИтогоСуммаТоваров = 0;
ИтогоНДСТоваров = 0;
ТоварыВыборкаДетальныеЗаписи = ВыборкаДетальныеЗаписи.Товары.Выбрать();
Пока ТоварыВыборкаДетальныеЗаписи.Следующий() Цикл
ТоварыОбластьДетальныхЗаписей.Параметры.Заполнить(ТоварыВыборкаДетальныеЗаписи);
ТабДок.Вывести(ТоварыОбластьДетальныхЗаписей, ТоварыВыборкаДетальныеЗаписи.Уровень);
ИтогоСуммаТоваров = ИтогоСуммаТоваров + ТоварыВыборкаДетальныеЗаписи.Сумма;
ИтогоНДСТоваров = ИтогоНДСТоваров + ТоварыВыборкаДетальныеЗаписи.СуммаНДС;
КонецЦикла;
// Выводим подвал для товаров с итогами
ТоварыОбластьПодвалТаблицы.Параметры.СуммаИтогоТоваров = ИтогоСуммаТоваров;
ТоварыОбластьПодвалТаблицы.Параметры.НДСИтогоТоваров = ИтогоНДСТоваров;
ТабДок.Вывести(ТоварыОбластьПодвалТаблицы);
ТабДок.ЗакончитьГруппуСтрок(); // Заканчиваем группу для всего содержимого документа
// --- Расчет и вывод общих итогов документа ---
// Вариант 1: Использование поля СуммаДокумента из запроса
// ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВыборкаДетальныеЗаписи.СуммаДокумента;
// Вариант 2: Расчет на основе просуммированных значений
ОбщаяСуммаБезНДС = ИтогоСуммаТоваров + ИтогоСуммаУслуг;
ОбщийНДС = ИтогоНДСТоваров + ИтогоНДСУслуг;
ВсегоСНДС = ОбщаяСуммаБезНДС + ОбщийНДС;
ОбластьПодвалТаблицы.Параметры.ВсегоСНДС = ВсегоСНДС;
ОбластьПодвалТаблицы.Параметры.ОбщаяСуммаБезНДС = ОбщаяСуммаБезНДС;
ОбластьПодвалТаблицы.Параметры.ОбщийНДС = ОбщийНДС;
ТабДок.Вывести(ОбластьПодвалТаблицы);
// Выводим общий подвал (например, для подписей)
ТабДок.Вывести(ОбластьПодвал);
КонецЦикла;
КонецПроцедуры
Важные моменты:
ТабДок.Очистить()
Переменные итогов: Переменные
ИтогоСуммаУслуг
ИтогоНДСУслуг
ИтогоСуммаТоваров
ИтогоНДСТоваров
Параметры макета: Еще раз подчеркнем, что имена параметров, используемые в коде (например,
СуммаИтогоТоваров
ТабДок.НачатьАвтогруппировкуСтрок
ТабДок.ЗакончитьАвтогруппировкуСтрок
НачатьГруппуСтрок
НачатьАвтогруппировкуСтрок
Таким образом, комбинируя правильную логику накопления данных в коде и корректную настройку макета, вы сможете эффективно выводить итоговые значения в ваших внешних печатных формах 1С.