Как вывести иерархический справочник в управляемой форме 1С и настроить программный отбор?

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

Нередко разработчики и пользователи сталкиваются с тем, что иерархический справочник в управляемой форме 1С отображается не в виде дерева, а плоским списком. Особенно остро эта проблема проявляется при программном открытии форм и попытках установить сложные отборы. Давайте разберем основные причины такого поведения и рассмотрим различные решения, которые помогут вам корректно настроить отображение и отбор данных.

Причина 1: Справочник является подчиненным

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

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

Решение:

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

Причина 2: Стандартные настройки отображения формы

Если справочник не подчиненный или проблема не в этом, необходимо проверить стандартные настройки формы списка.

  1. Свойства формы списка в конфигураторе:

    Откроем конфигуратор и перейдем к форме списка вашего справочника. На закладке "Элементы" найдите табличное поле, которое отображает список элементов справочника (обычно оно называется "Список"). У этого элемента есть свойство Отображение. Оно может быть установлено в одно из значений:

    • ИерархическийСписок – для справочников с иерархией групп/элементов.
    • Дерево – для справочников с иерархией элементов.
    • Список – плоский список без иерархии.

    Для корректного иерархического отображения убедитесь, что выбрано значение ИерархическийСписок или Дерево, в зависимости от типа иерархии вашего справочника.

  2. Меню "Все действия" в режиме пользователя:

    Иногда режим просмотра можно изменить непосредственно в пользовательском режиме. В форме списка справочника найдите меню "Все действия" (или аналогичное, в зависимости от версии платформы). В нем может быть пункт "Режим просмотра", а внутри — "Иерархический список" или "Список".

    Если эти кнопки неактивны, выясним причину. Обычно это происходит в двух случаях:

    • Включен поиск по списку: Попробуйте отключить поиск (например, через "Все действия - Отменить поиск"). Активный поиск часто блокирует изменение режима отображения.
    • Форма открыта программно с определенными параметрами: Если форма открывается не стандартно, а с помощью программного кода, разработчик (или вы сами) могли специально настроить отображение списка в плоском виде. В этом случае, вам потребуется изменить программный код, который открывает форму.

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

Когда нам требуется жестко задать режим отображения списка (например, всегда показывать его плоским, даже если справочник иерархический), мы можем сделать это программно.

  1. Изменение свойства Отображение элемента формы:

    Чтобы программно переключить отображение списка, вам нужно обратиться к элементу формы, который является табличным полем списка (обычно с именем "Список"), и изменить его свойство Отображение. Чаще всего это делается в обработчике события формы, например, ПриОткрытии или ПриСозданииНаСервере.

    
    // В модуле формы списка справочника
    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
        Элементы.Список.Отображение = ОтображениеТаблицы.Список; // Устанавливаем плоский список
    КонецПроцедуры
    

    В этом примере мы принудительно устанавливаем плоский режим отображения. Для иерархического списка можно использовать ОтображениеТаблицы.ИерархическийСписок или ОтображениеТаблицы.Дерево, в зависимости от структуры иерархии справочника.

  2. Изменение отображения при программном открытии формы:

    Если вы открываете форму программно из другой формы или обработки, вы можете настроить отображение перед ее открытием.

    
    ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора"); // Получаем объект формы
    ФормаВыбора.Элементы.Список.Отображение = ОтображениеТаблицы.Список; // Устанавливаем плоский список
    ФормаВыбора.Открыть(); // Открываем форму
    

    Важно помнить о правильном пути к форме. Если в конфигурации существуют различные формы для справочника (например, `ФормаСписка`, `ФормаВыбора`), то для того чтобы получить именно нужную форму, лучше указывать полный путь, как мы рассмотрим далее.

Программное управление отбором данных

Установка отборов при программном открытии форм выбора или списков — распространенная задача. Рассмотрим различные сценарии.

