当然你也可以为单元格指定公式: var AFormula:String; …… AFormula:='=Rand()'; wkSheet.Range['F3','G6'].Value:=AFormula; 上面的方法非常直接简单,但是速度非常慢,不适合作大型报表。那么能不能把所有的数据依次传递给Excel呢?我们可以使用Range,这个对象代表工作表中的一个区域,象我们用鼠标拖出的那样,一般是一个矩形区域,只要给定其左上角和右下角单元格的位置就可以了,如Range[‘C3’,’J42’]。这里还有一个小问题,因为如果数据超出26列(比如有100列)或者需要在运行中确定目标区域范围的话,使用字符名称标记单元格就比较麻烦。回想一下,既然“C3”是单元格的标记,那么我们当然也可以使用Cells,比如Range[Cells.Item[1,1], Cells.Item[100,100]]。可以想象,Range的值应该是数组,但是绝对不能用Delphi中的Array给它赋值!要记住,在Delphi中,Excel对象的值总是Variant类型的。 var Datas : Variant; Ir, ic: Integer; …… Datas:= varArrayCreate([1,ir,1,ic],varVariant); //这里创建100*100的动态数组 …… //这里为数组元素赋值 with wkSheet do Range[cells.Item[3,1],cells.Item[ir+2,ic]].Value:=Datas;
要注意,工作表与Range都有Cells属性,为了明确起见,这里使用了with语句。此外, Range是有方向性的,用VarArrayCreate建立的一维数组只能赋给单行的Range,如果要为单列 的Range定义值,必须使用二维数组,比如: Datas:=VarArrayCreate([1,100,1,1], varVariant); //创建100*1的动态数组。顺便提一下,Cells.Item[]实际上返回的也是Range对象。从工作表中取 回数据基本上是写数据的逆过程,稍微需要注意的是如何确定工作表的数据范围: var ir, ic : Integer; …… wkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam).Activate; ir := Excel.ActiveCell.Row; ic := Excel.ActiveCell.Column; 这里巧妙地利用特殊单元格函数SpecialCells取得包含数据的最后一个单元格。 数据编辑 下面是数据编辑的两个例子。 var DestRange: OleVariant; begin DestRange := Excel.Range['C1', 'D4']; Excel.Range['A1', 'B4'].Copy(DestRange); 上面的例子复制了8个单元格的内容。如果给Copy函数传递一个空参数,则该区域的数据被复制到剪贴板, 以后可以用Paste方法粘贴到别的位置。 var WS: _ Worksheet; …… Excel.Range['A1', 'B4'].Copy(EmptyParam); //在一个工作表中复制数据到剪贴板 WS := Excel.Activesheet as _Worksheet; //改变活动工作表 WS.Range['C1', 'D4'].Select; WS.Paste(EmptyParam, EmptyParam, lcid); //把剪贴板中的内容粘贴到新的工作表中
格式设置选择Excel作为报表服务器主要是因为它强大的格式化能力。我们首先把标题“通讯录”进行单元格合并, 居中显示,然后修改字体为18磅的“隶书”,粗体: with wkSheet.Range['A1','D1'],Font do begin Merge(True); //合并单元格 HorizontalAlignment:= xlCenter; Size:=18; Name:='隶书'; FontStyle:=Bold; end;
如果单元格内容较长,将有部分内容无法显示,通常的做法是双击选定区域右侧的边线是各列的宽度自动适应内容的长度。在Delphi中通过AutoFit方法也可实现自适应的列宽行高,需要注意的是该方法仅能用于整行整列,否则会提示OLE方法拒绝执行的错误: wkSheet.Columns.EntireColumn.AutoFit; 中式报表通常需要上下封顶的表格线,可以使用Borders集合属性。要注意,VBA中的集合对象通常都有一个缺省的Item属性,Delphi中是不能省略的。Weight属性用于定义表格线的粗细: with Aname.RefersToRange,Borders do begin HorizontalAlignment:= xlRight; Item[xlEdgeBottom].Weight:=xlMedium; Item[xlEdgeTop].Weight:=xlMedium; Item[xlInsideHorizontal].Weight:=xlThin; item[xlInsideVertical].Weight:=xlThin; end; 页面设置与打印页面设置是通过工作表的PageSetUp对象属性设置的。Excel VBA中预设了40余种纸张常量,需要注意的是某些打印机只支持其中的一部分纸张类型。属性Orientation用于控制打印的方向, 常量landscape = 2表示横向打印。布尔属性CenterHorizontally和CenterVertically用于确定打印的内容是否在水平和垂直方向上居中。 with wkSheet.PageSetUp do begin PaperSize:=xlPaperA4; //Paper type A4 PrintTitleRows := 'A1:D1'; //Repeat this row/page LeftMargin:=18; //0.25" Left Margin RightMargin:=18; //0.25" will vary between printers TopMargin:=36; //0.5" BottomMargin:=36; //0.5" CenterHorizontally:=True; Orientation:=1; //横向打印(landscape)=2, portrait=1 end; 打印报表可以调用工作表的PrintOut方法,VBA定义的该方法共有8个可选参数,前两个用于规定起止页,第三格式打印的份数,不过在Delphi中为其在最后增加了一个LCID参数,而且该参数不能使用EmptyParam。类似地,打印预览方法PrintPreview在VBA中没有参数,而在Delphi中调用需要两个参数。 wkBook.PrintPreview(True,LCID); //for previewing wkSheet.PrintOut(EmptyParam,EmptyParam,1, EmptyParam,EmptyParam,EmptyParam, EmptyParam,EmptyParam,LCID); 命名区域与宏如果报表的格式比较复杂,为特定的表格区域命名然后按名引用是一种比较好的方法。Names是WorkBook的一个集合对象属性,它有一个的Add方法可以完成这项工作。 Var Aname : Excel2000.Name; …… Aname := wkBook.Names.Add('通讯录','=Sheet1!$A$3:$D$7', EmptyParam, EmptyParam, EmptyParam,EmptyParam,EmptyParam, EmptyParam, EmptyParam,EmptyParam,EmptyParam);
其中Add函数的第一个参数是定义的名称,第二个参数是名称所表示的单元格区域。要注意区域名称的类型必须使用限定符,如果使用类型库(D4),则限定符为Excel_TLB。此外,命名的区域应使用绝对引用方式,即加上“$”符号。一旦命名了一个区域,就可以使用这个名称来引用它,下面的一行代码使通讯录内容以粗体显示: AName.RefersToRange.Font.Bold:=True; 不过最令人惊喜的也许是你能够在Delphi中动态地修改Excel宏程序!下面的代码为我们的工作簿创建了一个宏,在关闭工作簿时记录上一次访问的时间: var LineNo: integer; CM: CodeModule; sDate:String; begin CM := WkBook.VBProject.VBComponents.Item('ThisWorkbook').Codemodule; LineNo := CM.CreateEventProc('BeforeClose', 'Workbook'); SDate:='上次访问日期:'+DateToStr(Date()); CM.InsertLines(LineNo + 1, ' Range("B2").Value = "'+sDate+'"'); End;
修改宏需要在前面的uses一节加上一个单元:VBIDE2000,如果使用类型库则相应的单元为VBIDE_TLB。这段代码的关键是CodeModule对象,遗憾的是在Excel VBA help文中找不到该对象的踪迹,只能去检索MSDN了。 Delphi4及以前的版本 Delphi4没有提供TExcelApplication对象,需要引入类型库使用OLE自动化技术,Excel97的类型库是Excel8.olb。这两种方法的主要区别在于与服务器程序建立连接的方法,下面是通过类型库控制Excel的程序框架: uses Windows, ComObj, ActiveX, Excel_TLB; var Excel: _Application; LCID: integer; Unknown:IUnknown; Result: HResult; begin LCID := LOCALE_USER_DEFAULT; Result := GetActiveObject(CLASS_Application, nil, Unknown); //尝试捕获运行中的程序实例 if (Result = MK_E_UNAVAILABLE) then Excel := CoApplication.Create //启动新的程序实例 else begin {检查GetActiveObject方法调用过程中的错误} OleCheck(Result); OleCheck(Unknown.QueryInterface(_Application, Excel)); end; …… //进行数据处理 Excel.Visible[LCID] := True; // Excel.DisplayAlerts[LCID] := False; //显示提示对话框 Excel.Quit; End;
谢谢! 我是要做一个接口,把数据导到excel,让别人来读取。
以不打开Execl为好,让别人来直接读取。
那就更簡單了用ado直接連接excel文件就可以了
要处理大量数据,只能一个个的去生成Excel文件,去读取。怎么连。
前提是不打开Excel,直接生成excel文件。
别说没人回procedure TForm1.printToExcel(dataset:Tdataset); var i:integer; s:Tstringlist; tmp:string; begin if not dataset.Active then begin MessageDlg('请打开数据!',mtinformation,[mbYes],0); exit; end; if not SaveDialog1.Execute then begin exit; end; s:=tstringlist.create; dataset.DisableControls; Screen.Cursor:=crHourGlass; try tmp:=''; for i:=0 to dataset.fields.count-1 do tmp:=tmp+dataset.fields[i].DisplayLabel+#9; s.add(tmp); dataset.first; while not dataset.eof do begin tmp:=''; for i:=0 to dataset.fields.count-1 do tmp:=tmp+(dataset.fields[i].asstring)+#9; s.Add(tmp); dataset.next; end; s.savetofile(SaveDialog1.filename); MessageDlg('导出数据成功!',mtinformation,[mbYes],0); finally s.free; dataset.EnableControls; Screen.Cursor:=crArrow; end; END;
ExcelWorkbook1.ConnectTo(Excel . ActiveWorkbook);
ExcelWorksheet1.ConnectTo(Excel . ActiveSheet as _Worksheet);
ExcelWorksheet2.ConnectTo(Excel . Worksheets.Item['Sheet2'] as _Worksheet); 要注意,使用ConnectTo方法前必须先打开相应的工作簿或工作表,另外这些控件在多数情况下并不会带来额外的便利,因此最好只使用一个TExcelApplication。一旦与Excel服务器建立联系,就可以创建新的工作簿:
var
wkBook : _WorkBook;
LCID : Integer;
...
LCID := GetUserDefaultLCID();
wkBook := Excel.Workbooks.Add(EmptyParam, LCID);
Add函数的第一个参数用于定义新建工作簿所使用的模板,可以使用xlWBATChart、 xlWBATExcel4IntlMacroSheet、 xlWBATExcel4MacroSheet或者xlWBATWorksheet常量,
也可以是已有的xls文件名。这里的EmptyParam是Variants单元与定义的变量,
表示使用默认的通用模板创建新工作簿。如果打开已有的xls文档,则应把要打开的文
件名作为第一个参数传递给Open函数: wkBook:=Excel.WorkBooks.Open(edtDesFile.text,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,LCID); 要知道,所有的数据操作主要是针对活动工作表而言的,下面的语句使用一个_WorkSheet变量代表当前的活动单元格。如果知道工作表的名称,其中的索引号可以用工作表名代替: wkSheet:=wkBook.Sheets[1] as _WorkSheet; 完成数据交换后需要保存工作簿: Excel.ActiveWorkBook.SaveAs ('MyOutput', EmptyParam,EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, LCID);
或者:
Excel.ActiveWorkBook.Save(LCID); 最后要关闭工作簿并断开与Excel的连接:
wkBook.Close(True, SaveAsName, EmptyParam, LCID);
//Excel.Quit; Excel.Disconnect; 这里的Close方法包含有保存的功能,第一个参数说明在关闭工作簿之前是否保存所做的修改,第二个参数给出要保存的文件名,第三个参数用于多位作者处理文档的情况。第二行要求终止Excel的运行。 与工作表交换数据输入数据是对活动工作表的某个单元格或区域进行的,Range与cells都是工作表的对象属性。Cells是单元格的集合,如果没有指定具体位置可以代表整个工作表的所有单元格,但一般使用它是为了引用某个具体的单元格,比如WS.Cells.Item[1,1]就表示最左上角的单元格A1,注意在VBA中Item是Cells的默认属性可以省略,但在Delphi中就没有这种便利了。为单元格赋值要引用其Value属性,不言而喻,该属性是一个Variant变量,例如: wkSheet.Cells.Item[1, 1].Value := '通讯录';
var AFormula:String; …… AFormula:='=Rand()';
wkSheet.Range['F3','G6'].Value:=AFormula; 上面的方法非常直接简单,但是速度非常慢,不适合作大型报表。那么能不能把所有的数据依次传递给Excel呢?我们可以使用Range,这个对象代表工作表中的一个区域,象我们用鼠标拖出的那样,一般是一个矩形区域,只要给定其左上角和右下角单元格的位置就可以了,如Range[‘C3’,’J42’]。这里还有一个小问题,因为如果数据超出26列(比如有100列)或者需要在运行中确定目标区域范围的话,使用字符名称标记单元格就比较麻烦。回想一下,既然“C3”是单元格的标记,那么我们当然也可以使用Cells,比如Range[Cells.Item[1,1], Cells.Item[100,100]]。可以想象,Range的值应该是数组,但是绝对不能用Delphi中的Array给它赋值!要记住,在Delphi中,Excel对象的值总是Variant类型的。 var Datas : Variant;
Ir, ic: Integer;
……
Datas:= varArrayCreate([1,ir,1,ic],varVariant); //这里创建100*100的动态数组 …… //这里为数组元素赋值
with wkSheet do
Range[cells.Item[3,1],cells.Item[ir+2,ic]].Value:=Datas;
要注意,工作表与Range都有Cells属性,为了明确起见,这里使用了with语句。此外, Range是有方向性的,用VarArrayCreate建立的一维数组只能赋给单行的Range,如果要为单列 的Range定义值,必须使用二维数组,比如: Datas:=VarArrayCreate([1,100,1,1], varVariant); //创建100*1的动态数组。顺便提一下,Cells.Item[]实际上返回的也是Range对象。从工作表中取 回数据基本上是写数据的逆过程,稍微需要注意的是如何确定工作表的数据范围: var ir, ic : Integer;
…… wkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam).Activate;
ir := Excel.ActiveCell.Row; ic := Excel.ActiveCell.Column; 这里巧妙地利用特殊单元格函数SpecialCells取得包含数据的最后一个单元格。 数据编辑 下面是数据编辑的两个例子。
var
DestRange: OleVariant;
begin
DestRange := Excel.Range['C1', 'D4'];
Excel.Range['A1', 'B4'].Copy(DestRange); 上面的例子复制了8个单元格的内容。如果给Copy函数传递一个空参数,则该区域的数据被复制到剪贴板,
以后可以用Paste方法粘贴到别的位置。
var WS: _
Worksheet;
……
Excel.Range['A1', 'B4'].Copy(EmptyParam); //在一个工作表中复制数据到剪贴板
WS := Excel.Activesheet as _Worksheet; //改变活动工作表
WS.Range['C1', 'D4'].Select; WS.Paste(EmptyParam, EmptyParam, lcid); //把剪贴板中的内容粘贴到新的工作表中
格式设置选择Excel作为报表服务器主要是因为它强大的格式化能力。我们首先把标题“通讯录”进行单元格合并,
居中显示,然后修改字体为18磅的“隶书”,粗体:
with wkSheet.Range['A1','D1'],Font do
begin
Merge(True); //合并单元格
HorizontalAlignment:= xlCenter;
Size:=18; Name:='隶书';
FontStyle:=Bold;
end;
with Aname.RefersToRange,Borders do
begin
HorizontalAlignment:= xlRight;
Item[xlEdgeBottom].Weight:=xlMedium;
Item[xlEdgeTop].Weight:=xlMedium;
Item[xlInsideHorizontal].Weight:=xlThin;
item[xlInsideVertical].Weight:=xlThin;
end; 页面设置与打印页面设置是通过工作表的PageSetUp对象属性设置的。Excel VBA中预设了40余种纸张常量,需要注意的是某些打印机只支持其中的一部分纸张类型。属性Orientation用于控制打印的方向,
常量landscape = 2表示横向打印。布尔属性CenterHorizontally和CenterVertically用于确定打印的内容是否在水平和垂直方向上居中。
with wkSheet.PageSetUp do
begin
PaperSize:=xlPaperA4; //Paper type A4
PrintTitleRows := 'A1:D1'; //Repeat this row/page
LeftMargin:=18; //0.25" Left Margin
RightMargin:=18; //0.25" will vary between printers
TopMargin:=36; //0.5"
BottomMargin:=36; //0.5"
CenterHorizontally:=True;
Orientation:=1; //横向打印(landscape)=2,
portrait=1
end;
打印报表可以调用工作表的PrintOut方法,VBA定义的该方法共有8个可选参数,前两个用于规定起止页,第三格式打印的份数,不过在Delphi中为其在最后增加了一个LCID参数,而且该参数不能使用EmptyParam。类似地,打印预览方法PrintPreview在VBA中没有参数,而在Delphi中调用需要两个参数。
wkBook.PrintPreview(True,LCID); //for previewing
wkSheet.PrintOut(EmptyParam,EmptyParam,1, EmptyParam,EmptyParam,EmptyParam, EmptyParam,EmptyParam,LCID); 命名区域与宏如果报表的格式比较复杂,为特定的表格区域命名然后按名引用是一种比较好的方法。Names是WorkBook的一个集合对象属性,它有一个的Add方法可以完成这项工作。
Var
Aname : Excel2000.Name;
……
Aname := wkBook.Names.Add('通讯录','=Sheet1!$A$3:$D$7', EmptyParam,
EmptyParam, EmptyParam,EmptyParam,EmptyParam,
EmptyParam, EmptyParam,EmptyParam,EmptyParam);
其中Add函数的第一个参数是定义的名称,第二个参数是名称所表示的单元格区域。要注意区域名称的类型必须使用限定符,如果使用类型库(D4),则限定符为Excel_TLB。此外,命名的区域应使用绝对引用方式,即加上“$”符号。一旦命名了一个区域,就可以使用这个名称来引用它,下面的一行代码使通讯录内容以粗体显示: AName.RefersToRange.Font.Bold:=True; 不过最令人惊喜的也许是你能够在Delphi中动态地修改Excel宏程序!下面的代码为我们的工作簿创建了一个宏,在关闭工作簿时记录上一次访问的时间:
var
LineNo: integer;
CM: CodeModule;
sDate:String;
begin
CM := WkBook.VBProject.VBComponents.Item('ThisWorkbook').Codemodule;
LineNo := CM.CreateEventProc('BeforeClose', 'Workbook');
SDate:='上次访问日期:'+DateToStr(Date());
CM.InsertLines(LineNo + 1, ' Range("B2").Value = "'+sDate+'"');
End;
修改宏需要在前面的uses一节加上一个单元:VBIDE2000,如果使用类型库则相应的单元为VBIDE_TLB。这段代码的关键是CodeModule对象,遗憾的是在Excel VBA help文中找不到该对象的踪迹,只能去检索MSDN了。 Delphi4及以前的版本 Delphi4没有提供TExcelApplication对象,需要引入类型库使用OLE自动化技术,Excel97的类型库是Excel8.olb。这两种方法的主要区别在于与服务器程序建立连接的方法,下面是通过类型库控制Excel的程序框架: uses Windows, ComObj, ActiveX, Excel_TLB; var
Excel: _Application;
LCID: integer;
Unknown:IUnknown;
Result: HResult; begin
LCID := LOCALE_USER_DEFAULT;
Result := GetActiveObject(CLASS_Application, nil, Unknown); //尝试捕获运行中的程序实例
if (Result = MK_E_UNAVAILABLE) then
Excel := CoApplication.Create //启动新的程序实例
else begin {检查GetActiveObject方法调用过程中的错误}
OleCheck(Result);
OleCheck(Unknown.QueryInterface(_Application, Excel));
end;
…… //进行数据处理
Excel.Visible[LCID] := True; //
Excel.DisplayAlerts[LCID] := False; //显示提示对话框
Excel.Quit;
End;
我是要做一个接口,把数据导到excel,让别人来读取。
var
i:integer;
s:Tstringlist;
tmp:string;
begin
if not dataset.Active then
begin
MessageDlg('请打开数据!',mtinformation,[mbYes],0);
exit;
end; if not SaveDialog1.Execute then
begin
exit;
end; s:=tstringlist.create;
dataset.DisableControls;
Screen.Cursor:=crHourGlass;
try
tmp:=''; for i:=0 to dataset.fields.count-1 do
tmp:=tmp+dataset.fields[i].DisplayLabel+#9;
s.add(tmp);
dataset.first;
while not dataset.eof do
begin
tmp:='';
for i:=0 to dataset.fields.count-1 do
tmp:=tmp+(dataset.fields[i].asstring)+#9;
s.Add(tmp); dataset.next;
end;
s.savetofile(SaveDialog1.filename); MessageDlg('导出数据成功!',mtinformation,[mbYes],0); finally
s.free;
dataset.EnableControls;
Screen.Cursor:=crArrow; end;
END;
不需要安装过EXCEL也可以用
我不管你使用ADO连接还是OLE连接,最起码的东西都没有,那怎么做啊?