Многоуровневая структура из XDTO

27.09.21

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

Преобразование Объекта XDTO в многоуровневую Структуру. Вывод многоуровневой структуры в табличный документ.

Данная публикация развивает тему, поднятую в

https://forum.infostart.ru/forum104/topic194804/

Однако, преобразует не в одноуровневую, а в многоуровневую структуру.

Собственно сам код:

Передаём данные файла:

Функция ПрочитатьФайлНаСервере(ДанныеФайла,СвернутьПоле="") Экспорт

	ЧтениеДанных = Новый ЧтениеXML;
	ЧтениеДанных.УстановитьСтроку(ДанныеФайла);
	ЧтениеДанных.Прочитать();
	
	Данные=ФабрикаXDTO.ПрочитатьXML(ЧтениеДанных);
    Если ТипЗнч(Данные)=Тип("ОбъектXDTO") Тогда
        СтруктураРезультат=Новый Структура(); 
        Владелец="";
        ВычСтрока="Структ";
        ЗаписатьОбъектXDTOВСтруктуру(Данные,СтруктураРезультат,Владелец,ВычСтрока,Истина);
    Иначе
        ВызватьИсключение "XDTO. Что-то пошло не так....";
    КонецЕсли; 
КонецФункции // ПрочитатьФайлНаСервере(ДанныеФайла)

Функция, возвращающая структуру. Если не использовать ТаблицуЗначений, то полученную структуру можно смело загружать в JSon

Функция ПолучитьМассивИзСписка(Список)
    ВремМассив=Новый ТаблицаЗначений;
    АТутСписок=Новый СписокЗначений;
    Для каждого Стр Из Список Цикл
        НовСтр=ВремМассив.Добавить();
        Для каждого ВСтр Из Стр.Свойства() Цикл
            Если ВремМассив.Колонки.Найти(ВСтр.Имя)=Неопределено Тогда
                ВремМассив.Колонки.Добавить(ВСтр.Имя);
                Если ВСтр.ВерхняяГраница<>1 Тогда
                    АТутСписок.Добавить(ВСтр.Имя);
                КонецЕсли; 
            КонецЕсли;
            Если АТутСписок.НайтиПоЗначению(Встр.Имя)=Неопределено Тогда
                НовСтр[ВСтр.Имя]=Стр.Получить(ВСтр);
            Иначе
                НовСтр[ВСтр.Имя]=ПолучитьМассивИзСписка(Стр[ВСтр.Имя]);
            КонецЕсли; 
        КонецЦикла; 
    КонецЦикла; 
	Возврат ВремМассив;
КонецФункции // ПолучитьМассивИзСписка(Список)

Функция ЗаписатьОбъектXDTOВСтруктуру(Данные,Структ,Владелец,Знач ВычСтрока,ВложеннуюСтруктуруВТЗ=Ложь) Экспорт
    Если ТипЗнч(Данные)=Тип("ОбъектXDTO")=Ложь Тогда
        Сообщить("Это не XDTO");
    	Возврат Новый Структура(); 
    КонецЕсли;
    Коллекция=Данные.Свойства();
    Если Коллекция.Количество()=0 Тогда
        Владелец="";
    	Возврат Новый Структура();
    Иначе
        ВычСтрока=ВычСтрока+Владелец;
    КонецЕсли;
    ТТТ=Вычислить(ВычСтрока);
    н=0;
    Для каждого Элем Из Коллекция Цикл
        н=н+1;
        ТекКлюч=Элем.Имя;
        Если Элем.ВерхняяГраница=1 Тогда
            ЭлемДанные=Данные.Получить(Элем);
            Если ТипЗнч(ЭлемДанные)=Тип("ОбъектXDTO") Тогда
                Если ТТТ.Свойство(ТекКлюч)=Ложь Тогда
                    Владелец="."+ТекКлюч;
                    ТТТ.Вставить(ТекКлюч,Новый Структура);
                    ТТТ[ТекКлюч]=ЗаписатьОбъектXDTOВСтруктуру(Данные.Получить(Элем),Структ,Владелец,ВычСтрока,ВложеннуюСтруктуруВТЗ);
                КонецЕсли;
            ИначеЕсли ТипЗнч(Данные.Получить(Элем))=Тип("Строка") Тогда
                ТТТ.Вставить(ТекКлюч,ЭлемДанные);
            Иначе
                А=1; //можно установить точку останова и посмотреть, что тут.....
            КонецЕсли;
        Иначе
            АТутСписок=Новый СписокЗначений;
            Если ВложеннуюСтруктуруВТЗ=Истина Тогда
                ВремМассив=ПолучитьМассивИзСписка(Данные[ТекКлюч]);
            Иначе
                ВремМассив=Новый Массив;
                Для каждого Стр Из Данные[ТекКлюч] Цикл
                    ВремСтр=Новый Структура(); 
                    Для каждого ВСтр Из Стр.Свойства() Цикл
                        Если ВСтр.ВерхняяГраница=1 Тогда
                            ВремСтр.Вставить(ВСтр.Имя,Стр.Получить(ВСтр));
                        Иначе
                            ВремСтр.Вставить(ВСтр.Имя,"Если есть желание, то можно дописать"); //если у кого-то список в списке.... может дописать :-)
                        КонецЕсли; 
                    КонецЦикла; 
                    ВремМассив.Добавить(ВремСтр);
                КонецЦикла; 
            КонецЕсли; 
            ТТТ.Вставить(ТекКлюч,ВремМассив);
        КонецЕсли; 
    КонецЦикла;
    Возврат ТТТ;