Сценарий 1: Отбор по точному совпадению ("Равно")

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

  1. Передача структуры с параметрами отбора:

    Мы создадим структуру с именем "Отбор", внутри которой будут пары "ИмяРеквизита" - "ЗначениеОтбора". Затем эту структуру передадим вторым параметром в метод ПолучитьФорму.

    
    // Создаем структуру для отбора
    Отбор = Новый Структура("Артикул", "7232"); 
    
    // Создаем структуру с параметрами формы, включающую наш отбор
    ПараметрыОтбора = Новый Структура("Отбор", Отбор); 
    
    // Получаем форму выбора, передавая параметры отбора
    ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыОтбора); 
    
    // Если требуется изменить отображение
    ФормаВыбора.Элементы.Список.Отображение = ОтображениеТаблицы.Список; 
    
    // Открываем форму модально
    ФормаВыбора.ОткрытьМодально();
    

    Обратите внимание, что в данном случае отбор устанавливается в параметрах формы, а не непосредственно в динамическом списке до ее открытия. Это один из наиболее надежных способов для сравнения "Равно".

  2. Использование ОткрытьФормуМодально с параметрами:

    Еще более компактный вариант, если вам нужно сразу открыть форму модально и передать в нее отбор и настройки отображения:

    
    // Создаем структуру для отбора
    Отбор = Новый Структура("Артикул", "7232");
    
    // Открываем форму модально, передавая отбор и отображение
    // 'Отбор' будет воспринят формой как настройка отбора по умолчанию
    // 'Отображение' - это кастомный параметр, который форма должна будет обработать
    ОткрытьФормуМодально("Справочник.Номенклатура.ФормаВыбора", Новый Структура("Отбор,Отображение", Отбор, ОтображениеТаблицы.Список), ЭтаФорма);
    

    Однако, для того чтобы параметр "Отображение" сработал, в модуле открываемой формы должен быть соответствующий код, который будет его обрабатывать, например, в обработчике ПриСозданииНаСервере:

    
    // В модуле формы списка/выбора Справочник.Номенклатура
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ)
        Если Параметры.Свойство("Отображение") Тогда
            Элементы.Список.Отображение = Параметры.Отображение;
        КонецЕсли;
    КонецПроцедуры
    

    Этот подход требует модификации целевой формы, что не всегда возможно.

Сценарий 2: Отбор по сложному условию ("Содержит", "ВСписке", "Больше" и т.д.)

