Как заменить обращение к дереву значений формы, чтобы перенести код в общий модуль

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

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

Анализ проблемы: различие между данными формы и программным объектом

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

Важный момент: у объекта ДеревоЗначений и его строк нет метода ПолучитьЭлементы(). Вместо него используется универсальное свойство Строки. Попытка вызвать метод формы на сервере — это фундаментальная ошибка типизации.

Перенос кода: замена методов

Рассмотрим, как должен измениться ваш код при переходе от формы к серверному объекту. Если в форме вы писали:


// Код в модуле формы (использование ДанныеФормыДерево)
ЭлементыУровня = ТекущаяСтрока.ПолучитьЭлементы();
Для Каждого Стр Из ЭлементыУровня Цикл
    // Обработка
КонецЦикла;

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


// Код на сервере (использование ДеревоЗначений)
ЭлементыУровня = ТекущаяСтрока.Строки; 
Для Каждого Стр Из ЭлементыУровня Цикл
    // Обработка
КонецЦикла;

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

Рекурсивный обход дерева значений на сервере

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


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

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

Преобразование между формой и сервером

Если ваша задача — взять данные из дерева, которое пользователь уже заполнил на форме, и передать их в общий модуль для сложной обработки, вам потребуются методы преобразования. Мы не можем просто передать Элементы.ДеревоНаФорме в серверную функцию. Нам нужно преобразовать данные формы в значение объекта:

  1. Используем метод ДанныеФормыВЗначение(), чтобы получить чистый объект ДеревоЗначений.
  2. Передаем полученный объект в общий модуль.
  3. При необходимости вернуть результат на форму используем обратный метод ЗначениеВДанныеФормы().

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


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

Альтернативные варианты замены дерева

Иногда отказ от ДеревоЗначений продиктован требованиями производительности. Проанализируем ситуацию: если в вашем дереве более 100 000 строк, работа с ним может стать крайне медленной из-за особенностей сериализации. В таких случаях рассмотрим альтернативы:

Подведем итоги

Для успешного отказа от использования формы в коде при работе с деревьями необходимо помнить три правила:

  1. Забудьте про метод ПолучитьЭлементы() вне контекста элементов формы. Используйте свойство Строки.
  2. Используйте типизацию: всегда четко понимайте, с чем вы работаете — с ДанныеФормыДерево (на клиенте/в модуле формы) или с ДеревоЗначений (в серверной логике).
  3. Рекурсия — ваш главный инструмент: для программной обработки иерархии всегда создавайте вспомогательные процедуры, принимающие коллекцию строк в качестве параметра.

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

← На главную