Как организовать несохраняемые расчетные колонки в табличной части управляемой формы

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

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

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

Выясним причину сброса данных при записи

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

  1. В момент записи на сервере данные управляемой формы преобразуются в прикладной объект информационной базы через механизм, аналогичный вызову РеквизитФормыВЗначение.
  2. Реквизиты, добавленные исключительно в коллекцию формы Объект.НашаТабличнаяЧасть и отсутствующие в метаданных документа конфигурации, не переносятся в объект базы данных.
  3. После успешной записи платформа выполняет обратную синхронизацию: заново считывает записанный объект из базы и инициализирует коллекцию строк формы.
  4. В результате такой повторной инициализации все колонки, не привязанные к метаданным табличной части, сбрасываются в значения по умолчанию (числа становятся нулями, строки — пустыми).

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

События формы для инициализации и обновления расчетных колонок

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

  1. ПриЧтенииНаСервере — вызывается при открытии уже сохраненного документа, а также при принудительном перечитывании данных. Здесь выполняется первичный расчет вспомогательных колонок по существующим строкам.
  2. ПриСозданииНаСервере — требуется использовать, если документ создается копированием или вводится на основании другого объекта, когда строки в табличной части уже присутствуют до первой интерактивной записи.
  3. ПослеЗаписиНаСервере — ключевой обработчик, срабатывающий сразу после того, как форма заново перечитала объект из базы. Именно здесь нужно повторно вызвать процедуру расчета, чтобы восстановить сброшенные значения.
  4. ПриИзменении (события элементов формы) — если пользователь меняет ключевые поля (например, номенклатуру или количество), пересчет зависимых колонок для текущей строки выполняется интерактивно на клиенте через свойство Элементы.НашаТабличнаяЧасть.ТекущиеДанные или с серверным вызовом.

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


&НаСервере
Процедура ЗаполнитьРасчетныеДанныеТабличнойЧасти()
    
    // Получаем массив ключевых ссылок для пакетного запроса
    МассивНоменклатуры = Объект.Товары.Выгрузить().ВыгрузитьКолонку("Номенклатура");
    
    // Выполняем запрос к виртуальным таблицам остатков
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Остатки.Номенклатура КАК Номенклатура,
        |	Остатки.ВНаличииОстаток КАК Остаток
        |ИЗ
        |	РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура В (&МассивНоменклатуры)) КАК Остатки";
    Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
    
    ТаблицаОстатков = Запрос.Выполнить().Выгрузить();
    ТаблицаОстатков.Индексы.Добавить("Номенклатура");
    
    // Заполняем несохраняемые колонки на форме
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        СтрокаОстатка = ТаблицаОстатков.Найти(СтрокаТЧ.Номенклатура, "Номенклатура");
        Если СтрокаОстатка <> Неопределено Тогда
            СтрокаТЧ.ОстатокНаСкладе = СтрокаОстатка.Остаток;
        Иначе
            СтрокаТЧ.ОстатокНаСкладе = 0;
        КонецЕсли;
        
        СтрокаТЧ.Отклонение = СтрокаТЧ.Количество - СтрокаТЧ.ОстатокНаСкладе;
    КонецЦикла;

КонецПроцедуры

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    ЗаполнитьРасчетныеДанныеТабличнойЧасти();
КонецПроцедуры

&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    ЗаполнитьРасчетныеДанныеТабличнойЧасти();
КонецПроцедуры

Способы организации структуры данных на форме

Существует два основных архитектурных подхода к проектированию таких интерфейсов:

  1. Добавление колонок в коллекцию формы Объект.<ИмяТЧ>:

    В редакторе формы в ветке реквизита Объект внутри нужной табличной части создаются дополнительные реквизиты. Данные остаются связанными со строками коллекции ДанныеФормыКоллекция. Это наиболее простой способ, требующий лишь вызова процедур пересчета в событиях ПриЧтенииНаСервере и ПослеЗаписиНаСервере.

  2. Использование отдельной таблицы значений формы:

    На форме создается независимый реквизит с типом ТаблицаЗначений, включающий в себя как сохраняемые поля, так и расчетные. Пользователь работает исключительно с этой таблицей. При открытии выполняется загрузка из Объект.<ИмяТЧ> с расчетом колонок, а в обработчике ПередЗаписьюНаСервере данные сохраняемых колонок программно переносятся обратно в реквизит Объект.

Оптимизация производительности и рекомендации

Рассмотрим важные правила оптимизации, которые предотвратят замедление работы формы:

  1. Пакетная выборка данных: Никогда не выполняйте запросы к базе данных в цикле по строкам табличной части. Всегда выгружайте список ссылок и получайте остатки или цены одним запросом.
  2. Использование идентификаторов строк: При сопоставлении строк коллекции формы с результатами запросов используйте методы ПолучитьИдентификаторы() и НайтиПоИдентификатору(), так как пользовательские сортировки таблицы могут менять физические индексы строк.
  3. Информационные панели как альтернатива: Если табличная часть содержит большое количество колонок, динамические справочные показатели часто удобнее выносить не в саму таблицу, а в отдельную информационную панель формы (декорации или надписи), обновляемую в событии ПриАктивизацииСтроки.
← На главную