Когда требуется использовать более сложные виды сравнения, такие как "Содержит", передача отбора через структуру параметров может быть недостаточной. Нам потребуется напрямую работать с динамическим списком формы.

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

  1. Правильное получение объекта формы:

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

    
    // Некорректно (может работать, но ненадежно, если есть несколько форм)
    // ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора"); 
    
    // Корректно (получаем именно форму выбора справочника)
    ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", , ЭтаФорма);
    

    Использование .Форма.ФормаВыбора гарантирует, что мы получим именно тот объект формы, который хотим настроить.

  2. Установка отбора на динамический список:

    После получения объекта формы, мы обращаемся к ее динамическому списку (обычно элемент формы с именем "Список") и добавляем элементы отбора:

    
    // 1. Получаем форму (с правильным путем)
    ФормаВыбораНоменклатуры = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", , ЭтаФорма); 
    
    // 2. Получаем объект динамического списка
    // Важно: обращение к Значение элемента формы, если Список - это элемент формы.
    // Или напрямую к свойству Форма.Список, если это основное свойство формы.
    СписокНом = ФормаВыбораНоменклатуры.Список; 
    
    // 3. Создаем и добавляем элемент отбора
    ЭлементОтбора = СписокНом.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование"); // Поле, по которому отбираем
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит; // Вид сравнения (например, "Содержит")
    ЭлементОтбора.ПравоеЗначение = "ЧастьНаименования"; // Значение для сравнения
    ЭлементОтбора.Использование = Истина; // Включаем отбор
    
    // 4. Если нужно, устанавливаем режим отображения
    ФормаВыбораНоменклатуры.Элементы.Список.Отображение = ОтображениеТаблицы.Список; 
    
    // 5. Устанавливаем режим выбора, если это форма выбора
    ФормаВыбораНоменклатуры.Параметры.РежимВыбора = Истина;
    
    // 6. Открываем форму
    Номенклатура = ФормаВыбораНоменклатуры.ОткрытьМодально(); 
    

    Важный нюанс с порядком действий и модальным открытием:

    В приведенном выше примере `ОткрытьМодально()` выполняется в конце. Это означает, что отбор и режим отображения устанавливаются *до* того, как пользователь увидит форму. Однако, на определенных платформах или при определенных условиях, отбор может не "сработать" сразу, если форма открывается модально.

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

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

    
    // 1. Получаем форму
    ФормаСпр = ПолучитьФорму("Справочник.Контрагенты.ФормаВыбора",,ЭтаФорма);
    
    // 2. Устанавливаем отбор (например, "ВСписке")
    // Для примера используем вспомогательную функцию УстановитьЭлементОтбора,
    // но можно добавлять ЭлементыОтбораКомпоновкиДанных напрямую, как показано выше.
    // ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора( 
    //     ФормаСпр.Список.Отбор, 
    //     "Ссылка", 
    //     СписокКонтрагентов, // СписокЗначений с отобранными ссылками
    //     ВидСравненияКомпоновкиДанных.ВСписке, 
    //     , 
    //     Истина, 
    //     РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ
    // ); 
    
    // 3. Открываем форму НЕмодально, чтобы дать ей инициализироваться
    ФормаСпр.Открыть(); 
    
    // 4. Сразу же устанавливаем отображение и ЗАКРЫВАЕМ форму.
    // Это "заставляет" форму обновить свои параметры и отборы.
    ФормаСпр.Элементы.Список.Отображение = ОтображениеТаблицы.Список; 
    ФормаСпр.Закрыть(); 
    
    // 5. Теперь открываем форму МОДАЛЬНО с уже настроенными параметрами
    // (отбор и отображение должны быть 'запомнены' формой после предыдущего открытия и закрытия)
    ЗначениеСпр = ФормаСпр.ОткрытьМодально(); 
    
    Если НЕ ЗначениеСпр = Неопределено Тогда
        Объект.Контрагент = ЗначениеСпр;
    КонецЕсли;
    

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

  3. Установка отбора в модуле открываемой формы:

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

    Код в вызывающей форме/обработке:

    
    // Создаем структуру с нашими сложными параметрами отбора
    ПараметрыДляОтбора = Новый Структура();
    ПараметрыДляОтбора.Вставить("ИмяРеквизитаОтбора", "Наименование");
    ПараметрыДляОтбора.Вставить("ВидСравненияОтбора", ВидСравненияКомпоновкиДанных.Содержит);
    ПараметрыДляОтбора.Вставить("ЗначениеОтбора", "ЧастьНаименования");
    ПараметрыДляОтбора.Вставить("ТребуемоеОтображение", ОтображениеТаблицы.Список);
    
    // Передаем параметры в новую форму
    ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыДляОтбора, ЭтаФорма);
    ФормаВыбора.ОткрытьМодально();
    

    Код в модуле открываемой формы (Справочник.Номенклатура.Форма.ФормаВыбора):

    
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ)
        Если Параметры.Свойство("ИмяРеквизитаОтбора") Тогда
            // Устанавливаем отбор
            ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
            ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(Параметры.ИмяРеквизитаОтбора);
            ЭлементОтбора.ВидСравнения = Параметры.ВидСравненияОтбора;
            ЭлементОтбора.ПравоеЗначение = Параметры.ЗначениеОтбора;
            ЭлементОтбора.Использование = Истина;
        КонецЕсли;
    
        Если Параметры.Свойство("ТребуемоеОтображение") Тогда
            // Устанавливаем режим отображения
            Элементы.Список.Отображение = Параметры.ТребуемоеОтображение;
        КонецЕсли;
    КонецПроцедуры
    

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

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

← На главную