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

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

В практике разработки на платформе «1С:Предприятие 8.3» часто возникает задача: добавить в табличную часть документа или обработки колонку, которая нужна только для визуального отображения или оперативных расчетов. Такие данные не должны попадать в базу данных (БД), поэтому разработчик создает реквизит формы внутри коллекции табличной части, а не реквизит самого объекта.

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

Анализируем причину исчезновения данных

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

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

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

Важный момент: при вызове метода ЗначениеВРеквизитФормы платформа полностью перезаписывает структуру данных на форме данными из объекта. Поскольку в объекте (в метаданных документа) вашего «виртуального» реквизита не существует, платформа просто не знает, чем его заполнить, и устанавливает значение по умолчанию (пустое значение). Рассмотрим подробнее способы решения этой задачи.

Способ 1: Работа напрямую с коллекцией формы (ДанныеФормыКоллекция)

Самый надежный способ избежать потери данных — отказаться от преобразования в объект, если логика заполнения это позволяет. Когда мы работаем с Объект.ИмяТабличнойЧасти непосредственно на сервере в контексте формы, мы работаем с ДанныеФормыКоллекция. В этом случае программно добавленные реквизиты формы доступны нам «наравне» с обычными реквизитами.

Рассмотрим пример кода, который очищает таблицу и заполняет её заново, сохраняя значения в реквизите формы:


&НаСервере
Процедура ПерезаполнитьТабличнуюЧастьНаСервере()
    
    // Очищаем табличную часть напрямую в реквизите формы
    Объект.Товары.Очистить();
    
    // Допустим, мы получаем данные из запроса
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Номенклатура, Количество ИЗ Справочник.Номенклатура";
    РезультатЗапроса = Запрос.Выполнить().Выбрать();
    
    Пока РезультатЗапроса.Следующий() Цикл
        НоваяСтрока = Объект.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, РезультатЗапроса);
        
        // РеквизитФормы_Статус - это колонка, которой нет в БД
        // Она доступна напрямую, так как мы не выходили из контекста ДанныеФормы
        НоваяСтрока.РеквизитФормы_Статус = "Обновлено: " + ТекущаяДата();
    КонецЦикла;

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

В данном примере мы не используем РеквизитФормыВЗначение, поэтому платформа не затирает структуру формы данными из метаданных. Это самый чистый и эффективный путь.

Способ 2: Использование идентичных колонок в Таблице Значений

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

Посмотрим на пример ситуации, когда данные могут потеряться:


// ОШИБОЧНЫЙ ВАРИАНТ
ТЗ = Объект.Товары.Выгрузить(); // Выгрузятся только колонки из БД
// ... какая-то обработка ТЗ ...
Объект.Товары.Загрузить(ТЗ); // Колонка реквизита формы очистится

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


&НаСервере
Процедура ЗагрузитьДанныеИзТЗ()
    
    // Создаем таблицу значений
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Номенклатура");
    ТЗ.Колонки.Добавить("Количество");
    
    // КРИТИЧЕСКИ ВАЖНО: Добавляем колонку, имя которой совпадает 
    // с именем реквизита формы в табличной части
    ТЗ.Колонки.Добавить("РеквизитФормы_Статус");
    
    // Заполняем ТЗ данными
    НоваяСтрокаТЗ = ТЗ.Добавить();
    НоваяСтрокаТЗ.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
    НоваяСтрокаТЗ.Количество = 10;
    НоваяСтрокаТЗ.РеквизитФормы_Статус = "Данные из ТЗ";
    
    // Теперь метод Загрузить увидит совпадение имен и заполнит реквизит формы
    Объект.Товары.Загрузить(ТЗ);

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

Способ 3: Повторное заполнение после синхронизации с объектом

Иногда использование РеквизитФормыВЗначение неизбежно (например, если логика заполнения ТЧ зашита в модуле объекта документа). В этом случае нам придется выполнить «двойную работу». Проанализируем ситуацию: сначала мы преобразуем форму в объект, теряя «виртуальные» данные, выполняем логику, возвращаем данные на форму, а затем отдельным циклом или запросом восстанавливаем значения в колонке формы.

Рассмотрим пример такой реализации:


&НаСервере
Процедура ВыполнитьЛогикуМодуляОбъекта()
    
    // 1. Конвертируем форму в объект для доступа к методам модуля объекта
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // 2. Вызываем процедуру из модуля объекта, которая перезаполняет ТЧ
    ДокОбъект.ЗаполнитьПоОстаткам(); 
    
    // 3. Возвращаем данные на форму (в этот момент колонка-реквизит формы пустеет)
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
    
    // 4. Восстанавливаем данные в реквизите формы
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        // Здесь может быть сложный расчет или поиск данных
        СтрокаТЧ.РеквизитФормы_Статус = ПолучитьСтатусНаСервере(СтрокаТЧ.Номенклатура);
    КонецЦикла;

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

Рекомендации по оптимизации

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

  1. Проверяйте контекст: Если вы используете &НаСервереБезКонтекста, вы не сможете напрямую обратиться к Объект.Товары. Вам придется передавать коллекцию как параметр и возвращать её обратно, что усложняет сохранение виртуальных колонок. Старайтесь использовать &НаСервере для таких задач.
  2. Используйте Условное оформление: Если ваша задача — просто выводить текст (например, «В наличии» или «Нет на складе»), рассмотрите возможность использования Условного оформления формы. В поле «Текст» можно подставить значение, которое не требует физического наличия данных в строке, а вычисляется платформой динамически.
  3. Типизация: Убедитесь, что тип данных реквизита формы соответствует типу данных, который вы пытаетесь в него записать. Если в ТЗ колонка имеет тип Строка, а на форме реквизит типа Число, метод Загрузить() выдаст пустые значения без ошибок.

Таким образом, мы выяснили, что основной проблемой является механизм полной перезаписи данных формы при синхронизации с объектом. Используя прямое обращение к ДанныеФормыКоллекция или синхронизацию имен колонок в Таблице Значений, вы сможете добиться корректного отображения любых данных в интерфейсе ваших решений.

← На главную