Как работать с колонками табличной части, не связанными с реквизитами объекта, чтобы данные не исчезали при записи?

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

В процессе разработки на платформе 1С:Предприятие 8.3 (Управляемые формы) часто возникает задача отображения в табличной части данных, которые не хранятся в базе данных, а рассчитываются динамически. Это могут быть сложные математические вычисления, текстовые примечания или статусы, зависящие от нескольких условий. Однако начинающие разработчики часто сталкиваются с тем, что такие "виртуальные" колонки очищаются при нажатии кнопок Записать или Провести. В этой статье мы подробно разберем, почему это происходит и как правильно организовать жизненный цикл данных в таких колонках.

Почему очищается колонка, не связанная с реквизитом?

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

Когда вы нажимаете "Записать", данные формы передаются на сервер, преобразуются в объект, записываются в базу данных, а затем объект снова считывается в данные формы для обновления интерфейса. Поскольку в объекте метаданных вашей расчетной колонки нет, платформа "не знает", что в ней нужно что-то сохранять, и после перечитывания данных из базы колонка оказывается пустой. Чтобы этого избежать, нам нужно принудительно заполнять её на определенных этапах работы формы.

Основное решение: Использование серверных обработчиков

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

1. Событие ПриЧтенииНаСервере

Это событие идеально подходит для первичного заполнения расчетных данных. Оно срабатывает при открытии существующего объекта и при выполнении команды "Перечитать". В отличие от ПриСозданииНаСервере, этот обработчик гарантирует, что данные объекта уже загружены из базы в форму.

2. Событие ПослеЗаписиНаСервере

Многие разработчики забывают про этот этап. После того как объект успешно записан в базу, форма обновляет свои данные. Если не прописать расчет здесь, пользователь увидит пустые ячейки сразу после нажатия кнопки "Записать".

Разберем пример кода, который решает задачу заполнения колонки КолонкаВсего (сумма + НДС):


&НаСервере
Процедура ЗаполнитьРасчетныеКолонки()
    
    // Проанализируем каждую строку табличной части
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        // Производим расчет и записываем в колонку, не связанную с реквизитом
        СтрокаТЧ.КолонкаВсего = СтрокаТЧ.Сумма + СтрокаТЧ.СуммаНДС;
    КонецЦикла;
    
КонецПроцедуры

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

&НаСервере
Процедура ПослеЗаписиНаСервере(ПараметрыЗаписи)
    // Обновляем данные после фиксации в БД
    ЗаполнитьРасчетныеКолонки();
КонецПроцедуры

Важное замечание: Обязательно проверьте, что процедуры ПриЧтенииНаСервере и ПослеЗаписиНаСервере подключены в палитре свойств формы в качестве обработчиков соответствующих событий. Простого копирования кода в модуль недостаточно — платформа должна "знать", что эти методы нужно вызывать.

Альтернативный метод: Условное оформление формы

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

Этот метод хорош тем, что:

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

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

Обработка изменений в реальном времени

Если пользователь меняет данные в строке (например, количество или цену), расчетная колонка должна обновиться мгновенно, не дожидаясь записи на сервер. Для этого мы должны проанализировать клиентские события элементов формы.

Выясним, как это реализовать. Нам потребуется обработчик события ПриИзменении для тех реквизитов, от которых зависит расчет. Например, для реквизита Сумма:


&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
    
    СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        // Мгновенный пересчет на клиенте
        СтрокаТЧ.КолонкаВсего = СтрокаТЧ.Сумма + СтрокаТЧ.СуммаНДС;
    КонецЕсли;
    
КонецПроцедуры

Проблемы производительности и пути их решения

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

Ограничения вычисляемых колонок

Проанализируем важный нюанс, о котором часто забывают. По колонкам, которые существуют только в памяти формы и не связаны с реквизитами объекта:

  1. Не работает стандартная сортировка платформы.
  2. Не работает стандартный поиск (Ctrl+F).
  3. Нельзя строить отборы через стандартное меню.

Если пользователю критически важно сортировать список товаров по этой расчетной колонке, у вас есть только один путь — сделать её реальным реквизитом объекта и записывать значение в базу данных. В противном случае платформа просто не сможет построить индекс для выполнения быстрых операций сортировки и поиска.

Итоги

Для корректной работы с расчетными полями в ТЧ всегда придерживайтесь следующего алгоритма:

1. Создайте реквизит формы (не объекта!) с нужным типом данных и вынесите его в таблицу на форме.

2. Реализуйте заполнение в ПриЧтенииНаСервере для отображения данных при открытии.

3. Дублируйте заполнение в ПослеЗаписиНаСервере для обновления данных после сохранения.

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

5. Для интерактивности добавьте расчет в клиентские события ПриИзменении соответствующих полей.

← На главную