Загрузка таблицы Excel до 10 000 строк в 1С 8.2 Управляемые формы

1. Farkhod82 07.12.12 18:25 Сейчас в теме
Добрый день

Подкиньте пжл идею как можно реализовать задачку по втягу таблицы excel в 1С 8.2 самым скоростным способом

Обычное COMОбъект("Excel.Application") с дальнейшем перебором строк занимает около 3 - 4 часов, требуеться управиться за час.


Всем спасибо хоть за какую идею
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. zamichnik 07.12.12 21:01 Сейчас в теме
Я один раз для считывания матрицы 3000 строк х 200 столбцов банальным копи-пастом воспользовался.
Получилось довольно шустро. Может и вам пригодится...
На управляемой форме разместил реквизит типа 'ТабличныйДокумент', обозвал его 'ТаблицаДанных'.
Ну и по кнопочке на клиенте выполняю код:

 Excel = Новый COMОбъект("Excel.Application");
   Книга = Excel.WorkBooks.Open("ИмяФайла");
   Range = Excel.Sheets(1).Range(("A1:GR3000"));	
   Range.Select();
   Range.Copy();
   ЭтаФорма.ТекущийЭлемент = Элементы.ТаблицаДанных;
   WSHShell = Новый COMОбъект("WScript.Shell"); 
   WSHShell.SendKeys("^v");      // имитация нажатия клавиш ctrl+v


Происходит вставка данных из буфера обмена Windows, а дальше из табличного документа считывайте их куда нужно...
Ava_1c; Eugeneer; +2 Ответить
6. пользователь 07.12.12 21:12
Сообщение было скрыто модератором.
...
7. пользователь 07.12.12 21:13
Сообщение было скрыто модератором.
...
14. Salavat 13 10.12.12 14:01 Сейчас в теме
(3) zamichnik, странно. я такое тоже пробовал. однако результат был противоположным - считывание с табличного документа происходило медленне, чем считывание из экселя.

причём - разница была видна невооружённым взглядом.

потом уже нарыл в инете, что 1с с табличным документом работает медленннее, чем с экселем.

если переубедите - буду рад.
9. GPL 3 07.12.12 22:35 Сейчас в теме
(1) Farkhod82, можно уйти от OLE сохранив файл в csv и дальше парсить его как текст.
у нас решалась обратная задача, правда не в 1С. выгружались строки в текст, запускался файл Excel, который встроенным макросом тексты в себя затягивал
12. Salavat 13 10.12.12 13:25 Сейчас в теме
(9) GPL, c текстовым файлом мудохаться приходится - разбирать его на составные части.
11. Salavat 13 10.12.12 13:24 Сейчас в теме
тоже мудохался. в итоге счас гружу через:
Excel = Новый COMОбъект("Excel.Application");
	WB	= Excel.Workbooks.Open(ИмяФайла);
	WS	= WB.Worksheets(1);
	Excel.range("A1").value=текущаядата(); // это чтоб с первой ячейки был массив
arr	= WS.UsedRange.Value;
	WB.Close(0);
	Excel.quit();	
	Excel = Неопределено;
	
...
     МассивКолонок             = arr.Выгрузить();
	ОбщееКоличествоКолонок     = arr.GetUpperBound(0);
	ОбщееКоличествоСтрок     = arr.GetUpperBound(1);
	Для Инд = 1 По ОбщееКоличествоСтрок Цикл
	  НовСтр = товары.Добавить();    
	КонецЦикла;
Показать


скорости не прибавилось, правда. но зато, удобнее работать - не нужно вычислять ячейку типа R..C..
13. starjevschik 10.12.12 13:50 Сейчас в теме
(1) Farkhod82, че-то не заметил в обсуждении, какая же часть обработки занимает больше всего времени. И сколько колонок в екселе, и куда все это складируется.
Через Оле перебор пусть даже 10000 строк Екселя не занимает четыре часа.
Короче, где замер производительности-то? :)
15. Ягг 495 10.12.12 14:54 Сейчас в теме
(1) Farkhod82, а я при загрузке больших таблиц из EXCEL (11 000 тыс примерно) копирую изначально таблицу в буфер, затем создаю текстовый документ и загоняю данные из буфера туда. Там конечно уже не таблица, а обычный текст в котором колонки разнесены по специальному символу. Дальше читаю строчку, по символу ее режу и уже получаю конкретные колонки.

