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

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке внешних обработок заполнения табличных частей в обычных формах (толстый клиент) разработчики часто сталкиваются с ситуацией, когда строки табличной части заполняются корректно, однако расчетные поля на форме документа (например, остатки, расхождения, итоги) остаются пустыми или не пересчитываются. Разберем, почему возникает эта проблема и как правильно организовать алгоритм работы.

Анализируем причину проблемы: разделение контекста объекта и формы

Рассмотрим типовой сценарий: создается внешняя обработка заполнения табличной части документа «Акт сверки взаиморасчетов» для конфигурации «Бухгалтерия предприятия 2.0». В модуль объекта обработки помещается процедура Инициализировать, в которую платформа передает ссылку на объект документа:


Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПоле) Экспорт
    // Заполнение реквизитов и табличной части
    ЗаполнитьПоДаннымБухгалтерскогоУчета(ФильтрСписокСчетов);
    ПересчитатьОстатки(Объект);
КонецПроцедуры

Если внутри процедуры попытаться обратиться к элементам формы через вызов Объект.ПолучитьФорму(), то изменение свойств элементов не принесет результата:


Процедура ПересчитатьОстатки(Объект)
    ФормаДок = Объект.ПолучитьФорму();
    ЭлементыФормы = ФормаДок.ЭлементыФормы;
    // Данная строка изменит элемент только во вновь созданной копии формы,
    // но не в открытой форме пользователя:
    ЭлементыФормы.ОстатокНаКонец.Значение = ОстатокНаКонец;
КонецПроцедуры

Выясним причину такого поведения платформы 1С:

  1. Создание нового экземпляра формы: Метод ПолучитьФорму() создает в оперативной памяти новый экземпляр формы документа. Все изменения свойств через ЭлементыФормы применяются к этому новому экземпляру, в то время как пользователь продолжает видеть исходную форму, где данные остались прежними.
  2. Отсутствие реквизитов в метаданных: В документе «Акт сверки взаиморасчетов» поля «Остаток на конец», «Остаток на начало (контрагент)» и «Расхождение» зачастую не являются реквизитами самого документа (не сохраняются в базе данных), а рассчитываются динамически и отображаются исключительно в элементах диалога открытой формы.
  3. Отсутствие вызова событий формы: При программном изменении строк табличной части из внешней обработки стандартные события формы (например, ПриИзменении) не вызываются автоматически, следовательно, встроенный в форму расчет итогов не срабатывает.

Способ 1. Заполнение реальных реквизитов документа

Если изменяемые данные связаны с реквизитами самого объекта документа, то обращаться к элементам формы не требуется. Достаточно напрямую присваивать значения реквизитам переданного объекта:


Объект.ОстатокНаНачало = РассчитанныйОстаток;
Объект.Расхождение = РасчетноеРасхождение;

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

Способ 2. Создание автономной внешней обработки вместо механизма заполнения ТЧ

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

  1. Создаем внешнюю обработку со своей экранной формой.
  2. Размещаем на форме реквизит ДокументСсылка (или реквизиты параметров сверки: организация, контрагент, период).
  3. Программно формируем движения и создаем новый документ либо считываем существующий:
    
    НовыйАкт = Документы.АктСверкиВзаиморасчетов.СоздатьДокумент();
    НовыйАкт.Организация = Организация;
    НовыйАкт.Контрагент = Контрагент;
    НовыйАкт.ДатаНачала = ДатаНачала;
    НовыйАкт.ДатаОкончания = ДатаОкончания;
    
    // Заполняем строки табличной части
    // ...
    
    // Записываем документ в базу данных
    НовыйАкт.Записать();
    
    // Открываем форму созданного документа
    ФормаДокумента = НовыйАкт.ПолучитьФорму("ФормаДокумента");
    ФормаДокумента.Открыть();
    
  4. При открытии формы документа штатные обработчики инициализации формы автоматически рассчитают все зависимые итоги и выведут их в поля ввода.

Способ 3. Пересчет итогов через интерактивное обновление данных

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

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

Особенности реализации на управляемых формах (БСП)

Если в дальнейшем планируется перенос логики на управляемые формы или конфигурации с Библиотекой стандартных подсистем (БСП), механизм взаимодействия с формой строится иначе. Команды заполнения выполняются в контексте формы через передачу структуры ЭтаФорма, что позволяет преобразовывать данные формы в прикладной объект и обратно с сохранением контекста открытого окна:


&НаСервере
Процедура ЗаполнитьДокументНаСервере(ДанныеФормы)
    ДокОбъект = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.АктСверкиВзаиморасчетов"));
    // Выполняем алгоритм заполнения объекта
    // ...
    ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);
КонецПроцедуры

Таким образом, для обычных форм основным правилом остается разграничение логики: внешняя обработка заполнения оперирует исключительно данными переданного объекта (реквизитами и строками табличных частей), а расчет визуальных итогов формы возлагается на штатные механизмы открытия или интерактивного пересчета документа.

← На главную