紧急求助!!!报表输出到 Excel 的问题,送100分(100分)

  • 主题发起人 主题发起人 crpp0602
  • 开始时间 开始时间
C

crpp0602

Unregistered / Unconfirmed
GUEST, unregistred user!
要求将本厂所有的报表都比较好的输出到 Excel 中,因报表较多,且做得不统一,报表都是通过quickrep 做出来的。我用 QRCSVFilter 和 QRExcelFilter 组件输出都得不到老大可以接受的结果,自己采用了如下方法:用 ExcelApplication 或 OLE 连接 Excel 软件,在每一个 band 的BeforePrint事件中调用如下的过程。该过程的目的是每次触发band 的BeforePrint事件时将该 band 上显示的内容输出到 Excel 中,但存在的问题是:报 无效的指针操作或读地址内存错误,这个错误很有可能在里面的二重循环中,该二重循环很简单的,还有一个问题: TQRExpr 和 TQRExprMemo 类上显示的内容输出不到 excel 中,特恳请各位帮忙。
procedure OutPutToExcel(Sender: TQRCustomBand);
var
n,k:integer;
TmpIntLeft:array of integer;
tmpint,length0:integer;

begin
with senderdo
begin

length0:=(sender as TQRCustomBand).ControlCount;
setlength(TmpIntLeft,length0);
for n:=0 to length0-1do
TmpIntLeft[n]:=controls[n].Left;
for k:=0 to length0-2do
//冒泡排序法排列各个组件的 left 属性值 ??
begin
for n:=0 to length0-1-kdo
begin
if TmpIntLeft[n]>TmpIntLeft[n+1] then
begin
tmpint:=TmpIntLeft[n];
TmpIntLeft[n]:=TmpIntLeft[n+1];
TmpIntLeft[n+1]:=tmpint;
end;
end;
end;
end;
with senderdo
//用二重循环将 band 组件上显示的内容依其 left 属性值的大小次序输出到 excel 的单元格中
begin
i:=1;
for n:=0 to length0-1do
begin
for k:=0 to length0-1do
begin
if controls[k].Left=TmpIntLeft[n] then
begin
if controls[k] is TQRLabel then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRLabel).Caption;
if controls[k] is TQRDBText then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRDBText).DataSet.fieldbyname((controls[k] as TQRDBText).DataField).asstring;
if controls[k] is TQRExpr then

ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRExpr).Caption;
if controls[k] is TQRSysData then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRSysData).Caption;
if controls[k] is TQRMemo then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRMemo).Lines.Text;
if controls[k] is TQRExprMemo then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRExprMemo).Caption;
if controls[k] is TQRRichText then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRRichText).Lines.Text;
if controls[k] is TQRDBRichText then
ExcelWorksheet1.Cells.Item[j,i]:=(controls[k] as TQRDBRichText).DataSet.fieldbyname((controls[k] as TQRDBRichText).DataField).asstring;
inc(i);
end;
end;
end;
inc(j);
end;
end;
 
用Word做Delphi报表输出工具

笔者在实际应用中发现,报表的内容一般很少变动,但其字体格式及版式是经常变动的,而且有时用户为了某种需要,不想修改数据库的真实内容而又要改变报表内容。如果用ReportSmith可以解决前者问题,但对于后者则无能为力了,且其界面是英文的,不合用户习惯。如果用3.0中的TQReport的报表部件,则两者都不能实时解决,必须修改原代码后重新编译才能使用。而使用Word及Excel则完全可以克服以上不足。具体实现如下(以Word实现为例):

首先用Word编辑报表格式,并排好版,把将要输出的数据项用表单域代替,并取名。这里我们暂时假设有表单域Item1及Item2(均为文本型)
将这个文档存为模板文件Example.dot,然后按如下步骤进行:

1)运行Delphi3,在Form1里加入一个System部件集里的TDdeClientCov部件,取名为DdeExample
将其ConnectMode设为ddeManual(手动方式);将DdeService设为‘(WinWord)’;将ServiceApplication设为‘WinWord’。

2)编写一个自定义过程,以激活Word,如下:
procedure Tform1.WordActive(Cmds: TStrings);
var
WordPath: String;
begin

if(not DdeExample.OpenLink) then
{判断是否巳动态链接}
begin

if(FindWindow('OpusApp'
nil)=0) then

begin

WordPath := 'C:/msoffice/winword';
if(WordPath='') then

ShowMessage('中文Word未安装或未设置路径,请安装设置Word中文 版。')
else
begin

DdeExample.ServiceApplication := WordPath+'/Winword.exe';
if(DdeExample.OpenLink) then
{如果巳动态链接执行宏命令}   
DdeExample.ExecuteMacroLines(Cmds
False)
else

ShowMessage('无法启动Word中文版!');
DdeExample.ServiceApplication := 'WinWord.exe';
end;

end
else
begin
{如果巳动态链接执行宏命令}
DdeExample.ExecuteMacroLines(Cmds
False);
end;

end
else

DdeExample.ExecuteMacroLines(Cmds
false);
end;

在private声明区里加入如下:
procedure ActiveWord(Cmds: TStrings);

3)在Form1中加入一个按钮Button1
在其onclick事件里写如下代码:
procedure TForm1.Button1Click(Sender: TObject);
var
Cmds:TStringList;{创建Cmds}
TempItem1
TempItem2:String;
begin

cmds:=TStringList.Create;
cmds.Clear;
TempItem1:='数据项一';
TempItem2:='数据项二';
with Cmdsdo

begin

Clear;
Add('[FileNew.Template ="Example.Dot″]');{打开模板文件Example.Dot}
Add('[AppMaximize]');{文档最大化}
Add('[SetFormResult"Item1″
″'+TempItem1+'″]');{将数据TempItem1传给表单域Item1}
Add('[SetFormResult"Item2″
″'+TempItem2+'″]);{将数据TempItem2传给表单域Item2}
end;

WordActive(DdeExample
Cmds);{调用自定义过程}
Cmds.Free;{释放Cmds}
end;

运行这个程序,单击Button1,大家可以发现Word被启动了,屏幕上出现了:数据项一;数据项二两个数据项。最后,大家可以任意修改本报表的格式及数据,因为这时这个报表与具体的应用程序巳没有关系了。

本例中用的是中文Word6或中文Word7。由于Word97的宏命令巳变为Visual Basic语句,如大家想用Word97实现,请将其宏命令改变为相应的代码。

这是个简单的示例,大家可以利用Word的宏录制功能,录取更多的宏(如自动生成表格、填充文字、变动字体等宏命令),并与数据库的各种表联系起来,依次加入Cmds中即可实现您所要求的更复杂的功能。
 
与其将band中的内容导出execl,还不如直接就将band所关联的数据集中的内容直接就导出到excel中,这样不是更方便???
 
后退
顶部