深入QuickReport(二)

深入QuickReport(二)

作者:董维春

(本文已在《CSDN开发高手》04年第一、二、三期上发表,应广大网友的要求,经编辑同意,发表在CSDN作者本人文档中,略有修改,但仅即于此,未经CSDN或作者本人同意任何个人与网站不得转载、摘抄,否则任何涉及到版权的行为后果自负)

 

第二部分:深入QuickReprot例程

 

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

 

例一:TQuickRep、TQRLabel、TQRDBText组件的应用
        
实践是最好的老师,我们先通过一个例子来看一下QR的快捷与方便。
         1
建立一个新Project
         2
)放一个TTableForm上,这里我们用BCB中自带的数据库。DatabaseName设为BCDEMOSTableName指向Customer表,Active设为true
         3
放一个TQuickRep控件在Form上,DataSet属性为Table1(即要显示Table1所指向的表的内容)。
         4
展开TQuickRepBands属性,设HasDetailtrue,这时自动增加个Detail Band(一个TQRBand控件,故也可以直接放一个TQRBand控件,BandType属性设为rbDetail就行了)。这个区段是重复区段。
         5
)放一个TQRLabelTQRDBText控件在Detail Band上面,TQRLabelCaption属性设置为“公司:”二字;TQRDBText DataSet指向Table1DataField指向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
)放一个TQueryTForm上,其SQL属性为:select * from customer order by State,Company,即根据州、公司排序,DatabaseNameBCDEMOSActivetrue
        3
放一个TQuickRep控件在Form1上,DataSetQuery1
        4
)放一个TQRBandTQuickRep上面,把其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中断,接着显示其他省的城市名),TQRGroup1Expression属性设为Query1.State(根据不同的州来中断)

注意:为什么不直接再放一个TQRGroup,因为无论我们放多少个系统都会默认为 Group Header。
       6
)放一个TQRExpr控件在Group Header上面,其Expression属性为:IF(Query1.State <> '',Query1.State,'不清楚什么地区的'),即如果公司的州没填,就归入“不清楚什么地区的”,否则归入具体的州。
       7
)放三个TQRDBTextDetail上,他们的DataSet都指向Query1DataField分别指向CompanyContactPhone
       8
)再放一个TQRExpr控件在Group Footer  Band上面,ExpressionQuery1.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属性左端的编辑按钮,展开其属性值来进行正确的设置,如下图:

 

6TQRBandWidth设为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组件的设置:

1Master的值设为所在TQuickRep组件的名;

2DataSet的值设为连接明细表的组件名;

3)点击Bands前面的“+”,展开属性,能看到HasFooterHasHeader 两个属性,把其值设为true,这样我们就得到了一对Group(当然完全我们完全可以用别的方法)。

注意:通过TQRSubDetail属性Band里的HasHeader、HasFooter产生的Group组,在Group Header中没有Expression,她们默认按主/明细表的关联关系分组。其实没有他们,TQRSubDetail也是这样用的。                                       

我们建立如下图的主/明细报表:

 

 

1)设置数据集

在窗体上放置TTableTDataSourceTQuery组件,把Table1Query1DatabaseName属性设置为BCDEMOS,把Table1TableName设为customer.db(主表名),把IndexFieldName设为索引字段名CustNo。把DataSource1DataSet设为Table1,为做主/明细数据做好准备。

连接明细表的Query1,我们把其DataSource设为DataSource1,从而建立关联关系,并将其SQL属性设成:

 

SELECT  *        FROM  orders         WHERE       CustNo         =:             CustNo

          ^                          ^                     ^              ^             ^                    ^

          ||                          ||                     ||             ||             ||                    ||

选择所有字段   从orders表(从表)    条件   从表的字段   建立主从关系  主表字段

 

 

这样我们就建立了明细表与主表的关联,明细表是按上式关系分组的,就是把CustNo一样的放在一起。

2)设置报表结构

首先,在前面设计的窗体上放置一个报表组件TQucikRep,在对象查看器窗口中把Band属性展开,将其HasColumnHeaderHasDetailHasPageFooterHasPageHeaderHasSummaryHasTitle属性设为true

QuickRep1DataSet属性设为Table1,为报表主表指定数据源。

然后,把TQRSubDetail组件放到QuickRep1组件上,作为明细表Band区段。把其Master属性设置为QuickRep1,设置Bands的子属性HasHeaderHasFootertrue,并将其DataSet属性设置为Query1,指定明细表数据来源。

3)设置主/明细报表的主体

ColumnHeaderBand1区段中添加主表中各字段的标题使用的报表标签组件(TQRLable),它们的Caption分别为客户号、公司、电话、传真和所在城市。在DetailBand1区段中添加显示主表字段值的报表组件(TQRDBText),与前面标题对应设置其字段,要注意的是它们的DataSet都为Table1

在明细报表部分,我们首先在GroupHeaderBand1中放置明细表的表头标签(TQRLable),它们的Caption依次设置为定单号、条款、付款方式、款项总额和未付款额。在QRSubDetail1区段中放置显示明细报表的组件对象(TQRDBText),其DataSet属性全设为Query1,字段名称依次是OrderNoTermsPaymentMethodItemsTotal。接着添加一个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))

这样这个报表的主体我们就做完了,其它设置看一下上面的图你就应该明白了。

下面我们再添加例一中的那样的程序代码,至此这样的一个复杂报表我们就完成了。

