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

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

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

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

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

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

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

Когда программное добавление оправдано, а когда — нет

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

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

Маршрут решения

Как выбрать подход

Колонка нужна только для отображения или временного ввода в одной формеИспользуйте ИзменитьРеквизиты() и динамическую колонку
Данные должны сохраняться в базе и участвовать в проведении или отчётахДобавьте реквизит табличной части в конфигураторе
Конфигурация типовая на поддержке и менять её нельзяСоздайте расширение конфигурации с новым реквизитом
Состав колонок зависит от данных (периоды, склады, поля файла)Стройте реквизиты динамически в ПриСозданииНаСервере

Метод ИзменитьРеквизиты: синтаксис и описание реквизита

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

Для колонки табличной части путь строится так: имя реквизита формы типа «ДинамическийСписок» или «ДанныеФормыКоллекция», представляющего табличную часть, а третьим параметром передаётся путь к этой коллекции. В типовом документе табличная часть «Товары» на форме обычно представлена реквизитом Объект.Товары, поэтому путь к родителю — Объект.Товары.

&НаСервере

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

МассивДобавляемых = Новый Массив;

ОписаниеТипа = Новый ОписаниеТипов("Число",

Новый КвалификаторыЧисла(15, 2));

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

"ПроцентСкидки", // имя колонки

ОписаниеТипа, // тип

"Объект.Товары", // путь к табличной части

"Процент скидки"); // заголовок

МассивДобавляемых.Добавить(НовыйРеквизит);

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

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

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

Добавление колонки на форму после создания реквизита

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

&НаСервере

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

// ... добавление реквизита через ИзменитьРеквизиты ...

НоваяКолонка = Элементы.Добавить("ТоварыПроцентСкидки",

Тип("ПолеФормы"), Элементы.Товары);

НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;

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

НоваяКолонка.Заголовок = "Процент скидки";

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

Вид поля выбирайте по типу данных: ПолеВвода для чисел, строк и ссылок, ПолеФлажка для булево, ПолеНадписи для колонок только для чтения. Если колонка должна быть недоступна для редактирования, установите ТолькоПросмотр = Истина у элемента, а не у реквизита.

Полный пример: добавление колонки при открытии формы документа

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

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

ДобавитьСлужебныеКолонки();

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

&НаСервере

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

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

ОписаниеСтроки = Новый ОписаниеТипов("Строка",

Новый КвалификаторыСтроки(100));

Добавляемые.Добавить(Новый ОписаниеРеквизитаФормы(

"КомментарийСтроки", ОписаниеСтроки,

"Объект.Товары", "Комментарий"));

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

Колонка = Элементы.Добавить("ТоварыКомментарийСтроки",

Тип("ПолеФормы"), Элементы.Товары);

Колонка.Вид = ВидПоляФормы.ПолеВвода;

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

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

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

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

Удаление и обновление динамических реквизитов

Если структура колонок перестраивается многократно за время жизни формы — например, пользователь меняет период и набор колонок-месяцев меняется, — старые реквизиты нужно удалять. Для этого во второй параметр ИзменитьРеквизиты() передаётся массив строк с полными путями удаляемых реквизитов, например "Объект.Товары.ПроцентСкидки".

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

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

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

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

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

Итог

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

Динамическая колонка табличной части создаётся связкой ИзменитьРеквизиты() плюс программный элемент ПолеФормы с корректным ПутьКДанным. Код выполняется только на сервере. Такой реквизит не хранится в базе — для постоянных данных используйте конфигуратор или расширение.

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

Можно ли добавить реквизит табличной части без изменения конфигурации?

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

Почему возникает ошибка «Метод объекта не обнаружен: ИзменитьРеквизиты»?

Чаще всего метод вызван в клиентской процедуре — он доступен только на сервере. Перенесите вызов в серверную процедуру модуля формы. Реже причина в том, что код размещён не в модуле формы, а в общем модуле, где объекта формы нет.

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

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

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

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

Можно ли программно добавить реквизит, который сохранится в документе?

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

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

В два действия: удалите элемент формы методом Элементы.Удалить(Элементы.ИмяКолонки) и передайте полный путь реквизита (например, «Объект.Товары.МояКолонка») во второй параметр метода ИзменитьРеквизиты(). Удалять реквизит без удаления связанного элемента нельзя — форма выдаст ошибку.