Delphi数据库数据用文件流方式快速写入Excel文件
在开发数据库应用程序中,经常要将类型相同的数据导出来,放到Excel文件中,利用Excel强大的编辑功能,对数据作进一步的加工处理。这有许多的方法,我们可以使用OLE技术,在Delphi中创建一个自动化对象,通过该对象来传送数据。也可以使用ADO,通过与Excel数据存储建立连接,使用ADO这种独立于数据库后端的技术来导出数据集的数据。
可这两种技术都有一个共同的缺点,那就是慢,数据量少还好,用户不会有太多的感觉,可一旦数据量大,比如,超过1千条,速度就让人难以忍受了,那么有没有更好的办法,既可以快速地导出数据,又不用安装附加的软件。也许好多人都想到了剪贴板的方式,这种方式速度是快,可也有不好的一面,那就是数据量大占用内存也大,并且在Excel中调用PASTE方法时,需要锁定输入,这使用起来,就有点不方便了
这里我为大家介始一种比较好的方法,使用文件流的方式,通过TfileStream直接写入Excel文件。我写了一个函数,通过它可将数据集中的数据直接导入到Excel文件中。我测试了一下,1M的数据,不到十秒就完成了。附源程序。
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,DB, ADODB, Grids, DBGrids, StdCtrls; type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
ADOTable1: TADOTable;
DataSource1: TDataSource;
ADOConnection1: TADOConnection;
ADOTable1record_id: TIntegerField;
ADOTable1action_id: TIntegerField;
ADOTable1action_name: TStringField;
ADOTable1net_name: TStringField;
ADOTable1deal_no: TStringField;
ADOTable1name: TStringField;
ADOTable1getno_date: TDateTimeField;
ADOTable1window_no: TIntegerField;
ADOTable1staff_id: TStringField;
ADOTable1staff_name: TStringField;
ADOTable1deal_date: TDateTimeField;
ADOTable1deal_type: TStringField;
ADOTable1finish_date: TDateTimeField;
ADOTable1state: TStringField;
ADOTable1appraise: TStringField;
ADOTable1appraised_flag: TBooleanField;
ADOTable1cancel_led_time: TDateTimeField;
ADOTable1wait_time: TBCDField;
ADOTable1wait_time2: TStringField;
ADOTable1accept_time: TBCDField;
ADOTable1accept_time2: TStringField;
ADOTable1getnumber_addr: TIntegerField;
ADOTable1cust_level: TIntegerField;
ADOTable1cust_level_name: TStringField;
ADOTable1cust_level_name_remark: TStringField;
ADOTable1operation_sum: TIntegerField;
Button1: TButton;
SaveDialog1: TSaveDialog;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1;
arXlsBegin: array[0..5] of Word = ($809, 8, 0, $10, 0, 0);
arXlsEnd: array[0..1] of Word = ($0A, 00); arXlsString: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
arXlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0); arXlsInteger: array[0..4] of Word = ($27E, 10, 0, 0, 0); arXlsBlank: array[0..4] of Word = ($201, 6, 0, 0, $17);
implementation {$R *.dfm} Procedure ExportExcelFile(FileName: string; bWriteTitle: Boolean; aDataSet: TDataSet);
var
i, j: integer;
Col, row: word;
ABookMark: TBookMark;
aFileStream: TFileStream;
procedure incColRow; //增加行列号
begin
if Col = ADataSet.FieldCount - 1 then
begin
Inc(Row);
Col :=0;
end
else
Inc(Col);
end;
procedure WriteStringCell(AValue: string);//写字符串数据
var
L: Word;
begin
L := Length(AValue);
arXlsString[1] := 8 + L;
arXlsString[2] := Row;
arXlsString[3] := Col;
arXlsString[5] := L;
aFileStream.WriteBuffer(arXlsString, SizeOf(arXlsString));
aFileStream.WriteBuffer(Pointer(AValue)^, L);
IncColRow;
end;
procedure WriteIntegerCell(AValue: integer);//写整数
var
V: Integer;
begin
arXlsInteger[2] := Row;
arXlsInteger[3] := Col;
aFileStream.WriteBuffer(arXlsInteger, SizeOf(arXlsInteger));
V := (AValue shl 2) or 2;
aFileStream.WriteBuffer(V, 4);
IncColRow;
end;
procedure WriteFloatCell(AValue: double);//写浮点数
begin
arXlsNumber[2] := Row;
arXlsNumber[3] := Col;
aFileStream.WriteBuffer(arXlsNumber, SizeOf(arXlsNumber));
aFileStream.WriteBuffer(AValue, 8);
IncColRow;
end;
begin
if FileExists(FileName) then
DeleteFile(FileName); //文件存在,先删除
aFileStream := TFileStream.Create(FileName, fmCreate);
Try
//写文件头
aFileStream.WriteBuffer(arXlsBegin, SizeOf(arXlsBegin));
//写列头
Col := 0; Row := 0;
if bWriteTitle then
begin
for i := 0 to aDataSet.FieldCount - 1 do
WriteStringCell(aDataSet.Fields[i].FieldName);
end;
//写数据集中的数据
aDataSet.DisableControls;
ABookMark := aDataSet.GetBookmark;
aDataSet.First;
while not aDataSet.Eof do
begin
for i := 0 to aDataSet.FieldCount - 1 do
case ADataSet.Fields[i].DataType of
ftSmallint, ftInteger, ftWord, ftAutoInc, ftBytes:
WriteIntegerCell(aDataSet.Fields[i].AsInteger);
ftFloat, ftCurrency, ftBCD:
WriteFloatCell(aDataSet.Fields[i].AsFloat)
else
WriteStringCell(aDataSet.Fields[i].AsString);
end;
aDataSet.Next;
end;
//写文件尾
AFileStream.WriteBuffer(arXlsEnd, SizeOf(arXlsEnd));
if ADataSet.BookmarkValid(ABookMark) then
aDataSet.GotoBookmark(ABookMark);
finally
AFileStream.Free;
ADataSet.EnableControls;
end;
end; procedure TForm1.Button1Click(Sender: TObject);
begin
if SaveDialog1.Execute then
begin
ExportExcelFile(SaveDialog1.FileName,True,DBGrid1.DataSource.DataSet);
end;
end; end.
Delphi数据库数据用文件流方式快速写入Excel文件的更多相关文章
- Python:将爬取的网页数据写入Excel文件中
Python:将爬取的网页数据写入Excel文件中 通过网络爬虫爬取信息后,我们一般是将内容存入txt文件或者数据库中,也可以写入Excel文件中,这里介绍关于使用Excel文件保存爬取到的网页数据的 ...
- java写入excel文件poi
java写入excel文件 java写入excel文件poi,支持xlsx与xls,没有文件自动创建 package com.utils; import java.io.File; import ja ...
- Python中使用第三方库xlrd来写入Excel文件示例
Python中使用第三方库xlrd来写入Excel文件示例 这一篇文章就来介绍下,如何来写Excel,写Excel我们需要使用第三方库xlwt,和xlrd一样,xlrd表示read xls,xlwt表 ...
- python pandas写入excel文件
pandas读取.写入csv数据非常方便,但是有时希望通过excel画个简单的图表看一下数据质量.变化趋势并保存,这时候csv格式的数据就略显不便,因此尝试直接将数据写入excel文件. pandas ...
- 从网络上获取图片,并写入excel文件
package com.weChat.utils; import com.manage.utils.DateUtil;import com.manage.utils.MD5Util;import or ...
- [R语言]读取文件夹下所有子文件夹中的excel文件,并根据分类合并。
解决的问题:需要读取某个大文件夹下所有子文件夹中的excel文件,并汇总,汇总文件中需要包含的2部分的信息:1.该条数据来源于哪个子文件夹:2.该条数据来源于哪个excel文件.最终,按照子文件夹单独 ...
- 读取某文件夹下所有excel文件 python
import os import pandas as pd from sklearn import linear_model path = r'D:\新数据\每日收益率' filenames = os ...
- 【集中工作薄】 当前文件夹中所有Excel文件中 多个工作簿的第一个工作表 复制到工作簿中
功能:当前文件夹中所有Excel文件中 多个工作簿的第一个工作表 复制到工作簿中 Sub Books2Sheets() '定义对话框变量 Dim fd As FileDialog Set fd = A ...
- 把当前文件夹的xlsx或xls文件合并到一个excel文件中的不同sheet中
把当前文件夹的xlsx或xls文件合并到一个excel文件中的不同sheet中步骤如下: 把需要合并的文件放到同一个文件夹 在该文件夹中新建一个excel文件 打开新建的excel问价,把鼠标放到sh ...
随机推荐
- XML文件详解以及解析
转自:https://blog.csdn.net/com_ma/article/details/73277535 一.xml基础详解: 1.概述: xml:即可扩展标记语言,xml是互联网数据传输的重 ...
- 12. SpringBoot国际化
1).编写国际化配置文件: 2).使用ResourceBundleMessageSource管理国际化资源文件 3).在页面使用fmt:message取出国际化内容 步骤:1).编写国际化配置文件,抽 ...
- mysql 案例 ~ pt-kill工具的使用
一 简介:学习pt-kill工具使用 二 功能: 能按照多维角度进行kill的查杀,迅速的降低数据库使用负载 三 常用命令 pt-kill --match-command 'Query|Sleep' ...
- mysql原理~undo
mysql undo详谈1 简介:undo是MVCC机制的基础部分之一2 作用:为了实现可重复性读,存储历史数据3 存储:5.6以前undo都存储在内存和ibdata1中,5.6以后undo可以独立成 ...
- redis实现消息队列&发布/订阅模式使用
在项目中用到了redis作为缓存,再学习了ActiveMq之后想着用redis实现简单的消息队列,下面做记录. Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性 ...
- shiroWeb项目-认证及MD5认证信息在页面显示(十)
realm设置完整认证信息 // realm的认证方法,从数据库查询用户信息 @Override protected AuthenticationInfo doGetAuthenticationInf ...
- Theano教程:Python的内存管理
在写大型程序时候的一大挑战是如何保证最少的内存使用率.但是在Python中的内存管理是比较简单的.Python显示分配内存,使用引用计数系统管理对象,当指向某一个对象的引用数变为 0 的时候,该对象所 ...
- C# 清理消息管道的消息
using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System. ...
- jvm系列四、jvm知识点总结
原文链接:http://www.cnblogs.com/ityouknow/p/6482464.html jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 ...
- zabbix3.0使用ss命令对tcp连接数和状态的监控性能优化
zabbix3.0对tcp连接数及状态的监控优化 之前对tcp的监控采用netstat命令,发现在服务器繁忙的时候效果不理想,这个命令占用大量的cpu有时候高达90%以上,可能会导致业务的不稳定,所以 ...