При разработке интерфейсов подбора или справочников в среде «1С:Предприятие 8.3» часто возникает задача: отобразить список номенклатуры так, чтобы позиции разворачивались в иерархический список подчиненных характеристик. При попытке реализовать такую структуру в динамическом списке разработчики сталкиваются с техническими ограничениями платформы.
Разберем подробно, почему стандартный динамический список не позволяет построить произвольное дерево из двух разных справочников, какие ошибки при этом возникают и какие практические способы решения существуют.
Проанализируем архитектуру механизма динамического списка:
Родитель той же таблицы). Построить дерево, где родительским узлом является строка справочника Справочник.Номенклатура, а дочерним — элемент справочника Справочник.ХарактеристикиНоменклатуры, штатными средствами динамического списка невозможно.Ссылка номенклатуры дублируется для каждой характеристики. Если для списка указана ОсновнаяТаблица, платформа требует уникальности ссылочного ключа для каждой строки. В результате динамический список выдает ошибку дублирования ключа.Справочник.ХарактеристикиНоменклатуры, в выборку перестанут попадать позиции номенклатуры, для которых характеристики не ведутся или еще не заведены. Если же попытаться дополнить выборку через ОБЪЕДИНИТЬ ВСЕ, платформа запретит использовать свойство ОсновнаяТаблица.Рассмотрим 3 проверенных варианта реализации задачи в зависимости от требований к интерфейсу и производительности.
Это стандартный паттерн, используемый в большинстве типовых конфигураций (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей, 1С:УНФ). Вместо попытки объединить разнородные данные в одно дерево мы размещаем на форме два независимых динамических списка.
Разберем по шагам настройку этой схемы:
Справочник.Номенклатура.Справочник.ХарактеристикиНоменклатуры.Посмотрим на пример программной установки отбора:
&НаКлиенте
Процедура СписокНоменклатураПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
УстановитьОтборПоВладельцу(ТекущиеДанные.Ссылка);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьОтборПоВладельцу(СсылкаНоменклатура)
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
СписокХарактеристики,
"Владелец",
СсылкаНоменклатура,
ВидСравненияКомпоновкиДанных.Равно
);
КонецПроцедуры
Преимущества такого подхода: максимальная скорость работы, сохранение стандартного быстрого поиска по подстроке и поддержка динамического считывания порций данных без перегрузки памяти.
Если заказчику требуется видеть всю информацию в одной таблице, но допустимо отказаться от иерархического сворачивания в пользу плоского списка, настроим составной ключ строки.
Выполним следующие настройки динамического списка:
ЕСТЬNULL(), так как ключевые поля не должны принимать значения NULL:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ЕСТЬNULL(Характеристики.Ссылка, ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК Характеристика,
Номенклатура.Артикул КАК Артикул,
Номенклатура.Наименование КАК Наименование,
Характеристики.Наименование КАК НаименованиеХарактеристики
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ПО Характеристики.Владелец = Номенклатура.Ссылка
Номенклатура, Характеристика.Такой подход устраняет ошибку дублирования ключей, отображает все позиции (даже без характеристик) и сохраняет возможности полнотекстового поиска платформы.
Если отображение в виде дерева с плюсиками для раскрытия характеристик является обязательным условием, используем реквизит формы с типом ДеревоЗначений.
Посмотрим на пример заполнения дерева запросом с группировкой через итоги:
&НаСервере
Процедура ЗаполнитьДеревоНоменклатурыНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Наименование КАК Наименование,
| Характеристики.Ссылка КАК Характеристика,
| Характеристики.Наименование КАК НаименованиеХарактеристики
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК Характеристики
| ПО Характеристики.Владелец = Номенклатура.Ссылка
|ИТОГИ ПО
| Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
// Преобразуем выборку в ДеревоЗначений формы
ДеревоОбъект = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоНоменклатуры");
КонецПроцедуры
Важные особенности при работе с деревом значений:
ПОДОБНО в запросе либо обходят строки дерева на клиенте, устанавливая свойство видимости строк.