КонецФункции // ЗаписатьОбъектXDTOВСтруктуру(Данные,Структ)

Функция для вывода структуры на печать.

Функция ПечатьСтруктуры(СтруктураРезультат,ЗаголовокШапки="Мой заголовок",СвернутьПоле="") Экспорт
    Если ТипЗнч(СтруктураРезультат)=Тип("Структура") Тогда
        ТабличныйДокумент = Новый ТабличныйДокумент;
        ТабличныйДокумент.ПолеСверху              = 0;
        ТабличныйДокумент.ПолеСлева               = 0;
        ТабличныйДокумент.ПолеСнизу               = 0;
        ТабличныйДокумент.ПолеСправа              = 0;
        ТабличныйДокумент.РазмерКолонтитулаСверху = 0;
        ТабличныйДокумент.ОриентацияСтраницы      = ОриентацияСтраницы.Ландшафт;
        ТабличныйДокумент.АвтоМасштаб=Истина;
        ТабличныйДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ДанныеДляСтруктуры";
        
        Макет = ПолучитьМакет("ДанныеДляСтруктуры");
        
        ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
        Таб=ОбластьШапка.Параметры;
        Таб.Заголовок=ЗаголовокШапки;
        ТабличныйДокумент.Вывести(ОбластьШапка);
        
        ТабличныйДокумент.НачатьАвтогруппировкуСтрок();
            ВывестиСтруктуруНаПечать(СтруктураРезультат,ТабличныйДокумент,0,Макет,СвернутьПоле);
        ТабличныйДокумент.ЗакончитьАвтогруппировкуСтрок();
        
        Возврат ТабличныйДокумент;
    Иначе
        ВызватьИсключение "Структура. Что-то пошло не так....";
    КонецЕсли;
КонецФункции // ПечатьСтруктуры()

