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

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

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

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

Этап 1: Добавление колонки в объект ДеревоЗначений

Первым шагом необходимо изменить структуру самого дерева значений. Реквизит формы, который мы видим, — это не сам объект ДеревоЗначений, а специальный тип ДанныеФормыСтруктураСКоллекцией или аналогичный. Чтобы работать с ним как с обычным деревом, нужно выполнить преобразование. Если же ваша задача связана с импортом данных, вам может пригодиться чтение файла в таблицу или дерево значений перед тем, как выводить эти данные на форму.

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

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

Посмотрим на пример. Допустим, у нас есть реквизит формы ЗаданияНаПеревозкуПланируемые, и мы хотим добавить в него колонку НомерРаспоряжения.


&НаСервере
Процедура ДобавитьКолонкуВДерево()

    // 1. Преобразуем данные формы в объект ДеревоЗначений
    ДЗ = ДанныеФормыВЗначение(ЗаданияНаПеревозкуПланируемые, Тип("ДеревоЗначений"));
    
    // 2. Проверяем, существует ли уже такая колонка
    Если ДЗ.Колонки.Найти("НомерРаспоряжения") = Неопределено Тогда
        // 3. Добавляем новую колонку, если ее нет
        ДЗ.Колонки.Добавить("НомерРаспоряжения", Новый ОписаниеТипов("Строка"));
    КонецЕсли;
    
    // 4. Преобразуем измененный объект обратно в данные формы
    ЗначениеВДанныеФормы(ДЗ, ЗаданияНаПеревозкуПланируемые);

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

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

Этап 2: Создание реквизита формы

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

На этом этапе возникает первая распространенная ошибка. При создании объекта РеквизитФормы нужно правильно указать путь. Разберем конструктор:

Новый РеквизитФормы(Имя, Тип, [ПутьКРеквизиту], [Заголовок])

Проанализируем ошибку из исходной темы. Изначально был указан неверный путь:


// НЕПРАВИЛЬНО!
// Путь "ЗаданияНаПеревозкуПланируемые.НомерРаспоряжения" указывает на сам реквизит, а не на его родителя
МассивДобавляемыхРекизитов.Добавить(Новый РеквизитФормы("НомерРаспоряжения", ..., "ЗаданияНаПеревозкуПланируемые.НомерРаспоряжения", ...));

Это приводит к ошибке "Недопустимый путь к реквизиту". Система не может найти родительский реквизит по такому пути. Правильный вариант — указать только имя дерева значений:


// ПРАВИЛЬНО!
// Указываем путь к родительскому реквизиту - нашему дереву
МассивДобавляемыхРекизитов.Добавить(Новый РеквизитФормы("НомерРаспоряжения", ..., "ЗаданияНаПеревозкуПланируемые", "Номер Распоряжения"));

Теперь соберем код для этого этапа:


&НаСервере
Процедура СоздатьРеквизитФормы()

    МассивДобавляемыхРекизитов = Новый Массив;
    
    // Создаем описание типа для новой колонки
    ТипСтрока = Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(11));
    
    // Создаем описание нового реквизита, указывая правильный путь к родителю
    НовыйРеквизит = Новый РеквизитФормы(
        "НомерРаспоряжения",
        ТипСтрока,
        "ЗаданияНаПеревозкуПланируемые",
        "Номер Распоряжения"
    );
    
    МассивДобавляемыхРекизитов.Добавить(НовыйРеквизит);
    
    // Применяем изменения к реквизитам формы
    ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРекизитов);
    
КонецПроцедуры

Этап 3: Создание элемента формы и привязка к данным

Последний шаг — создать на форме видимый элемент (например, поле ввода в таблице) и связать его с созданным реквизитом. Для этого используется коллекция ЭтаФорма.Элементы и ее методы, например, Вставить(). Если в дальнейшем вам потребуется изменить положение колонки, можно использовать алгоритм на программное перемещение колонки.

Здесь кроется вторая частая ошибка, связанная со свойством ПутьКДанным. Это свойство должно содержать полный путь к данным колонки, начиная от корня реквизитов формы. Он состоит из имени дерева и имени колонки, разделенных точкой. Подобный принцип используется и в других случаях, например, когда нужно реализовать флажок в динамическом списке.

Снова посмотрим на неверный вариант из обсуждения:


// НЕПРАВИЛЬНО!
НовыйЭлемент = ЭтаФорма.Элементы.Вставить("НомерРаспоряжения", Тип("ПолеФормы"), ЭтаФорма.Элементы.ЗаданияНаПеревозкуПланируемые);
НовыйЭлемент.ПутьКДанным = "НомерРаспоряжения"; // Ошибка: путь неполный

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

Правильный путь должен выглядеть так:


// ПРАВИЛЬНО!
НовыйЭлемент = ЭтаФорма.Элементы.Вставить("НомерРаспоряжения", Тип("ПолеФормы"), ЭтаФорма.Элементы.ЗаданияНаПеревозкуПланируемые);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "ЗаданияНаПеревозкуПланируемые.НомерРаспоряжения";

В методе Вставить() третий параметр указывает родительский элемент (группу или таблицу), куда будет добавлен новый элемент.

Итоговый пример кода

Объединим все шаги в одной процедуре. Этот код демонстрирует полный цикл добавления колонки "ИНН" в дерево "Контрагенты" и заполнения ее данными. Это отличный шаблон для использования в ваших проектах.


&НаСервере
Процедура ПрограммноДобавитьКолонкуИНН()

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

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

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

← На главную