📄 ch11.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 11 -- Creating Reports</TITLE>
<META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT SIZE=6 COLOR=#FF0000>Chapter 11</FONT></H1>
<H1><FONT SIZE=6 COLOR=#FF0000>Creating Reports</FONT></H1>
<HR>
<P>
<CENTER><B><FONT SIZE=5>CONTENTS</FONT></B></CENTER>
<UL>
<LI><A HREF="#WhatsaFormatStatement">
What's a Format Statement?</A>
<UL>
<LI><A HREF="#ExampleUsingFieldLines">
Example: Using Field Lines</A>
<LI><A HREF="#ExampleReportHeadings">
Example: Report Headings</A>
<LI><A HREF="#ExampleUsingFuNCtionsintheValueLine">
Example: Using FuNCtions in the Value Line</A>
<LI><A HREF="#ExampleChangingFormats">
Example: Changing Formats</A>
<LI><A HREF="#ExampleUsingLongPiecesofTextinReports">
Example: Using Long Pieces of Text in Reports</A>
<LI><A HREF="#ExampleWritingtoaFileInsteadofISTDOUTI">
Example: Writing to a File Instead of <I>STDOUT</I></A>
</UL>
<LI><A HREF="#Summary">
Summary</A>
<LI><A HREF="#ReviewQuestions">
Review Questions</A>
<LI><A HREF="#ReviewExercises">
Review Exercises</A>
</UL>
<HR>
<P>
Perl has a few special features that let you create simple reports.
The reports can have a header area where you can place a title,
page number, and other information that stays the same from one
page to the next. Perl will track how many lines have been used
in the report and automatically generate new pages as needed.
<P>
Compared to learning about regular expressions, learning how to
create reports will be a breeze. There are only a few tricky parts,
which I'll be sure to point out.
<P>
This chapter starts out by using the print() fuNCtion to display
a CD collection and then gradually moves from displaying the data
to a fully formatted report. The data file shown in Listing 11.1
is used for all of the examples in this chapter. The format is
pretty simple: the CD album's title, the artist's name, and the
album's price.
<HR>
<BLOCKQUOTE>
<B>Listing 11.1 FORMAT.DAT-The Data File<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
The Lion King!
Tumbleweed Connection!Elton John!123.32
Photographs & Memories!Jim Croce!4.95
Heads & Tales!Harry Chapin!12.50
</PRE>
</BLOCKQUOTE>
<HR>
<P>
You'll find that Perl is very handy for small text-based data
files like this. You can create them in any editor and use any
field delimiter you like. In this file, I used an exclamation
point to delimit the field. However, I could just as easily have
used a caret, a tilde, or any other character.
<P>
Now that we have some data, let's look at Listing 11.2, which
is a program that reads the data file and displays the information.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Open the </I><TT><I>FORMAT.DAT</I></TT><I>
file.<BR>
<I>Read all the file's lines and place them in the </I></I><TT><I>@lines</I></TT><I>
array. Each line becomes a different element in the array.<BR>
Close the file.<BR>
Iterate over the </I><TT><I>@lines</I></TT><I>
array. </I><TT><I>$_</I></TT><I> is
set to a different array element each time through the loop.<BR>
Remove the linefeed character from the end of the string.<BR>
Split the string into three fields using the exclamation point
as the delimiter. Place each field into the </I><TT><I>$album</I></TT><I>,
</I><TT><I>$artist</I></TT><I>, and
</I><TT><I>$price</I></TT><I> variables.
<BR>
Print the variables.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 11.2 11LIST02.PL-A Program to Read and Display
the Data File<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
open(FILE, "<format.dat");
@lines = <FILE>;
close(FILE);
foreach (@lines) {
chop;
($album, $artist, $price) = (split(/!/));
print("Album=$album Artist=$artist Price=$price\n");
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
Use of uninitialized value at 11lst02.pl line 8.
Album=The Lion King Artist= Price=
Album=Tumbleweed Connection Artist=Elton John Price=123.32
Album=Photographs & Memories Artist=Jim Croce Price=4.95
Album=Heads & Tales Artist=Harry Chapin Price=12.50
</PRE>
</BLOCKQUOTE>
<P>
Why is an error being displayed on the first line of the output?
If you said that the split() fuNCtion was returning the undefined
value when there was no matching field in the input file, you
were correct. The first input line was the following:
<BLOCKQUOTE>
<PRE>
The Lion King!
</PRE>
</BLOCKQUOTE>
<P>
There are no entries for the <TT>Artist</TT>
or <TT>Price</TT> fields. Therefore,
the <TT>$artist </TT>and <TT>$price</TT>
variables were assigned the undefined value, which resulted in
Perl complaining about uninitialized values. You can avoid this
problem by assigning the empty string to any variable that has
the undefined value. Listing 11.3 shows a program that does this.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Open the </I><TT><I>FORMAT.DAT</I></TT><I>
file, read all the lines into </I><TT><I>@lines</I></TT><I>,
and then close the file.<BR>
<I>Iterate over the </I></I><TT><I>@lines</I></TT><I>
array.<BR>
Remove the linefeed character.<BR>
Split the string into three fields.<BR>
If any of the three fields is not present in the line, provide
a default value of an empty string.<BR>
Print the variables.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 11.3 11LST03.PL-How to Avoid the Uninitialized
Error When Using the <I>Split()</I> FuNCtion<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
open(FILE, "<format.dat");
@lines = <FILE>;
close(FILE);
foreach (@lines) {
chop;
($album, $artist, $price) = (split(/!/));
$album = "" if !defined($album); These lines assign null
$artist = "" if !defined($artist); strings if no info is
$price = "" if !defined($price); present in the record.
print("Album=$album Artist=$artist Price=$price\n");
}
The first four lines this program displays are the following:
Album=The Lion King Artist= Price=
Album=Tumbleweed Connection Artist=Elton John Price=123.32
Album=Photographs & Memories Artist=Jim Croce Price=4.95
Album=Heads & Tales Artist=Harry Chapin Price=12.50
</PRE>
</BLOCKQUOTE>
<HR>
<P>
The error has been eliminated, but it is still very hard to read
the output because the columns are not aligned. The rest of this
chapter is devoted to turning this jumbled output into a report.
<P>
Perl reports have <I>heading</I> and have <I>detail lines</I>.
A heading is used to identify the report title, the page number,
the date, and any other information that needs to appear at the
top of each page. Detail lines are used to show information about
each record in the report. In the data file being used for the
examples in this chapter (refer to Listing 11.1), each CD has
its own detail line.
<P>
Headings and detail lines are defined by using format statements,
which are discussed in the next section.
<H2><A NAME="WhatsaFormatStatement"><FONT SIZE=5 COLOR=#FF0000>
What's a Format Statement?</FONT></A></H2>
<P>
Perl uses <I>formats</I> as guidelines when writing report information.
A format is used to tell Perl what static text is needed and where
variable information should be placed. Formats are defined by
using the <TT>format</TT> statement.
The syntax for the <TT>format</TT>
statement is
<BLOCKQUOTE>
<PRE>
format FORMATNAME =
FIELD_LINE
VALUE_LINE
</PRE>
</BLOCKQUOTE>
<P>
The <TT>FORMATNAME</TT> is usually
the same name as the file handle that is used to accept the report
output. The section "Example: Changing Formats," later
in this chapter, talks about using the <TT>format</TT>
statement where the <TT>FORMATNAME</TT>
is different from the file handle. If you don't specify a <TT>FORMATNAME</TT>,
Perl uses <TT>STDOUT</TT>. The <TT>FIELD_LINE</TT>
part of the format statement consists of text and field holders.
A <I>field holder</I> represents a given line width that Perl
will fill with the value of a variable. The <TT>VALUE_LINE</TT>
line consists of a comma-delimited list of expressions used to
fill the field holders in <TT>FIELD_LINE</TT>.
<P>
Report headings, which appear at the top of each page, have the
following format:
<BLOCKQUOTE>
<PRE>
format FORMATNAME_TOP =
FIELD_LINE
VALUE_LINE
</PRE>
</BLOCKQUOTE>
<P>
Yes, the only differeNCe between a detail line and a heading is
that <TT>_TOP</TT> is appended to
the <TT>FORMATNAME</TT>.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
The location of <TT>format</TT> statements is unimportant because they define only a format and never are executed. I feel that they should appear either at the beginning of a program or the end of a program, rarely in the middle. Placing <TT>format</TT>
statements in the middle of your program might make them hard to find when they need to be changed. Of course, you should be consistent where you place them.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
A typical <TT>format</TT> statement
might look like this:
<BLOCKQUOTE>
<PRE>
format =
The total amount is $@###.##
$total
</PRE>
</BLOCKQUOTE>
<P>
The at character @ is used to start a field holder. In this example,
the field holder is seven characters long (the at sign and decimal
point count, as well as the pound signs #). The next section,
"Example: Using Field Lines," goes into more detail
about field lines and field holders.
<P>
<TT>Format</TT> statements are used
only when invoked by the write() fuNCtion. The write() fuNCtion
takes only one parameter: a file handle to send output to. Like
many things in Perl, if no parameter is specified, a default is
provided. In this case, STDOUT will be used when no FORMATNAME
is specified. In order to use the preceding format, you simply
assign a value to $total and then call the write() fuNCtion. For
example:
<BLOCKQUOTE>
<PRE>
$total = 243.45
write();
$total = 50.00
write();
</PRE>
</BLOCKQUOTE>
<P>
These lines will display:
<BLOCKQUOTE>
<PRE>
The total amount is $ 243.45
The total amount is $ 50.50
</PRE>
</BLOCKQUOTE>
<P>
The output will be sent to STDOUT. Notice that the decimal points
are automatically lined up when the lines are displayed.
<H3><A NAME="ExampleUsingFieldLines">
Example: Using Field Lines</A></H3>
<P>
The field lines of a <TT>format</TT>
statement control what is displayed and how. The simplest field
line contains only static text. You can use <I>static</I> or uNChanging
text as labels for variable information, dollar signs in front
of amounts, a separator character such as a comma between first
and last name, or whatever else is needed. However, you'll rarely
use just static text in your format statement. Most likely, you'll
use a mix of static text and field holders.
<P>
You saw a field holder in action in the last section in which
I demonstrated sending the report to STDOUT. I'll repeat the format
statement here so you can look at it in more detail:
<BLOCKQUOTE>
<PRE>
format =
The total amount is $@###.##
$total
</PRE>
</BLOCKQUOTE>
<P>
The character sequeNCe <TT>The total amount
is $</TT> is static text. It will not change no matter
how many times the report is printed. The character sequeNCe @###.##,
however, is a field holder. It reserves seven spaces in the line
for a number to be inserted. The third line is the value line;
it tells Perl which variable to use with the field holder. Table
11.1 contains a list of the different format characters you can
use in field lines.<BR>
<P>
<CENTER><B>Table 11.1 Field Holder Formats</B></CENTER>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD WIDTH=133><CENTER><I>Format Character</I></CENTER></TD>
<TD WIDTH=457><CENTER><I>Description</I></CENTER></TD></TR>
<TR><TD WIDTH=133><CENTER><TT>@</TT></CENTER>
</TD><TD WIDTH=457>This character represents the start of a field holder.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT><</TT></CENTER>
</TD><TD WIDTH=457>This character indicates that the field should be left-justified.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>></TT></CENTER>
</TD><TD WIDTH=457>This character indicates that the field should be right-justified.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>|</TT></CENTER>
</TD><TD WIDTH=457>This character indicates that the field should be centered.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>#</TT></CENTER>
</TD><TD WIDTH=457>This character indicates that the field will be numeric. If used as the first character in the line, it indicates that the entire line is a comment.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>.</TT></CENTER>
</TD><TD WIDTH=457>This character indicates that a decimal point should be used with numeric fields.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>^</TT></CENTER>
</TD><TD WIDTH=457>This character also represents the start of a field holder. Moreover, it tells Perl to turn on word-wrap mode. See the section "Example: Using Long Pieces of Text in Reports" later in this chapter for more information about
word-wrapping.
</TD></TR>
<TR><TD WIDTH=133><CENTER><TT>~</TT></CENTER>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -