Unit 4.12 Nice Reports and Formatting

PROG

a.   demo the use of strings u412.pas (Page Number 1)
b.   demo the use of strings on files u412a.pas (Page Number 2)
c.   demo formatting numbers and strings u412b.pas (Page Number 3)
d.   city page formatting simple report u412c.pas (Page Number 5)
e.   city page formatting with addresses u412d.pas (Page Number 5) 
PED
a.   to learn how to use variables or boxes of type string
b.   to learn how to print numbers the way you (or your boss) likes them
c.   to learn how to print reports with nice headings on each page
d.   to learn how to print reports with subtotals or subaverages 

CONCEPTS

simple report

keep a variable called linecount that keeps track of how many lines
Determine how many lines you want on a page
initialize linecount to this number

also determine how many chars for each column
colwidth1,colwidth2,colwidth3...colwidthn
determine how many chars between columns
colspace1,colspace2,colspace3,...,colspacen-1

Include code in loop

  if linecount=number of lines on a page then begin
write(report,char(12)); --- skips a page physically
write(report,heading1:colwidth1,'':colspace1,...
'':colwidthn-1,headingn:colwidthn)
heading1-headingn strings
linecount=0
endif;

dump out data line with
write(report,variable1:colwidth1,'':colspace1,variable2,colwidth2,'');
increment linecount

control-break situation where old value of variable not = current value of variable

keep oldvariable and update with
oldvalue:=newvalue

each time through loop
include code

if oldvalue <> newvalue then begin
print out summary information---average, sum, etc.
reinitialize summary variables--- sums, counters
end;



SF

string

A box of type string contains up to 255 chars
Has a length
Read in with "readln"
Entire line is read into a string variable
If you read a string after you read in a number do a "readln" before the input.
String can be output with writeln

formatting

A number or string followed by ":n" in a write statement means--
output will be displayed in n fields, iff there is enough room for it
A real number with the format
n:-m
will displayed in scientific notation with m places after decimal point
total width will be n characters
Format n:m
will be displayed in regular format with m places after decimal point
total width with n characters
copy(string,1,n) will truncate the string to n characters

other string stuff

' ' is a character string constant
'':n can be used to skip n spaces

to skip a page

write(char(12));



Unit 4.12 Nice Reports and Formatting

All the programs in this unit lead up to writing programs that produce nice reports.By nice reports, I mean columns of numbers, each column proceeded by a header on each page. We will have to learn several things in order to do this:

a)    how to read in and write out strings

      we learn this to read in names for cities, parts, individuals etc. so we don't have to refer to
      them as city number 3, person number 359, etc.

b)    how to print out numbers the right way

      We have to learn how to print out numbers that are right justified in a given column.  That way
      all our numbers line up.
In addition, we want each number to have a specific number of decimal places. That way the decimal points always line up. In the case of money, we would want dollar values to have two decimal places--corresponding to the number of cents.
c)    how to print out headings

      On the top of the column, we would like a heading to appear.  We want the headings to print
      out on each new page.  See page XXX for an example of such a report.

d)    how to print subtotals.

      These are called "control breaks" in some COBOL books.  When one has a big file containing
      names and other info for each name, one sorts this by name.  For example each line of a file
      could contain the name of a person followed by a transaction he made.  There would probably
      be several transactions for each individual.  There would be one line for each transaction.  Each
      such line would have the same name.  If we "sort" the file by the field containing the name,
      then all the transactions containing the name would be together in the file.

      Sort utilities are available on the IBM PC and most other computers.

      We write a loop that keeps track of the old name and the new name read in. That is the
      program knows the name on the line previously read in and for which we printed the
      information and the program also knows the name on the line just read and for which have yet
      to print out the line on the report.

      When we encounter a situation where the old name and the new name are different,the report
      program should print out the information, often a total, for the old name.  Then it should
      reinitialize the variables appropriate--often simply initializing a sum to zero.  A blank line or new
      page may also be needed at this point.
Let's deal with strings first. A string variable is a box that contains a sequence of characters like 'abc' or 'def ghi jkl' or 'Laurence L. Leff' or '123456789'. Just as we write blah:integer; to create a box that will contain a single number, we write blah1:string; to create a box that will contain a single sequence of characters. We will learn that we can read a string off either a data file or from the keyboard. We can write the string out--again to a data file such as a report or to the keyboard. We also can compare two strings to determine if they are equal. (There are many other operations as well. We will discuss some of them in Section Seven.)

Aside:

One thing I should mention is that most Pascals do not contain any "strings" They do allow arrays of single chars. Turbo Pascal has added many features that are not define in Standard Pascal. Strings are one of them. Various organizations such as the International Standards Organization prepare detailed documents describing programming languages such as Pascal, COBOL, C, FORTRAN, etc. These documents are called standards. If one only uses the features mentioned in these standards, then one can move ones progrtams from place to place.

