请教如何使用DELPHI自带的报表控件,实现例如对金额这个字段的合计功能(100分)

  • 主题发起人 主题发起人 gwy427
  • 开始时间 开始时间
G

gwy427

Unregistered / Unconfirmed
GUEST, unregistred user!
请教如何使用DELPHI自带的报表控件,实现例如对金额这个字段的合计功能
 
是QUICKREPORT,还是rave??
DELPHI是什么版本?
 
是QUICKREPORT,6.0
 
原記錄
A01 aaa 100
A01 bbb 200
A02 aaa 50
A03 bbb 100
A03 ccc 20
A03 ddd 20
...
打印出
A01 aaa 100
A01 bbb 200
sum: 300
A02 aaa 50
sum: 50
A03 bbb 100
A03 ccc 20
A03 ddd 20
sum: 140
具体操作:
加入控件
QuickRep1 : TQuickRep;
qrGroup1 : TQrGroup;
qrDetail1 : TQrDetail;
qrBand1 : TQrBand;
qrDbText1, qrDBText2, qrDBText3 : TQrDBText;
qrExpr : TQrExpr;
其中:
QuickRep1.Dataset := 一个TDataset对象;
qrGroup1.Expression := 第一列的字段名;
qrGroup1.FooterBand := qrBand1;
qrBand1.BandType := rbGroupFooter;
qrDBText1, qrDBText2, qrDBText3为qrDetail1的子控件且它们的
Dataset属性相同,DataField属性分别为各自的字段名
qrExpr.Expression := '''Sum : '' + Sum(字段名)';
qrExpr为qrBand1的子控件
看下面:qrGroup1.Expression
原記錄
A010 aaa 100
A011 bbb 200
A020 aaa 50
A030 bbb 100
A031 ccc 20
A032 ddd 20
...
打印出
A010 aaa 100
A011 bbb 200
sum: 300
A020 aaa 50
sum: 50
A030 bbb 100
A031 ccc 20
A032 ddd 20
sum: 140
...
用QuickReport的分组报表功能
实现分组可参考QRGroup控件的Expression、FooterBand属性的含意。
实现合计用QRExpr控件,关键属性有Expression、ResetAfterprint等,同时
了解QRBand的BandType属性的各个含意。并且记住数据库要按分组字段排序。
 
qrExpr.Expression := '''Sum : '' + Sum(字段名)';
是什么意思?
是不是[sum([ADOQuery1.jfje])] ,不行的.试过了
 
ResetAfterprint的属性应该是什么
 
你自己去看帮助吧
转贴:

第二部分:深入QuickReprot例程

在应用中学习,在实践中进步,这是我学习QuickReport的最大感受,通过上面的介绍,我想你对QuickReport也有了一定的了解,那么下一步我们将通过例程逐步深入QuickReportJ

例一:TQuickRep、TQRLabel、TQRDBText组件的应用 实践是最好的老师,我们先通过一个例子来看一下QR的快捷与方便。 1) 建立一个新Project 。 2)放一个TTable到Form上,这里我们用BCB中自带的数据库。DatabaseName设为BCDEMOS,TableName指向Customer表,Active设为true。 3) 放一个TQuickRep控件在Form上,DataSet属性为Table1(即要显示Table1所指向的表的内容)。 4)展开TQuickRep的Bands属性,设HasDetail为true,这时自动增加个Detail Band(一个TQRBand控件,故也可以直接放一个TQRBand控件,BandType属性设为rbDetail就行了)。这个区段是重复区段。 5)放一个TQRLabel与TQRDBText控件在Detail Band上面,TQRLabel的Caption属性设置为“公司:”二字;TQRDBText的 DataSet指向Table1,DataField指向Company。 6)选TQuickRep控件(不要指在区段上),按右键,选择“Preview”预览,应该看到表Customer的字段Company中所有字段值。 到这一个简单的例子就OK了。但这个程序你编译后,会得到与你布置时一样的QuickReport组件,看不到你想要的报表内容。程序要实现刚才Preview时的效果只能利用TQRuickRep自带的打印功能了,我们只要在Form中加上一个按钮,在它的OnClick事件中写上:QuickRep1->Preview();
就可以了。没有人希望那个什么也不显示的TQuickRep组件摆在窗体上,这也告诉我们一点我们的程序中最好有两个Form:一个是放置控制QuickReport显示、打印或实现其它功能的,比如本例中放置控制按扭;一个是提供给QuickReport布置组件的。
当然这不是说在一个Form中实现不了上述功能,其实你只要在窗体的OnCreate事件中把TQuickRep组件隐藏起来就可以了:
void __fastcall TForm1::Form1Create(TObject *Sender)
{
QuickRep1->Hide();
}
要注意QR你不能用Show()调用,那你将得不到你想要的程序,当然用Preview()就没错了。以下是本例的程序源代码:
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------
void __fastcall TForm1::Form1Create(TObject *Sender)
{
QuickRep1->Hide();
}
//---------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
QuickRep1->Preview();
}
//---------------------------------------------------------------
进一步思考:有时我们想实现垂直输出,比如用TQRLabel里的内容我们想垂直显示能否实现?
当然能实现。只要我们按如下设置就可以实现:
AutoSize=false;//默认为true
AutoStrech=true;// 默认为false
WordWrap=true;// 默认为true,这是设置中的重点,这与Label中的设置是一样的
Caption的值要注意,每个字符间一定要有空格;//一般的设置我们不会留空格,因为设计空格除了美观,没什么实际意义,但在这里必须留空格
进一步思考:我们想显示有两位小数的数字,应该如何办呢? 只要把该可视化组件的mask属性设为0.00就可以实现了。

例二:TQRGroup、TQRExpr组件的应用
该报表先列出州名,接着列出该州的所有公司及公司总数,一个州列完后空一行(Group中断),列出新的州名,接着列新州下的所有公司,没有填州名的公司统一列在“不清楚什么地区的”下面。 1)新建一个Project。 2)放一个TQuery在TForm上,其SQL属性为:select * from customer order by State,Company,即根据州、公司排序,DatabaseName为BCDEMOS,Active为true。 3) 放一个TQuickRep控件在Form1上,DataSet为Query1。 4)放一个TQRBand在TQuickRep上面,把其BandType设成rbDetail。
5)放一个TQRGroup控件在TQuickRep上,这时默认为Group Header。(任何时候当Group中断或更高级别的Group中断,这个Header都将打印出来,如果有表达式,根据表达式的值显示内容),接着添加一个Group Footer Band,但我们却不能找到这样的一个组件,那应该如何设计出Group Footer Band区段呢?我们只要放一个QRBand2在报表上,把TQRGroup的FooterBand属性指向QRBand2,看一下,QRBand2是不是变成了Group Footer Band 。(TQRGroup的一个重要特性是表达式,任何时候当表达式的值改变时,Group都将中断,如表达式是按省列出城市名,当前列出辽宁省,当属于辽宁省的城市列完后,表达式值改变,这时Group中断,接着显示其他省的城市名),TQRGroup1的Expression属性设为Query1.State(根据不同的州来中断)。
注意:为什么不直接再放一个TQRGroup,因为无论我们放多少个系统都会默认为 Group Header。 6)放一个TQRExpr控件在Group Header上面,其Expression属性为:IF(Query1.State <> '',Query1.State,'不清楚什么地区的'),即如果公司的州没填,就归入“不清楚什么地区的”,否则归入具体的州。 7)放三个TQRDBText在Detail上,他们的DataSet都指向Query1,DataField分别指向Company、Contact、Phone。 8)再放一个TQRExpr控件在Group Footer Band上面,Expression为Query1.State+'共有:'+STR(COUNT)+’个公司’,作用是在每个州的公司列完后显示这个州总共有多少个公司。 9)把鼠标放在QuickRep组件上(不能放在Band区段上),按右键选预览,应该看到不同的州名及其公司名称和该州公司总数。
注意:大家发现看到并不是每个州公司的总数,每个州后列出的都是把上一个州的总数也加上的累计值,难道是我们错了,没有,检查一下你的Expression组件(运行COUNT那个)的ResetAfterPrint的属性值是否为true,如果不是把他改为true,现在看一下J
进一步思考:每一组内容都联在一起,有些不爽,要是每组内容之间被什么分隔开就好了?
其实这并不难实现,我们只要把QRBand2(group Footer)的HasChild属性设为true就可以了。当然你直接把一个TQRChildBand组件放在QuickRep1上,把她的ParentBand属性设置为QRBand2,同样可以实现上面的设置。另外我们同样可以在TQRChildBand布置其它可视化组件J
进一步思考:要是每组结束后就换页,那不是更爽吗?
只要我们把QRGroup1的ForceNewPage属性改为true就可以了,同样的组件还有一个ForceNewColumn。但一定要注意,我们改了哪个区段的这两个属性,就从哪个区段开始NewPage/NewColumn。

