📄 ch17.htm
字号:
Report in design mode.</I></P>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>I don't think you can make it through
this chapter without at least a minimal understanding of the Address2 program. This
program was discussed
in depth in Chapter 13. The source for that program, including
the reports it uses, are found in the <TT>Chap13</TT> directory on the CD that accompanies
this book. <BR>
<BR>
If you want to work along with me by creating the forms on your machine
as I describe
them in this book, open up the Address2 program, and add a new form to it. There
is no harm in having two forms in the program that perform the same task; that way,
you can easily open up my sample form if you get stuck. <BR>
<BR>
Remember, this material does not cause brain strain. You just need to understand
how these components work, and then you will be able to write your own reports.
<HR>
</BLOCKQUOTE>
<P>Now drop down three <TT>TQRBand</TT> components. Don't place
them one on top of
the other; lay one down, click on the main form, lay the next one down, and so on.
That way, they are positioned one above the other on the main form. The final position
of the controls at runtime is determined by the
<TT>BandType</TT> property of each
<TT>TQRBand</TT>. If you want to change the order of the controls on the form, drag
them around with the mouse, the same way you move items in the Tab Order list box
from the Edit menu. The <TT>Align</TT> property
for these forms can be left at the
default position of <TT>alTop</TT>. Remember, it usually doesn't really matter what
order these controls have on your form; what matters is the <TT>BandType</TT> property.</P>
<P>The <TT>BandType</TT> for the top
<TT>QRBand</TT> control should be set to <TT>rbTitle</TT>,
the next one should be set to <TT>rbDetail</TT>, and the last one should be set to
<TT>rbPageFooter</TT>. Drop down the <TT>Frame</TT> property of the detail band and
set its
<TT>DrawLeft</TT>, <TT>DrawRight</TT>, <TT>DrawTop</TT>, and <TT>DrawBottom</TT>
properties to <TT>True</TT>.</P>
<P>The title band should have a <TT>TQRLabel</TT> component placed on it. Set its
alignment to <TT>taCenter</TT> and set
<TT>AlignToBand</TT> to <TT>True</TT>. Use
the <TT>Font</TT> property to select a large bold font. Set the <TT>Caption</TT>
property to the title of the report.</P>
<P>Another way to create a title involves using the <TT>TQRSysData</TT> component.
Drop one down on the title band and set its alignment and font as you did the <TT>TQRLabel</TT>.
Instead of changing the <TT>Caption</TT> property of this component, set its <TT>Data</TT>
property to <TT>qrsReportTitle</TT>. Click on the
<TT>TQuickReport</TT> component
and set its <TT>ReportTitle</TT> property to the name of the report. For instance,
you might set it to <TT>Address Report</TT>. Now when you run the report, the title
will show up automatically at the top of the first
page.</P>
<P>On the detail band, drop down four <TT>TQRDBText</TT> controls and set their <TT>DataSource</TT>
property to the <TT>AddressSource</TT> from the program's data module and their fields
to <TT>FirstLast</TT>, <TT>Address1</TT>,
<TT>Address2</TT>, and <TT>CityStateZip</TT>.
The first and last fields are calculated fields. The code for creating the calculated
fields looks like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TDMod::AddressTableCalcFields(TDataSet *DataSet)
{
if ((!AddressTableFName->IsNull) || (!AddressTableLName->IsNull))
AddressTableFirstLast->Value =
AddressTableFName->Value + " " + AddressTableLName->Value;
else if (!AddressTableCompany->IsNull)
AddressTableFirstLast->Value = AddressTableCompany->Value;
else
AddressTableFirstLast->Value = "Blank Record";
AddressTableCityStateZip->Value = AddressTableCity->Value + " " +
AddressTableState->Value + ", " + AddressTableZip->Value;
}
</FONT></PRE>
<P>The code for creating the <TT>AddressTableFirstLast</TT> field was described during
the initial discussion of the Address2 program in Chapter 13. The code
for creating
the <TT>AddressTableCityStateZip</TT> field involves nothing more than concatenating
the three fields, and adding spaces and commas where appropriate. In a professional
program, you might want to add more code to eliminate the possibility
that a blank
set of fields would generate a string that consists of nothing but a comma. I will
omit such code here so that you can more easily decipher the code I do include.</P>
<P>To display more than one column in a report, turn to the
<TT>TQuickReport</TT>
component and set its <TT>Column</TT> property to the value you desire, such as <TT>2</TT>
or <TT>3</TT>.</P>
<P>The final band in the report cover appears as a footer with the current date and
time on it, as well as the page
number. You can use the <TT>TQRSysData</TT> component
to retrieve this data. Set one component's <TT>Data</TT> property to <TT>qrsDateTime</TT>
and the other to <TT>qrsPageNumber</TT>.</P>
<P>If you want to show a print dialog to the user, you can do
so in the <TT>BeforePrint</TT>
event of the <TT>TQuickReport</TT> component:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TAddressReport::QuickReport1BeforePrint(bool &PrintReport)
{
if (PrintDialog1->Execute())
{
PrintReport =
True;
}
else
{
PrintReport = False;
}
}
</FONT></PRE>
<P>This code pops up a print dialog, as shown in Figure 17.3. The <TT>TPrintDialog</TT>
component is found on the Dialogs page of the Component Palette. The settings selected
by
the user in the print dialog are sometimes passed on to the system without intervention
on your part. However, if you need to access the settings, you can do so via the
fields of the component. You can then pass this information on to QuickReport if
necessary.<BR>
<BR>
<A NAME="Heading10"></A><A HREF="17ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu03.jpg">FIGURE 17.3.</A><FONT COLOR="#000077">
</FONT><I>Showing a print dialog so the user can select a printer.</I>
<H3 ALIGN="CENTER"></H3>
<BLOCKQUOTE>
<P>
<HR>
<FONT
COLOR="#000077"><B>NOTE:</B></FONT><B> </B>There is a button on the <TT>TPrintDialog</TT>
control that will pop up a setup dialog for the printer. As a result, there is rarely
any reason for you to include a <TT>TPrinterSetupDialog</TT> in your
program. The
act of including a <TT>TPrintDialog</TT> covers both bases automatically.
<HR>
</BLOCKQUOTE>
<P>To show the report to the user, you can set up a menu item on the main form of
the program with its caption set to the string
<TT>"Address Report"</TT>.
This is what the response to a click on this control should look like:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::PrintAddresses1Click(TObject *Sender)
{
AddressReport->QuickReport1->Preview();
}
</FONT></PRE>
<P>This assumes the name of the form on which the report is stored is called <TT>AddressReport</TT>,
and the unit containing this form has been included in the main form:</P>
<PRE><FONT
COLOR="#0066FF">#include "QRAddress1.h"
</FONT></PRE>
<P>The Preview screen has a button on it that allows the user to print the report.
If you didn't want to show the preview first, you can call <TT>PRINT</TT> directly:</P>
<PRE><FONT
COLOR="#0066FF">AddressReport->QuickReport1->Print();
</FONT></PRE>
<P>As you can see, creating reports using <TT>TQuickReport</TT> is trivial in the
extreme. This is the kind of operation you can usually roll out in about 30 minutes,
or less.
If you find things getting complicated, you can usually clean up the mess
by writing a query. On the rare occasions when you need more power than QuickReport
offers, you should use another printing tool, such as ReportSmith or Crystal Reports.
These
third-party products ship with VCL links for both high-quality tools.
<H3 ALIGN="CENTER"></H3>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>ReportSmith is still officially
part of the Borland suite of products, but most
of its day-to-day operations are
now being handled by a third party. As a result, it does not ship with the new versions
of BCB or Delphi, though it did ship with Delphi 1.0 and Delphi 2.0.
<HR>
</BLOCKQUOTE>
<H4><A NAME="Address2: Grouping Data
in a Rep"></A><FONT COLOR="#000077">Address2:
Grouping Data in a Report</FONT></H4>
<P>Reports often have to be presented in groups. For instance, the Address2 program
has a <TT>Category</TT> field that allows the user to put each record in a separate
category, such as <TT>Work</TT>, <TT>Home</TT>, <TT>Family</TT>, <TT>Fun</TT>, or
<TT>Entertainment</TT>. The user wants to be able to generate reports by groups,
as shown in Figure 17.4.</P>
<P>QuickReport makes it easy to create a report of this
kind. To get started, drop
down three <TT>TQRBand</TT> components, setting the <TT>BandType</TT> property from
the first to <TT>rbGroupHeader</TT>, the second to <TT>rbDetail</TT>, and the third
to <TT>rbGroupFooter</TT>. Also drop down a
<TT>TQuickReport</TT> control and set
its <TT>DataSource</TT> property to the <TT>AddressSource</TT> control from the program's
data module.</P>
<P>You now need to drop down a <TT>TQRGroup</TT> component and set its <TT>DataSource</TT>
to
<TT>AddressSource</TT> and its <TT>DataField</TT> to <TT>Category</TT>. Set the
<TT>HeaderBand</TT> property to the first <TT>TQRBand</TT> control and the <TT>FooterBand</TT>
property to the third <TT>TQRBand</TT> control.<BR>
<BR>
<A
NAME="Heading13"></A><A HREF="17ebu04.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu04.jpg">FIGURE 17.4.</A><FONT COLOR="#000077">
</FONT><I>A report from the Address2 program grouped on the <TT>Category</TT> field.</I></P>
<P>You can now drop down and hook up some <TT>TQRSysData</TT> and
<TT>TQRDBText</TT>
controls so that you can display information to the user. The final report should
look like the screen shot shown in Figure 17.5.<BR>
<BR>
<A NAME="Heading14"></A><A HREF="17ebu05.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu05.jpg">FIGURE 17.5.</A><FONT COLOR="#000077">
</FONT><I>The GroupReport as it appears at design time.</I>
<H4 ALIGN="CENTER"></H4>
<H4><A NAME="Troubleshooting Tips"></A><FONT COLOR="#000077">Troubleshooting Tips</FONT></H4>
<P>Generating reports with <TT>TQuickReport</TT> is very simple, but
occasionally
things will go wrong. Here are some troubleshooting tips:
<UL>
<LI>If you see only one record when you are expecting to see many, check to see if
you have set the <TT>DataSource</TT> field of the <TT>TQuickReport</TT> control to
the
correct data set.
<P>
<LI>If one of the fields is blank, check its <TT>DataSource</TT> and <TT>DataField</TT>
properties.
</UL>
<H4><A NAME="Reports in the Music Program"></A><FONT COLOR="#000077">Reports in the
Music Program</FONT></H4>
<P>The
Music program appeared in Chapter 16, "Advanced InterBase Concepts."
There are two types of reports in the music program:
<DL>
<DD><B>1.</B> A one-to-many report that shows all the albums associated with each
artist.<BR>
<BR>
<B>2.</B>
A group-by report that groups each album under its associated type, such
as jazz or rock.
</DL>
<P>The next few pages cover both types of reports. Again, my text will be a bit abrupt
at times. The material here is so simple that the best approach is
just to give you
a few hints about how to proceed, and then let you hammer out the details by working
live with the tools.
<H3><FONT COLOR="#000077">One-to-Many Reports</FONT></H3>
<P>The one-to-many report from the Music program shows how to use the
<TT>TQRDetailLink</TT>
component. See Figure 17.6.<BR>
<BR>
<A NAME="Heading15"></A><A HREF="17ebu06.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu06.jpg">FIGURE 17.6.</A><FONT COLOR="#000077">
</FONT><I>The one-to-many Album report as it appears in print preview mode.</I></P>
<P>To get
started, drop down four <TT>TQRBand</TT> components. Set the <TT>BandType</TT>
for the first component to <TT>rbPageHeader</TT>, the second one to <TT>rbGroupHeader</TT>,
the third one to <TT>rbSubDetail</TT>, and the last one to
<TT>rbPageFooter</TT>.
You might find it useful to name each component after its type:<BR>
<BR>
<TABLE BORDER="1">
<TR>
<TD WIDTH="119" VALIGN="TOP">Component name</TD>
<TD VALIGN="TOP"><TT>BandType</TT></TD>
</TR>
<TR>
<TD WIDTH="119"
VALIGN="TOP"><TT>PageHeaderBand</TT></TD>
<TD VALIGN="TOP"><TT>rbPageHeader</TT></TD>
</TR>
<TR>
<TD WIDTH="119" VALIGN="TOP"><TT>GroupHeaderBand</TT></TD>
<TD VALIGN="TOP"><TT>rbGroupHeader</TT></TD>
</TR>
<TR>
<TD WIDTH="119"
VALIGN="TOP"><TT>SubDetailBand</TT></TD>
<TD VALIGN="TOP"><TT>rbSubDetail</TT></TD>
</TR>
<TR>
<TD WIDTH="119" VALIGN="TOP"><TT>PageFooterBand</TT></TD>
<TD VALIGN="TOP"><TT>rbPageFooter</TT></TD>
</TR>
</TABLE>
<BR>
<BR>
The header and
footer bands should use <TT>TQRSysData</TT> components to display
standard information such as the report title, page number, and the time and date
the report is printed.</P>
<P>Drop down a <TT>TQuickReport</TT> component and connect it to the
<TT>ArtistSource</TT>
on the data module. Now drop down a <TT>TQRDetailLink</TT> component, which is designed
to help you set up one-to-many reports. The <TT>TQRDetailLink</TT> component should
have its <TT>DataSource</TT> property set to the
<TT>ArtistSource</TT> from the data
module and its <TT>Master</TT> property set to <TT>QuickReport1</TT>. The <TT>DetailBand</TT>
property should be set to the <TT>SubDetailBand</TT> and the <TT>HeaderBand</TT>
property to the
<TT>GroupHeaderBand</TT>.</P>
<P>After you have everything in place, drop down <TT>TQRDBText</TT> controls to display
the fields of your data. In particular, place one <TT>TQRDBText</TT> control on the
<TT>GroupHeaderBand</TT>, set the
<TT>DataSource</TT> property equal to <TT>ArtistSource</TT>
from the program's data module, and set its <TT>DataField</TT> property equal to
its <TT>FirstLast</TT> calculated field.</P>
<P>On the <TT>SubDetailBand</TT>, drop down four
<TT>TQRDBText</TT> components and
set the <TT>DataSource</TT> property equal to <TT>DMod->AlbumSource</TT>. Set
the <TT>DataField</TT> property for these controls to the <TT>Album</TT> and <TT>Rating</TT>
fields, and to the <TT>LoudLookup</TT> and
<TT>MediumLookup</TT> calculated fields.
The result should look like the image shown in Figure 17.7.<BR>
<BR>
<A NAME="Heading16"></A><A HREF="17ebu07.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu07.jpg">FIGURE 17.7.</A><FONT COLOR="#000077">
</FONT><I>The one-to-many Album report as it
appears at design time.</I></P>
<P>You can now set up a menu item on the program's main page that will launch the
form. When you run the program, the form you have created should make a report like
that shown in Figure 17.7.</P>
<H3><A NAME="Using
Queries to Help with Group"></A><FONT COLOR="#000077">Using Queries
to Help with Grouped Reports</FONT></H3>
<P>The second report from the Music program groups all the records in the report
according to their type. For instance, it groups all the jazz
albums together and
all the rock albums together.</P>
<P>I've already shown you one grouped report in this chapter. I'm showing you another
because this one uses queries to easily resolve what appears to be a rather complicated
problem. The difficulty
here is that you want the report to group according to the
type of album, but to also organize the report so that each album is grouped under
a particular artist. This is a bit tricky to do, given the design of the database.
To remedy the problem, I
created a query that generates most of my report for me:</P>
<PRE><FONT COLOR="#0066FF">select Types.Types, Artist.First,
Artist.Last, Album.Album, Album.Rating, Loudness.Loudness
from Artist, Album, Types, Loudness
where Artist.Code =
Album.GroupCode and
Types.Code=Album.Types and
Loudness.Code = Album.Loudness
group by Types.Types, Artist.Last,
Artist.First, Album.Album, Album.Rating, Loudness.Loudness
</FONT></PRE>
<P>This is a fairly straightforward query that
gives me all the records in the table
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -