К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как программно добавить колонку в табличную часть на форме в 1С

Как программно добавить колонку в табличную часть формы в 1С 8.3: модификация реквизитов, ИзменитьРеквизиты, добавление ЭлементыФормы, примеры кода и типичные ошибки.

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

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

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

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

Табличная часть документа или справочника — это данные объекта, а не формы. Их состав фиксирован в конфигурации, и форма лишь отображает существующие реквизиты. Попытка добавить элемент формы с путём к данным, которого нет в объекте, приведёт к ошибке «Поле не найдено» при открытии формы.

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

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

Шаг 1. Добавление реквизита-колонки через ИзменитьРеквизиты

Метод ИзменитьРеквизиты(ДобавляемыеРеквизиты, УдаляемыеРеквизиты) принимает два массива объектов типа «ОписаниеРеквизитаФормы». Для добавления колонки в таблицу значений формы у описания реквизита указывается имя, тип и путь — имя родительского реквизита-таблицы.

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

&НаСервере

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

ДобавляемыеРеквизиты = Новый Массив;

ОписаниеРеквизита = Новый ОписаниеРеквизитаФормы(

"ОстатокНаСкладе", // имя колонки

Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)),

"ТоварыТаблица", // путь: реквизит-таблица формы

"Остаток на складе", // заголовок

Ложь);

ДобавляемыеРеквизиты.Добавить(ОписаниеРеквизита);

ИзменитьРеквизиты(ДобавляемыеРеквизиты);

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

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

Шаг 2. Создание элемента формы для новой колонки

После добавления реквизита данные в таблице уже есть, но пользователь их не увидит — нужен элемент формы. Колонка добавляется методом Элементы.Добавить() с типом Тип("ПолеФормы"), родителем указывается таблица формы, а свойство ПутьКДанным связывает элемент с реквизитом.

&НаСервере

Процедура ДобавитьЭлементКолонки()

НовыйЭлемент = Элементы.Добавить("ТоварыОстатокНаСкладе", Тип("ПолеФормы"), Элементы.ТоварыТаблица);

НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;

НовыйЭлемент.ПутьКДанным = "ТоварыТаблица.ОстатокНаСкладе";

НовыйЭлемент.Заголовок = "Остаток на складе";

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

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

ПутьКДанным строится по шаблону «ИмяТаблицы.ИмяКолонки». Ошибка в одной букве не всегда выявляется сразу: иногда колонка просто остаётся пустой, что затрудняет диагностику.

Порядок действий
  1. 1
    Создайте на форме динамический реквизит типа «ТаблицаЗначений» и элемент-таблицу для его отображения
  2. 2
    В серверной процедуре сформируйте массив ОписаниеРеквизитаФормы с путём к таблице и вызовите ИзменитьРеквизиты()
  3. 3
    Добавьте элемент формы типа ПолеФормы с ПутьКДанным «Таблица.Колонка»
  4. 4
    Заполните данные: переберите строки реквизита-таблицы и присвойте значения новой колонке
  5. 5
    Проверьте результат, открыв форму: колонка видна и содержит значения

Шаг 3. Заполнение новой колонки данными

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

&НаСервере

Процедура ЗаполнитьОстатки()

Для Каждого СтрокаТовара Из ТоварыТаблица Цикл

СтрокаТовара.ОстатокНаСкладе = ПолучитьОстаток(СтрокаТовара.Номенклатура);

КонецЦикла;

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

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

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

Динамическое добавление и удаление колонок по условию

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

Удаление делается тем же ИзменитьРеквизиты(), но массив удаляемых заполняется путями: "ТоварыТаблица.ОстатокНаСкладе". Элементы формы удаляются методом Элементы.Удалить() до или после изменения реквизитов — порядок не критичен, главное не оставить элемент, ссылающийся на несуществующий реквизит.

&НаСервере

Процедура ПерестроитьКолонки()

// Удаление старых колонок

УдаляемыеРеквизиты = Новый Массив;

Для Каждого ИмяКолонки Из СписокДинамическихКолонок Цикл

УдаляемыеРеквизиты.Добавить("ТоварыТаблица." + ИмяКолонки);

ЭлементКолонки = Элементы.Найти("Товары_" + ИмяКолонки);

Если ЭлементКолонки <> Неопределено Тогда

Элементы.Удалить(ЭлементКолонки);

КонецЕсли;

КонецЦикла;

ИзменитьРеквизиты(, УдаляемыеРеквизиты);

