Почему не меняется итоговая сумма в таблице при удалении строки и как это исправить?

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

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

Анализ причины проблемы: уровни событий формы

Рассмотрим ситуацию, описанную автором темы. Первоначально код пересчета был размещен в обработчике ПриИзменении конкретного элемента (колонки) таблицы. Выглядело это примерно так:


&НаКлиенте
Процедура ПриходИзТорговыхТочекСуммаПриИзменении(Элемент)
    СуммаДокумента = 0;
    Для Каждого Стр Из Объект.ПриходИзТорговыхТочек Цикл
        СуммаДокумента = СуммаДокумента + Стр.Сумма;
    КонецЦикла;
    Объект.СуммаДокумента = СуммаДокумента;
КонецПроцедуры

Проанализируем этот подход. Данное событие привязано к полю ввода внутри строки. Оно срабатывает только тогда, когда пользователь непосредственно меняет значение в ячейке "Сумма". Когда же происходит удаление строки целиком, фокус ввода не меняется в контексте конкретной ячейки, и событие ПриИзменении колонки попросту не вызывается. Выясним, как заставить систему реагировать на изменение состава строк.

Решение 1: Использование событий самой таблицы

Для того чтобы сумма пересчитывалась при любых манипуляциях с табличной частью (добавление, удаление, копирование строк), необходимо использовать обработчики событий не отдельной колонки, а всего элемента формы Таблица.

Рассмотрим ключевые события:

  1. ПриИзменении: Этот обработчик элемента формы (таблицы) вызывается при добавлении новой строки, окончании редактирования строки или ее копировании.
  2. ПослеУдаления: Это критически важное событие, которое срабатывает сразу после того, как строка была удалена из коллекции. Именно его чаще всего забывают реализовать новички.

Посмотрим на пример правильной реализации в модуле формы:


&НаКлиенте
Процедура ПриходИзТорговыхТочекПриИзменении(Элемент)
    ПересчитатьСуммуДокумента();
КонецПроцедуры

&НаКлиенте
Процедура ПриходИзТорговыхТочекПослеУдаления(Элемент)
    ПересчитатьСуммуДокумента();
КонецПроцедуры

&НаКлиенте
Процедура ПересчитатьСуммуДокумента()
    // Используем метод Итог() для быстрого расчета по всей колонке
    Объект.СуммаДокумента = Объект.ПриходИзТорговыхТочек.Итог("Сумма");
КонецПроцедуры

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

Решение 2: Пересчет перед записью объекта

Иногда интерактивного пересчета "на лету" на клиенте бывает недостаточно (например, если логика расчета очень сложная или зависит от данных, доступных только на сервере). В этом случае крайне важно продублировать расчет в модуле объекта в процедуре ПередЗаписью. Это гарантирует, что в базу данных всегда попадет верная сумма, даже если программный код формы отработал некорректно или документ был изменен внешней обработкой.

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


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

Важный нюанс: В модуле объекта мы обращаемся к табличной части напрямую (как к свойству объекта), а не через переменную Объект, как это делается в форме.

Решение 3: Автоматические итоги в подвале (без кода)

Если ваша задача состоит только в том, чтобы показать пользователю итоговую сумму внизу таблицы, а хранить её в реквизите СуммаДокумента не обязательно (или эта сумма вычисляемая), в управляемых формах 1С 8.3 есть встроенный механизм:

  1. Откройте свойства элемента формы Таблица.
  2. Установите флаг Подвал (Footer).
  3. Выберите колонку, итог которой нужно отобразить.
  4. В свойстве ПутьКДаннымПодвала выберите значение вида Объект.ИмяТабличнойЧасти.ИтогСумма.

При таком подходе платформа сама будет обновлять итоговое значение в подвале при любых изменениях в таблице без написания единой строки кода на языке 1С. Это наиболее производительный и современный метод визуализации итогов.

Типичные ошибки при реализации

Разберем, почему некоторые попытки автора темы не увенчались успехом:

Подведем итог: Для надежного решения проблемы всегда комбинируйте интерактивный пересчет в событиях таблицы ПриИзменении и ПослеУдаления на форме с финальной проверкой в ПередЗаписью в модуле объекта. Это обеспечит и удобство работы пользователя, и целостность данных в информационной системе.

← На главную