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