К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как очистить дерево значений в 1С

Как очистить дерево значений в 1С: метод Очистить(), удаление строк, очистка колонок и реквизита формы. Примеры кода, типичные ошибки и проверка результата.

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

Очистить дерево значений можно несколькими способами: методом Очистить() коллекции строк, удалением строк в цикле, пересозданием объекта или очисткой реквизита формы. Выбор зависит от того, где находится дерево — в переменной на сервере, в реквизите управляемой формы или в элементе формы «Дерево значений».

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

Что происходит при очистке дерева значений

Объект «ДеревоЗначений» состоит из двух частей: коллекции колонок (описание структуры) и коллекции строк (сами данные). Очистка затрагивает именно строки: удаляются все элементы коллекции Строки верхнего уровня, а вместе с ними — все вложенные подчинённые строки любой глубины вложенности.

Колонки при стандартной очистке не удаляются. Это важно: если после очистки вы снова заполняете дерево по той же структуре, пересоздавать колонки не нужно. Если же структура должна измениться, колонки удаляют отдельно через Дерево.Колонки.Очистить() или создают новый объект.

Очистка строк методом Очистить()

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

Дерево.Строки.Очистить();

Если нужно очистить не всё дерево, а только ветку конкретной строки, вызовите метод у её коллекции подчинённых строк:

СтрокаРодитель = Дерево.Строки.Найти(ИскомоеЗначение, "Номенклатура");

Если СтрокаРодитель <> Неопределено Тогда

СтрокаРодитель.Строки.Очистить();

КонецЕсли;

После выполнения метода дерево остаётся валидным объектом с пустой коллекцией строк — его можно сразу заполнять заново без пересоздания.

bsl
Дерево.Строки.Очистить(); // удаляет все строки вместе с подчинёнными

Очистка дерева в реквизите управляемой формы

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

Первый вариант — очистить строки напрямую у реквизита формы, не извлекая объект. Коллекция строк реквизита поддерживает метод Очистить():

ДеревоДанных.ПолучитьЭлементы().Очистить();

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

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

Удаление строк в цикле и по условию

Иногда требуется удалить не все строки, а только часть — по условию или по одной. Для единичного удаления используется метод Удалить() коллекции строк:

СтрокаДляУдаления = Дерево.Строки.Найти(ЗначениеПоиска, "Код", Истина);

Если СтрокаДляУдаления <> Неопределено Тогда

Родитель = СтрокаДляУдаления.Родитель;

Если Родитель = Неопределено Тогда

Дерево.Строки.Удалить(СтрокаДляУдаления);

Иначе

Родитель.Строки.Удалить(СтрокаДляУдаления);

КонецЕсли;

КонецЕсли;

Для выборочного удаления по условию удобен обход коллекции с конца, чтобы удаление не сбивало индексы:

КоллекцияСтрок = Дерево.Строки;

Для Индекс = 1 - КоллекцияСтрок.Количество() По 0 Цикл

Строка = КоллекцияСтрок[-Индекс];

Если Строка.Пометка = Ложь Тогда

КоллекцияСтрок.Удалить(Строка);

КонецЕсли;

КонецЦикла;

При рекурсивной обработке вложенных уровней учитывайте, что удаление родительской строки удаляет и все её подчинённые ветки — отдельно очищать их не требуется.

Пересоздание объекта как альтернатива очистке

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

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

Дерево.Колонки.Добавить("Номенклатура");

Дерево.Колонки.Добавить("Количество");

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

Сравнение способов очистки

Строки.Очистить()

Универсальный способ для переменной и реквизита формы; сохраняет колонки и связь с элементом формы

Удаление в цикле

Подходит для выборочного удаления по условию; медленнее и требует аккуратной работы с индексами

Пересоздание объекта

Уместно при смене структуры колонок; для реквизита формы требует повторной привязки данных

Проверка результата и типичные ошибки

После очистки убедитесь, что дерево действительно пусто: проверьте Дерево.Строки.Количество() = 0 для переменной или ДеревоДанных.ПолучитьЭлементы().Количество() = 0 для реквизита формы. Для вложенных уровней дополнительная проверка не нужна — очистка верхнего уровня удаляет всё поддерево.

Частая ситуация: код очистки выполнен, но на форме данные остались. Причина почти всегда в том, что очищена локальная копия объекта, полученная через РеквизитФормыВЗначение(), а результат не возвращён в реквизит формы. Либо очищена другая переменная, не связанная с отображаемым деревом.

Типичные ошибки
01
Очистка объекта после РеквизитФормыВЗначение() без обратного ЗначениеВРеквизитФормы() — форма продолжает показывать старые данные
02
Удаление строк в прямом цикле по индексу — пропускаются элементы из-за сдвига индексов при удалении
03
Очистка колонок вместе со строками, когда структура нужна для повторного заполнения — приходится пересоздавать колонки
04
Попытка вызвать Строки.Очистить() у реквизита формы напрямую — у данных формы нет свойства Строки, используйте ПолучитьЭлементы()
Контрольные точки

Как проверить результат

Количество строк верхнего уровня
Норма

Равно нулю после очистки

Тревожный признак

Больше нуля — очистка не выполнена или очищена другая коллекция

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

Элемент формы пуст сразу после очистки реквизита

Тревожный признак

Данные видны — очищена копия объекта, не связанная с формой

Структура колонок
Норма

Колонки на месте, дерево готово к повторному заполнению

Тревожный признак

Колонки удалены — при заполнении возникнут ошибки обращения к полям

FAQ

Удаляются ли подчинённые строки при очистке верхнего уровня?

Да. Метод Очистить() у коллекции строк верхнего уровня удаляет каждую строку вместе со всей её вложенной иерархией любой глубины. Отдельно обходить и очищать вложенные уровни не требуется.

Как очистить только одну ветку дерева, а не всё целиком?

Найдите нужную строку-родителя (например, методом Найти) и вызовите Очистить() у её коллекции подчинённых строк: СтрокаРодитель.Строки.Очистить(). Сама строка-родитель при этом сохранится, удалятся только её потомки.

Почему после очистки дерево на форме не обновилось?

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

Нужно ли пересоздавать колонки после Очистить()?

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

Чем очистка отличается от присвоения Неопределено переменной с деревом?

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

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

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

Итог

Что важно запомнить

Для очистки дерева значений вызывайте Очистить() у коллекции строк: у переменной — Дерево.Строки.Очистить(), у реквизита формы — Реквизит.ПолучитьЭлементы().Очистить(). Колонки при этом сохраняются, подчинённые строки удаляются автоматически. После очистки проверяйте, что количество строк равно нулю и форма показывает пустое дерево.