Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

импорт данных из Excel [D7, WinXP]


ArhArhangel ©   (2005-11-08 14:56:00) 

Здравствуйте уважаемые мастера!

Надо реализовать импорт большого количества(несколько тысяч строк) данных из Excel в MS SQL.
Я написал программу на Delphi, которая через com считывает данные из *.xls и вносит их в MS SQL. Но программа работает медленно. (реализована через позднее связывание).
А именно: медленно работает считывание данных из Excel.

Пока ячейки не пустые, считываем данные и генерируем sql запрос.
Как только попадаются несколько подряд пустых ячеек, цикл прерывается и  sql запрос отправляется на сервер.

Вопрос заключается в следующем:
Возможно ли как-нибудь по-другому искать конец документа?
Или по-другому делать импорт данных?

P.S. В документе xls всего одна таблица.


//Формирование SQL запроса
 if DM.QuerySQL.Fields.FieldByNumber(1).AsInteger=0 then  //Если нет записей в таблице, то выполняем добавление строк
   begin
     while string(Values[i,j])<>'' do //считываем поля, пока не всретим пустую ячейку
       begin
         sql.Add('Insert into xlsTempTab'+IntToStr(idBook)+'(id,['+Field+']) values ('+IntToStr(id)+','''+string(Values[i,j])+''')' );
         inc(i);//проходим по строкам
         inc(id);
         FormImport.StatusBar1.Panels[1].Text:='ячейка: '+IntToStr(id);
         FormImport.StatusBar1.Repaint;
       end;
   end
 else        //В противном случае, выполняем обновление строк
   begin
     while (string(Values[i,j])<>'') do //считываем поля, пока не всретим пустую ячейку
       begin
         sql.Add('Update xlsTempTab'+IntToStr(idBook)+' Set '+ '['+Field+']='''+string(Values[i,j])+''' ');
         sql.Add('where id=id');// последняя строка запроса
         inc(i);//проходим по строкам
         inc(id);
         FormImport.StatusBar1.Panels[1].Text:='ячейка: '+IntToStr(id);
         FormImport.StatusBar1.Repaint;
       end;


alex_***   (2005-11-10 10:29:00) [1]

а что на это заморачиваться, если обращаемся к outproc серверу


Digitman   (2005-11-10 10:26:00) [2]


> реализована через позднеесвязывание.


ну а что ж ты хотел ?

позднее связывание само по себе уступает в производительности раннему - всякий раз при обращении к методу интерфейса происходит разрешение имени метода в его Id, в отличии от раннего, где Id'ы методов интерфейса контроллеру автоматизации известны заранее


alex_***   (2005-11-10 10:18:00) [3]

какое считывание ячеек? сказали же - определяешь Range и копируешь его в Variant. Никакого считывания ячеек


ArhArhangel   (2005-11-10 10:08:00) [4]

я проверял даже без использования запроса..
Медленность возникает не из за него, а из за считывания ячеек.
Может есть другие методы импорта из Excel.
Мне сказали, что к Excel можно и через АДО подключится (Provider=Jet-Extended Properties=Excel 8.x)

но как это сделать, я так и не понял..
при создании *.UDL я такого провайдера не нашёл..


Digitman   (2005-11-09 09:12:00) [5]


> как ещё можно написать, чтобы не строить всякий раз при
> каждой итерации  практически один и тот же текст запроса?
>


использовать запрос с параметрами


isasa   (2005-11-08 21:01:00) [6]

Возможно ли как-нибудь по-другому искать конец документа?

Как вариант - именованный диапазон в документе Excel.


umbra   (2005-11-08 20:55:00) [7]

чтобы ускорить работу программы надо как можно быстрее избавиться от экселя.
например - сохранить файл в другом формате и работать с этим новым файлом.
К тому же для определения непрерывного блока данных лучше использовать не UsedRange, а CurrentRegion


ArhArhangel   (2005-11-08 19:49:00) [8]


> "тормоза" у тебя (Excel не рассматриваем) в :
>
> - неоптимальной работе с запросами : вместо использования
> парам.запроса ты всякий раз при каждой итерации вновь строишь
> практически один и тот же текст запроса ;


А как ещё можно написать, чтобы не строить всякий раз при каждой итерации  практически один и тот же текст запроса?


> - обновлении виз.контролов (см. Statusbar) при каждой итерации

я поставил, только чтобы было видно работу программы.
Это только на этапе разработки.


Digitman   (2005-11-08 16:04:00) [9]


> ArhArhangel ©   (08.11.05 15:58) [4]


"тормоза" у тебя (Excel не рассматриваем) в :

- неоптимальной работе с запросами : вместо использования парам.запроса ты всякий раз при каждой итерации вновь строишь практически один и тот же текст запроса ;

- обновлении виз.контролов (см. Statusbar) при каждой итерации


ArhArhangel   (2005-11-08 16:02:00) [10]

Интересно, а как выполняет импорт MS SQL сервер? Там же ведь тоже реализовано через COM.
Там все данные импортируются влёт. ( Только вот не обрабатываются :-) )
Значит есть какие-то хитрости..


ArhArhangel   (2005-11-08 15:58:00) [11]

этот вариант реализаци работает с такой же скоростью..
я делал то же самое, но не через VarArrayCreate, а через Values: OLEVariant;


Антоныч   (2005-11-08 15:17:00) [12]

Я делал поиск последней строки с данными в Excel так (работает при условии, что данные записаны без пропусков):
var
 XLApp, WorkBk, WorkSheet: Variant;
 nach, kon, cur: integer;
 s: string;
begin
 XLApp := CreateOLEObject('Excel.Application');
 WorkBk := XLApp.WorkBooks.Open(filename);
 WorkSheet := WorkBk.Sheets.Item[1];
 nach:=1; kon:=65536;
 repeat
   cur:=(nach+kon) div 2;
   s:=WorkSheet.Cells[cur,6];
   if s='' then kon:=cur else nach:=cur;
 until (kon-nach)<=1;
 s:=WorkSheet.Cells[nach,6];
 if s='' then dec(nach);
 ShowMessage(IntToStr(nach));
 WorkBk.Close;

А быстрый экспорт/импорт данных осуществляется через VarArrayCreate:

var
 XLApp, WorkBk, WorkSheet: Variant;
begin
 XLApp := CreateOLEObject('Excel.Application');
 WorkBk := XLApp.WorkBooks.Open(fname);
 WorkSheet := WorkBk.Sheets.Item[1];
 Buf:=VarArrayCreate([1,1732,1,35], VarVariant);
 Buf:=WorkSheet.Range['B2','AJ1733'].Value;
 WorkBk.Close;

и работаешь с Buf как обычным двумерным массивом


ArhArhangel   (2005-11-08 15:15:00) [13]


try
 IRange := fTableExcelInfo.ExcelBook[idBook].ISheet.UsedRange[0]; //UsedRange листа. Это прямоугольная область, заключенная между ўлевой верхней непустойч и ўправой нижней непустойч ячейками.
 Values := IRange.Value;  //Свойство Value интерфейса Range в состоянии вернуть вариантный массив.
finally
 IRange := nil;
end;


umbra   (2005-11-08 15:05:00) [14]

а что это за Values[i,j]?


Наверх

Титульная страница Поиск, карта сайта Написать письмо