相信使用过OLE导入导出Excel的人都知道,微软出的这个东西真是慢到极点,慢到你想砸电脑。
上述方法我测试下来的结果是比二进制导出还要快很多。我测试导6W行27列的数据,二进制需要5分钟,上述方法需要1分钟左右。
我们公司以前Excel导出大概2w行,30多列,耗时20多分钟。想屎的心都有。。。。
现在有一些快速导出Excel的方法,一般都是使用二进制导出,就是不依靠Excel软件,利用二进制流直接填写数据,比如DBGridEh的SaveDBGridEhToExportFile方法,这种方法确实非常快,但是有一个弊端,就是二进制导出的文件如果系统后续需要导入这个文件的话解析就会出错,所以要想导入只有重新使用Excel另存一下,使格式标准。
那么,有没有一种即使用OLE,速度又和二进制差不多甚至更快的方法?
答案当然是有的,程序猿都知道算法要考虑时间复杂度和空间复杂度。要想加快程序的运行一个很常用的方法就是用空间来换时间,前提是你内存足够,当然现在内存白菜价。。。
废话讲了一堆,下面就讲讲这种方法,我讲的是基于Delphi 的基础的,语言都是想通的。。其实很简单。
首先假设我们的数据是在DBGrid里面要导出到Excel。那么我们可以先把数据以一定数据格式全部拿到内存中,然后复制到剪贴板,最后粘贴到Excel中不就可以不用一个个Cell去填写了。
Excel复制粘贴的数据格式是:A tab B tab C tab D.....
……
X tab Y……
tab是制表符,都懂得哈。
示例源码:
procedure ExportToXLS(Sender: TObject);
var
fileName: string;
i,j,m:Integer;
BM:TBookmark;
ExcelApp: Variant;
sCopyStrings:TStrings; //用来存放导出数据
sline:string;
begin
try
BM:=nil;
SaveDialog.Filter:='Excel 文件(*.xls)|*.xls|文本文件(*.txt)|*.txt';
if (not SaveDialog.Execute) then exit;
fileName := Trim(SaveDialog.FileName);
try
ExcelApp := CreateOleObject('Excel.Application');
ExcelApp.DisplayAlerts := False;
ExcelApp.Workbooks.Add;
except
ShowMessage('没有安装Excel!');
Exit;
end;
while ExcelApp.WorkSheets.Count>1 do
begin
ExcelApp.WorkSheets[1].Delete;
end;
sCopyStrings:=TStringList.Create(); //TStrings是抽象类,不能实例化,用从TString继承来的TStringList
sCopyStrings.Clear;
tmpQuery.DisableControls;
BM:=tmpQuery.GetBookmark;
sline:='';
for j:=0 to DBGrid.Columns.Count-1 do
begin
sline:=sline+DBGrid.Columns[j].Title.Caption+#9; //数据格式,#9就是tab 这是表头
end;
sCopyStrings.Add(sline);
m:=0;
tmpQuery.First;
while not tmpQuery.Eof do
begin
sline:='';
for j:=0 to dbRisk.Columns.Count-1 do
begin
sline := sline + dbRisk.Columns[j].Field.AsString + #9;
Inc(m);//m可以用来统计导出进度,这里没实现
Application.ProcessMessages; //处理消息,防止界面假死
end;
sCopyStrings.Add(sline);
tmpQuery.Next;
end;
Clipboard.AsText:=sCopyStrings.Text;//复制到剪贴板,这里的Clipboard是TClipboard的一个对象,Delphi已经给你实例化好了,在uses里加clipbrd
try
ExcelApp.Workbooks[1].Worksheets[1].Range['A:ZZ'].Select ;
ExcelApp.Selection.NumberFormat:='@'; //这两句是将Excel的从A到ZZ列格式设为文本,如果不改的话,如果是00123样子的数据导入话,到Excel中就只剩123了。
ExcelApp.Workbooks[1].WorkSheets[1].Cells[1,1].Select;//加上这句是为了保证执行下面Paste时不会出现Paste方法无效的错误。
ExcelApp.Workbooks[1].WorkSheets[1].Paste;
ExcelApp.workbooks[1].SaveAs(fileName);
finally
Clipboard.Clear;
Clipboard.Close;
ExcelApp.WorkBooks.Close;
ExcelApp.Quit;
tmpQuery.GotoBookmark(BM);
tmpQuery.EnableControls;
if Assigned(sCopyStrings) then FreeAndNil(sCopyStrings);
end;
end
end
上述方法我测试下来的结果是比二进制导出还要快很多。我测试导6W行27列的数据,二进制需要5分钟,上述方法需要1分钟左右。