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