ДеревоЗначений в 1С: реквизит формы или реквизит объекта — что выбрать и как работать?

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

При разработке сложных обработок в системе 1С:Предприятие 8.3, особенно когда речь идет о пакетном изменении данных (например, справочника контрагентов), перед программистом часто встает архитектурный вопрос: где именно объявить коллекцию данных, такую как ДеревоЗначений? Стоит ли сделать его реквизитом самой формы или вынести в реквизиты объекта обработки? На первый взгляд разница кажется несущественной, но она критически влияет на доступность данных в коде, производительность и возможность работы в фоновом режиме. Разберем эту тему подробно, проанализируем нюансы реализации и выясним, как избежать типичных ошибок при работе с типами данных управляемого приложения.

Различия в области видимости и доступе к данным

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

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

Особенности преобразования данных: РеквизитФормыВЗначение

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

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


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

А теперь выясним причину распространенной ошибки, упомянутой в обсуждении. Если вы создали ДЗКонтрагенты как реквизит объекта, попытка вызвать РеквизитФормыВЗначение("ДЗКонтрагенты") приведет к ошибке «Недопустимое значение параметра». Это происходит потому, что дерево теперь является частью структуры Объект. Чтобы получить к нему доступ как к объекту, нужно преобразовывать весь объект целиком:


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

Производительность и объем передаваемых данных

Рассмотрим важный аспект, который часто упускают при проектировании — сериализацию. Когда вы нажимаете кнопку на форме, вызывающую серверную процедуру, 1С передает контекст формы с клиента на сервер. Если ДеревоЗначений является реквизитом объекта (Объект.ДЗКонтрагенты), оно будет передаваться на сервер и обратно всегда, когда в процедуре задействован Объект. Если в дереве тысячи строк контрагентов, это вызовет заметные задержки («тормоза») интерфейса.

В случае, если дерево — это отдельный реквизит формы, у нас появляется больше гибкости. Мы можем вызывать серверные процедуры без контекста (&НаСервереБезКонтекста) и передавать туда только необходимые данные, либо не передавать дерево вовсе, если в конкретном вызове оно не требуется.

Динамическое изменение структуры

Выясним, как обстоят дела с гибкостью структуры колонок.

  1. Для реквизита объекта: Состав колонок жестко задан в конфигураторе. Если завтра вам понадобится добавить колонку «Дополнительная информация» в зависимости от настроек пользователя, сделать это в реквизите объекта «на лету» крайне сложно.
  2. Для реквизита формы: Вы можете программно управлять составом колонок с помощью метода формы ИзменитьРеквизиты(). Это позволяет создавать универсальные обработки, которые подстраиваются под текущие задачи (например, выводят разные наборы реквизитов контрагента для проверки).

Работа в фоновом режиме

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


// Пример вызова из внешнего кода
Обработка = Обработки.МассовоеИзменениеКонтрагентов.Создать();
Обработка.ЗаполнитьДеревоПоФильтру(ПараметрыОтбора); // Метод в модуле объекта
Обработка.ВыполнитьИзменения();

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

Итоги и рекомендации

Подведем итог нашему анализу. Выбор места размещения ДереваЗначений зависит от ваших целей:

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

← На главную