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