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