Имя: Пароль:
1C
1С v8
Несоблюдение иерархи в xml документе при иерархическом обходе справочника Номенк
,
0 starjons
 
29.08.11
10:51
Здравствуйте, прошу вашей помощи. Стандарная конфа Торговли 10.3. Делаю внешную обработку, которая состоит из 2-х основных полей: справочниксписок номенклатура и вторая - таблица значений, в которую складываю нужные мне папки из номенклатуры. Хочу создать xml файл из выбранных папок со всеми вложенными товарами и подпапками. Пишу код:
Для каждого СтрокаТабЧасти Из Товар Цикл
//перебираю папки с формы и указываю их в качестве владельцев при выбратьИерархически.
пишу код который перебирает товары и группы....

КонецЦикла;

Проблема в том, что документ у меня создается, первая вложенная папка и товары в ней находятся в правильном месте дерева, но последующие папки и товары в xml клеятся к последней добавленной папке или товару - несоблюдаяется иерархия. Прощу помощи или совета. Заранее спасибо
1 starjons
 
29.08.11
11:16
если я непонятно объяснила, то приму любые пожелания, каков порядок выгрузки иерархично номенклатуры определенных папок в xml
2 Defender aka LINN
 
29.08.11
11:21
(0) Как ты их пишешь, так они и располагаются.
3 starjons
 
29.08.11
11:22
щас я скину свой код - уже голову сломала
4 Ахиллес
 
29.08.11
11:24
(3) Лучше сначала объясни что у тебя в обработке выбирается и что ты записать в файл хочешь.
5 starjons
 
29.08.11
11:27
я хочу чтобы из справочника номенклатура товарищ выбрал какие то подпапки и их выгружать с вложенными товарами и папками
6 starjons
 
29.08.11
11:29
я вот и делаю иерархическийм обход справочника номенклатура с отбором по выбранным папкам последовательно
7 starjons
 
29.08.11
11:34
Процедура ВыгрузитьДанные()
   // Надо получить цены выбранного типа и пересчитать их по заданной формуле.
   // Цены базового типа достанем запросом.

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

   ВыборкаЦенТоваров = Запрос.Выполнить().Выгрузить();
   
   Запись = Новый ЗаписьXML;
   Запись.ОткрытьФайл(ПутьВыгрузки);
   Запись.ЗаписатьОбъявлениеXML();
   //корневой элемент
   Запись.ЗаписатьНачалоЭлемента("document");
   Запись.ЗаписатьАтрибут("Справочник", "Номенклатура");
   Запись.ЗаписатьКомментарий("Иерархический перебор справочника Номенклатура");

   
   //Обходим список из групп выгружаемой номенклатуры и берем ссылку на нужный элемент всего справочника
   Для каждого СтрокаТабличнойЧасти Из Товар Цикл
           СсылкаНаСпр = СтрокаТабличнойЧасти.Ссылка;
           ВыбСправочник = Справочники.Номенклатура.ВыбратьИерархически(СсылкаНаСпр);
           //поиск по куску справочника номенклатура с группами
           Запись.ЗаписатьНачалоЭлемента("group");
           Запись.ЗаписатьАтрибут("id", СокрЛП(СсылкаНаСпр.Код));
           Запись.ЗаписатьАтрибут("name", СокрЛП(СсылкаНаСпр.Наименование));
           //текущий родитель
           РодТов = СсылкаНаСпр.Ссылка;
           Прород = СсылкаНаСпр.Ссылка;

           
           сч=0;
           Пока ВыбСправочник.Следующий() Цикл
               Если ВыбСправочник.ЭтоГруппа=Истина Тогда
                   Запись.ЗаписатьНачалоЭлемента("group");
                   Запись.ЗаписатьАтрибут("id", СокрЛП((ВыбСправочник.Код)));
                   Запись.ЗаписатьАтрибут("name", СокрЛП((ВыбСправочник.Наименование)));
                   //текущий родитель
                   РодТов = ВыбСправочник.Ссылка;
                   //прородитель
                   Прород = ВыбСправочник.Родитель;
                   //надо каким то образом запоминать текущую группу и сравнивать ее с родителем каждого из перебираемого элемента
                   //иначе не понятно каким образом надо закрывать группу
                   //мы должны создать дополнительную вложенность и не искать цены    
               Иначе
                   Если ВыбСправочник.ПометкаУдаления = Истина Тогда
                       //нам не нужны помеченные на удаление товары
                       Продолжить;
                   Иначе
                       //берем товар и ищем ему актуальную цену
                       НайденнаяЦена = ВыборкаЦенТоваров.Найти(ВыбСправочник.Код, "Код");
                       Запись.ЗаписатьНачалоЭлемента("product");
                       Запись.ЗаписатьАтрибут("id", СокрЛП((ВыбСправочник.Код)));

                               //имя
                               Запись.ЗаписатьНачалоЭлемента("name");
                               Запись.ЗаписатьТекст(СокрЛП((ВыбСправочник.Наименование)));
                               Запись.ЗаписатьКонецЭлемента();

                               //полное описание
                               Запись.ЗаписатьНачалоЭлемента("descr");
                               Запись.ЗаписатьТекст(СокрЛП((ВыбСправочник.НаименованиеПолное)));
                               Запись.ЗаписатьКонецЭлемента();
                               
                               Если НайденнаяЦена = Неопределено ТОгда
                                   //цена
                                   Запись.ЗаписатьНачалоЭлемента("price");
                                   Запись.ЗаписатьТекст("0");
                                   Запись.ЗаписатьКонецЭлемента();
                                   
                                   //единицы измерения
                                   Запись.ЗаписатьНачалоЭлемента("wareunit");
                                   Запись.ЗаписатьТекст(Строка(""));
                                   Запись.ЗаписатьКонецЭлемента();
                               Иначе
                                   //цена
                                   Запись.ЗаписатьНачалоЭлемента("price");
                                   Запись.ЗаписатьТекст(Строка(НайденнаяЦена.Цена));
                                   Запись.ЗаписатьКонецЭлемента();
                                   
                                   //единицы измерения
                                   Запись.ЗаписатьНачалоЭлемента("wareunit");
                                   Запись.ЗаписатьТекст(СокрЛП((НайденнаяЦена.ЕдиницаИзмерения)));
                                   Запись.ЗаписатьКонецЭлемента();
                               КонецЕсли;
                               
                           Запись.ЗаписатьКонецЭлемента();
                           //проверка родителя
                           Если ВыбСправочник.Родитель = РодТов Тогда
                               //не закрываем групп
                           Иначе
                               //закрываем группу
                               Запись.ЗаписатьКонецЭлемента();
                               //текущий родитель
                               РодТов = ВыбСправочник.Родитель;
                               //прородитель
                               Прород = ВыбСправочник.Родитель.Родитель;
                           КонецЕсли;
                           
                       КонецЕсли;    
               КонецЕсли;
               сч= сч+1;    
            КонецЦикла;
           Сообщить(сч);
           
           //закрыли список табличной части
           Запись.ЗаписатьКонецЭлемента();
   КонецЦикла;
   
   //закрыли корневой элемент
   Запись.ЗаписатьКонецЭлемента();
   Запись.Закрыть();
           
