Иерархическая загрузка номенклатуры из Excel-файла

Обмен - Загрузка и выгрузка в Excel

OutlineLevel excel эксель xls xlsx загрузка чтение иерархия прайс иерархический

27
Столкнулся с задачей загрузки данных из Excel-файла в 1С с учетом представленной в файле иерархией. Сам по себе процесс перекачки данных из экселя в 1с трудностей не представляет. В сети очень много обработок и примеров кода, которые позволяют общаться с Excel. Но облазив много форумов, я нигде не нашел внятного объяснения как произвести загрузку с учетом иерархии, при условии что количество уровней этой самой иерархии произвольно и разные уровни группировок находятся в одной колонке, а не каждый уровень в своей. Хочу поделиться тем, что получилось у меня. Может кому-то пригодится.

Здесь самое важное - это свойство OutlineLevel. Оно содержит уровень группировки для текущей строки. По нему можно определить входит ли данная строка в какую-то группировку или нет, а так же уровень иерархии, то есть количество группировок. 

Прикладываю архив с обработкой и тестовой версией файла, чтобы было проще на примере понять механизм работы.

27

Скачать файлы

Наименование Файл Версия Размер
Иерархическая загрузка номенклатуры из Excel-файла:
.rar 60,92Kb
17.05.18
26
.rar 60,92Kb 26 Скачать

См. также

Комментарии
Избранное Подписка Сортировка: Древо
1. webester 27 26.01.14 05:52 Сейчас в теме
Когда вижу
На супероптимальность кода и быстродействие не претендую :)

читаю как
Честно говоря я понятия не имею, как это делается. поэтому сделал уж как получилось


Здесь самое важное - это свойство OutlineLevel: "ExcelЛист.Rows(ТекСтр).OutlineLevel;". Оно содержит уровень группировки для текущей строки. По нему можно определить входит ли данная строка в какую-то группировку или нет, а так же уровень иерархии, то есть количество группировок.

На этом можно было начать и закончить статью, новичок все равно код не разберет, а спец, все равно свой код писать будет.
dj_serega; Chibis; eaa; +3 Ответить
10. akostrovdon 22.03.15 22:25 Сейчас в теме
Вот пример загрузки номенклатуры без деревьев(упр.форма), просто через Таблицу значений
Суть в том что уровни(группы) просто добавляем в массив по мере поступления.
Создаем группы которых нет и присваеваем их вновь созданным элементам, с учетом проверки уже существующих в базе.
Кто знает как OutlineLevel получить через ADODB??
Перебор элементов excel чушь полная если более 10 тыс. строк.


&Наклиенте
Процедура Команда1(Команда)
   
   	
	
	ОбъектЭксель	= Новый COMОбъект("Excel.Application");
	ФайлExcel		= ОбъектЭксель.Workbooks.Open(ФайлЗагрузки);
	ЛистExcel		= ФайлExcel.Sheets(1);
	КоличествоСтрок = ЛистExcel.UsedRange.Rows.Count;
		
	Для ном =НачатьСномераСтроки По КоличествоСтрок Цикл		
	 	
		ЗначениеАртикула = СокрЛП(ЛистExcel.Cells(ном,1).Value);
		Этогруппа=ложь;
		Если ЗначениеАртикула="" Тогда 			
			этоГруппа=истина;
		КонецЕсли;
		Если  СокрЛП(ЛистExcel.Cells(ном,2).Value)=""  Тогда
			Прервать;
		КонецЕсли;
		Наименование=СокрЛП(ЛистExcel.Cells(ном,2).Value);
		
		Цена=0;
		Если не Этогруппа тогда
		 Наименование=СтрЗаменить(Наименование,"-книжка","");
		 Наименование=СтрЗаменить(Наименование,"_"," ");
		 Наименование=СтрЗаменить(Наименование,"_"," ");
		 Наименование=СтрЗаменить(Наименование,"--","");
		 Наименование=СтрЗаменить(Наименование,"No Name","");
		 Наименование=СтрЗаменить(Наименование,"-футляр","");
		 Наименование=СтрЗаменить(Наименование," *","");
		Цена = ЧИСЛО(ЛистExcel.Cells(ном,5).Value); 	
		КонецЕсли;
		Если не Этогруппа тогда
			НайденнаяНоменклатура =найтипореквизиту(ЗначениеАртикула,"Артикул");
			Если ЗначениеЗаполнено(НайденнаяНоменклатура) тогда
				Наименование=НайденнаяНоменклатура;
			КонецЕСли;
		иначе
			НайденнаяГруппа= НайтиПоНаименованию(Наименование);
			
			Если ЗначениеЗаполнено(НайденнаяГруппа) тогда
				Наименование=НайденнаяГруппа;
			КонецЕСли;
		КонецЕСлИ;				
	 	нс= тз.Добавить();					 
	 	Если ЗначениеАртикула="" тогда
	    нс.группа=	Наименование;
		нс.Уровень=ОбъектЭксель.Rows(ном).OutlineLevel-1;
		иначе
		нс.Код=ЗначениеАртикула;
		Нс.Наименование=Наименование;
		нс.вхцена=Цена;
		нс.Цена= нс.вхцена*наценка;
		нс.Уровень=ОбъектЭксель.Rows(ном).OutlineLevel-1; 
		КонецЕслИ;				

