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

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

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

Архитектура и отличия от ТаблицыЗначений

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

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

⚠️ Внимание: Не путайте объект метаданных «Дерево значений» (используется в СКД) и программный объект ДеревоЗначений. Хотя концепция похожа, способы работы с ними в коде различаются.

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

💡

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

Создание объекта и описание колонок

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

Для описания колонок используется объект ОписаниеТипов, который позволяет задавать не только тип (Число, Строка, Дата), но и дополнительные параметры, такие как длина строки или точность числа. Это обеспечивает строгий контроль целостности данных внутри вашей временной структуры.

Рассмотрим пример создания дерева с тремя колонками: "Номенклатура", "Количество" и "Сумма".

Дерево = Новый ДеревоЗначений;

Дерево.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

Дерево.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", , 15, 3));

Дерево.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", , 15, 2));

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

☑️ Подготовка структуры дерева

Выполнено: 0 / 4

Наполнение данными и работа с иерархией

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

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

  • 🌳 Добавление корневой строки: Строка = Дерево.Добавить()
  • 🌿 Добавление вложенной строки: Дочерняя = Строка.Добавить()
  • 📝 Запись значения: Строка.Номенклатура = СсылкаНаТовар
  • 🔄 Перемещение узла: изменение свойства Родитель у строки

Часто возникает необходимость скопировать данные из результата запроса в дерево. В таких случаях удобно использовать цикл по выборке запроса. Внутри цикла вы создаете новые строки в дереве и присваиваете им значения из полей выборки. Это стандартный паттерн переноса данных из базы в оперативную память для дальнейшей обработки.

⚠️ Внимание: При копировании больших объемов данных (сотни тысяч строк) в дерево значений учитывайте потребление оперативной памяти сервера. В таких случаях эффективнее использовать временные таблицы.

📊 Как вы чаще всего заполняете дерево значений?
Вручную в цикле
Копированием из ТаблицыЗначений
Загрузкой из XML/JSON
Через консоль запросов

Сортировка, фильтрация и поиск данных

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

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

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

Метод/Свойство Назначение Возвращаемое значение
Сортировка Установка порядка строк КоллекцияСортировки
НайтиСтроки() Поиск по критериям Массив строк дерева
Фильтр Отбор видимых элементов КоллекцияФильтра
ПолучитьЭлементы() Доступ к строкам уровня КоллекцияСтрокДереваЗначений

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

Особенность поиска

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

Преобразование типов и передача в отчеты

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

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

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

ТаблицаПлоская = Дерево.ПолучитьТаблицуЗначений();

// Теперь таблицу можно передать в макет или записать в файл

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

💡

Для передачи в печатные формы чаще всего используют метод ПолучитьТаблицуЗначений(), но для веб-сервисов лучше подходит прямая сериализация в JSON.

Оптимизация производительности и типичные ошибки

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

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

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

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

⚠️ Внимание: Интерфейс объектов системы 1С может обновляться в новых версиях платформы. Всегда проверяйте документацию по вашей конкретной версии релиза, если используете новые методы работы с коллекциями.

Лайфхак для скорости

Если нужно просто накопить данные без иерархии, используйте ТаблицуЗначений. Она работает быстрее на операциях добавления за счет более простой внутренней структуры.

Можно ли изменить тип колонки после создания дерева?

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

Как удалить строку из дерева значений?

Для удаления строки используется метод Удалить() у объекта строки. Также можно удалить всю коллекцию дочерних элементов через метод Очистить() у родительской строки или у самого дерева для полного сброса.

В чем разница между ДеревоЗначений и ТаблицейЗначений?

Главное отличие — наличие иерархии. ДеревоЗначений поддерживает вложенность строк (родитель-потомок), тогда как ТаблицаЗначений представляет собой плоский список записей без уровней вложенности.

Как передать дерево значений в другую форму или модуль?

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

Поддерживает ли дерево значений индексацию для быстрого поиска?

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