动态生成报表?悬赏400分(100分)

  • 主题发起人 主题发起人 filter
  • 开始时间 开始时间
F

filter

Unregistered / Unconfirmed
GUEST, unregistred user!
一个报表的字段来源于另一个数据表的记录(记录是可由用户增加删除的)例:tzcmcb中记录为
dmmc
电脑
办公桌
椅子
生成报表TEMP为科室 电脑 办公桌 椅子
zc 1 2 3
dd 2 3 4
现已用存储过程动态生成临时表temp,
现要根据TEMP生成REPORT,但生成时出错。源代码如下:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, QuickRpt, Db, DBTables,QRCTRLS;
type
TForm2 = class(TForm)
QuickRep1: TQuickRep;
DetailBand1: TQRBand;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;
QRLabel: array of TQRLabel;
QRShape: array of TQRShape;
QRDBText:array of TQRDBText;
k: integer;
implementation
uses main;
{$R *.DFM}
procedure TForm2.FormDestroy(Sender: TObject);
var
i:integer;
begin
for i:=0 to k-1 do
//k为tzcmcb中的记录数,记录数数量=已创建的控件数量
begin
qrlabel.Destroy;
QRShape.Destroy;
QRDBText.Destroy;
end;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
i,j: integer;
begin
with Form1.Query2 do
//确定报表中字段的数目
begin
close;
sql.clear;
sql.add('select * from tzcmcb');
try
open;
k:=recordcount;
except
application.MessageBox ('数据库连接超时!','警告',mb_ok+mb_iconerror);
end;
end;
with Form1.query3 do
//激活临时表,准备显示记录,临时表的字段名就是 tzcmcb中dmmc字段的记录
begin
close;
sql.clear;
sql.add('select * from temp');
try
open;
except
application.MessageBox ('数据库连接超时!','警告',mb_ok+mb_iconerror);
end;
end;
SetLength(QRLabel,k-1);
//设置动态数组长度
SetLength(QRShape,k-1);

SetLength(QRDBText,k-1);

xzjlst:=1;

for i:=0 to k-1 do
begin
QRShape:=TQRShape.Create(self);
with QRShape do
begin
Parent:=DetailBand1;
Left:=i*92;
Top:=i*24;
Height:=25;
Width:=93;
Enabled:=True;
Visible:=True;
end;
QRLabel:=TQRLabel.Create(self);
with QRLabel do
begin
Parent:=DetailBand1;
Left:=i*60+60;
Top:=100;
Height:=100;
Width:=90;
Alignment:=TaCenter;
AutoSize:=True;
Caption:='';
Enabled:=True;
Visible:=True;
end;
QRDBText:=TQRDBText.Create(self);
with QRDBText do
begin
Parent:=DetailBand1;
Left:=i*60+60;
Top:=200;
Height:=50;
Width:=90;
Alignment:=TaCenter;
AutoSize:=True;
//Caption:='';
Enabled:=True;
Visible:=True;
end;
end;
Form1.query2.first;
i:=0;
while not Form1.query2.eof do
//确定动态创建的QRLABEL名及字段名
begin
QRLabel.Caption:=Form1.query2.fieldbyname('dmmc').asstring;
QRDBText.DataSet:=Form1.query3;
QRDBText.DataField:=Form1.query2.fieldbyname('dmmc').asstring;
i:=i+1;
Form1.query2.next;
end;
end;

end.

问题1:显示仅能显于一条记录,其余记录未见。且预览关闭时,报'INVALID POINTER OPERATION' 出错?
问题2:由于TEMP是动态的,可能字段会很长很长,采用每增加一个字段即增加quickrep的width,虽然可以解决,但对一用户来说是
不方便的(只有竖向打印),能不能做成每八个字段打印一页,随字段的多少/8来创建多个quickrep.
头晕!如何解决呢
问题3:如不用quickreport,而采用fastreport时,上面有frPRINTGRID可根据DBGRID的的显示来自动调整页,但觉得不是很美观,且一些属性无法调整(另:fastreport中,怎么我用frReport1.Preview一预览就报错)
希望只用quickreport,请大侠们最好能给出源代码。
 
显示这一条记录对吗?
 
只有一个记录的原因极有可能是因为QUICKREP的TABLE/DATASOURCE没有设置
 
