Как разрешить выбор группы в дереве значений и заполнить подчиненные элементы в 1С?

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

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

Настройка разрешения выбора групп на управляемой форме

По умолчанию в полях ввода, связанных с иерархическими справочниками, действует ограничение: выбирать разрешено только конечные элементы. Если попытаться выбрать группу (папку), платформа выводит предупреждение о том, что требуется выбрать элемент. В табличных частях метаданных свойство выбора групп можно задать у реквизита, однако у реквизитов формы типа ДеревоЗначений таких настроек метаданных нет.

Рассмотрим, где именно задается эта настройка в интерфейсе управляемой формы:

  1. Откроем редактор формы в конфигураторе и перейдем в окно элементов формы.
  2. Найдем таблицу, отображающую дерево значений, и раскроем ее состав.
  3. Выделим элемент — поле ввода соответствующей колонки (например, поле КолонкаСправочник1).
  4. В палитре свойств найдем категорию Использование и параметр Выбор групп и элементов.
  5. Установим значение в Группы и элементы (или Группы, если требуется ограничить выбор исключительно папками).

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


Элементы.КолонкаСправочник1.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.ГруппыИЭлементы;

Ограничения хранения дерева значений в базе данных

Проанализируем архитектурную особенность платформы: объект ДеревоЗначений является чисто программной коллекцией. Он не может выступать типом реквизита объекта метаданных (например, реквизита справочника). Дерево значений может существовать только в оперативной памяти — в коде или в виде реквизита формы.

Чтобы сохранить древовидную структуру в данных самого справочника, на практике применяют один из двух подходов:

  1. Использование плоской табличной части: создаем табличную часть со служебными колонками (например, Родитель или Уровень). При открытии формы строки программно сворачиваются в дерево значений, а перед записью объекта дерево разворачивается обратно в плоскую таблицу.
  2. Использование хранилища значений: дерево значений целиком сериализуется и сохраняется в реквизит объекта с типом ХранилищеЗначения. Этот способ исключает возможность формировать отчеты и писать запросы к содержимому дерева средствами СУБД, но позволяет сохранить сложную структуру без настройки связей в табличной части.

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

После включения свойства Группы и элементы пользователь сможет выбрать папку, однако платформа стандартно запишет в текущую ячейку только ссылку на эту папку. Вложенные строки сами по себе не появятся. Чтобы развернуть состав выбранной группы, обработаем событие поля ввода.

Перехватим выбор пользователя в событии ОбработкаВыбора поля ввода на клиенте, отменим стандартное поведение и обратимся к серверу для построения иерархического дерева.


&НаКлиенте
Процедура ДеревоКолонкаСправочник1ОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    // Отменяем стандартную вставку единственного значения
    СтандартнаяОбработка = Ложь;
    
    // Вызываем серверную процедуру для заполнения дерева иерархией
    ЗаполнитьДеревоПоГруппеНаСервере(ВыбранноеЗначение);
    
КонецПроцедуры

Теперь разберем серверную логику. Чтобы выбрать саму группу и все входящие в нее подпапки и элементы на любую глубину вложенности, используем язык запросов с конструкцией В ИЕРАРХИИ и предложением ИТОГИ ПО ... ИЕРАРХИЯ:


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

Выясним, как работают ключевые инструкции данного метода:

  1. Конструкция В ИЕРАРХИИ(&ВыбраннаяГруппа) отбирает из базы данных как саму родительскую папку, так и все дочерние узлы независимо от количества уровней вложенности.
  2. Инструкция ИТОГИ ПО Ссылка ИЕРАРХИЯ строит иерархические выборки в соответствии со связями родителей и потомков в справочнике.
  3. Метод РезультатЗапроса.Выгрузить() с параметром ОбходРезультатаЗапроса.ПоГруппировкамСИерархией трансформирует линейную выборку в объект ДеревоЗначений с уже сформированными коллекциями Строки у каждого родительского узла.
  4. Процедура ЗначениеВРеквизитФормы конвертирует серверный объект ДеревоЗначений в прикладной реквизит управляемой формы ДанныеФормыДерево, после чего таблица на форме мгновенно отображает полное дерево с возможностью сворачивания и разворачивания узлов.
← На главную