📄 20010417001.htm
字号:
<HTML>
<HEAD>
<TITLE>如何快速自动生成并定制报表</TITLE>
<META content="MSHTML 5.00.2314.1000" name=GENERATOR>
</HEAD>
<BODY aLink=#FF0000 bgColor=#ffffff leftMargin=0 link=#187800 topMargin=0
vLink=#990099>
<div align="center">
<table width="744" border="0" cellspacing="0" cellpadding="0" height="76">
<tr>
<td>
<table align=center width=680>
<tbody>
<tr>
<td align=middle><br>
<h2 align="center"><font size="3">如何快速自动生成并定制报表</font></h2>
<b>西南交通大学电气学院(610031) 童晓阳</b> </td>
</tr>
</tbody>
</table>
<br>
<table align=center width=620>
<tbody>
<tr>
<td
class=a14>在各种管理信息系统应用中,需要产生大量的报表,通常的做法是由编程人员一个个手工制作,工作效率较低;另外,用户希望能够将在应用程序里查询得到的结果生成报表以便打印。为了解决以上两种问题,本文利用动态生成技术实现了快速自动产生报表,允许用户手工对报表进行修饰,并将实现过程封装成一个类。</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14><b>1.设计思路</b></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>使用过C++ Builder或Delphi的编程人员知道,有一个TDBGrid控件,它能以表格的形式显示和操作用户查询的数据记录;而要制作一个可供打印的报表,则需要使用TQuickRep控件,在它上面增加TQRLabel、TQRDBText、TQRShape等控件,设置它们对应的数据集、数据字段等属性,然后编排它们的位置,以表格或其它格式显示出来供预览和打印,这是一个很繁琐的过程。有时,用户希望能将查询出来的显示在TDBGrid控件的数据打印出来,按照以往的做法,就需要由编程人员按照TDBGrid的显示内容手工设计报表。在这里,本文利用动态生成技术,读出TDBGrid的有关显示信息,在TQuickRep控件里动态生成相应的TQRLabel、TQRDBText、TQRShape等控件,设置各字段的标题和数据以及表格分割条。这是完全可行的,因为在C++
Builder里所有的控件都可以由程序动态生成,不仅仅是在设计阶段才产生的。另外,如果用户对产生的报表表格布局不太满意,本文提供了接口使用户可对报表进行手工调整,调整表格的高度、宽度等布局,实现用户对报表的一定程度的定制。</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td
class=a14>利用C++的封装性特点,将自动产生并定制报表的实现封装成一个新类TGridPrint,对外提供编程人员关心的公用接口,屏蔽了内部信息和具体实现,体现了面向对象的设计思想,为编程人员带来方便。编程人员还可以在它基础上进一步扩充功能。这样设计的新类减轻了编程人员的工作量,同时为用户提供了定制报表的接口,提高了报表的质量和用户参与的积极性。</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14><b>2.实现过程</b></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>自动产生并定制报表的实现过程包括自动产生和定制两部分。新类的定义和实现分别在GridPrint.h GridPrint.cpp文件里,另包含3个文件RepRst.h、RepRst.cpp、RepRst.dfm,它们是已产生的一个窗口FrmRepRst,在它里面已增加一个TQuickRep控件,它的属性Bands的各子属性的值全为true。</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14><i>2.1 自动产生报表</i></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td
class=a14>先定义一个表示表格某一列信息的结构,在报表里一列有固定标题和显示的数据文本两种信息,为了能画出表格,每一列固定标题栏和数据栏右边分别增加一个分隔条。在类TGridPrint的构造函数里,先根据传入的TQuickRep
*pSrcQuickRep(报表指针),TDBGrid * pSrcDBGrid(数据表格指针),TQRBand *SrcTitleBand1(报表中的总标题栏指针),
TQRBand *SrcColumnHeaderBand1(报表中的字段标题栏指针),TQRBand * SrcDetailBand1(报表中的数据栏指针)参数设置类的私有变量。再动态生成并设置总标题文本、字段标题栏矩形框、数据栏矩形框的属性。然后通过一个循环,读出TDBGrid中各字段的标题和数据信息,动态生成报表中各字段的标题标签控件、数据文本控件以及对应的表格分割竖条控件。在类的析构函数里,删除所有由构造函数动态生成的对象。类的打印预览函数实现报表的打印预览功能。其它的函数说明略。</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>自动生成报表类的定义(GridPrint.h)</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>#include <DBGrids.hpp> //包含的相关头文件</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>#include <Db.hpp></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>#include <Printers.hpp></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>#include <QuickRpt.hpp></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>#include <Qrctrls.hpp></td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>typedef struct tagFieldType{ //表示表格某一列信息的结构</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>AnsiString sTitle; //字段标题名称</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>int iWidth; //表格单元的宽度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRLabel *pLabel; //字段标题控件</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRDBText *pDBText; //显示的数据控件</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRShape *pShapeTitle, *pShapeData; //字段标题和数据的表格分隔条</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>} NEWFIELDTYPE;</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>class TGridPrint{</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>public:</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TGridPrint(TQuickRep *pSrcQuickRep,TDBGrid * pSrcDBGrid,TQRBand
*SrcTitleBand1,</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRBand *SrcColumnHeaderBand1,TQRBand * SrcDetailBand1);
//构造函数</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>~TGridPrint(); //析构函数</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void DoPreview(); //报表的打印预览</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void SetPrntTitle(AnsiString sTitle); //手工设置表格的总标题</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void SetColumnsWidth(int *ColumnsWidth); //手工设置表格各列宽度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void SetHeadRectHeight(int iHeight); //手工设置字段标题行的高度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void SetDetailRectHeight(int iHeight); //手工设置数据行的高度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>private:</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TDBGrid * pDBGrid; //将要显示的DBGrid</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TDataSet * pDataSet; //DBGrid对应数据集</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQuickRep * pQuickRep; //报表控件</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRBand * TitleBand1; //报表的总标题栏</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRBand * ColumnHeaderBand1; //报表的字段标题栏</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRBand * DetailBand1; //报表的数据栏</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRLabel * pTitleLabel; //总标题控件 </td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>TQRShape * pHeadRect, * pDetailRect; //整个字段标题栏、数据栏的表格矩形控件</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>int iHeadRectHeight, iDetailRectHeight; //对应表格矩形框的高度,它们宽度相同</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>int _iTotalWidth; //整个表格的总宽度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>int _iIntClearance; //表格内部数据列到左表格的距离</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>int _iFieldCount; //将要打印的字段数目</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>NEWFIELDTYPE _arrayFieldType[40]; //支持到40个字段的打印</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>void AutoAdjustColumnsWidth(); //程序自动调整各列宽度</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>};</td>
</tr>
</tbody>
</table>
<table align=center width=620>
<tbody>
<tr>
<td class=a14>类的主要公用方法的实现(GridPrint.cpp)</td>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -