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

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

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

Постановка задачи и основные принципы

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

  1. Создать новые реквизиты формы (типизированные поля в памяти сервера).
  2. Создать элементы формы (визуальные колонки в таблице).
  3. Заполнить созданные поля данными, обращаясь к ним по динамическим именам.

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

Проанализируем механизм добавления реквизитов. Нам нельзя просто добавить колонку на форму — у нее должен быть источник данных. Поскольку в метаданных (в конфигураторе) таких колонок нет, мы создаем их программно через массив объектов РеквизитФормы. Рассмотрим пример кода, который подготавливает эти данные.

Важный нюанс: метод ИзменитьРеквизиты является "тяжелым", так как вызывает полную перегенерацию контекста формы на сервере. Поэтому крайне важно собрать все новые колонки в один массив и вызвать этот метод один раз, а не внутри цикла.


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

// Допустим, у нас есть список складов
Для Каждого СкладСсылка Из СписокСкладов Цикл
    
    // Формируем имя колонки. Помним, что в имени не должно быть пробелов!
    // Используем УникальныйИдентификатор без тире для гарантии уникальности
    ИмяКолонки = "Склад_" + СтрЗаменить(Строка(СкладСсылка.УникальныйИдентификатор()), "-", "_");
    МассивИменКолонок.Добавить(ИмяКолонки);
    
    ТипЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3));
    
    // Создаем объект РеквизитФормы
    // 3-й параметр - путь к родительскому реквизиту (наша табличная часть)
    НовыйРеквизит = Новый РеквизитФормы(ИмяКолонки, ТипЧисло, "Объект.Товары", "Остаток: " + СкладСсылка.Наименование);
    НовыеРеквизиты.Добавить(НовыйРеквизит);
    
КонецЦикла;

// Добавляем реквизиты на форму одним вызовом
ЭтаФорма.ИзменитьРеквизиты(НовыеРеквизиты);

Шаг 2: Создание элементов интерфейса

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


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

Шаг 3: Заполнение колонок данными

Теперь выясним, как проставить значения на пересечении строки (Номенклатура) и колонки (Склад). Так как мы добавили реквизиты программно, мы не можем обратиться к ним через точку (например, СтрокаТЧ.Склад_1), так как конфигуратор не знает о них на этапе компиляции. Однако мы можем использовать обращение через квадратные скобки по имени колонки.

Рассмотрим алгоритм заполнения:


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

Типичные ошибки и рекомендации

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

  1. Пробелы и спецсимволы в именах: Имя реквизита формы должно быть правильным идентификатором. Если вы используете наименование склада напрямую, программа выдаст ошибку. Всегда очищайте имя или используйте префиксы.
  2. Очистка старых колонок: Если пользователь нажимает кнопку "Обновить" несколько раз, попытка добавить реквизит с тем же именем вызовет ошибку. Перед добавлением необходимо удалять предыдущие программные реквизиты, используя тот же метод ИзменитьРеквизиты, передавая массив имен для удаления во второй параметр.
  3. Потеря данных: Программные реквизиты формы живут только в рамках сеанса работы с формой. Если вы добавили их к Объект.Товары, данные в них не сохранятся автоматически в базу данных при записи документа (так как в самой табличной части объекта этих колонок нет). Для сохранения таких данных используйте дополнительные механизмы, например, сериализацию в служебный реквизит или запись в регистры сведений.
  4. Производительность: Если колонок очень много (сотни), работа формы может замедлиться. В этом случае рассмотрите возможность использования ТаблицыЗначений как отдельного реквизита формы вместо привязки к табличной части объекта.

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

← На главную