Как автоматически пересчитывать зависимые колонки в табличной части 1С?

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

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

Почему не срабатывает событие ПриИзменении для вычисляемой колонки

Проанализируем архитектурную особенность платформы «1С:Предприятие». События элементов формы, такие как ПриИзменении, генерируются исключительно при интерактивных действиях пользователя в пользовательском интерфейсе. Когда мы программно присваиваем значение реквизиту строки (например, пишем СтрокаТабличнойЧасти.ВыручкаВсего = ...), платформа принципиально не генерирует событие изменения для поля ВыручкаВсего.

Имитировать или программно инициировать интерактивное событие невозможно. Поэтому попытка «повесить» расчет четвертой колонки на событие изменения третьей колонки, которая сама заполняется из кода, не сработает. Выясним, как грамотно выстроить цепочку вычислений.

Организация каскадного пересчета через единую процедуру

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

  1. Рассчитываем и записываем значение итоговой выручки на основе исходных полей.
  2. Рассчитываем зависимый показатель (начисление) на основе только что полученной итоговой выручки.

Реализуем процедуру пересчета на клиенте:


&НаКлиенте
Процедура РассчитатьСтрокуСмены(СтрокаТабличнойЧасти)
    
    // Шаг 1: Расчет общей выручки
    СтрокаТабличнойЧасти.ВыручкаВсего = СтрокаТабличнойЧасти.ВыручкаНал + СтрокаТабличнойЧасти.ВыручкаБезнал;
    
    // Шаг 2: Расчет начисления в зависимости от полученной суммы
    Если СтрокаТабличнойЧасти.ВыручкаВсего >= 7000 Тогда
        СтрокаТабличнойЧасти.НачисленоПоВыручке = СтрокаТабличнойЧасти.ВыручкаВсего * 0.5;
    Иначе
        СтрокаТабличнойЧасти.НачисленоПоВыручке = СтрокаТабличнойЧасти.ВыручкаВсего * 0.4;
    КонецЕсли;
    
КонецПроцедуры

Подключение процедуры к элементам формы

Теперь разберем, как вызывать процедуру пересчета без дублирования исходного кода. Платформа 1С позволяет назначить один и тот же обработчик события для разных элементов управления. В палитре свойств для колонок ТабличнаяЧастьСменаВодителейВыручкаНал и ТабличнаяЧастьСменаВодителейВыручкаБезнал укажем единое имя обработчика в событии ПриИзменении — например, КолонкаВыручкиПриИзменении.

В коде модуля формы напишем единый обработчик:


&НаКлиенте
Процедура КолонкаВыручкиПриИзменении(Элемент)
    
    СтрокаТабличнойЧасти = Элементы.ТабличнаяЧастьСменаВодителей.ТекущиеДанные;
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    РассчитатьСтрокуСмены(СтрокаТабличнойЧасти);
    
КонецПроцедуры

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

Особенности события таблицы ПриОкончанииРедактирования

Иногда для пересчетов пытаются использовать событие таблицы формы ПриОкончанииРедактирования. Рассмотрим особенности и ограничения этого подхода:

  1. Данное событие принадлежит самому элементу управления «Таблица формы», а не ее колонкам или полям ввода.
  2. Оно срабатывает только в тот момент, когда пользователь полностью покидает режим редактирования всей строки (например, нажимает клавишу Enter или переходит курсором на другую строку). При обычном переходе между колонками внутри строки событие не вызывается. Из-за этого пользователь не видит моментального пересчета сумм, что снижает комфорт работы в интерфейсе.
  3. При использовании данного обработчика критически важно проверять параметр ОтменаРедактирования. Если пользователь отменил ввод клавишей Esc, выполнять расчет нельзя:

&НаКлиенте
Процедура ТабличнаяЧастьСменаВодителейПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
    
    Если ОтменаРедактирования Тогда
        Возврат;
    КонецЕсли;
    
    СтрокаТабличнойЧасти = Элемент.ТекущиеДанные;
    Если СтрокаТабличнойЧасти <> Неопределено Тогда
        РассчитатьСтрокуСмены(СтрокаТабличнойЧасти);
    КонецЕсли;
    
КонецПроцедуры

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

Защита вычисляемых колонок от ручного изменения

Чтобы целостность расчетов не нарушалась, колонки ВыручкаВсего и НачисленоПоВыручке следует защитить от случайного редактирования пользователем. Для соответствующих элементов формы в дереве элементов рекомендуется установить свойство ТолькоПросмотр в значение Истина либо отключить флажок Доступность. Это гарантирует, что итоговые суммы всегда будут строго соответствовать введенным слагаемым.

← На главную