КонецЦикла;
ОбъектЭксель.WorkBooks.Close();
ОбъектЭксель.Quit();

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

&Насервере

Процедура создатьэлементы()
	Массив=Новый Массив;
	
	
ПоследняяГруппа=Справочники.Номенклатура.ПустаяСсылка();
для каждого стр из тз цикл

		
если  значениезаполнено(стр.Наименование) тогда

Если ТипЗнч(стр.Наименование)=Тип("Строка") Тогда
спр=справочники.Номенклатура.СоздатьЭлемент();
спр.ЕдиницаИзмерения=константы.ЕдиницаИзмеренияОбъема.Получить();
спр.Наименование=стр.наименование;
спр.НаименованиеПолное=стр.наименование;
спр.Артикул=стр.код;
спр.СтавкаНДС=перечисления.СтавкиНДС.БезНДС;
спр.ВидНоменклатуры=справочники.ВидыНоменклатуры.НайтиПоНаименованию("Аксессуары");
спр.ВариантОформленияПродажи=Перечисления.ВариантыОформленияПродажи.РеализацияТоваровУслуг;
спр.ИспользованиеХарактеристик=перечисления.ВариантыИспользованияХарактеристикНоменклатуры.НеИспользовать;
спр.Родитель=ПоследняяГруппа;
спр.Записать();
конецесли;
конецесли;
если  значениезаполнено(стр.Группа) тогда
	Если ТипЗнч(стр.группа)=Тип("Строка") Тогда
     гр=справочники.Номенклатура.СоздатьГруппу();
     гр.Наименование=стр.группа;
	 
     Если стр.Уровень>1 тогда
	 Родитель=Массив[стр.Уровень-2];
	 гр.Родитель=Родитель;
	 КонецЕсли;
	 гр.Записать();	       
	 ПоследняяГруппа=гр.Ссылка;
	 		 
 иначе
	 ПоследняяГруппа=стр.группа;
 КонецЕсли; 
 
		 Если стр.Уровень>Массив.Количество() Тогда
			 Массив.Добавить(ПоследняяГруппа);
		 иначе
			 Массив.Установить(стр.Уровень-1,ПоследняяГруппа);
		 КонецЕслИ;
 
КонецЕсли;

Конеццикла;

конецпроцедуры

&Насервере
Функция   найтипореквизиту(имя,реквизит);
	 возврат Справочники.Номенклатура.НайтиПоРеквизиту(реквизит,имя);	 
 КонецФункции 
 
 Функция   найтипонаименованию(имя);
	 возврат Справочники.Номенклатура.НайтиПоНаименованию(имя,истина);
	 
 КонецФункции
Показать
SergeyRomanov; tinkerbell; Sirgeli; +3 1 Ответить
13. tinkerbell 29.06.16 08:54 Сейчас в теме
(10) akostrovdon, неправильно работает, когда в группе после вложенной группы есть еще и элементы. Последнюю группу надо вычислять и для элемента тоже. Но за идею спасибо!
15. varius82 18.11.16 22:17 Сейчас в теме
Мой вариант:
Процедура ПрочитатьИзФайла(ПерваяСтрока) Экспорт
	
	ВыбФайл = Новый Файл(ФайлИмпорта);
	Если НЕ ВыбФайл.Существует() Тогда
		Сообщить("Файл не существует!");
		Возврат;
	КонецЕсли;
	
	Попытка
		Excel = Новый COMОбъект("Excel.Application");
		Excel.WorkBooks.Open(ФайлИмпорта);
		//Состояние("Обработка файла Microsoft Excel...");
		ExcelЛист = Excel.Sheets(1);
	Исключение
		Сообщить("Ошибка. Возможно неверно указан номер листа книги Excel.");
		Возврат;
	КонецПопытки;
	//первая значимая строка
	ТекСтр = ПерваяСтрока;
	
	xlCellTypeLastCell = 11;
	ExcelПоследняяСтрока = ExcelЛист.Cells.SpecialCells(xlCellTypeLastCell).Row;
	МассивУровней = Новый Массив;
	ТекущийУровень = 1;	
	
	ЕдИзм = Справочники.УпаковкиЕдиницыИзмерения.НайтиПоНаименованию("шт", Истина);
	ВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Товар", Истина);
	ПапкаРодитель = Справочники.Номенклатура.ПустаяСсылка();

	Пока ТекСтр < ExcelПоследняяСтрока Цикл
		Наименование = СокрЛп(ExcelЛист.Cells(ТекСтр,3).Value);
		Артикул = СокрЛп(ExcelЛист.Cells(ТекСтр,2).Value);
		Цвет = ExcelЛист.Cells(ТекСтр,3).interior.ColorIndex;
		Если Наименование = "" И Артикул = "" Тогда
			ТекСтр = ТекСтр + 1;
			Продолжить;
		КонецЕсли;
		ЭтоГруппа = Ложь;
		
		Если Артикул = "" И Цвет = 19 Тогда
			ЭтоГруппа = Истина;		
		КонецЕсли;
		ПолученныйУровень = ExcelЛист.Rows(ТекСтр).OutlineLevel;
		Если ЭтоГруппа Тогда
			Родитель = Справочники.Номенклатура.ПустаяСсылка();
			
			Если ПолученныйУровень > 1 Тогда
				Родитель = МассивУровней[ПолученныйУровень-1];
			КонецЕсли;
			НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
			НоваяГруппа.Наименование = Наименование;
			НоваяГруппа.Родитель = Родитель;
			НоваяГруппа.Записать();
			Ссылка = НоваяГруппа.Ссылка;
			МассивУровней.Вставить(ПолученныйУровень, Ссылка);
		Иначе
			Родитель = ПапкаРодитель;
			НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
			НовыйЭлемент.ОбменДанными.Загрузка = Истина;
			НовыйЭлемент.Родитель = Родитель;
			НовыйЭлемент.Наименование = Наименование;
			НовыйЭлемент.Артикул = Артикул;
			НовыйЭлемент.ВидНоменклатуры = ВидНоменклатуры;
			НовыйЭлемент.ТипНоменклатуры = Перечисления.ТипыНоменклатуры.Товар;
			НовыйЭлемент.ВариантОформленияПродажи = Перечисления.ВариантыОформленияПродажи.РеализацияТоваровУслуг;
			НовыйЭлемент.ИспользованиеХарактеристик = Перечисления.ВариантыИспользованияХарактеристикНоменклатуры.НеИспользовать;
			НовыйЭлемент.ЕдиницаДляОтчетов = ЕдИзм;
			НовыйЭлемент.ЕдиницаИзмерения = ЕдИзм;
			НовыйЭлемент.СтавкаНДС = Перечисления.СтавкиНДС.БезНДС;
			НовыйЭлемент.Записать();
			
		КонецЕсли;
		
		ТекСтр = ТекСтр + 1;
		Если ЭтоГруппа Тогда
			ПапкаРодитель = Ссылка;
		КонецЕсли;
		
	КонеЦЦикла;
	
	Excel.WorkBooks.Close();
	Excel = 0;
	
