Как вывести номенклатуру с характеристиками в виде дерева в динамическом списке 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов подбора или справочников в среде «1С:Предприятие 8.3» часто возникает задача: отобразить список номенклатуры так, чтобы позиции разворачивались в иерархический список подчиненных характеристик. При попытке реализовать такую структуру в динамическом списке разработчики сталкиваются с техническими ограничениями платформы.

Разберем подробно, почему стандартный динамический список не позволяет построить произвольное дерево из двух разных справочников, какие ошибки при этом возникают и какие практические способы решения существуют.

Почему динамический список не строит дерево из номенклатуры и характеристик?

Проанализируем архитектуру механизма динамического списка:

  1. Ограничение встроенной иерархии: динамический список умеет отображать дерево только на основании иерархии одного конкретного объекта метаданных (когда у справочника включена иерархия групп и элементов или иерархия элементов, где родителем выступает поле Родитель той же таблицы). Построить дерево, где родительским узлом является строка справочника Справочник.Номенклатура, а дочерним — элемент справочника Справочник.ХарактеристикиНоменклатуры, штатными средствами динамического списка невозможно.
  2. Ошибка «Дублирование ключевых значений»: при объединении таблиц со связью «один ко многим» поле Ссылка номенклатуры дублируется для каждой характеристики. Если для списка указана ОсновнаяТаблица, платформа требует уникальности ссылочного ключа для каждой строки. В результате динамический список выдает ошибку дублирования ключа.
  3. Потеря номенклатуры без характеристик: если в качестве основной таблицы указать Справочник.ХарактеристикиНоменклатуры, в выборку перестанут попадать позиции номенклатуры, для которых характеристики не ведутся или еще не заведены. Если же попытаться дополнить выборку через ОБЪЕДИНИТЬ ВСЕ, платформа запретит использовать свойство ОсновнаяТаблица.

Рассмотрим 3 проверенных варианта реализации задачи в зависимости от требований к интерфейсу и производительности.

Вариант 1. Разделение на два связанных списка (Master-Detail)

Это стандартный паттерн, используемый в большинстве типовых конфигураций (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей, 1С:УНФ). Вместо попытки объединить разнородные данные в одно дерево мы размещаем на форме два независимых динамических списка.

Разберем по шагам настройку этой схемы:

  1. Размещаем на форме первый динамический список для таблицы Справочник.Номенклатура.
  2. Рядом (или снизу) размещаем второй динамический список для таблицы Справочник.ХарактеристикиНоменклатуры.
  3. В обработчике события активизации строки таблицы номенклатуры устанавливаем отбор для списка характеристик по текущему владельцу.

Посмотрим на пример программной установки отбора:


&НаКлиенте
Процедура СписокНоменклатураПриАктивизацииСтроки(Элемент)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    УстановитьОтборПоВладельцу(ТекущиеДанные.Ссылка);
КонецПроцедуры

&НаКлиенте
Процедура УстановитьОтборПоВладельцу(СсылкаНоменклатура)
    ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
        СписокХарактеристики,
        "Владелец",
        СсылкаНоменклатура,
        ВидСравненияКомпоновкиДанных.Равно
    );
КонецПроцедуры

Преимущества такого подхода: максимальная скорость работы, сохранение стандартного быстрого поиска по подстроке и поддержка динамического считывания порций данных без перегрузки памяти.

Вариант 2. Плоский динамический список с составным ключом

Если заказчику требуется видеть всю информацию в одной таблице, но допустимо отказаться от иерархического сворачивания в пользу плоского списка, настроим составной ключ строки.

Выполним следующие настройки динамического списка:

  1. В свойствах динамического списка очищаем свойство ОсновнаяТаблица.
  2. Включаем флаг ПроизвольныйЗапрос и пишем текст запроса с левым соединением характеристик. Обязательно используем функцию ЕСТЬNULL(), так как ключевые поля не должны принимать значения NULL:

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура,
    ЕСТЬNULL(Характеристики.Ссылка, ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК Характеристика,
    Номенклатура.Артикул КАК Артикул,
    Номенклатура.Наименование КАК Наименование,
    Характеристики.Наименование КАК НаименованиеХарактеристики
ИЗ
    Справочник.Номенклатура КАК Номенклатура
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК Характеристики
        ПО Характеристики.Владелец = Номенклатура.Ссылка
  1. В свойствах списка находим параметр ВидКлюча и переключаем его в значение КлючСтроки.
  2. В свойстве ПоляКлюча указываем массив полей: Номенклатура, Характеристика.

Такой подход устраняет ошибку дублирования ключей, отображает все позиции (даже без характеристик) и сохраняет возможности полнотекстового поиска платформы.

Вариант 3. Формирование дерева значений на форме

Если отображение в виде дерева с плюсиками для раскрытия характеристик является обязательным условием, используем реквизит формы с типом ДеревоЗначений.

Посмотрим на пример заполнения дерева запросом с группировкой через итоги:


&НаСервере
Процедура ЗаполнитьДеревоНоменклатурыНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Номенклатура.Ссылка КАК Номенклатура,
        |   Номенклатура.Наименование КАК Наименование,
        |   Характеристики.Ссылка КАК Характеристика,
        |   Характеристики.Наименование КАК НаименованиеХарактеристики
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК Характеристики
        |       ПО Характеристики.Владелец = Номенклатура.Ссылка
        |ИТОГИ ПО
        |   Номенклатура";
        
    РезультатЗапроса = Запрос.Выполнить();
    
    // Преобразуем выборку в ДеревоЗначений формы
    ДеревоОбъект = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
    ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоНоменклатуры");
КонецПроцедуры

Важные особенности при работе с деревом значений:

  1. Производительность: дерево значений выгружается целиком в оперативную память клиента и сервера, поэтому на больших справочниках (от 10 000 позиций) открытие формы может замедлиться. В таких случаях применяют динамическую подгрузку дочерних узлов в момент раскрытия строки.
  2. Поиск: стандартная строка поиска динамического списка для дерева значений недоступна. Для организации поиска добавляют отдельное поле ввода на форму и перезаполняют дерево с условием ПОДОБНО в запросе либо обходят строки дерева на клиенте, устанавливая свойство видимости строк.
← На главную