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