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

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

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

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

Рассмотрим типичный пример кода, который часто размещают в модуле управляемой формы:


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

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

  1. Ограничение событий элементов формы: событие ПриИзменении генерируется платформой только при интерактивном вводе пользователем. Если в процедуре ТоварыНоменклатураПриИзменении мы программно присваиваем значение свойству Строка.Цена = ПолученнаяЦена;, событие ТоварыЦенаПриИзменении автоматически платформой не вызывается. Платформа 1С не отслеживает цепочки зависимостей реквизитов самостоятельно.
  2. Отсутствие привязки события: процедура может существовать в модуле формы, но не быть привязанной в палитре свойств к событию ПриИзменении соответствующего элемента формы.
  3. Особенности свойства ТекущиеДанные: свойство Элементы.Товары.ТекущиеДанные возвращает Неопределено, если табличная часть не находится в фокусе, строка создается программно или фокус переключен на другой элемент интерфейса.

Шаг 1. Создание универсальной процедуры пересчета строки

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

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


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

Шаг 2. Подключение пересчета ко всем событиям формы

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

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


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

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

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

&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатуры(СсылкаНоменклатура)
    
    Если Не ЗначениеЗаполнено(СсылкаНоменклатура) Тогда
        Возврат 0;
    КонецЕсли;
    
    // Считываем цену из реквизита справочника или регистра сведений
    Возврат СсылкаНоменклатура.Цена;
    
КонецФункции

Шаг 3. Обработка ручного изменения суммы пользователем

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


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

Рекомендации по надежной работе с табличными частями

  1. Проверяйте привязку событий в конфигураторе: всегда открывайте свойства элемента формы (например, поля ввода ТоварыНоменклатура) и убеждайтесь, что в строке события ПриИзменении указано имя созданной процедуры.
  2. Используйте серверные вызовы без контекста: получение цен и других справочных данных следует выносить в функции с директивой &НаСервереБезКонтекста. Это минимизирует объем передаваемых между клиентом и сервером данных и ускоряет работу формы.
  3. Учитывайте множественный подбор: если в документе реализован подбор номенклатуры из отдельной формы через событие ОбработкаВыбора, вызов процедуры РассчитатьСуммуСтроки необходимо выполнять в цикле по всем переданным позициям непосредственно после их добавления в табличную часть.
← На главную