Как программно добавить новую колонку в табличную часть на управляемой форме 1С?

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

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

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

Почему возникает ошибка "Недопустимое значение"?

Давайте проанализируем первоначальный код, который приводит к ошибке:


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

Ошибка при установке свойства ПутьКДанным возникает потому, что мы пытаемся связать визуальный элемент (колонку) с данными, которых не существует в структуре объекта. Путь "Объект.ТЧГлавная.Вес" означает, что платформа должна найти в табличной части ТЧГлавная документа (или другого объекта) реквизит с именем Вес. Но мы не добавляли его в конфигураторе.

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

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

Решение: правильный алгоритм из двух шагов

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

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

Рассмотрим каждый шаг подробно на примере.

Шаг 1. Программное создание реквизита формы

Для добавления новых реквизитов на лету используется метод формы ИзменитьРеквизиты(). Ему нужно передать массив с описаниями добавляемых реквизитов. Каждый такой реквизит создается с помощью конструктора Новый РеквизитФормы(). Весь этот код следует размещать в серверном обработчике события, например, ПриСозданииНаСервере.

Посмотрим на пример кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

После выполнения этого кода в коллекции реквизитов формы появился новый реквизит. Теперь путь "Объект.ТЧГлавная.Вес" стал для формы корректным, и мы можем переходить к созданию визуальной колонки.

Шаг 2. Создание элемента формы (колонки) и его привязка

Теперь, когда "хранилище" для данных готово, создадим саму колонку и укажем ей правильный путь к данным. Этот код можно разместить в той же процедуре ПриСозданииНаСервере после кода из Шага 1.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // ... код с Шага 1 для создания реквизита формы ...

    // Получаем таблицу на форме, в которую будем добавлять колонку
    ТаблицаНаФорме = Элементы.ТЧГлавная;
    
    // Добавляем новый элемент формы типа "ПолеФормы" внутрь таблицы
    НоваяКолонка = Элементы.Добавить("ТЧГлавнаяВес", Тип("ПолеФормы"), ТаблицаНаФорме);
    НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
    
    // Устанавливаем путь к данным. Теперь этот путь корректен!
    // Он указывает на реквизит формы, который мы создали ранее.
    НоваяКолонка.ПутьКДанным = "Объект.ТЧГлавная.Вес";
    
    // Можно также настроить заголовок, если он отличается от заголовка реквизита
    // НоваяКолонка.Заголовок = "Вес товара";
    
КонецПроцедуры

После выполнения этих двух шагов форма откроется с новой колонкой "Вес, кг", в которую можно будет вводить данные. Ошибки больше не будет.

Шаг 3. Заполнение данными программно созданной колонки

Возникает следующий логичный вопрос: как теперь программно заполнить эту колонку данными? Например, при загрузке из Excel. Обращение к такому динамически добавленному реквизиту имеет особенность.

Прямое обращение через точку (НоваяСтрока.Вес = 15.5) может не сработать или работать нестабильно. Надежный и рекомендуемый способ — обращение через квадратные скобки, как к элементу коллекции по имени.

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


&НаКлиенте
Процедура ЗаполнитьДанные()
    // Допустим, мы на сервере получили какие-то данные
    ЗаполнитьДанныеНаСервере();
КонецПроцедуры

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

    // Заполняем наш программно созданный реквизит "Вес"
    // Используем синтаксис с квадратными скобками!
    НоваяСтрока["Вес"] = 15.5; 
КонецПроцедуры

Этот синтаксис гарантированно работает для реквизитов, добавленных во время выполнения.

Шаг 4 (Опционально). Как сохранить данные из временной колонки?

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

Для этого можно использовать обходной маневр с помощью реквизита типа ХранилищеЗначения.

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

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

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

← На главную