В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает необходимость динамически изменять состав колонок в табличной части документа или справочника. Это может быть связано с особенностями внедрения, когда мы не хотим менять структуру метаданных в основной конфигурации, а предпочитаем использовать расширения или программные механизмы. Рассмотрим подробно, как реализовать эту задачу, разберем типичные ошибки и проанализируем работающий программный код.
Процесс программного добавления колонки всегда состоит из двух принципиально разных этапов:
Разберем эти этапы на конкретном примере. Предположим, нам нужно добавить колонку Должность в табличную часть ДанныеОВремени объекта Объект.
Для добавления реквизита используется метод ИзменитьРеквизиты. Важно понимать, что это «тяжелая» операция, которая полностью перестраивает контекст формы. Проанализируем пример кода:
// Создаем массив для новых реквизитов
ДобавленныеРеквизиты = Новый Массив;
// Описываем новый реквизит.
// Параметры: Имя, Тип, ПутьКРодителю, Заголовок, СохраняемыеДанные
НовыйРеквизит = Новый РеквизитФормы("Должность", Новый ОписаниеТипов("Строка"), "Объект.ДанныеОВремени", "Должность", Ложь);
// Добавляем реквизит в массив
ДобавленныеРеквизиты.Добавить(НовыйРеквизит);
// Применяем изменения на форме
ЭтаФорма.ИзменитьРеквизиты(ДобавленныеРеквизиты);
Обратите внимание на третий параметр конструктора РеквизитФормы. Указывая "Объект.ДанныеОВремени", мы сообщаем системе, что новый реквизит должен появиться внутри каждой строки существующей табличной части. Если этот параметр оставить пустым, реквизит будет добавлен в корень формы.
После того как данные созданы, нам нужно вывести их на экран. Рассмотрим, как вставить новую колонку в конкретное место таблицы:
// Определяем родительский элемент (саму таблицу на форме)
Родитель = Элементы.ДанныеОВремени;
// Определяем элемент, ПЕРЕД которым хотим вставить новую колонку
ЭлементПередКоторымВставляем = Элементы.ДанныеОВремениВремяИтог;
// Вставляем новый элемент управления
НовыйЭлемент = Элементы.Вставить("Должность", Тип("ПолеФормы"), Родитель, ЭлементПередКоторымВставляем);
// Настраиваем свойства элемента
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
// Указываем полный путь к данным, включая имя самого реквизита
НовыйЭлемент.ПутьКДанным = "Объект.ДанныеОВремени.Должность";
Важный момент: Свойство ПутьКДанным должно содержать полную цепочку обращения к реквизиту. Ошибка «Недопустимое значение», с которой часто сталкиваются разработчики, чаще всего вызвана тем, что в реквизитах путь прописан верно, а в элементе формы — с опечаткой или без указания родительской таблицы. Чтобы детально изучить этот процесс на практике, можно использовать обработку-пример с динамическим добавлением и удалением элементов.
Проанализируем ситуацию, когда код кажется верным, но система выдает ошибку. Выясним причину наиболее популярных затруднений:
ИзменитьРеквизиты доступен только в серверном контексте. Если вы пытаетесь вызвать его из общего модуля, убедитесь, что в процедуру передается сама Форма как объект. Как показывает практика (сообщение 23), иногда в сложных конфигурациях (например, ERP или ЗУП 3.1) код стабильнее работает, если он размещен непосредственно в модуле формы в обработчике ПриСозданииНаСервере или в его расширении (После).
НовыйРеквизит = Новый РеквизитФормы("Сотрудник", Новый ОписаниеТипов("СправочникСсылка.Сотрудники"), "Объект.Товары");
ДанныеФормыКоллекция (ТЧ объекта) это встречается реже, но стоит проверить, не ограничена ли видимость колонок в настройках самой таблицы.Вставить элемент между ними может вызвать конфликт. Попробуйте использовать метод Добавить, чтобы поместить колонку в конец таблицы.Просто вывести колонку часто недостаточно — нам нужно, чтобы при изменении значения в ней что-то происходило. Рассмотрим, как программно назначить обработчик события:
// Назначаем действие "ПриИзменении"
НовыйЭлемент.УстановитьДействие("ПриИзменении", "Подключаемый_КолонкаПриИзменении");
В модуле формы при этом должна существовать экспортная процедура:
&НаКлиенте
Процедура Подключаемый_КолонкаПриИзменении(Элемент)
// Ваша логика обработки
Сообщить("Значение в новой колонке изменено!");
КонецПроцедуры
Посмотрим на ситуацию, когда нужно добавить сразу пять колонок. Типичная ошибка начинающего программиста — вызывать ИзменитьРеквизиты в цикле пять раз. Это крайне неэффективно. Правильный подход — собрать все изменения в один массив и вызвать метод единожды:
МассивДобавления = Новый Массив;
МассивДобавления.Добавить(Новый РеквизитФормы("Колонка1", ТипСтрока, "Объект.Товары"));
МассивДобавления.Добавить(Новый РеквизитФормы("Колонка2", ТипЧисло, "Объект.Товары"));
// ... добавляем остальные
ЭтаФорма.ИзменитьРеквизиты(МассивДобавления);
Этот подход значительно ускоряет работу формы, так как сервер выполняет перестроение контекста один раз вместо нескольких. Для упрощения этой задачи можно применить готовый общий модуль для программного изменения управляемых форм, содержащий все необходимые функции добавления элементов.
Программное добавление колонок — мощный инструмент разработчика 1С. Главное — строго соблюдать последовательность: сначала реквизит с указанием пути к коллекции (таблице), затем элемент формы с указанием полного пути к данным. Помните, что все манипуляции с составом реквизитов должны происходить на сервере, а для надежности лучше всего использовать типовые события формы, такие как ПриСозданииНаСервере.