Функция ВывестиСтруктуруНаПечать(Знач Данные,Таб,Знач Уровень,Макет,СвернутьПоле="") Экспорт
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка"+Формат(?(Уровень>5,5,Уровень),"ЧГ=0"));
    ВлСтр=Макет.ПолучитьОбласть("ВложеннаяСтруктура|Айди");
    ВлСтрК=Макет.ПолучитьОбласть("ВложеннаяСтруктура|Колонка");
    ТЗКлюч=Макет.ПолучитьОбласть("ТЗКлюч|Айди");
    ТЗРасш=Макет.ПолучитьОбласть("ТЗРасш|Айди");
    Для каждого Стр Из Данные Цикл
        ОбластьСтрока.Параметры.АйДи=Стр.Ключ;
        Если ТипЗнч(Стр.Значение)=Тип("Структура") Тогда
            ОбластьСтрока.Параметры.Значение="";
            Если Стр.Ключ=СвернутьПоле Тогда
                Таб.НачатьГруппуСтрок(СвернутьПоле,Ложь);
                    Таб.Вывести(ОбластьСтрока,Уровень,,Ложь);
                    Если Стр.Значение.Количество()>0 Тогда
                        ВывестиСтруктуруНаПечать(Стр.Значение,Таб,Уровень+1,Макет,СвернутьПоле)
                    КонецЕсли;
                Таб.ЗакончитьГруппуСтрок();
            Иначе
                Таб.Вывести(ОбластьСтрока,Уровень);
                Если Стр.Значение.Количество()>0 Тогда
                    ВывестиСтруктуруНаПечать(Стр.Значение,Таб,Уровень+1,Макет,СвернутьПоле)
                КонецЕсли;
            КонецЕсли; 
        ИначеЕсли ТипЗнч(Стр.Значение)=Тип("Массив") Тогда
            ОбластьСтрока.Параметры.Значение="";
            Таб.Вывести(ОбластьСтрока,Уровень);
            Для каждого Элем Из Стр.Значение Цикл
                Если ТипЗнч(Элем)=Тип("Структура") Тогда
                    Таб.Вывести(ВлСтр,Уровень+1,,Ложь);
                    Для каждого ЭС Из Элем Цикл
                        ВлСтрК.Параметры.Заполнить(ЭС);
                        Таб.Присоединить(ВлСтрК);
                    КонецЦикла; 
            	ИначеЕсли ТипЗнч(Элем)=Тип("Строка") Тогда
                    ОбластьСтрока.Параметры.Значение=Элем;
                    Таб.Вывести(ОбластьСтрока,Уровень+1);
                Иначе
                    сообщить(""+Стр.Ключ+": "+Стр.Значение); 
                КонецЕсли; 
            КонецЦикла; 
        ИначеЕсли ТипЗнч(Стр.Значение)=Тип("Строка") Тогда
            ОбластьСтрока.Параметры.Значение=Стр.Значение;
            Таб.Вывести(ОбластьСтрока,Уровень);
        ИначеЕсли ТипЗнч(Стр.Значение)=Тип("ТаблицаЗначений") Тогда
            ОбластьСтрока.Параметры.Значение="";
            Таб.Вывести(ОбластьСтрока,Уровень);
            ТЗ=Стр.Значение;
            Если 1=2 Тогда
            	ТЗ=Новый ТаблицаЗначений;
            КонецЕсли;
            ТЗКлючК=Макет.ПолучитьОбласть("ТЗКлюч|Колонка");
            Таб.Вывести(ТЗКлюч,Уровень+1,,Ложь);
            Для каждого ТЗК Из ТЗ.Колонки Цикл
            	ТЗКлючК.Параметры.Ключ=ТЗК.Имя;
                Таб.Присоединить(ТЗКлючК);
            КонецЦикла; 
            ТЗКлючК=Макет.ПолучитьОбласть("ТЗЗначение|Колонка");
            Для каждого СтрТЗ Из ТЗ Цикл
                Таб.Вывести(ТЗКлюч,Уровень+1,,Ложь);
                КолонкиС_ТЗ=Новый Структура(); 
                Для каждого ТЗК Из ТЗ.Колонки Цикл
                    Если ТипЗнч(СтрТЗ[ТЗК.Имя])=Тип("ТаблицаЗначений") Тогда
                        ТЗКлючК.Параметры.Значение="Расшифровка ниже";
                        КолонкиС_ТЗ.Вставить(ТЗК.Имя,СтрТЗ[ТЗК.Имя]);
                        Таб.Присоединить(ТЗКлючК);
                    Иначе
                    	ТЗКлючК.Параметры.Значение=СтрТЗ[ТЗК.Имя];
                        Таб.Присоединить(ТЗКлючК);
                    КонецЕсли;
                КонецЦикла; 
                Если КолонкиС_ТЗ.Количество()>0 Тогда
                    ПервыйКлюч="";
                    Для каждого ТЗС Из КолонкиС_ТЗ Цикл
                        Если ПервыйКлюч=ТЗС.Ключ Тогда
                            Таб.Вывести(ТЗКлюч,Уровень+2,,Ложь);
                        Иначе
                            ПервыйКлюч=ТЗС.Ключ;
                            ТЗРасш.Параметры.Айди=ПервыйКлюч;
                            Таб.Вывести(ТЗРасш,Уровень+2,,Ложь);
                            Для каждого ТЗК Из ТЗС.Значение.Колонки Цикл
                                ТЗКлючК.Параметры.Значение=ТЗК.Имя;
                                Таб.Присоединить(ТЗКлючК);
                            КонецЦикла; 
                        КонецЕсли;
                        Для каждого СтрТЗВл Из ТЗС.Значение Цикл
                            Таб.Вывести(ТЗКлюч,Уровень+2,,Ложь);
                            Для каждого ТЗК Из ТЗС.Значение.Колонки Цикл
                                ТЗКлючК.Параметры.Значение=СтрТЗВл[ТЗК.Имя];
                                Таб.Присоединить(ТЗКлючК);
                            КонецЦикла; 
                        КонецЦикла; 
                    КонецЦикла; 
                    А=1;
                КонецЕсли; 
            КонецЦикла; 
        Иначе
            сообщить(""+Стр.Ключ+": "+Стр.Значение); 
        КонецЕсли; 
    КонецЦикла;
    Возврат Таб;
КонецФункции // ВывестиСтруктуруНаПечать(Парам,Таб)

При выводе на печать есть ограничение, если у кого-то будет извращение, что списокXDTO, содержит поле со спискомXDTO, в котором будет ещё поле со списком XDTO, то при использовании таблицы значений (ТЗ) , третья и следующие ТЗ не будут выведены.

 

Пример макета:

 

 

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

загрузка XDTO

См. также

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

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

30.10.2025    4156    Abysswalker    11    

46

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

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

14.05.2025    7750    DeerCven    15    

61

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

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

21.05.2024    52927    dimanich70    84    

174

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

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

1 стартмани

18.03.2024    7691    7    John_d    13    

59

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

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

12.02.2024    67441    atdonya    31    

72

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

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

30.11.2023    9635    ke.92@mail.ru    17    

68
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. vko_70 8 10.02.22 12:48 Сейчас в теме
Доделал получение массива из списка. Появилась возможность обработки в списке Объекта XDTO и получения его в виде Таблицы значений, структуры или массива


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