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

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

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

Анализ причины ошибки: Табличная часть vs Дерево значений

Проанализируем ситуацию: автор пытается использовать метод ДокНормыВыдачиСИЗ.ЛичныеНормыВыдачи.Строки.Добавить(). С точки зрения платформы 1С, это принципиальная ошибка в понимании типов данных. Выясним причину:

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

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

Как реализовать иерархию в плоской таблице

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

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


// Инициализируем переменную для хранения текущего родительского узла
Переменная ТекущаяДолжность = Неопределено;

Для Каждого СтрТЗ Из ТаблицаИсточник Цикл
    
    // Создаем новую строку в табличной части документа
    НоваяСтрока = ДокОбъект.ЛичныеНормыВыдачи.Добавить();
    
    // Проверяем, заполнена ли должность в источнике (новая ветка дерева)
    Если ЗначениеЗаполнено(СтрТЗ.Должность) Тогда
        
        // Ищем должность в справочнике или создаем новую
        НайденнаяДолжность = Справочники.Должности.НайтиПоНаименованию(СокрЛП(СтрТЗ.Должность), Истина);
        
        Если НайденнаяДолжность.Пустая() Тогда
            НовыйОбъект = Справочники.Должности.СоздатьЭлемент();
            НовыйОбъект.Наименование = СокрЛП(СтрТЗ.Должность);
            НовыйОбъект.Записать();
            НайденнаяДолжность = НовыйОбъект.Ссылка;
        КонецЕсли;
        
        // Устанавливаем значение и запоминаем его как текущее для последующих строк
        НоваяСтрока.ДолжностьПрофессия = НайденнаяДолжность;
        ТекущаяДолжность = НайденнаяДолжность;
        
    Иначе
        // Если должность в текущей строке источника пуста, 
        // привязываем строку к последней найденной должности
        НоваяСтрока.ДолжностьПрофессия = ТекущаяДолжность;
    КонецЕсли;
    
    // Заполняем остальные реквизиты (СИЗ, количество и т.д.)
    НоваяСтрока.СредствоЗащиты = Справочники.СредстваИндивидуальнойЗащиты.НайтиПоНаименованию(СтрТЗ.СредствоЗащиты);
    // ... заполнение других полей
КонецЦикла;

В данном примере мы используем плоскую структуру, где каждая строка содержит ссылку на должность. Если на форме настроена группировка по полю ДолжностьПрофессия, пользователь увидит дерево, хотя в базе данных все строки будут равноправны.

Работа с настоящим Деревом значений через форму

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

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

Посмотрим на пример реализации такой задачи в модуле формы:


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

Важные рекомендации по оптимизации кода

Разберем несколько критических моментов, которые часто упускают начинающие разработчики при автоматическом создании элементов справочников и заполнении документов:

  1. Поиск по наименованию: Использование метода НайтиПоНаименованию внутри цикла — крайне ресурсоемкая операция. Если в вашей таблице тысячи строк, обработка будет работать очень медленно. Рекомендуется предварительно выгрузить справочник в Соответствие или ТаблицуЗначений и производить поиск в оперативной памяти.
  2. Транзакции и создание объектов: В коде автора (сообщение 7) объекты справочников создаются и записываются по одному. Проанализируем ситуацию: если в процессе записи произойдет сбой, часть данных останется в базе, а часть — нет. Правильнее объединять такие операции в одну транзакцию.
  3. Контроль дублей: При автоматическом создании должностей по строковым данным из внешних файлов (Excel, CSV) легко наплодить дублей из-за лишних пробелов или разного регистра. Всегда используйте СокрЛП() и, по возможности, приводите строки к одному регистру перед сравнением.

Подведем итог: если вы видите дерево на форме документа, сначала определите, как оно реализовано — через группировку плоской табличной части или через отдельный реквизит формы типа ДеревоЗначений. В первом случае используйте метод Добавить() у табличной части документа, во втором — работайте через преобразование реквизита формы в значение.

← На главную