End of Aside

Strings are read in with "readln" and not "read." We read in a string by writing read(box_name) where box_name is the box, declared "char" of course, which will contain the string.

There is one thing we have to be careful of. If we read in a number, just before we read in a string, we should issue a "readln" just before the actual readln for the string. E.G., if we wanted to read in int1 and string1, we would write:
read(int1);
readln;
readln(string1);

Character strings have a length which is an integer which tells how many characters we have in the string. In the case of readln, the length would be set by how many characters we have in the line being read in. For example, assume that our program executed the statement:
readln(xyz)
where xyz was declared string.

For example, if the user typed 'abcdef' when that readln occured and then a carriage return, the string xyz would contain 'abcdef' and have a length of five.

We can write out a string with "write". It will transfer the characters in the string to the current line--the string won't necessarily take a whole line unless we use "writeln"

The items in quotes--we often used them for prompts--are character string constants. Just as 123 is a constant for an integer and 123.45 is a constant for a real, 'abcdef' is a constant for a string.

We can also compare two character strings with any of the operators we use for numbers like <,>,=,<=,>=, and <>. Two strings are equal if they contain exactly the same characters. 'abcd' is equal to 'abcd'. 'abcd' is not equal to 'abcde'. For inequalities, we do them by dictionary or lexicographic order. 'abcd' is less than 'abcde' 'abcd' is less than 'bbcdefadf' and 'xyz' is
greater than 'abc'.

The first program on page 1 illustrates character strings. The program simply reads two strings from the input. It then will output the second string read in followed by the first one.

The two strings are declared on line 2. That is, we tell the Pascal compiler to create boxes for FirstString and SecondString. Because, we have ":string" at the end of line 2, the Pascal compiler knows that these boxes will contain character strings and not numbers.

Line 6 reads the FirstString from the user. Line 8 reads a line into SecondString. Both of these lines will be input from the keyboard.

Let's assume the first input was 'abcdef' and the second was 'ghi' Line 10 through 12 will print out a line which will be:
the second string you gave me is ghi

Lines 13 through 15 will print out a line which will be:
the first string you gave me is abcdef

Page 2 illustrates the same sort of program with a file containing the two strings.
Assume the file u412a.txt contains
abcdef
ghi

Then line 12 will read in 'abcdef' to FirstString.
Line 13 will read in 'ghi' to SecondString.

Liens 15 through 17 will output the string:
ghi abcdef
Note that write of a string in this case will not take the entire line for the string.

When we output a number, real or integer, or a character string, it will take so many places. Then the next number or string follows. Thus the number 1 takes precisely one place. The number 15 takes two characters. The string 'abcdef' takes six places. You have probably observed that if we output several numbers without doing a "writeln" between them, we get no spaces and they are all juxtaposed as if they were one number.

Thus, if we issue the commands:

a:=1;
b:=12;
c:=231;
write(a);
write(b);
write(c);

The output would be

112231

Also, if we output each number on a separate line, they won't be right justified.

a:=1;
b:=12;
c:=231;
write(a);
writeln;
write(b);
writeln;
write(c);
writeln;

will generate the output
1
12
231

We would like the output:
1
12
231

The way we do this is by giving a colon followed by a number after the variable to be output.
The number will be right-justified in the indicated number of spaces. (Should the number be too big to fit in that space, the number will print out in as many spaces as it needs. Some languages will simply put stars in the field when this happens. They take the philosophy that if it won't fit, we won't
print anything.)

If we want each number to appear lined up as shown before, we would write a program like:

a:=1;
b:=12;
c:=231;
write(a:3);
writeln;
write(b:3);
writeln;
write(c:3);
writeln;

The same principle also applies to character strings. If the string variable, string1, contains 'abcd' and we issue the command:

write(string1:6);
writeln;

The computer will output two blanks followed by abcd, like so:

abcd

With real numbers, we have the option of specifying the number of digits after the decimal point.
The form a:m:n means that we will output the variable a using m spaces. There will n digits after the decimal point. The number will be rounded as necessary. For example, if a had the number

1234.5678

and we outputted it with the statement

write(a:10:2)

we would get the output
1234.57

Note that we got "57" instead of "56" as the last two digits because the
number was rounded.

There is one more option to print out real numbers. That is, we can print
out the number in scientific notation. The number is printed out as
some small number times a power of ten. For example, 2456.23 would
be printed out as 2.45623E+04. That means 2.45623 times 104 or 2.45623 times 10,000.

We use the format a:n:-m to indicate we want scientific notation.

The m is still the number of digits after the decimal place.

Thus if a contained 2456.23 and we printed it out with

write(a:10:2);
we would get

2.46E+04

