При разработке интерфейсов в 1С часто возникает задача организации каскадных вычислений в строках табличной части. Классический сценарий: пользователь заполняет сумму наличной и безналичной выручки, система должна сложить их в колонку общей выручки, а затем на основании общей выручки рассчитать начисленное вознаграждение. Разберем, как правильно реализовать такой расчет, почему не срабатывают стандартные события при программном заполнении ячеек и как избежать дублирования кода.
Проанализируем архитектурную особенность платформы «1С:Предприятие». События элементов формы, такие как ПриИзменении, генерируются исключительно при интерактивных действиях пользователя в пользовательском интерфейсе. Когда мы программно присваиваем значение реквизиту строки (например, пишем СтрокаТабличнойЧасти.ВыручкаВсего = ...), платформа принципиально не генерирует событие изменения для поля ВыручкаВсего.
Имитировать или программно инициировать интерактивное событие невозможно. Поэтому попытка «повесить» расчет четвертой колонки на событие изменения третьей колонки, которая сама заполняется из кода, не сработает. Выясним, как грамотно выстроить цепочку вычислений.
Наиболее чистое и надежное архитектурное решение заключается в создании отдельной процедуры пересчета строки. Эта процедура принимает строку таблицы в качестве параметра и выполняет последовательный расчет всех зависимых колонок. Посмотрим на структуру такого алгоритма:
Реализуем процедуру пересчета на клиенте:
&НаКлиенте
Процедура РассчитатьСтрокуСмены(СтрокаТабличнойЧасти)
// Шаг 1: Расчет общей выручки
СтрокаТабличнойЧасти.ВыручкаВсего = СтрокаТабличнойЧасти.ВыручкаНал + СтрокаТабличнойЧасти.ВыручкаБезнал;
// Шаг 2: Расчет начисления в зависимости от полученной суммы
Если СтрокаТабличнойЧасти.ВыручкаВсего >= 7000 Тогда
СтрокаТабличнойЧасти.НачисленоПоВыручке = СтрокаТабличнойЧасти.ВыручкаВсего * 0.5;
Иначе
СтрокаТабличнойЧасти.НачисленоПоВыручке = СтрокаТабличнойЧасти.ВыручкаВсего * 0.4;
КонецЕсли;
КонецПроцедуры
Теперь разберем, как вызывать процедуру пересчета без дублирования исходного кода. Платформа 1С позволяет назначить один и тот же обработчик события для разных элементов управления. В палитре свойств для колонок ТабличнаяЧастьСменаВодителейВыручкаНал и ТабличнаяЧастьСменаВодителейВыручкаБезнал укажем единое имя обработчика в событии ПриИзменении — например, КолонкаВыручкиПриИзменении.
В коде модуля формы напишем единый обработчик:
&НаКлиенте
Процедура КолонкаВыручкиПриИзменении(Элемент)
СтрокаТабличнойЧасти = Элементы.ТабличнаяЧастьСменаВодителей.ТекущиеДанные;
Если СтрокаТабличнойЧасти = Неопределено Тогда
Возврат;
КонецЕсли;
РассчитатьСтрокуСмены(СтрокаТабличнойЧасти);
КонецПроцедуры
Обратим внимание на получение текущей строки. Обращение Элементы.ИмяТаблицы.ТекущиеДанные возвращает объект ДанныеФормыЭлементКоллекции, представляющий активную строку. Передавая этот объект в процедуру РассчитатьСтрокуСмены, мы меняем значения непосредственно в данных формы, и обновленные числа сразу отображаются пользователю.
Иногда для пересчетов пытаются использовать событие таблицы формы ПриОкончанииРедактирования. Рассмотрим особенности и ограничения этого подхода:
ОтменаРедактирования. Если пользователь отменил ввод клавишей Esc, выполнять расчет нельзя:
&НаКлиенте
Процедура ТабличнаяЧастьСменаВодителейПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
Если ОтменаРедактирования Тогда
Возврат;
КонецЕсли;
СтрокаТабличнойЧасти = Элемент.ТекущиеДанные;
Если СтрокаТабличнойЧасти <> Неопределено Тогда
РассчитатьСтрокуСмены(СтрокаТабличнойЧасти);
КонецЕсли;
КонецПроцедуры
В большинстве сценариев обработчик ПриИзменении на исходных ячейках является более предпочтительным, так как обеспечивает мгновенную визуальную обратную связь.
Чтобы целостность расчетов не нарушалась, колонки ВыручкаВсего и НачисленоПоВыручке следует защитить от случайного редактирования пользователем. Для соответствующих элементов формы в дереве элементов рекомендуется установить свойство ТолькоПросмотр в значение Истина либо отключить флажок Доступность. Это гарантирует, что итоговые суммы всегда будут строго соответствовать введенным слагаемым.