本例是用TTableTQuery做的主/明细数据关联,同样我们可以用TTableTTable做主/明细数据关联,实现本例这样的报表。

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
一、 简单了解各控件功能   以下是各控件最简单的使用功能,其他功能依具体的实现而介绍。  TquickRep:带有坐标,作为其他报表控件(如TQRBand)的容器,它的Band属性可以自动添加各种类型的TQRBand.   TQRLabel:打印静态的文本(即不是根据数据库值来改变的),作用象Tlabel , Caption的内容就打印出来的内容。   TQRDBText:打印数据库字段值,一个值一行。作用象TDBText.把它的DataSet , DataField分别赋予Table1,Company时,将打印Table1所指向的表的Company字段的内容。   TQRSysData:打印系统信息如时间,页码,报表头等。   TQRMemo:非常象TQRLabel,只是它可以打印多行,也是打印静态数据。   TQRRichText:打印RichText格式,能够连接到一个Form上的RichEdit控件并打印它的内容,不过必须是32位版本的。   TQRShape:打印方框、圆和垂直、水平线。   TQRImage:打印静态的图片,包括(BMP,WMF,ICON).   TQRDBImage:从数据库接收图片。   TQRBand:用来确定报表的不同位置应该显示什么内容,它上面可以放控件(参见)。   TQRGoups:Groups可以不限级别的组操作。当你连接了几个datasets到报表时可以通过Groups成组的对dataset进行操作。   报表的控件摆放循序   出现在所有页上的标题(PageHeader)   标题(只有首页才有)(Title)   所有列的标题(ColumnHeader)   记录的内容,一个字段一列(Detail)   摘要(最后一页才有)(Summary)   出现在所有页上的页脚(PageFooter)   这些根据设置不同的Band(不是控件,一种类型而已,在其上面可以放其他控件)来定位。总共有六种Band。   三、 一个简单的例子   这个例子制作打印一张表的部分字段名及该字段数据内容的报表。   建立一个新project   放一个TTable到Form上,DatabaseName设为BCDEMOS,TableName指向Customer表,Active设为true.   放一个TquickRep控件在Form上,DataSet属性为Table1.(即要显示上边Table1所指向的表的内)。   展开TquickRep的Bands属性,设HasDetail为true,这时自动增加个detail band(一个TQRBand控件,故也可以直接放一个TQRBand控件,BandType属性设为detail就行了)。   放一个TQRDBText控件在detail band上面,设DataSet指向Table1,DataField指向Company。第四步是设置在报表的什么位置显示什么类型的数据,而TQRDBText则具体实现。   选TquickRep控件,按右键,选择”Preview”预览,应该看到表Customer的字段Company的所有字段值。  到这一个简单的例子就OK了,程序实现预览及利用TQRuickRep自带的打印功能只须在Form中加一个按钮,它的OnClick事件为:QuickRep1->Preview();  四、一个使用TQRGoups、TQRExpr控件的报表   该报表先列出州名,接着列出该州的所有公司及公司总数,一个州列完后空一行(groups中断),列出新的州名,接着列新州下的所有公司,没有填州名的公司统一列在Unknown state下面。  建立一个新project。   放一个Tquery在Tquickrep上,其SQL属性为:select * from customer order by State,Company;(即根据州、公司排序),DatabaseName为BCDMome,Active为true.   放一个TquickRep控件在Form1上,DataSet为Tquery1.   放一个TQRGroups控件在TquickRep上,这时默认为group header。(任何时候当group中断或更高级别的group中断,这个header都将打印出来,如果有表达式,根据表达式的值显示内容。)接着添加一个group footer band,添加时,放一个TQRBand控件在报表上,连接TQRGroups的FooterBand属性到这个QRBand,这时这个新建的TQRBand就成为Group Footer. (TQRGroup的一个重要特性是表达式,任何时候当表达式的值变时Group都将中断,如表达式是按省列出城市名,当前列出广东省,当属于该省的城市列完后,表达式值改变,这时Group中断,接着显示其他省的城市名。)TQRGroups的Expression属性设为Query1.State(根据不同的州来中断)。   放一个TQRBand控件在报表上,BandType为rbDetail.   放一个TQRExpr控件在group header上面,其Expression属性为:if(State<>’’,State,’Unknown state’),即如果公司的州没填,就归入Unknown state,否则归入State.   放三个TQRDBText在Detail上,他们的DataSet都指向Query1,DataField分别指向Company,Contact,Phone.   在放一个TQRExpr控件在group Footer上面,Expression为’Customers in’+State+’:’+Str(Count) 作用是在每个州的公司列完后显示该州总共有多少个公司。   按右键选预览,应该看到不同的州名及其公司和公司公司总数。  五、QuickReport 条件式列印   可以直接在 TQuickReport 的 OnFilter 事件中写明条件判断,OnFilter事件的引数中有一个以 var 宣告的 PrintRecord 布林型态变数,将这个变数设为 True(预设值), 该笔记录便会印出;反之, 设为False,就不印出这笔记录. procedure TForm1.QuickReport1Filter(var PrintRecord: Boolean); begin PrintRecord := False; if YourTable.FieldByName(‘WantedField‘).AsInteger <= 100 then Exit; if YourTable.FieldByName(‘WantedField‘).AsInteger >= 150 then Exit; PrintRecord := True;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值