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