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