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