Работает быстро. Код примерно такой:

	
	оЭксел 	= новый COMОбъект("Excel.Application");
	оКнига	= оЭксел.WorkBooks.Open(ИмяФайла);
	оЛист 	= оКнига.Worksheets(1);
	оЛист.Cells.Copy();

	ОбъектКопирования = Новый COMОбъект("htmlfile");
        Текст = новый ТекстовыйДокумент;
	Текст.УстановитьТекст(ОбъектКопирования.ParentWindow.ClipboardData.Getdata("Text"));

	для Индикатор=ПерваяСтрока по МаксСтрок цикл
		
		рез = Текст.ПолучитьСтроку(Индикатор);
		Мас = Общие.СтрокуВМассив(рез,Символ(9),истина); // уже массив колонок
		Мас.Добавить(""); // для пустых колонок

        КонецЦикла
Показать


Код "нарезан" из обработки.
МАС[0] - первая колонка EXCEL и т.д..

КОнечно, не совсем универсальный способ, так как если где то в ячейке есть "Символ(9)" то вся схема летит :) но в моем случае подходит. Ускорение было в разы.

ЗЫ. Блин, по сути дела продублировал 3 пост. Виноват :( Правда операторы немного другие - но суть та же
2. Goruch 7 07.12.12 18:57 Сейчас в теме
У себя использую так:
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = "+ПутьКФайлуОтчета;
	СтрокаПодключения = СтрокаПодключения + "; Extended Properties = "+"""Excel 12.0"+";HDR=NO;IMEX=1"";";
	
	// Подключаемся
	
	Об_Конект = Новый COMОбъект("ADODB.Connection");
	
	Попытка
		Об_Конект.Open(СтрокаПодключения); 
	Исключение
		Сообщить ("Невозможно подключится к Microsoft Excel Driver!!! Возможно файл ["+ПутьКФайлуОтчета+"] открыт другим пользователем.");
		Возврат;
	КонецПопытки;
	
	СтрЗапроса = "
	|SELECT *
	|FROM [A" + Формат(2,"ЧГ=0") + ":CZ" + Формат(99999,"ЧГ=0") + "] 
	|"; //данный запрос выбирает все заполненные ячейки листа, однако можно наложить условия отбора. синтаксис SQL
	
	Попытка
		RecordSet = Об_Конект.Execute(СтрЗапроса);
	Исключение
		Сообщить("Не удалось выполнить запрос к файлу Excel "+ ОписаниеОшибки(),СтатусСообщения.Важное);
		Возврат;
	КонецПопытки;
	
	Пока НЕ RecordSet.EOF() Цикл    
		ШтрихКод = RecordSet.Fields(3).value;
 		Количество = RecordSet.Fields(5).value;
		ЦенаКомитента = RecordSet.Fields(6).value;
		СуммаНДСКомитента = RecordSet.Fields(8).value;
		СуммаКомитента = RecordSet.Fields(7).value;
		ЦенаПродажи = RecordSet.Fields(9).value;
		СуммаНДСПродажи = RecordSet.Fields(11).value;
		СуммаПродажи = RecordSet.Fields(10).value;
		
		ЗагрузитьСтрокуОтчета(ОтчетКомиссионера,ШтрихКод,Количество, ЦенаКомитента,СуммаНДСКомитента,СуммаКомитента,ЦенаПродажи,СуммаНДСПродажи,СуммаПродажи);
		
		RecordSet.MoveNext();    
	КонецЦикла;
Показать


Взято с мисты, ссылку не помню.
zamichnik; +1 Ответить
4. zamichnik 07.12.12 21:04 Сейчас в теме
(2) Goruch,
и вам спасибо за хороший пример, буду использовать :)
5. пользователь 07.12.12 21:10
Сообщение было скрыто модератором.
...
8. Farkhod82 07.12.12 21:36 Сейчас в теме
Всем спасибо, буду пробовать варианты в ответах 2 и 3, на 10 тыс. строках. Кто быстрее.
Объясню почему 3-4 часа, колонок у таблицы около 20, и много нюансов по втягу, такие как найти номенклатура по коду, если не нашли, создать новую. То же самое с контрагентом, Партнером и т.д.
10. FIERYLIONS 222 08.12.12 18:03 Сейчас в теме
я тоже за копи паст ))))
16. _HakerAlex_ 11.04.13 18:03 Сейчас в теме
Хоть и старый пост но может кому будет интересно, самый быстрый на сегодня способ который смог реализовать....
&НаСервере
Процедура ЗаполнитьТаблицу(МассивДанных,КоличествоСтрок)
	
	Объект.ТаблицаЗагрузки.Очистить();
	
	НашаТаблица=Объект.ТаблицаЗагрузки.Выгрузить();
	Для инд=1 по КоличествоСтрок Цикл
		НашаТаблица.Добавить();
	КонецЦикла;
	
	инд=0;
	Для каждого СтрокаМассива из МассивДанных Цикл
		Если инд=0 Тогда
			НашаТаблица.ЗагрузитьКолонку(СтрокаМассива,"ТорговаяТочка");
		ИначеЕсли инд=1 Тогда
			НашаТаблица.ЗагрузитьКолонку(СтрокаМассива,"Номенклатура");
		ИначеЕсли инд=2 Тогда	
			НашаТаблица.ЗагрузитьКолонку(СтрокаМассива,"КодТМЦ");
		ИначеЕсли инд=3 Тогда		
			НашаТаблица.ЗагрузитьКолонку(СтрокаМассива,"План");
		КонецЕсли;
		инд=инд+1;
	КонецЦикла;
	
	Если НашаТаблица.Количество()>0 Тогда
		НашаТаблица.Удалить(НашаТаблица[0]);
	КонецЕсли;
	
	
	Объект.ТаблицаЗагрузки.Загрузить(НашаТаблица.Скопировать());
	
	Для каждого СтрокаТаблицы из Объект.ТаблицаЗагрузки Цикл
		
		СтрокаТаблицы.ТМЦ=Справочники.Номенклатура.НайтиПоКоду(Прав("000000"+СтрЗаменить(СтрокаТаблицы.КодТМЦ,Символ(160),""),6));
		СтрокаТаблицы.ТоварнаяГруппа=СтрокаТаблицы.ТМЦ.ПоследняяТоварнаяГруппа;
		СтрокаТаблицы.Магазин=Справочники.ПР_ТорговыеТочки.НайтиПоНаименованию(СокрЛП(СтрокаТаблицы.ТорговаяТочка));
		СтрокаТаблицы.КлассификацияD=?(СтрокаТаблицы.ТМЦ.Классификация=Справочники.Ном_КлассификацияНоменклатуры.Классификация_D,Истина,Ложь);
		Если СтрокаТаблицы.ТМЦ=Справочники.Номенклатура.ПустаяСсылка() Тогда
			Сообщить("Не найдена номенклатура по коду: "+СтрокаТаблицы.КодТМЦ+" наименование "+СтрокаТаблицы.Номенклатура);
		КонецЕсли;	
		
		Если СтрокаТаблицы.Магазин=Справочники.ПР_ТорговыеТочки.ПустаяСсылка() Тогда
			Сообщить("Не найдена торговая точка по наименованию: "+СтрокаТаблицы.ТорговаяТочка);
		КонецЕсли;	
		
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьИзЭкселя(Команда)
	Попытка
		Excel = Новый COMОбъект("Excel.Application");
		ФайлХЛС=Excel.Application.Workbooks.Open(ПутьКФайлу);
		Состояние("Обработка файла Microsoft Excel...");
		ExcelЛист = Excel.Sheets(1);
	Исключение
		Сообщить("Ошибка. Возможно неверно указан номер листа книги Excel.");
		Возврат;		
	КонецПопытки;
	
	КонечнаяСтрокаДанных=ФайлХЛС.ActiveSheet.UsedRange.Rows.Count; 
	КоличествоКолонокДанных=ФайлХЛС.ActiveSheet.UsedRange.Columns.Count; 
	Состояние("Загрузка в память данных Excel...");
	ExcelЛист=ФайлХЛС.ActiveSheet;
	Область = Excel.Range(ExcelЛист.Cells(1,1), ExcelЛист.Cells(КонечнаяСтрокаДанных,КоличествоКолонокДанных));
	МассивДанныхEXEL = Область.Value.Выгрузить();
	Excel.WorkBooks.Close();
	
	ЗаполнитьТаблицу(МассивДанныхEXEL,КонечнаяСтрокаДанных);
	Excel.Quit();

КонецПроцедуры
Показать
17. spaminfostart 15 14.02.14 15:26 Сейчас в теме
У меня если использовать Excel - долго открывает большие файлы. Сейчас делаю через ADO.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот