При разработке документов в системе 1С:Предприятие 8.3 на управляемых формах начинающие программисты часто сталкиваются с ситуацией, когда стандартные подходы, работающие для табличных частей, не приносят результата в работе с реквизитами шапки. В этой статье мы подробно разберем, как правильно реализовать автоматический расчет суммы при изменении цены или количества, если эти поля находятся непосредственно в основном теле документа (шапке), а не в таблице.
Рассмотрим ситуацию: вы создали обработчик события ПриИзменении для поля Цена и написали внутри простой код: Сумма = Цена * Количество;. При выполнении этого кода система выдаст ошибку «Переменная не определена». Выясним причину этого поведения платформы.
В управляемом интерфейсе 1С форма и данные объекта разделены. Когда мы работаем в модуле формы, все реквизиты документа (такие как Цена, Количество, Сумма) не являются локальными переменными модуля. Они входят в состав основного реквизита формы, который по умолчанию называется Объект (имеет тип ДанныеФормыСтруктура). Поэтому для доступа к любому реквизиту документа необходимо использовать обращение через точку.
Для того чтобы система поняла, какие именно данные мы хотим перемножить, нам нужно явно указать на принадлежность этих полей объекту. Разберем правильный синтаксис в обработчике события:
&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
Объект.Сумма = Объект.Цена * Объект.Количество;
КонецПроцедуры
Аналогичную процедуру необходимо создать и для реквизита Количество. Однако, писать один и тот же код в двух разных местах — плохая практика программирования. Давайте оптимизируем наш подход.
Проанализируем ситуацию: логика расчета суммы всегда одинакова, независимо от того, изменил ли пользователь количество или цену. Профессиональным подходом считается вынесение этого алгоритма в отдельную служебную процедуру модуля формы.
Рассмотрим, как это реализовать по шагам:
РассчитатьСуммуНаФорме().
&НаКлиенте
Процедура РассчитатьСуммуНаФорме()
// Используем округление до 2 знаков для финансовых расчетов
Объект.Сумма = Окр(Объект.Цена * Объект.Количество, 2);
КонецПроцедуры
&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
РассчитатьСуммуНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
РассчитатьСуммуНаФорме();
КонецПроцедуры
Обратите внимание на использование функции Окр(). В финансовых документах крайне важно избегать появления «лишних» знаков после запятой, которые могут возникнуть из-за особенностей хранения чисел с плавающей точкой.
Иногда пользователю удобнее ввести общую итоговую сумму, чтобы система сама рассчитала цену за единицу товара (при условии, что количество уже заполнено). Это делает интерфейс более гибким и дружелюбным. Посмотрим на пример кода для события СуммаПриИзменении:
&НаКлиенте
Процедура СуммаПриИзменении(Элемент)
Если Объект.Количество <> 0 Тогда
Объект.Цена = Объект.Сумма / Объект.Количество;
Иначе
// Если количество не заполнено, расчет цены невозможен
// Можно либо обнулить цену, либо вывести предупреждение
Объект.Цена = 0;
КонецЕсли;
КонецПроцедуры
Важный момент: при делении всегда добавляйте проверку на ноль. Если пользователь очистит поле Количество и попытается изменить сумму, программа выдаст критическую ошибку деления на ноль, если такой проверки не будет.
Если ваша задача подразумевает учет налогов, логика расчета немного усложняется. Обычно в шапку добавляются реквизиты СтавкаНДС и СуммаНДС. Разберем, как расширить нашу процедуру расчета, чтобы она учитывала налоги.
Предположим, у нас есть функция, которая возвращает числовое значение ставки (например, 20). Тогда расчет будет выглядеть следующим образом:
&НаКлиенте
Процедура РассчитатьВсеПоказатели()
// Сначала считаем основную сумму
Объект.Сумма = Окр(Объект.Цена * Объект.Количество, 2);
// Затем выделяем или начисляем НДС (зависит от логики документа "в т.ч." или "сверху")
// В данном примере считаем НДС "сверху"
ЧисловаяСтавка = 20; // Обычно берется из реквизита СтавкаНДС
Объект.СуммаНДС = Окр(Объект.Сумма * ЧисловаяСтавка / 100, 2);
КонецПроцедуры
Чтобы обеспечить целостность данных и удобство работы, рекомендуем обратить внимание на следующие настройки свойств элементов в конфигураторе:
ТолькоПросмотр для элемента формы Сумма в значение Истина.Цена и Количество полезно включить проверку заполнения, чтобы система подсказывала пользователю о необходимости ввода данных.Подводя итог, можно сказать, что работа с реквизитами шапки в 1С требует понимания контекста выполнения кода. Всегда обращайтесь к данным через Объект, используйте округление и не забывайте про проверки на нулевые значения при выполнении арифметических операций.