例三、TQuickRep组件的Page属性应用
PVC胸卡有些朋友一定见过,做这样的卡片并不太难,最近笔者就参与制作了一批胸卡,这里我们要讲的是卡片的设计。
1)新建一个Project。
2)放一个Table组件,把它指向我们的资源数据库,并把Active设为true。
3)放置一个TQuickRep组件在Form1上,并把它DataSet设置为Table1,在她上面放一个TQRBand,把其BandType值设置成rbDetail。在Band区段上面按下图放置好四个TQRLabel组件、三个TQRDBText组件与一个TQRDBImage组件。


4)三个TQRDBText组件的设置基本上一样的,把DataSet指定为Table1,然后在从DataField中选取正确的字段。我们可以同样的设置好TQRDBImage的相关属性。
5)对页面进行设置,这是关键。一张纸上我们不可能只打印一个,打印得越多越多好,左边打完,在右边继续打印,这样才能充分利用原材料。我们这里用到了分栏,把Number of columns属性设为2,也就是分两栏。在TQuickRep中使用组件的快捷菜单Report settings打开Page的属性编辑器窗口,做如下设置:


其中Pager size选择为自定义,在其后输入纸的大小 ,其它设置按上图即可。当然我们也可以在对象查看器窗口单击Page属性左端的编辑按钮,展开其属性值来进行正确的设置,如下图:


6)TQRBand的Width设为228,然后重新调整好Band上组件的位置。228实际上是由38×6得到的。
7)把鼠标放在QuickRep组件上(不能放在Band区段上),按右键选预览,看一下效果吧。
难点:为了定位方便、准确, TQuickRep组件提供了坐标(一格一格的,边上带数字的,不会告诉我没看见吧J),从对纸张的设置我们知道这些坐标每整格相距为10mm,但在QR中,很多组件都没有单位,对于这10 mm,QR中对应的单位长度是38,这一点你一定要记住。

通过上面的三个例子,我们已经可以进行了一些简单的报表设计,从例四开始我们将进一步的学习QuickReport,下面例程也只讲关键点,着重分析,省略一些重复性的语言。

例四、主/明细(Master/Detail)报表与TQRSubDetail组件的应用
设计主/明细报表的关键有两点:一是主/明细数据表的连接;二是对TQRSubDetail组件的正确使用。

主从数据表连接示意图1(TTable与TTable)

Master表 关联 Detail表
组件名 TTable TDataSource1 TTable
重要属性 Name <=== DataSet Name
TableName Name <====DataSource
DabaseName<===指向同一库名==>DabaseName
(指定索引字段)IndexFieldName MasterField(点击右侧“…”调出Field Link Designer对话框,设置好关联字段)
Active<=======同设为true=======>Active


主从数据表连接示意图2(TTable与TQuery)

Master表 关联 Detail表
组件名 TTable TDataSource1 TTQuery
重要属性 Name <=== DataSet Name
TableName Name <====DataSource
DabaseName<===指向同一库名==>DabaseName
(指定索引字段)IndexFieldName SQL(点击右侧“…”调出String list Editor对话框设置好关联字段)
Active<=======同设为true=======>Active

