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

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

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

Анализ структуры цен и учет упаковок в запросе

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

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


ВЫБОР
    КОГДА НЕ ЦеныНоменклатуры.Упаковка.Коэффициент ЕСТЬ NULL
        И ЦеныНоменклатуры.Упаковка.Коэффициент <> 0
    ТОГДА ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) / ЦеныНоменклатуры.Упаковка.Коэффициент
    ИНАЧЕ ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0)
КОНЕЦ КАК Цена

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

Добавление расчета суммы строки в запрос

Выясним причину, почему простое умножение цены на количество может не сработать. Если в запросе соединение с регистром цен левое, а цена не найдена, поле цены будет содержать NULL. Умножение любого числа на NULL в языке запросов 1С возвращает NULL. Чтобы сумма строки рассчитывалась корректно для всех позиций, необходимо применять расчет с учетом обработанной цены.

Посмотрим на пример правильного формирования поля Сумма непосредственно в секции ВЫБРАТЬ:


(ВЫБОР
    КОГДА НЕ ЦеныНоменклатуры.Упаковка.Коэффициент ЕСТЬ NULL
        И ЦеныНоменклатуры.Упаковка.Коэффициент <> 0
    ТОГДА ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) / ЦеныНоменклатуры.Упаковка.Коэффициент
    ИНАЧЕ ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0)
КОНЕЦ) * СписаниеНедостачТоваровТовары.Количество КАК Сумма

Если в коде печатной формы уже предусмотрен отдельный пересчет по курсу валюты документа через переменную КурсВалюты, расчет суммы можно выполнять как в запросе, так и при обходе выборки строк в цикле.

Подсчет итоговой суммы по документу

Разберем два основных подхода к вычислению общей суммы списания: на уровне запроса и программно в цикле вывода строк.

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

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


ВсегоНаименований = 0;
ИтогоСумма = 0;

ВыборкаПоСтрокам = РезультатыПоТоварам[0].Выбрать();
Пока ВыборкаПоСтрокам.Следующий() Цикл
    
    // Вывод строки номенклатуры
    ОбластьТоварСтрока.Параметры.Заполнить(ВыборкаПоСтрокам);
    
    ЦенаНеЗадана = НЕ ЗначениеЗаполнено(ВыборкаПоСтрокам.Цена);
    ТекущаяЦена = ?(ЦенаНеЗадана, 0, ВыборкаПоСтрокам.Цена * КурсВалюты);
    ТекущаяСумма = Окр(ТекущаяЦена * ВыборкаПоСтрокам.Количество, 2);
    
    ОбластьТоварСтрока.Параметры.Цена = ТекущаяЦена;
    ОбластьТоварСтрока.Параметры.Сумма = ТекущаяСумма;
    
    ТабДокумент.Присоединить(ОбластьТоварСтрока);
    
    // Накопление итогов
    ВсегоНаименований = ВсегоНаименований + 1;
    ИтогоСумма = ИтогоСумма + ТекущаяСумма;
    
КонецЦикла;

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

Способ 2. Использование секции ИТОГИ в запросе

Если расчет суммы выполняется полностью на стороне СУБД, добавим в конец запроса секцию итогов:


ИТОГИ
    СУММА(Количество),
    СУММА(Сумма)
ПО
    ОБЩИЕ

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

Оформление макета табличного документа

Чтобы рассчитанные значения появились на печатной форме, проверим и настроим макет:

  1. В области строки таблицы (например, Строка|Товар или Строка|Данные) добавим колонки «Цена» и «Сумма».
  2. В свойствах добавленных ячеек установим тип заполнения Параметр и укажем имена Цена и Сумма. В свойствах формата ячеек зададим формат числовых значений: ЧДЦ=2; ЧГ=3,0.
  3. В области подвала таблицы добавим ячейку с параметром ИтогоСумма для вывода общего стоимостного итога.
  4. Если требуется вывести сумму прописью, в подвале документа сформируем строку с помощью встроенной функции ЧислоПрописью(ИтогоСумма, "L=ru_RU", "рубль, рубля, рублей, м, копейка, копейки, копеек, ж, 2").

Оптимизация: устранение запроса в цикле

Обратим внимание на важную деталь архитектуры: выполнение запроса цен внутри цикла Пока ВыборкаПоДокументам.Следующий() Цикл является антипаттерном («запрос в цикле»). При массовой печати актов списания это приводит к существенному падению производительности.

Правильным решением является объединение выборки данных документа и среза последних цен в единый пакетный запрос по всему массиву переданных документов &МассивОбъектов. Для этого условие среза последних соединяется с временной таблицей товаров документа по полям Номенклатура, Характеристика и ВидЦены, после чего результат обрабатывается за один проход.

← На главную