КонецПроцедуры
Показать
getup2010; igrned; +2 Ответить
2. OlesyaBelochka 33 10.06.14 14:07 Сейчас в теме
Спасибо, статья пригодилась.
3. widagon 23.07.14 22:03 Сейчас в теме
4. mpudy 23.07.14 23:39 Сейчас в теме
Недавно делал подобное, ориентировался на количество табов)))
5. blackilidan 9 27.09.14 12:29 Сейчас в теме
Огромное спасибо. Побольше бы таких людей, которые любят делиться тем, что опробовали.
6. Zmey_72 57 14.11.14 11:16 Сейчас в теме
статья интересная, но реализовать в свей обработке пришлось немного по-другому. И есть ошибки в коде:

Процедура ДобавитьВеткуВДерево(ExcelЛист, ТекущаяВетвь, ТекущийУровень, ТекСтр)

Пока ТекСтр ЦИКЛ
freeek; kot_dn; +2 Ответить
8. lisrws 74 16.12.14 13:49 Сейчас в теме
(6) Zmey_72, спасибо за найденную ошибку. подправил, но там немного не так.
7. gavrilova_m 25.11.14 11:22 Сейчас в теме
Интересная обработка! Правда, как молодой и зеленый специалист, пытаюсь разобраться в ней.
9. Yuri1C 2 18.03.15 13:32 Сейчас в теме
Ошибка, исправить нужно:

ПОКА ТекСтр < xlCellTypeLastCell ЦИКЛ
11. wolfsoft 2421 28.10.15 17:36 Сейчас в теме
Этогруппа=ложь; Если ЗначениеАртикула="" Тогда этоГруппа=истина; КонецЕсли;

При таком условии любой дурак код напишет.
dj_serega; +1 Ответить
14. kosyakov_anton 4 18.08.16 14:15 Сейчас в теме
Есть возможность поделиться уже готовой обработкой?
16. yabes 30.12.16 19:59 Сейчас в теме
Дружище, спасибо тебе большое. Ты меня сильно выручил. Есть, конечно недочеты, например, что бесконечно увеличивается количество вложенных рекурсий. Но это я поправил Следующим образом:
Вместо
Пока ТекСтр Цикл
я написал
Пока НЕ ЗакончитьРекурсию И ТекСтр <> ВсегоСтрок + 1 Цикл

и в конце процедуры вставил вот такой код:
ТекСтр = ТекСтр + 1;
        Если Не ВетвьУдалили Тогда
            ДобавитьВеткуВДерево(ExcelЛист, НоваяВетвь, ПолученныйУровень, ТекСтр);
		КонецЕсли;
		
		СледующийУровень = ExcelЛист.Rows(ТекСтр).OutlineLevel;
		
		Если СледующийУровень < ПолученныйУровень Тогда 
			ЗакончитьРекурсию = Истина;
		КонецЕсли;
Показать
Оставьте свое сообщение