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