TQRSubDetail组件的设置:
1)Master的值设为所在TQuickRep组件的名;
2)DataSet的值设为连接明细表的组件名;
3)点击Bands前面的“+”,展开属性,能看到HasFooter与HasHeader 两个属性,把其值设为true,这样我们就得到了一对Group(当然完全我们完全可以用别的方法)。
注意:通过TQRSubDetail属性Band里的HasHeader、HasFooter产生的Group组,在Group Header中没有Expression,她们默认按主/明细表的关联关系分组。其实没有他们,TQRSubDetail也是这样用的。
我们建立如下图的主/明细报表:



1)设置数据集
在窗体上放置TTable、TDataSource、TQuery组件,把Table1、Query1的DatabaseName属性设置为BCDEMOS,把Table1的TableName设为customer.db(主表名),把IndexFieldName设为索引字段名CustNo。把DataSource1的DataSet设为Table1,为做主/明细数据做好准备。
连接明细表的Query1,我们把其DataSource设为DataSource1,从而建立关联关系,并将其SQL属性设成:

SELECT * FROM orders WHERE CustNo =: CustNo
^ ^ ^ ^ ^ ^
|| || || || || ||
选择所有字段 从orders表(从表) 条件 从表的字段 建立主从关系 主表字段



这样我们就建立了明细表与主表的关联,明细表是按上式关系分组的,就是把CustNo一样的放在一起。
2)设置报表结构
首先,在前面设计的窗体上放置一个报表组件TQucikRep,在对象查看器窗口中把Band属性展开,将其HasColumnHeader、HasDetail、HasPageFooter、HasPageHeader、HasSummary和HasTitle属性设为true。
把QuickRep1的DataSet属性设为Table1,为报表主表指定数据源。
然后,把TQRSubDetail组件放到QuickRep1组件上,作为明细表Band区段。把其Master属性设置为QuickRep1,设置Bands的子属性HasHeader和HasFooter为true,并将其DataSet属性设置为Query1,指定明细表数据来源。
3)设置主/明细报表的主体
在ColumnHeaderBand1区段中添加主表中各字段的标题使用的报表标签组件(TQRLable),它们的Caption分别为客户号、公司、电话、传真和所在城市。在DetailBand1区段中添加显示主表字段值的报表组件(TQRDBText),与前面标题对应设置其字段,要注意的是它们的DataSet都为Table1。
在明细报表部分,我们首先在GroupHeaderBand1中放置明细表的表头标签(TQRLable),它们的Caption依次设置为定单号、条款、付款方式、款项总额和未付款额。在QRSubDetail1区段中放置显示明细报表的组件对象(TQRDBText),其DataSet属性全设为Query1,字段名称依次是OrderNo、Terms、PaymentMethod和ItemsTotal。接着添加一个TQRExpr组件,设置其Master属性为QRSubDetail,打开表达编辑器,输入下面的表达式:
INT(Query1.ItemsTotal-Query1.AmounPaid)
在GroupFooterBand1区段中添加统计报表组件QRExpr2,并将其属性设置为QRSubDetail1,打开表达式编辑器,输入如下 表达式:
SUM(INT(Query1.ItemsTotal-Query1.AmounPaid))
即计算未付款项的总额,并设置ResetAfterPrinter属性为true,这样,就可以统计出明细表的总额了。
在SummaryBand1区段中添加一个QRExpr3,打开表达式编辑器,在其中输入如下语句:
SUM(INT(Query1.ItemsTotal-Query1.AmounPaid))
这样这个报表的主体我们就做完了,其它设置看一下上面的图你就应该明白了。
下面我们再添加例一中的那样的程序代码,至此这样的一个复杂报表我们就完成了。
本例是用TTable与TQuery做的主/明细数据关联,同样我们可以用TTable与TTable做主/明细数据关联,实现本例这样的报表。
 
后退
顶部