我是调用EXCEL生成动态报表
 
将数据表中的数据装到一个定义为TStringList中去,一定能行,我就是这么实现的
 
简单,你自己创建QRLABEL,自己来控制写.我以前做的是一个鞋业领料单,中间有许多SIZE是
空的,要将这些空的去掉,后面的往前靠,而且分三排.用DataSet来做根本不可能,就自己写
着来控制就行了.部分代码如下:你看了应该就知道怎么做了.用QuickRep完全能够做到.
procedure TFrmQrt.CreateQRTxt;//动态建立各QR控件,只建立一次,在准备预览或打印之前.
var i,j:integer;
begin
SetLength(QRtxt,5,txtTotal);
for i:=0 to 4 do
for j:=0 to txtTotal-1 do
begin
QRtxt[i,j]:=TQRLabel.Create(Self);
QRtxt[i,j].Parent:=DetailBand1;
QRtxt[i,j].Caption:='';
QRtxt[i,j].AutoSize:=False;
QRtxt[i,j].Width:=txtWidth;
QRtxt[i,j].Height:=txtHeight;
QRtxt[i,j].Font.Name:='新細明體';
QRtxt[i,j].Font.Size:=11;
end;
for i:=0 to txtTotal-1 do
QRtxt[0,i].Alignment:=taCenter;
for i:=0 to 35 do
QRtxt[1,i].Alignment:=taCenter;
DrawLine;
for j:=32 to 35 do
begin
Qrtxt[0,j].Font.Size:=11;
Qrtxt[1,j].Font.Size:=11;
QRtxt[0,j].Top:=StrTop;
QRtxt[1,j].Top:=StrTop;
end;
QRtxt[0,32].Left:=0;
QRtxt[1,32].Left:=60;
QRtxt[0,33].Left:=150;
QRtxt[1,33].Left:=220;
QRtxt[0,34].Left:=310;
QRtxt[1,34].Left:=380;
QRtxt[0,35].Left:=480;
QRtxt[1,35].Left:=550;
QRtxt[0,32].Width:=60;
QRtxt[1,32].Width:=90;
QRtxt[0,33].Width:=70;
QRtxt[1,33].Width:=90;
QRtxt[0,34].Width:=70;
QRtxt[1,34].Width:=100;
QRtxt[0,35].Width:=70;
QRtxt[1,35].Width:=122;
for j:=0 to 15 do
begin
QRtxt[0,j].Left:=txtWidth*j;
QRtxt[1,j].Left:=txtWidth*j;
QRtxt[2,j].Left:=txtWidth*j;
QRtxt[3,j].Left:=txtWidth*j;
QRtxt[4,j].Left:=txtWidth*j;
QRtxt[0,j].Top:=txtTop;
QRtxt[1,j].Top:=txtTop+txtHeight;
QRtxt[2,j].Top:=txtTop+txtHeight*2;
QRtxt[3,j].Top:=txtTop+txtHeight*3;
QRtxt[4,j].Top:=txtTop+txtHeight*4;
end;
for j:=16 to 31 do
begin
QRtxt[0,j].Left:=txtWidth*(j-16);
QRtxt[1,j].Left:=txtWidth*(j-16);
QRtxt[2,j].Left:=txtWidth*(j-16);
QRtxt[3,j].Left:=txtWidth*(j-16);
QRtxt[4,j].Left:=txtWidth*(j-16);
QRtxt[0,j].Top:=txtTop+txtHeight*5+20;
QRtxt[1,j].Top:=txtTop+txtHeight*6+20;
QRtxt[2,j].Top:=txtTop+txtHeight*7+20;
QRtxt[3,j].Top:=txtTop+txtHeight*8+20;
QRtxt[4,j].Top:=txtTop+txtHeight*9+20;
end;
for i:=2 to 4 do
for j:=32 to 35 do
QRtxt[i,j].Free;
end;

