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