Как сложить суммы двух табличных частей в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке документов часто возникает задача сложить промежуточные итоги из нескольких табличных частей (например, «Оборудование» и «РаботыУслуги») и вывести общую стоимость на форме или сохранить её в реквизит объекта. Начинающие разработчики нередко сталкиваются с ситуацией, когда код не вызывает синтаксических ошибок, но итоговое значение не рассчитывается.

Разберем причины этой проблемы, проанализируем типичные ошибки и рассмотрим правильные варианты реализации расчета как на управляемой форме, так и при записи объекта.

Почему не работает обращение через коллекцию Элементы?

Выясним причину, по которой конструкция вида ИтогоСтоимость = Элементы.РаботыУслугиИтогСумма + Элементы.ОборудованиеИтогСумма; не дает ожидаемого результата:

  1. Элементы формы — это визуальные объекты, а не данные. Коллекция Элементы содержит элементы управления интерфейса (поля ввода, надписи, группы, таблицы). Попытка сложить два элемента интерфейса либо приводит к сложению ссылок на объекты, либо не выполняет математическую операцию над числами. Для арифметических действий необходимо обращаться к самим данным — реквизитам объекта (Объект.ИмяРеквизита) или реквизитам формы.
  2. События в подвале таблицы не срабатывают интерактивно. Подвалы колонок отображают итоговые данные автоматически. Пользователь не может кликнуть в подвал и изменить значение вручную, поэтому событие ПриИзменении для ячейки подвала не вызывается в процессе работы пользователя.
  3. Использование локальной переменной. Если переменная ИтогоСтоимость не объявлена в реквизитах формы или реквизитах шапки документа, присвоение ей значения внутри процедуры никак не отразится на экране пользователя.

Вариант 1. Динамический расчет на клиенте без вызова сервера

Рассмотрим, как правильно организовать мгновенный пересчет общей суммы на управляемой форме при редактировании пользователем строк любой из табличных частей. В управляемых формах 1С коллекции строк табличных частей (тип ДанныеФормыКоллекция) поддерживают встроенный метод Итог() непосредственно на клиенте. Это позволяет производить расчет без серверных вызовов.

Разберем по шагам создание универсальной процедуры пересчета:

  1. Создадим процедуру пересчета в модуле формы:

&НаКлиенте
Процедура РассчитатьОбщуюСтоимость()
    Объект.ИтогоСтоимость = Объект.Оборудование.Итог("Сумма") + Объект.РаботыУслуги.Итог("Сумма");
КонецПроцедуры
  1. Назначим вызов этой процедуры в событиях формы:

Чтобы итоговая сумма пересчитывалась при любых изменениях (вводе суммы, добавлении или удалении строк), вызовем процедуру РассчитатьОбщуюСтоимость() в следующих обработчиках событий:

  1. В событиях элементов колонок таблиц ОборудованиеСуммаПриИзменении и РаботыУслугиСуммаПриИзменении.
  2. В событиях самих таблиц формы — ПриИзменении (срабатывает при добавлении, копировании, удалении строк) и Очистка.

Посмотрим на пример обработчиков событий колонок:


&НаКлиенте
Процедура ОборудованиеСуммаПриИзменении(Элемент)
    РассчитатьОбщуюСтоимость();
КонецПроцедуры

&НаКлиенте
Процедура РаботыУслугиСуммаПриИзменении(Элемент)
    РассчитатьОбщуюСтоимость();
КонецПроцедуры

&НаКлиенте
Процедура ОборудованиеПриИзменении(Элемент)
    РассчитатьОбщуюСтоимость();
КонецПроцедуры

&НаКлиенте
Процедура РаботыУслугиПриИзменении(Элемент)
    РассчитатьОбщуюСтоимость();
КонецПроцедуры

Вариант 2. Расчет общей суммы в модуле объекта при записи

Если требуется гарантировать корректность суммы перед проведением или сохранением документа в базу данных независимо от формы, расчет следует разместить в модуле объекта.

Нерационально использовать явный перебор всех строк в цикле Для Каждого, так как встроенный метод Итог() работает значительно быстрее и делает код компактным.

Проанализируем пример кода для модуля объекта документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Подсчет суммы по колонкам двух табличных частей встроенным методом Итог
    ИтогоСтоимость = Оборудование.Итог("Сумма") + РаботыУслуги.Итог("Сумма");
    
КонецПроцедуры

Важно: Метод Итог("ИмяКолонки") чувствителен к имени реквизита табличной части. Имя числовой колонки передается в метод в виде строки и должно точно совпадать с именем реквизита в метаданных конфигурации.

← На главную