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

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

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

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

Почему возникает ошибка при установке Пути К Данным?

Основная причина ошибки заключается в том, что разработчики часто пытаются привязать программно созданный элемент (таблицу формы) к пути, которого еще не существует в структуре данных формы. Если вы пишете Таб.ПутьКДанным = "Объект.ТабличнаяЧасть1", то в метаданных документа обязательно должна существовать табличная часть с таким именем. Если же ваша задача — создать «виртуальную» таблицу, которой нет в метаданных, то путь "Объект..." использовать нельзя.

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

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

Прежде чем выводить таблицу на экран, мы должны подготовить «место» для хранения данных в памяти формы. Для этого используется метод ИзменитьРеквизиты(). Рассмотрим пример кода, который создает структуру таблицы и её колонки:


// Создаем массив для новых реквизитов
НовыеРеквизиты = Новый Массив;

// 1. Создаем саму таблицу (контейнер)
ИмяТаблицы = "ДинамическаяТаблица_" + ИмяДляЭлемента;
НовыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяТаблицы, Новый ОписаниеТипов("ТаблицаЗначений")));

// 2. Создаем колонки для этой таблицы
// Обратите внимание на третий параметр - это путь к родительскому реквизиту
НовыеРеквизиты.Добавить(Новый РеквизитФормы("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), ИмяТаблицы));
НовыеРеквизиты.Добавить(Новый РеквизитФормы("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 3)), ИмяТаблицы));

// Применяем изменения на форме
ИзменитьРеквизиты(НовыеРеквизиты);

Важный момент: метод ИзменитьРеквизиты() является ресурсоемким. Если вам нужно добавить несколько таблиц или десятки колонок, всегда собирайте их в один массив и вызывайте метод один раз в конце процедуры. Это значительно ускорит работу интерфейса.

Шаг 2. Создание элементов визуализации (Интерфейс)

После того как реквизиты созданы, мы можем приступить к созданию визуальных элементов. Нам понадобится сама ТаблицаФормы и ПоляФормы для каждой колонки. Проанализируем этот процесс:


// Добавляем таблицу на форму (например, в группу или на страницу)
ТабЭлемент = Элементы.Добавить(ИмяТаблицы, Тип("ТаблицаФормы"), РодительскийЭлемент);
ТабЭлемент.ПутьКДанным = ИмяТаблицы; // Теперь этот путь существует!
ТабЭлемент.Заголовок = "Программная таблица";

// Добавляем колонку "Номенклатура"
КолонкаНоменклатура = Элементы.Добавить(ИмяТаблицы + "Номенклатура", Тип("ПолеФормы"), ТабЭлемент);
КолонкаНоменклатура.Вид = ВидПоляФормы.ПолеВвода;
КолонкаНоменклатура.ПутьКДанным = ИмяТаблицы + ".Номенклатура";

// Добавляем колонку "Количество"
КолонкаКоличество = Элементы.Добавить(ИмяТаблицы + "Количество", Тип("ПолеФормы"), ТабЭлемент);
КолонкаКоличество.Вид = ВидПоляФормы.ПолеВвода;
КолонкаКоличество.ПутьКДанным = ИмяТаблицы + ".Количество";

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

Шаг 3. Обработка событий в динамических таблицах

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

Посмотрим на пример установки обработчика для таблицы:


ТабЭлемент.УстановитьДействие("ПриИзменении", "ПриИзмененииДинамическойТаблицы");

Сама процедура должна быть описана в модуле формы с директивой &НаКлиенте. Чтобы понять, в какой именно таблице произошло изменение, используйте параметр Элемент:


&НаКлиенте
Процедура ПриИзмененииДинамическойТаблицы(Элемент)
    
    // Получаем текущие данные строки, в которой произошло изменение
    ТекущиеДанные = Элементы[Элемент.Имя].ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        // Пример логики: расчет объема на основании взлива (как в исходном вопросе)
        // ТекущиеДанные.Объем = ТекущиеДанные.Взлив * Коэффициент;
    КонецЕсли;
    
КонецПроцедуры

Шаг 4. Сохранение данных динамических таблиц

Внимание! Реквизиты формы, созданные через ИзменитьРеквизиты(), являются временными. Они живут только пока открыта форма. Если вы закроете документ и откроете его снова, данные в этих таблицах исчезнут, так как они не связаны напрямую с табличными частями объекта метаданных.

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

  1. Создайте в документе одну скрытую «техническую» табличную часть или используйте внешний регистр сведений для хранения данных.
  2. В событии формы ПриЧтенииНаСервере программно создавайте динамические таблицы и заполняйте их данными из вашего хранилища.
  3. В событии ПередЗаписьюНаСервере выгружайте данные из динамических реквизитов (используя РеквизитФормыВЗначение) и записывайте их обратно в хранилище.

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

Проанализируем несколько советов, которые помогут избежать проблем при работе с динамическим интерфейсом:

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

← На главную