Как исправить ошибку «Отсутствует строка данных» при разворачивании дерева значений в 1С 8.3?

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

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

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

Причины возникновения ошибки

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

Выделим основные причины появления ошибки:

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

Решение 1. Использование актуального идентификатора текущей строки

Если задача заключается в том, чтобы развернуть строку, с которой в данный момент работает пользователь, необходимо получить её настоящий идентификатор. Для этого в управляемых формах используются методы объекта ДанныеФормыЭлементДерева или свойства самой таблицы формы.

Рассмотрим два варианта корректного вызова на клиенте:

Вариант А. Через метод ПолучитьИдентификатор():


&НаКлиенте
Процедура МесяцПриИзменении(Элемент)
    ТекДанные = Элементы.ДеревоБюджет.ТекущиеДанные;
    
    Если ТекДанные <> Неопределено Тогда
        // Пересчитываем данные на сервере
        РассчитатьДеревоПоСтроке(ТекДанные.Ссылка);
        
        // Получаем актуальный идентификатор и разворачиваем узел
        ИдентификаторСтроки = Элементы.ДеревоБюджет.ТекущиеДанные.ПолучитьИдентификатор();
        Элементы.ДеревоБюджет.Развернуть(ИдентификаторСтроки, Истина);
    КонецЕсли;
КонецПроцедуры

Вариант Б. Через свойство ТекущаяСтрока:

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


&НаКлиенте
Процедура РазвернутьТекущуюСтроку()
    Идентификатор = Элементы.ДеревоБюджет.ТекущаяСтрока;
    Если Идентификатор <> Неопределено Тогда
        Элементы.ДеревоБюджет.Развернуть(Идентификатор, Истина);
    КонецЕсли;
КонецПроцедуры

Решение 2. Разворачивание всех верхних узлов дерева

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


&НаКлиенте
Процедура РазвернутьВерхнийУровень()
    // Получаем коллекцию элементов верхнего уровня
    КорневыеЭлементы = Элементы.ДеревоБюджет.ПолучитьЭлементы();
    
    Для Каждого ЭлементКоллекции Из КорневыеЭлементы Цикл
        Идентификатор = ЭлементКоллекции.ПолучитьИдентификатор();
        Элементы.ДеревоБюджет.Развернуть(Идентификатор, Ложь); // Разворачивает только данный уровень
    КонецЦикла;
КонецПроцедуры

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

Дополнительно: Определение текущей колонки в управляемых формах

В обычных формах для получения активной колонки использовалась конструкция ЭлементыФормы.ДеревоБюджет.ТекущаяКолонка.Имя. В управляемом интерфейсе подход изменился.

Для определения текущего поля (колонки) в управляемой форме используем свойство ТекущийЭлемент у элемента таблицы формы:


&НаКлиенте
Процедура ОпределитьКолонку()
    ТекущееПоле = Элементы.ДеревоБюджет.ТекущийЭлемент;
    Если ТекущееПоле <> Неопределено Тогда
        ИмяКолонки = ТекущееПоле.Имя;
        Сообщить("Активная колонка: " + ИмяКолонки);
    КонецЕсли;
КонецПроцедуры

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

← На главную