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