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