Как получить и перебрать все данные из таблицы формы (дерева значений) в 1С?

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

При разработке на управляемых формах в 1С часто возникает задача получить данные не только из одной выделенной строки таблицы, но и обработать все строки целиком. Если раньше вы использовали конструкцию вида Элементы.ТаблицаУслуг.ТекущиеДанные.Заказ, то знаете, что она возвращает данные только той строки, на которой в данный момент установлен курсор. Более того, если таблица пуста, это свойство вернет Неопределено, что может привести к ошибке. Давайте разберем по шагам, как правильно перебрать все строки таблицы формы, особенно если она имеет тип дерева значений.

Понимание типа: Данные формы или Объект?

Для начала выясним причину, по которой обычный цикл по элементам формы часто выдает ошибку "Итератор для значения не определен". На управляемой форме мы работаем не напрямую с объектами 1С (такими как таблица значений или дерево значений), а с их специальными проекциями. Источник данных у таблицы формы в режиме дерева имеет тип ДанныеФормыДерево.

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

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

Рассмотрим подробнее, как обойти все элементы. Если мы обращаемся к реквизиту-источнику нашей таблицы (например, ТаблицаУслуг), нам нужно получить его верхний уровень, а затем погрузиться в подчиненные узлы.

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


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

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


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

// Пример вызова:
// ОбойтиДерево(ТаблицаУслуг.ПолучитьЭлементы());

Преобразование в полноценное Дерево Значений на сервере

Если нам нужно выполнить сложные операции (сортировку, поиск по нескольким колонкам, свертку или выгрузку в XML), которые не поддерживает ДанныеФормыДерево, мы можем преобразовать данные в полноценный объект ДеревоЗначений. Это следует делать на сервере.

Разберем по шагам, как это реализовать. Воспользуемся методами конвертации:


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

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

Работа с выделенными строками и поиск

Иногда перед нами стоит задача обработать не все дерево, а только те строки, которые выделил пользователь. В этом случае мы обращаемся к свойству элемента формы ВыделенныеСтроки, которое возвращает массив идентификаторов.

Рассмотрим пример получения данных только для выделенных строк:


&НаКлиенте
Процедура ОбработатьВыделенные()
    МассивИД = Элементы.ТаблицаУслуг.ВыделенныеСтроки;
    Для Каждого Идентификатор Из МассивИД Цикл
        // Получаем данные конкретной строки по ID
        ДанныеСтроки = ТаблицаУслуг.НайтиПоИдентификатору(Идентификатор);
        Если ДанныеСтроки <> Неопределено Тогда
            Сообщить("Выбрана услуга: " + ДанныеСтроки.Услуга);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

У каждой строки в коллекции ДанныеФормыДерево есть уникальный идентификатор. Мы можем получить его с помощью метода ПолучитьИдентификатор(), а затем в любой момент быстро "прыгнуть" к нужному узлу с помощью НайтиПоИдентификатору(). Это избавляет от необходимости каждый раз запускать полный обход дерева для поиска одной строки.

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

← На главную