Note the rounding of the number. Remember when we choose n, that the "E+nn" and the decimal point take room in addition to the digits themselves.

Page xx will demonstrate how to print numbers nicely. We read in three real numbers--remember those are numbers that could have a decimal point or be very large. Then we read in three integers--those don't have a decimal point. And lastly, we read in three strings,g,h, and i.

We output the integers d,e, and f. In line 37, d will take as much room as it needs. In line 41, e, will take five spaces, and lastly f, will take 10 spaces. Note that the last digit of e will be in the
fifth column and the last digit of f will be in the tenth column. The position of the last digit of d will depend upon how big the number in d is.

We then illustrate the output of the real numbers. a will be output in whatever space is needed. In line 13, we will print out b in scientific notation with five digits after the decimal place. Line 17 will print out c in scientific notation.

Lines 20 to 32 will print out the strings. Line g will come out starting at column 1. Line 31 will print out i. The last character of i will be in column 19--unless i were bigger than ten characters.

One little thing I introduced in line 27 is a way of truncating a string. If we suspect that a string might be too big and we wish to cut it down in a Procrustian bed to a certain number of characters,
we can use copy(var,1,m) which will cut it down to m characters.

We now look at program u413c which will illustrate a simple report.

The program can be found on page 5. The input file consists of a bunch of cities--each city is followed by a single temperature reading. That temperature reading is in Farenheit. We would like to print out a nice report with headings: An example of the input can be found on page 18. Note that each city is on a line by itself. Each city is followed by a single number--the Farenheit temperature. Note also the end of the file is indicated by a blank line followed by any number--see page 20.

This can be described by a simple loop that simply is of the form

read(data for a city)
while(not last city yet) do begin
new-page-stuff
print out info for current city
read next city
end;

Note that lines 24 to 33 implement the new page handling and check.

We want three headings:
city
temperature (degrees Farenheit)
temperature (degrees Centigrade)

Note the output for the given input data. Note also how the headings appear on the top of each page. See page 21.

We decide that colwidth1 -- for the city -- will be 20. colspace1 will be five. That is five characters will separate the column of city names from the next heading. That heading will be for the Farenheit reading. colwidth2 will be 30. colspace2 will be five--separating this temperature from that for Celsius. Lastly, colwidth3 will be 30 characters as well.

See the use of the 20, 5,30,5,30,5 and 30 for the widths of headings and spacing in liens 26, 29 and 35. We use the same number in all three places so the headings are directly over the underlines which are over the numbers for them.

We also decide that we want 51 lines of information per page. That is why we set linecount to 51 in line 20 and compare it to 51 in line 24.

The last program also prints out a similar report. However, it assumes that there are several values for each city. All the values for a given city will follow each other--assume the data went through a sort. An example of such data would be found on page 23. Note that there are several data item for Phoenix following each other, as there are for each of the other cities. One city has only one data item.

It's output has the same sort of heading structure. However, note the presence of average values after all the readings for each city. Also, each city's readings are grouped off by a blank line. This output is shown on Page 24.

We use the variable "oldcity" to keep the value of the city in the previous set of input. In line 11 of page 7, we see the control break code. If old city is different from the new city just read in, that means we have to print out the average of the previous city. And we do that in lines 12 through 19. Note that we also reset SumCity and CountCity for the next city to be found.



Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58
Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58
Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58
Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58
Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58
Phoenix
95
Tampa
90
Juneau
30
Metropolics
55
Atlanta
55
Macomb
58
Willamette
59
Portland
60
Dallas
70
El Paso
86
St. Louis
58

-1



city Temperature (degrees F) Temperature (degrees C) ____ _______________________ _______________________
Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0 Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4 Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0 Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4 Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0 Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4 Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0 Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4 Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0

city Temperature (degrees F) Temperature (degrees C) ____ _______________________ _______________________
Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4 Phoenix 95.0 35.0 Tampa 90.0 32.2 Juneau 30.0 -1.1 Metropolics 55.0 12.8 Atlanta 55.0 12.8 Macomb 58.0 14.4 Willamette 59.0 15.0 Portland 60.0 15.6 Dallas 70.0 21.1 El Paso 86.0 30.0 St. Louis 58.0 14.4


Phoenix
25
Phoenix
75
Atlanta
65
Atlanta
75
New York
30
New York
45
New York
60
Tampa
50

-1



city Temperature (degrees F) Temperature (degrees C) ____ _______________________ _______________________
Phoenix 25.0 -3.9 Phoenix 75.0 23.9 AVERAGE 50.0 10.0

Atlanta 65.0 18.3 Atlanta 75.0 23.9 AVERAGE 70.0 21.1

New York 30.0 -1.1 New York 45.0 7.2 New York 60.0 15.6 AVERAGE 45.0 7.2

Tampa 50.0 10.0 AVERAGE 50.0 10.0