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