// Добавление новых колонок по актуальному списку

...

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

Список динамических колонок удобно хранить в реквизите формы (например, строка с именами через запятую или таблица значений), чтобы при перестроении знать, что именно удалять. Без такого реестра «осиротевшие» реквизиты будут накапливаться.

Типичные ошибки
01
Вызов ИзменитьРеквизиты() в клиентском контексте — метод доступен только на сервере, код падает с ошибкой
02
Добавление элемента без указания пути к таблице в ОписаниеРеквизитаФормы — реквизит попадает в корень формы, а не в таблицу
03
Повторное добавление элемента с тем же именем без проверки Элементы.Найти() — ошибка дублирования
04
Опечатка в ПутьКДанным — колонка отображается, но остаётся пустой
05
Попытка добавить колонку в табличную часть объекта или динамический список — платформа выдаёт ошибку, так как состав этих данных фиксирован

Особенности для обычных форм и альтернативные подходы

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

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

Сравнение вариантов

ИзменитьРеквизиты + Элементы.Добавить

Универсальный способ для управляемых форм. Подходит, когда колонки зависят от данных и нужно редактирование. Требует аккуратного удаления старых реквизитов

Изменение запроса динамического списка

Подходит для списков, где колонки вычисляются запросом. Не работает для табличных частей объектов и не даёт редактируемых колонок

СКД с динамическими настройками

Подходит для отчётных форм без редактирования. Платформа сама строит колонки по настройкам, код минимален

Проверка результата и ограничения

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

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

Контрольные точки

Как проверить результат

Колонка видна в таблице на форме
Норма

Колонка отображается с заданным заголовком

Тревожный признак

Колонки нет — проверьте, что элемент добавлен с правильным родителем (таблица формы)

Данные в колонке
Норма

Ячейки заполнены значениями по строкам

Тревожный признак

Колонка пустая — проверьте ПутьКДанным и код заполнения

Повторное перестроение
Норма

Старые колонки исчезают, новые появляются без ошибок

Тревожный признак

Ошибка дублирования имени или ссылки на удалённый реквизит

Отдельно проверьте права и режим работы: в клиент-серверном варианте серверный вызов на каждое перестроение формы — это дополнительная нагрузка, поэтому перестройку колонок стоит делать по явному действию пользователя (кнопка, изменение отбора), а не на каждое событие формы.

Итог

Что важно запомнить

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

Частые вопросы

Можно ли добавить колонку непосредственно в табличную часть документа на форме?

Нет. Состав реквизитов табличной части фиксирован в метаданных объекта. Обходной путь — отображать данные через динамический реквизит формы типа «ТаблицаЗначений», куда табличная часть выгружается, и добавлять колонки уже в этот реквизит. При записи данные переносятся обратно в объект вручную.

Почему после ИзменитьРеквизиты колонка не появляется на форме?

Метод добавляет только данные, но не элемент интерфейса. Нужно дополнительно создать элемент формы методом Элементы.Добавить() с типом ПолеФормы, указать родителем таблицу формы и задать ПутьКДанным вида «ИмяТаблицы.ИмяКолонки».

Где вызывать ИзменитьРеквизиты — на клиенте или на сервере?

Только на сервере: в обработчике ПриСозданииНаСервере или в серверной процедуре формы. В клиентском контексте метод недоступен, и код завершится ошибкой. С клиента вызывайте серверную процедуру.

Как добавить сразу несколько колонок, например по списку складов?

Сформируйте один массив ОписаниеРеквизитаФормы для всех колонок и вызовите ИзменитьРеквизиты() один раз — это существенно быстрее, чем вызов в цикле. Затем в отдельном цикле создайте элементы формы и заполните данные. Имена колонок формируйте без спецсимволов, например «Склад_» + индекс, а соответствие склада и колонки храните в реквизите формы.

Колонка появилась, но пустая. В чём причина?

Чаще всего — ошибка в ПутьКДанным элемента или отсутствие кода заполнения. Проверьте, что путь точно совпадает с «ИмяТаблицы.ИмяРеквизита», и что после добавления реквизита выполняется перебор строк таблицы с присвоением значений новой колонке.

Как удалить программно добавленную колонку?

Вызовите ИзменитьРеквизиты() со вторым параметром — массивом путей удаляемых реквизитов вида «ТоварыТаблица.ОстатокНаСкладе», и удалите элемент формы через Элементы.Удалить(). Чтобы знать, что удалять, храните список динамических колонок в отдельном реквизите формы.