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