КонецПроцедуры
8 starjons
 
29.08.11
11:35
помогите, пожалуйста....
9 Ахиллес
 
29.08.11
11:36
Для каждого ТекСтрока из ТЗСгруппами цикл
СпрНом = Справочники.Номенклатура%
ТекВыборка = СпрНом.ВыбратьИерархически(ТекСтрока.ГруппаНом);
//обработка выборки по текущей группе
конеццикла;
10 starjons
 
29.08.11
11:39
а я разве не обхожу Номенклатуру?
СсылкаНаСпр = СтрокаТабличнойЧасти.Ссылка;
           ВыбСправочник =Справочники.Номенклатура.ВыбратьИерархически(СсылкаНаСпр);
Пока ВыбСправочник.Следующий() Цикл ....
11 Ахиллес
 
29.08.11
11:41
ну, я просто не видел ещё твоего поста в тот момент.
12 starjons
 
29.08.11
11:42
она обходит все что мне нужно, но я не могу сделать нормальную иерархию в дереве....
то есть у меня есть Ном - папка1 - папка12
                                - папка11 - товар - товар ..
                                - папка13 ....
вот когда я иерархически беру папку12, то вернуться на уровень выше или на n - уровней выше я не могу...((( она прилепляет мне все следующие подпапки друг в друга ...и труба(
13 starjons
 
29.08.11
11:45
<document Справочник="Номенклатура">
<!--Иерархический перебор справочника Номенклатура-->
?
<group id="00000000764" name="ГЕРМЕТИКИ, ЖИДКИЕ ГВОЗДИ">
?
<group id="00000000773" name="ГЕРМЕТИКИ">
?
<group id="УТ000000104" name="КРАСС">
+
<product id="00000002576">
<name>Герметик акриловый КРАСС белый 300 мл.</name>
<descr>Герметик акриловый КРАСС белый 300 мл.</descr>
<price>71</price>
<wareunit>шт</wareunit>
</product>
......
вот следующую папку мне надо положить в ГЕРМЕТИКИ. А она их лепит к продукту
14 Ахиллес
 
29.08.11
12:07
Не для Яндекс магазина случайно ваяешь?
15 starjons
 
29.08.11
12:08
нет, но для интернет-магазина. Есть какие-нибудь идеи? Или где посмотреть?
16 Ахиллес
 
29.08.11
12:10
В яндексовском формате просто другая структура. Сначала все папки идут, а потом элементы.
17 starjons
 
29.08.11
12:12
вот с этим столкнулась, но ответ нашла - так работает выбратьИерархически. Сначала папки, потом товары прикрепленные к этой папке. Ахиллес, как подняться в xml на уровень выше или на несколько уровней? Может как то делать дерево?
18 izekia
 
29.08.11
12:19
Сделай рекурсию, когда кончаются элементы - пишешь конец группы и поднимаешься выше
19 starjons
 
29.08.11
12:21
а можно пример или ссылку где посмотреть. Как же я рекурсию буду делать при обходе иерархическом... я не умею. Мне бы подсмотреть как это делают специалисты.Спасибо
20 Ахиллес
 
29.08.11
12:21
Че то перемудрила. Конец элемента надо записывать сразу. А к группе нужно добавлять id родителя если он есть. Тогда получится простая двух уровневая иерархия, а не матрёшка с десятью вложениями. Если есть возможнось, переползай на Яндекс формат. Он простой и логичный.
21 starjons
 
29.08.11
12:26
(20)в том то и дело что уровней вложения может быть очень много внутри. просто товары могут быть прикреплены к текущей папке, так и во вложенных. Он же пробегает внутрь, вот если идет Папка - товар, то у меня все работает, а если идет Папка1-Папка11-Папка111-Товар1, то Папку12 он прилепит непосредственно после товара, а не к Папке1.
22 izekia
 
29.08.11
12:30
Процедура ДобавитьГруппу(группа)
 ЗаписатьНачалоГруппыВХМЛ(группа);
 Для каждого элемент Из группа Цикл
   Если элемент.ЭтоГруппа Тогда
     ДобавитьГруппу(элемент);
   Иначе
     ЗаписатьЭлементВХМЛ(элемент);
   КонецЕсли;
 КонецЦикла;
 ЗаписатьКонецЭлементаВХМЛ();
КонецПроцедуры;

схематично примерно так
23 starjons
 
29.08.11
12:31
С рекурсией понятно, щас я попробую
24 starjons
 
29.08.11
14:37
Спасибо большое всем за помощь! Написала - пользуйтесь кому надо:
Процедура ВыгрузитьДанные()
   Запись = Новый ЗаписьXML;
   Запись.ОткрытьФайл(ПутьВыгрузки);
   Запись.ЗаписатьОбъявлениеXML();
   //корневой элемент
   Запись.ЗаписатьНачалоЭлемента("document");
   Запись.ЗаписатьАтрибут("Справочник", "Номенклатура");
   Запись.ЗаписатьКомментарий("Иерархический перебор справочника Номенклатура");

   
   //Обходим список из групп выгружаемой номенклатуры и берем ссылку на нужный элемент всего справочника
   Для каждого СтрокаТабличнойЧасти Из Товар Цикл
       Запись.ЗаписатьНачалоЭлемента("group");
       Запись.ЗаписатьАтрибут("id", СокрЛП(СтрокаТабличнойЧасти.Код));
       Запись.ЗаписатьАтрибут("name", СокрЛП(СтрокаТабличнойЧасти.Наименование));

       РекурсивноеБрожение(СтрокаТабличнойЧасти.Ссылка,Запись);
       
       Запись.ЗаписатьКонецЭлемента();
   КонецЦикла;
   
   //закрыли корневой элемент
   Запись.ЗаписатьКонецЭлемента();
   Запись.Закрыть();

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


Процедура РекурсивноеБрожение(ТекущаяПапка,Запись)
   //внутрь папки
   Выборка = Справочники.Номенклатура.Выбрать(ТекущаяПапка);
   Пока Выборка.Следующий() Цикл
           Если Выборка.ЭтоГруппа Тогда
           Запись.ЗаписатьНачалоЭлемента("group");
           Запись.ЗаписатьАтрибут("id", СокрЛП((Выборка.Код)));
           Запись.ЗаписатьАтрибут("name", СокрЛП((Выборка.Наименование)));
                   
           РекурсивноеБрожение(Выборка.Ссылка,Запись);
           Запись.ЗаписатьКонецЭлемента();

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

               //имя
               Запись.ЗаписатьНачалоЭлемента("name");
               Запись.ЗаписатьТекст(СокрЛП((Выборка.Наименование)));
               Запись.ЗаписатьКонецЭлемента();

               //полное описание
               Запись.ЗаписатьНачалоЭлемента("descr");
               Запись.ЗаписатьТекст(СокрЛП((Выборка.НаименованиеПолное)));
               Запись.ЗаписатьКонецЭлемента();
               
               Если НайденнаяЦена = Неопределено ТОгда
                   //цена
                   Запись.ЗаписатьНачалоЭлемента("price");
                   Запись.ЗаписатьТекст("0");
                   Запись.ЗаписатьКонецЭлемента();
                   
                   //единицы измерения
                   Запись.ЗаписатьНачалоЭлемента("wareunit");
                   Запись.ЗаписатьТекст(Строка(""));
                   Запись.ЗаписатьКонецЭлемента();
               Иначе
                   //цена
                   Запись.ЗаписатьНачалоЭлемента("price");
                   Запись.ЗаписатьТекст(СтрЗаменить(НайденнаяЦена.Цена,",","."));
                   Запись.ЗаписатьКонецЭлемента();
                   
                   //единицы измерения
                   Запись.ЗаписатьНачалоЭлемента("wareunit");
                   Запись.ЗаписатьТекст(СокрЛП((НайденнаяЦена.ЕдиницаИзмерения)));
                   Запись.ЗаписатьКонецЭлемента();
               КонецЕсли;
               
            Запись.ЗаписатьКонецЭлемента();
            КонецЕсли;
       КонецЕсли;
   КонецЦикла;
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший