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

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

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

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

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

Проблема в том, что «очистить дерево» — неоднозначная задача. Можно удалить все строки, оставив сам реквизит и колонки; можно очистить только подчинённые ветки конкретной строки; можно полностью пересоздать реквизит формы. Каждый вариант решается своим методом, и выбор неправильного приводит либо к лишним данным на форме, либо к падению кода с ошибкой «Поле объекта не обнаружено».

Ниже разобраны рабочие способы очистки дерева значений на управляемой форме: от простого вызова Очистить() до очистки связанных таблиц и динамически созданных реквизитов. Примеры приведены на встроенном языке 1С и подходят для типовых и самописных конфигураций на платформе 8.3.

Где хранится дерево на форме и почему это важно

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

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

Второй нюанс — идентификаторы строк. У ДанныеФормыДерево каждая строка имеет числовой идентификатор (ПолучитьИдентификатор()), по которому платформа связывает данные с элементом отображения. При очистке коллекции идентификаторы освобождаются, и любые сохранённые ранее ссылки на строки становятся недействительными.

Базовый способ: очистка всех строк дерева

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

&НаКлиенте

Процедура ОчиститьДерево(Команда)

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

КонецПроцедуры

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

Если очистка выполняется в серверной процедуре перед новым заполнением, код аналогичен:

&НаСервере

Процедура ЗаполнитьДеревоНаСервере()

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

// далее заполнение новыми данными

КонецПроцедуры

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

Порядок действий
  1. 1
    Определите имя реквизита формы с типом «ДеревоЗначений»
  2. 2
    В нужной процедуре вызовите Реквизит.ПолучитьЭлементы().Очистить()
  3. 3
    При необходимости заполните дерево новыми данными
  4. 4
    Проверьте: Количество() элементов равно 0, на форме пустая таблица

Очистка только подчинённых строк конкретной ветки

Не всегда нужно удалять дерево целиком. Типовая задача — свернуть ветку: оставить родительскую строку, но удалить всех её потомков, например при повторном раскрытии узла с актуальными данными.

Для этого получают коллекцию элементов нужной строки и очищают именно её:

СтрокаРодитель = Дерево.НайтиПоИдентификатору(ИдентификаторСтроки);

СтрокаРодитель.ПолучитьЭлементы().Очистить();

Родительская строка остаётся на месте, удаляются только вложенные. Этот приём удобен при «ленивой» подгрузке дерева: пользователь разворачивает узел — подгружаются свежие данные, перед чем старые потомки очищаются.

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

Очистка дерева, полученного через РеквизитФормыВЗначение

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

&НаСервере

Процедура ОчиститьНаСервере()

ДЗ = РеквизитФормыВЗначение("Дерево");

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

ЗначениеВРеквизитФормы(ДЗ, "Дерево");

КонецПроцедуры

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

У этого способа есть цена: преобразование реквизита в значение и обратно — относительно затратная операция, особенно на больших деревьях, и она сбрасывает состояние развёрнутости узлов на форме. Если нужно просто удалить строки, прямой вызов ПолучитьЭлементы().Очистить() предпочтительнее.

Сравнение вариантов

ПолучитьЭлементы().Очистить()

Быстро, без преобразований, работает и на клиенте, и на сервере. Подходит для большинства случаев.

РеквизитФормыВЗначение + Строки.Очистить()

Только на сервере, затратнее по ресурсам, сбрасывает развёрнутость узлов. Оправдан, если дальше идёт массовая обработка объекта.

Удаление реквизита

Полное удаление через ИзменитьРеквизиты(). Нужно редко — только если дерево создавалось программно и больше не требуется.

Очистка программно созданного дерева и связанных данных

Если дерево и его колонки созданы программно через ИзменитьРеквизиты(), простая очистка строк оставит сам реквизит и элементы формы. Когда дерево больше не нужно вовсе (например, закрывается вкладка динамической обработки), реквизит можно удалить:

МассивУдаляемых = Новый Массив;

МассивУдаляемых.Добавить("Дерево");

ИзменитьРеквизиты(, МассивУдаляемых);

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

Отдельная ситуация — связанные данные. Если строки дерева связаны с реквизитами формы через «СвязьПоВладельцу» или вы храните дополнительные данные в соответствиях и таблицах, очистка дерева их не трогает. Такие структуры нужно очищать явно, иначе в памяти останутся «сироты», которые могут привести к ошибкам при следующем заполнении.

Типичные ошибки при очистке дерева

Первая и самая распространённая — обращение к Строки в модуле управляемой формы. У ДанныеФормыДерево этого свойства нет, правильный путь — ПолучитьЭлементы(). Обратная ошибка встречается реже: попытка вызвать ПолучитьЭлементы() у обычного дерева значений, созданного через Новый ДеревоЗначений.

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

Третья группа проблем — работа с идентификаторами. После очистки дерева все ранее полученные идентификаторы строк недействительны. Если в переменных формы хранится, например, «ТекущаяСтрокаДерева», её нужно сбросить в Неопределено вместе с очисткой, иначе следующее обращение через НайтиПоИдентификатору() вернёт ошибку или неожиданный результат.

Типичные ошибки
01
Вызов Дерево.Строки.Очистить() в модуле формы — ошибка «Поле объекта не обнаружено», нужен ПолучитьЭлементы()
02
Удаление строк внутри цикла обхода коллекции — пропуск элементов или падение кода
03
Сохранение старых идентификаторов строк после очистки — ошибки при НайтиПоИдентификатору
04
Очистка только дерева без очистки связанных соответствий — устаревшие данные при повторном заполнении

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

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

Если Дерево.ПолучитьЭлементы().Количество() = 0 Тогда

// дерево очищено корректно

КонецЕсли;

Дополнительно проверьте, что очищены связанные структуры (соответствия, таблицы расшифровки), сброшены сохранённые идентификаторы строк и что повторное заполнение дерева не создаёт дублей. Если после очистки на форме остались строки — скорее всего, вы очищаете один реквизит, а таблица привязана к другому, либо очистка выполняется до асинхронной подгрузки данных, которая заполняет дерево заново.

Контрольные точки

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

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

ПолучитьЭлементы().Количество() = 0

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

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

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

Таблица дерева пустая, колонки на месте

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

Строки видны или пропали колонки — затронут реквизит/элемент формы

Сохранённые идентификаторы строк
Норма

Переменные с идентификаторами сброшены в Неопределено

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

Старые идентификаторы используются — ошибки при обращении

Частые вопросы

Чем очистка дерева на форме отличается от очистки обычного дерева значений?

На управляемой форме реквизит имеет тип ДанныеФормыДерево, у которого нет свойства «Строки» — вместо него метод ПолучитьЭлементы(). У обычного дерева значений (Новый ДеревоЗначений) строки очищаются через Строки.Очистить(). Синтаксис разный, результат одинаковый: удаляются все строки вместе с потомками.

Удалятся ли колонки дерева при вызове Очистить()?

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

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

Вызов Дерево.ПолучитьЭлементы().Очистить() работает и в клиентской процедуре — обращения к серверу не требуется, если дальше не нужно получать новые данные. Это быстрый способ сбросить содержимое перед локальными действиями пользователя.

Почему после очистки дерево снова заполняется старыми данными?

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

Нужно ли очищать дерево перед закрытием формы?

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

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

Очистить() здесь не подходит — нужен выборочный обход. Получите коллекцию элементов, пройдите по ней в обратном порядке по индексу (от Количество()-1 до 0) и удаляйте строки с установленным признаком через Коллекция.Удалить(Индекс). Обратный порядок нужен, чтобы удаление не сдвигало индексы ещё не обработанных строк.

Итог

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

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