Программное преобразование Таблицы значений в Дерево значений на управляемых формах

09.03.26

Разработка - Универсальные функции

Быстрое преобразование таблицы значений в дерево. Вывод дерева на форму, разворачивание строк по нужным условиям.

Искал на просторах интернета, но полного решения, которое меня устраивало, не нашел. 

Надеюсь, решение сохранит кому-то время.

 

Берём любую таблицу значений (ТЗ) или преобразовываем табличное поле в ТЗ.

На форме добавляем реквизит "ЕстьДерево" с типом Булево.

Передаём в (естественно, поля для упорядочивания и итогов должны быть в передаваемой ТЗ)

ДеревоОбъект=Обработки.СозданиеЗаказаПоставщику.ТаблицуЗначенийВДеревоЗначений(Объект.ТоварныеПозиции.Выгрузить());

 

Функция ТаблицуЗначенийВДеревоЗначений(ТаблицаЗначений) Экспорт
    Запрос=Новый Запрос;
    Запрос.МенеджерВременныхТаблиц=Новый МенеджерВременныхТаблиц;
    Текст="ВЫБРАТЬ
          | *
          |ПОМЕСТИТЬ НаЭкран
          |ИЗ
          | &ВремТЗ КАК ТаблицаЗначений
          |;
          |
          |////////////////////////////////////////////////////////////////////////////////
          |ВЫБРАТЬ
          | НаЭкран.*
          |ИЗ
          | НаЭкран КАК НаЭкран
          |УПОРЯДОЧИТЬ ПО
          | ПоставщикНаименование,
          | Рекомендовано УБЫВ, КЗаказу УБЫВ 
          |ИТОГИ ПО
          | Поставщик,КЗаказу";
    
    Запрос.УстановитьПараметр("ВремТЗ",ТаблицаЗначений);
    Запрос.Текст=Текст;
    Результат = Запрос.Выполнить();
    Дерево=Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
    Возврат Дерево;
КонецФункции  //ТаблицуЗначенийВДеревоЗначений(ТаблицаЗначений)

 

Полученное дерево отрисовываем на форме, попутно избавляясь от значения Null, которое ВСЕГДА добавляет запрос.

 

        
        Если ТипЗнч(ДеревоОбъект)=Тип("ДеревоЗначений") И ДеревоОбъект.Строки.Количество()>0 Тогда
            Если 1=2 Тогда
            	ДеревоОбъект=Новый ДеревоЗначений;
            КонецЕсли;
            ЕстьДерево=Истина;
            Элементы.ГруппаСвернуто.Видимость=Истина;
            Элементы.ТоварныеПозиции.Видимость=Ложь;
            МассивУдаляемыхРеквизитов = Новый Массив;
            РеквизитыФормы = ЭтаФорма.ПолучитьРеквизиты();
            ЕстьУдаляемые=Ложь;
            Для Каждого РеквизитФормы Из РеквизитыФормы Цикл
                ИмяРеквизита = РеквизитФормы.Имя;
                Если ИмяРеквизита="ЕстьДерево" Тогда
                	Продолжить;
                КонецЕсли;
                Если СтрНайти(ИмяРеквизита, "Дерево")>0 Тогда 
                    МассивУдаляемыхРеквизитов.Добавить(ИмяРеквизита);
                    ЕстьУдаляемые=Истина;
                КонецЕсли;
            КонецЦикла;
            ИзменитьРеквизиты(,МассивУдаляемыхРеквизитов);
            Если ЕстьУдаляемые=Истина Тогда
            	ПодчЭлем=Элементы.ГруппаСвернуто.ПодчиненныеЭлементы;
                Для каждого Элем Из ПодчЭлем Цикл
                    Попытка
                    	Элементы.Удалить(Элем);
                    Исключение
                    КонецПопытки;
                КонецЦикла;
            КонецЕсли;
            МассивДобавляемыхРеквизитов = Новый Массив;
            МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево", Новый ОписаниеТипов("ДеревоЗначений")));
            Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
                КолонкаИмя=Колонка.Имя;
                МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(КолонкаИмя, Новый ОписаниеТипов(Колонка.ТипЗначения,,"NULL"), "Дерево"));
            КонецЦикла;
            ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
            
            ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");
            
            ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"),Элементы.ГруппаСвернуто);
            ЭлементДерево.ПутьКДанным = "Дерево";
            ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;
            ЭлементДерево.ИзменятьСоставСтрок=Ложь;
            ЭлементДерево.ИзменятьПорядокСтрок=Ложь;
            
            Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
                КолонкаИмя=Колонка.Имя;
                НовыйЭлемент = Элементы.Добавить("_"+КолонкаИмя, Тип("ПолеФормы"), ЭлементДерево);
                НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
                Если КолонкаИмя="Поставщик" ИЛИ КолонкаИмя="Номенклатура" Тогда
                	НовыйЭлемент.Ширина=25;
                 ИначеЕсли КолонкаИмя="ДоОстатка" Тогда
                    НовыйЭлемент.Заголовок="ДО";
                    НовыйЭлемент.Подсказка="До остатка";
                    НовыйЭлемент.Вид=ВидПоляФормы.ПолеФлажка;
                    НовыйЭлемент.ВидФлажка=ВидФлажка.Флажок;
                    НовыйЭлемент.ШиринаЭлемента=3;
                ИначеЕсли КолонкаИмя="Рекомендовано" Тогда
                	НовыйЭлемент.Шрифт=Новый Шрифт(,,Истина);
                ИначеЕсли КолонкаИмя="ИсходныйНомерСтроки" Тогда
                	НовыйЭлемент.Видимость=Ложь; 
                Иначе
                	НовыйЭлемент.Ширина=7;
                КонецЕсли;
                НовыйЭлемент.ПутьКДанным = "Дерево." + КолонкаИмя;
            КонецЦикла;
        КонецЕсли;

 

