Разработка и Конфигурация · 10 мин
1С: как программно добавить колонку реквизита
Как в 1С программно добавить колонку реквизита в табличную часть, динамический список и форму: код, примеры, типичные ошибки и проверка результата.
Задача добавить колонку реквизита программно возникает, когда структуру формы нельзя задать статически в конфигураторе: состав колонок зависит от настроек пользователя, данных в базе или внешних источников. В управляемых формах 1С это делается через программное изменение реквизитов формы и элементов формы, а в обычных формах — через коллекции колонок табличного поля.
Важно различать три разные ситуации, которые часто путают. Первая — добавить колонку в таблицу значений или табличную часть объекта (изменение состава данных). Вторая — добавить реквизит формы и связанную с ним колонку таблицы на форме (изменение представления). Третья — изменить состав колонок динамического списка или отчёта на СКД. В каждом случае используются свои объекты и методы платформы.
Ниже разобраны основные сценарии с готовым кодом, ограничениями платформы и способами проверить результат. Примеры ориентированы на управляемое приложение, но раздел про обычные формы тоже приведён.
Добавление колонки в таблицу значений и табличную часть
Самый простой случай — колонка нужна только в данных, без отображения на форме. Для таблицы значений используется коллекция Колонки с методом Добавить(), которому передаются имя колонки, описание типа, заголовок и ширина.
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТаблицаДанных.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "Цена", 12);
ТаблицаДанных.Колонки.Добавить("Комментарий", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(200)));
У табличной части объекта (документа, справочника) состав колонок фиксируется в конфигураторе — программно добавить в неё новый реквизит в режиме предприятия нельзя. Если колонки должны меняться динамически, используют реквизит формы типа «ТаблицаЗначений», а не табличную часть объекта. Это принципиальное ограничение платформы, и попытка обойти его через изменение конфигурации кодом приведёт к необходимости обновления конфигурации базы данных.
Имя колонки должно удовлетворять правилам имён переменных: начинаться с буквы, не содержать пробелов и спецсимволов. Если имя уже существует, метод вернёт существующую колонку, поэтому перед добавлением полезно проверять наличие через Колонки.Найти(ИмяКолонки).
Добавление реквизита формы и колонки в управляемой форме
В управляемой форме отображение отделено от данных. Чтобы вывести новую колонку в таблицу на форме, нужно сначала добавить реквизит в таблицу значений формы, а затем создать элемент формы, который этот реквизит покажет. Всё это делается на сервере, обычно в обработчике ПриСозданииНаСервере или в отдельной серверной процедуре.
&НаСервере
Процедура ДобавитьКолонкуНаСервере()
ДобавляемыеРеквизиты = Новый Массив;
НовыйРеквизит = Новый РеквизитФормы("Скидка",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2)),
"Товары", "Скидка", Истина);
ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
НовыйЭлемент = Элементы.Добавить("ТоварыСкидка", Тип("ПолеФормы"), Элементы.Товары);
НовыйЭлемент.ПутьКДанным = "Товары.Скидка";
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.Заголовок = "Скидка";
КонецПроцедуры
Ключевые моменты кода: конструктор РеквизитФормы принимает имя, тип, путь (имя таблицы-владельца), заголовок и признак сохраняемости. Метод ИзменитьРеквизиты() применяет изменения — до его вызова реквизита в данных формы не существует, и обращение к Товары.Скидка вызовет ошибку. Только после изменения реквизитов создаётся элемент формы с привязкой ПутьКДанным.
Если колонок много и их состав известен заранее, удобно формировать массив реквизитов в цикле по описанию структуры, а затем вызывать ИзменитьРеквизиты() один раз — это быстрее и меньше нагружает форму, чем последовательные изменения.
Удаление и повторное добавление колонок
Типичный сценарий — колонки перестраиваются при изменении настройки. Здесь есть тонкость: удалить реквизит формы можно тем же методом ИзменитьРеквизиты(), передав вторым параметром массив удаляемых имён (полных путей), а элемент формы удаляется через Элементы.Удалить().
УдаляемыеРеквизиты = Новый Массив;
УдаляемыеРеквизиты.Добавить("Товары.Скидка");
ИзменитьРеквизиты(Новый Массив, УдаляемыеРеквизиты);
Элементы.Удалить(Элементы.ТоварыСкидка);
Порядок важен: сначала удаляют элемент формы или реквизит, но не пытаются удалить элемент, чей ПутьКДанным уже указывает на несуществующий реквизит в момент перерисовки. Безопасная последовательность — удалить элемент формы, затем удалить реквизит. При повторном добавлении используйте те же имена или генерируйте уникальные, чтобы не получить конфликт имён.
- 1Определите, где нужна колонка: в данных (таблица значений) или на форме
- 2Для формы: создайте РеквизитФормы и примените ИзменитьРеквизиты() на сервере
- 3Добавьте элемент формы через Элементы.Добавить() с указанием родителя-таблицы
- 4Установите ПутьКДанным, Вид, Заголовок и при необходимости ширину
- 5Проверьте заполнение данных и отображение в режиме предприятия
Добавление колонки в динамический список и отчёт СКД
Динамический список строится на запросе, поэтому «добавить колонку» означает изменить текст запроса и настройки списка. Если произвольный запрос разрешён (свойство ПроизвольныйЗапрос), можно программно подменить текст запроса, добавив поле, а затем добавить элемент формы для колонки списка по тому же принципу, что и для таблицы значений.
В отчётах на СКД колонки определяются настройками компоновки. Программно поле добавляют в коллекцию ВыбранныеПоля настроек: создают ВыбранноеПолеКомпоновкиДанных, указывают путь к полю, доступному в наборе данных. Поле должно присутствовать в запросе набора данных — иначе компоновщик выдаст ошибку о недоступности поля.
Сравнение вариантов
Подходит для программных данных без формы. Быстро, но не отображается автоматически.
Полный контроль над управляемой формой. Требует серверного контекста и аккуратного порядка вызовов.
Для отчётов и списков на компоновке. Гибко, но поле обязано быть в наборе данных.
Единственный способ добавить реквизит в табличную часть объекта. Требует обновления конфигурации БД.
Обычные формы: добавление колонки в табличное поле
В обычном приложении механика другая: у табличного поля есть коллекция Колонки, и колонка добавляется напрямую с привязкой к данным через свойство Данные или ДанныеФлажка.
НоваяКолонка = ЭлементыФормы.Товары.Колонки.Добавить("Скидка", "Скидка");
НоваяКолонка.Данные = "Скидка";
НоваяКолонка.Ширина = 10;
НоваяКолонка.ЭлементУправления.ТипЗначения = Новый ОписаниеТипов("Число");
Если табличное поле связано с табличной частью объекта, добавленная вручную колонка не получит данные автоматически — источником должен быть реквизит, существующий в данных. Поэтому в обычных формах чаще привязывают табличное поле к таблице значений, где состав колонок полностью контролируется кодом.
Частые ошибки и как их проверить
Наиболее распространённая ошибка — создание элемента формы до вызова ИзменитьРеквизиты(). Платформа не найдёт путь к данным и выдаст ошибку «Поле не найдено». Вторая типичная проблема — попытка добавить реквизит на клиенте: метод ИзменитьРеквизиты() недоступен в клиентском контексте, директива &НаСервере обязательна.
Ещё одна группа ошибок связана с именами: кириллица в именах допустима, но смешение с уже существующими именами элементов приводит к исключению «Элемент с таким именем уже существует». При динамической генерации добавляйте префикс или проверяйте Элементы.Найти(Имя) перед добавлением.
Проверка результата проста: откройте форму в режиме предприятия, убедитесь, что колонка отображается, содержит данные и позволяет редактирование (если задан вид «Поле ввода»). Дополнительно проверьте сценарий повторного открытия формы и смены настроек — именно там всплывают конфликты имён и утечки старых реквизитов.
Как проверить результат
Отображается с заданным заголовком и шириной
Колонки нет или ошибка при открытии формы
Значения заполняются и редактируются
Колонка пустая при заполненных данных
Нет ошибок, состав колонок корректен
Исключение о дублировании имени элемента
FAQ
Можно ли программно добавить реквизит в табличную часть документа?
Нет, в режиме предприятия состав реквизитов табличной части фиксирован метаданными. Изменить его можно только в конфигураторе с последующим обновлением конфигурации базы данных. Обходной путь — реквизит формы типа «ТаблицаЗначений» с произвольными колонками.
Почему после ИзменитьРеквизиты() пропали настройки динамического списка?
Метод пересоздаёт данные формы, и часть динамических настроек может сбрасываться. Сохраните настройки перед вызовом и восстановите после, либо вызывайте изменение реквизитов один раз при создании формы, до инициализации настроек.
Как добавить колонку с флажком, а не с полем ввода?
При создании элемента формы установите Вид = ВидПоляФормы.ПолеФлажка, а тип реквизита задайте как Булево. Тогда колонка отобразится в виде флажков без дополнительной настройки.
Можно ли добавить колонку в форму списка справочника?
Да, если список — динамический с разрешённым произвольным запросом: измените текст запроса, добавьте поле, затем создайте элемент формы с соответствующим ПутьКДанным. Для основного списка без произвольного запроса состав полей ограничен метаданными.
Как задать ширину и порядок новой колонки?
Ширина задаётся свойством элемента формы Ширина (в символах). Порядок определяется позицией среди подчинённых элементов таблицы — переместить элемент можно методом Элементы.Переместить() относительно соседней колонки.
Работает ли ИзменитьРеквизиты() во внешней обработке?
Да, механизм доступен в любых управляемых формах, включая формы внешних обработок и отчётов. Ограничения те же: только серверный контекст и корректный порядок создания реквизитов и элементов.
Что важно запомнить
Колонка на управляемой форме создаётся парой действий: РеквизитФормы + ИзменитьРеквизиты() на сервере, затем Элементы.Добавить() с ПутьКДанным. Для таблицы значений достаточно Колонки.Добавить(). Табличную часть объекта программно изменить нельзя — только через конфигуратор. Всегда проверяйте повторное открытие формы на конфликт имён.