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