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