procedure TFrmQrt.DrawLine;//因为我打印的是表格,所以要画线,一个QRLabel中可以画框线,我就选的这个.而且,我都是用的QRLabel来实现的,加上数据源就不能这么动态了.
var i,j:integer;
begin
for i:=0 to 4 do
for j:=0 to txtTotal-1 do
begin
QRtxt[i,j].Frame.DrawTop:=True;
QRtxt[i,j].Frame.DrawLeft:=True;
end;
for j:=0 to 31 do
QRtxt[4,j].Frame.DrawBottom:=True;
QRtxt[1,35].Frame.DrawRight:=True;
QRtxt[0,15].Frame.DrawRight:=True;
QRtxt[1,15].Frame.DrawRight:=True;
QRtxt[0,31].Frame.DrawRight:=True;
QRtxt[1,31].Frame.DrawRight:=True;
QRtxt[2,15].Frame.DrawRight:=True;
QRtxt[3,15].Frame.DrawRight:=True;
QRtxt[4,15].Frame.DrawRight:=True;
QRtxt[2,31].Frame.DrawRight:=True;
QRtxt[3,31].Frame.DrawRight:=True;
QRtxt[4,31].Frame.DrawRight:=True;
for j:=32 to 35 do
QRtxt[1,j].Alignment:=taLeftJustify;
QRtxt[0,32].Caption:='單據號';
QRtxt[0,33].Caption:='台 指 號';
QRtxt[0,34].Caption:='物料代號';
QRtxt[0,35].Caption:='部門名稱';
end;

procedure TFrmQrt.GetStyleData;//在这个里面就是一笔一笔的赋值,每一笔资料都能动态的改变,当然,你也可以改成哪个显示,哪个不显示.
var i,j,x:integer;
StyleData:array of array of string;
OrdData:array of array of string;
begin
SetLength(StyleData,2,36);
SetLength(OrdData,2,32);
QStyle:=DM.PDM.QryTemp;
QStyle.Active:=False;
QStyle.SQL.Text:='select a.*,b.* from ord a,style b where (a.fno=:fno) and (a.sty_no=b.no(+))';//取得数据,
QStyle.Params[0].AsString:=QPrn.FieldByName('fno').AsString;
QStyle.Active:=True;
x:=0;
if QPrn.FieldByName('times').AsInteger>0 then
QRTimes.Caption:='重印:'+IntToStr(QPrn.FieldByName('times').AsInteger)
else
QRTimes.Caption:='新單';
for i:=0 to 35 do
if Length(QStyle.Fields[105+i].AsString)>0 then
begin
StyleData[0,x]:=QStyle.Fields[105+i].AsString;
StyleData[1,x]:=QPrn.Fields[7+i].AsString;
x:=x+1;
end;
for i:=0 to 31 do
for j:=0 to 35 do
if (Length(QStyle.Fields[24+i*2].AsString)<=0) then
break
else
if QStyle.Fields[24+i*2].AsString=StyleData[0,j] then
begin
OrdData[0,i]:=StyleData[0,j];
OrdData[1,i]:=StyleData[1,j];
break;
end;
for j:=32 to 35 do
QRtxt[1,j].Caption:='';
QRtxt[1,32].Caption:=QPrn.Fields[0].AsString;
QRtxt[1,33].Caption:=' '+QPrn.Fields[2].AsString;
QRtxt[1,34].Caption:=' '+QPrn.Fields[3].AsString;
QRtxt[1,35].Caption:=' '+QPrn.FieldByName('depna').AsString;
for i:=0 to 1 do
for j:=0 to 31 do
QRtxt[i,j].Caption:='';
for i:=0 to 31 do
if OrdData[0,i]<>'' then
begin
QRtxt[0,i].Caption:=OrdData[0,i];
QRtxt[1,i].Caption:=OrdData[1,i];
end
else
break;
end;

procedure TFrmQrt.QuickRep1NeedData(Sender: TObject;
var MoreData: Boolean);//QR的OnNeedData事件
begin
if not QPrn.Eof then
MoreData:=True
else
if QPrn.Eof then
MoreData:=False;
if MoreData then
begin
GetStyleData;//这儿便是给各个QRLAbel赋值,
QPrn.Next;//然后转到下一笔.
end
else
begin
QuickRep1.QRPrinter.Progress := 100;
QPrn.First;
end;
end;

//差不多就是这些了,祝你好运.
而你的问题1可能是在OnNeedData中没有写好吧.注意MoreData是若后面还有资料就要设为True,
若没有了就设为False,你看我的例子.而你设为False,就只会有一笔资料.
 
接受答案了.
 
后退
顶部