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

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

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

В чем заключается корень проблемы: разделение данных и интерфейса

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

  1. Добавить описание колонки в структуру реквизитов формы на сервере, используя метод ИзменитьРеквизиты.
  2. Создать визуальный элемент управления (поле таблицы формы) с помощью коллекции Элементы и привязать его к добавленному реквизиту через свойство ПутьКДанным.

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

Критическая ошибка порядка выполнения вызовов

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

Пошаговый алгоритм добавления колонок

Разберем по шагам правильную последовательность действий, которую необходимо выполнять в серверном контексте формы:

  1. Подготовка массива описаний: создаем экземпляры объектов РеквизитФормы, указывая имя колонки, ее тип, путь к реквизиту-родителю (например, "Данные") и заголовок.
  2. Применение структуры реквизитов: вызываем метод ИзменитьРеквизиты(МассивДобавляемыхРеквизитов).
  3. Заполнение строк таблицы: загружаем данные в коллекцию формы из подготовленной таблицы значений.
  4. Создание визуальных элементов: вызываем Элементы.Добавить с типом ПолеФормы, указываем родительский элемент (таблицу формы), устанавливаем вид поля и связываем его с данными через ПутьКДанным.

Практический пример программного создания колонок

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


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

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

Очистка и повторное формирование динамических колонок

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

Важно соблюдать обратный порядок удаления:

  1. Сначала удаляются визуальные элементы управления: Элементы.Удалить(Элемент).
  2. Затем удаляются реквизиты формы через второй параметр метода ИзменитьРеквизиты.

Посмотрим на пример правильной очистки динамических колонок:


&НаСервере
Процедура УдалитьДинамическиеКолонки(СписокИменКолонок)
    
    // 1. Удаляем визуальные элементы интерфейса
    Для Каждого ИмяКолонки Из СписокИменКолонок Цикл
        ИмяЭлемента = "Данные_" + ИмяКолонки;
        Элемент = Элементы.Найти(ИмяЭлемента);
        Если Элемент <> Неопределено Тогда
            Элементы.Удалить(Элемент);
        КонецЕсли;
    КонецЦикла;
    
    // 2. Формируем массив путей к удаляемым реквизитам формы
    МассивУдаляемых = Новый Массив;
    Для Каждого ИмяКолонки Из СписокИменКолонок Цикл
        МассивУдаляемых.Добавить("Данные." + ИмяКолонки);
    КонецЦикла;
    
    // Передаем массив вторым параметром (первый параметр - массив добавления - пустой)
    ИзменитьРеквизиты(Новый Массив, МассивУдаляемых);
    
КонецПроцедуры

Рекомендации по оптимизации производительности

Обратите внимание на важные технические особенности работы с динамическими формами:

  1. Пакетное изменение: вызов метода ИзменитьРеквизиты инициирует полную пересборку контекста формы на сервере и повторную сериализацию структуры для клиента. Никогда не вызывайте данный метод внутри цикла. Всегда собирайте полный массив колонок и выполняйте ИзменитьРеквизиты ровно один раз.
  2. Контекст выполнения: добавление элементов и реквизитов выполняйте в рамках одного серверного вызова, не разделяя операцию между клиентом и сервером.
  3. Назначение событий: если в создаваемых полях ввода требуется перехватывать изменения, используйте метод элемента УстановитьДействие("ПриИзменении", "ИмяПроцедуры"), при этом сама процедура обработчика должна иметь директиву &НаКлиенте в модуле формы.
← На главную