一种加快OLE导出Excel的方法

5 篇文章 0 订阅
1 篇文章 0 订阅
相信使用过OLE导入导出Excel的人都知道,微软出的这个东西真是慢到极点,慢到你想砸电脑。

我们公司以前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分钟左右。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值