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