В клиентской процедуре добавляем рекурсивную процедуру для обработки (свертки, развертки строк дерева)

   

Если ЕстьДерево=Истина Тогда
        ОбойтиДеревоРекурсивноСтрокиДереваНаКлиенте(ЭтаФорма["Дерево"]);
    КонецЕсли;

 

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

 

Я рекурсию тут не использую, но возможность её есть. Нужно чуток поправить код под себя.

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    4238    Abysswalker    11    

46

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

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

14.05.2025    7863    DeerCven    15    

62

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    53386    dimanich70    84    

174

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    7718    7    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    67920    atdonya    31    

72

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    9682    ke.92@mail.ru    17    

68
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. gybson 6 09.03.26 20:41 Сейчас в теме
А чем это лучше ЗначениеВРеквизитФормы?
2. vko_70 8 10.03.26 09:34 Сейчас в теме
(1) Чтобы сохранять в реквизит формы - нужно заранее создавать структуру, здесь же дерево произвольной формы и можно формировать на лету
3. vbuots 20 10.03.26 10:25 Сейчас в теме
Если 1=2 Тогда
            	ДеревоОбъект=Новый ДеревоЗначений;
            КонецЕсли;


есть какой-то тайный смысл в этом?
4. starik-2005 3213 10.03.26 14:05 Сейчас в теме
(3)
тайный смысл
Автоподстановка.
6. vko_70 8 10.03.26 14:42 Сейчас в теме
(3) Это грязь кода) 1С часто теряет связи. Для их восстановления я часто юзаю 1=2 для определения значения.
5. starik-2005 3213 10.03.26 14:09 Сейчас в теме
Проц Рекурсивненько(СтрокаДерева, Таблица)
  Для Каждого Ст Из Строка.Строки Цикл
    ЗаполнитьЗначениеСвойств(Таблица.Добавить(), Ст);
    Рекурсивненько(Ст, Таблица);
  КонецЦикла;
КонецПроц

/// где-то там
Рекурсивненько(Дерево, Таблица);

Показать
Для отправки сообщения требуется регистрация/авторизация