怎么回事:
excelapplication1.workbooks.Open(FileName,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,0);
提示:
Error] Unit1.pas(119): Undeclared identifier: 'emptyparam'
excelapplication1.workbooks.Open(FileName,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,emptyparam,0);
提示:
Error] Unit1.pas(119): Undeclared identifier: 'emptyparam'
var
excel,excelsheet:variant;
begin
try
excel:=createoleobject('excel.application');
excelsheet:=createoleobject('excel.sheet');
except
showmessage('您的机器里未安装Microsoft Excel.');
exit;
excelsheet:=excel.workbooks.open('文件名');
excel.visible:=true;
end;
ExcelApplication1.Connect;
ExcelApplication1.Visible[0]:=True;
template=文件名
ExcelWorkbook1.ConnectTo(ExcelApplication1.Workbooks.Open(template,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,0));
我们的例子从一个带有TStringGrid(当然要填上一些数据)和两个按钮的主窗体开始,从控制面板的Servers页签中拖一个TExcelApplication控件放到窗体上。首先把ConnectKind设为ckRunningOrNew,表示如果能够检测到运行的Excel实例则与其建立联系,否则启动Excel。另外,如果希望程序一运行即与服务器程序建立联系,可以把AutoConnect属性设为True。
与Excel建立联系只要一条语句就可以了:
Excel . Connect;
也许你已经注意到Servers页签上还有其他几个Excel控件,这些控件通过ConnectTo方法可以与前面的Excel联系在一起:
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;
……
…… //这里为数组元素赋值
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属性用于定义表格线的粗细:
Uses语句中至少有以下几个单元!!!
Excel2000, ActiveX, Windows, OleCtrls, SysUtils;
定义:
WorkBook : _WorkBook;
WorkSheet : _WorkSheet;
然后可以通过如下方式取得纪录
WorkSheet := WorkBook.Sheets[1] as _WorkSheet; //取得当前Sheet
对每个Sheet,可以从初行到末行读取纪录:
For i := firstno to lastno do
ShowMessage(Trim(WorkSheet.Cells.Item[i, FieldNo]));