SQR Reports: The Basics | KEVIN RESCHENBERG 08-06-2014 |
The usual SQR report is just lines and columns of data in a fixed font, written to a PDF.
That's fine in many cases. But you can do much more: multiple fonts, color, images, lines
and grids, background colors and shading, overprinting, and precise positioning of elements. This begins
a series of posts on the basics of SQR printing and some more advanced items you might not have tried yet.
Over the years at various clients I've seen sort of a migration away from the standard
PDF tabular report and toward producing reports in Excel format. Once users try that, they seem
to like it (because they have more control over the data and format). However, there are still many
things that must be printed. Think about employee or customer statements, letters, invoices and such.
You can just dump some words and numbers on the page, or you can make it look good. SQR can probably do
anything you need. It is not nearly as easy and flexible as, for example, HTML and CSS. But with a little
extra effort you can have a lot of control over the format of your printed output.
Today I'll cover the basics of the report page. It's not necessarily obvious how this works.
In fact, confusion about the timing of certain events led me initially to start writing an SQR debugger
(which eventually led to SP Debugger for SQR).
Page sections
A report can have a heading, a body, and a footing. That's not surprising, but even this can be a little
confusing. Here we go...
The printed page always has a body area. It can also have a section at the top that is reserved for
a heading. Similarly, it can have a reserved footing area at the bottom.
begin-program
print 'This is the start of the body area' ()
let #i = 0
while #i < 100
add 1 to #i
print 'Body line ' (+1, 1)
print #i () edit '999'
end-while
end-program
begin-heading 5
print 'Heading line 1' (, 1)
print 'Heading line 2' (+1, 1)
end-heading
begin-footing 5
print 'Footing line 1' (, 1)
print 'Footing line 2' (+1, 1)
end-footing
Here is the first page of the resulting report:
There is a default margin. The BEGIN-HEADING 5 line specifies that five lines are reserved for
the heading (whether we use them or not). Therefore, the two printed lines are followed by three blank lines.
The body area starts immediately after that. The program tries to print 100 lines in the body, but there is room
for only 51. At that point we run into the area reserved for the footing. Again, five lines were reserved for the footing and so
we see the two lines printed by the program and then another three blank lines. That completes the first page. The second
page has the same heading and footing and body lines 52-100.
But notice that there is an extra blank line at the top of this page's body area. To understand this, we need to think about
what happens when we are printing into the body area. A normal PRINT statement that is not in the
header or footer section of the program will print into the body area. The positioning parameters
specify where to print. The very first line printed by the program is in position () ,
which means "exactly where we are right now". That would be the top of the body area. Every line after that is
printed using position (+1, 1) , which means that we advance a line before printing. So "This is the
start of the body area" prints at the very top of the body area, while "Body line 52" prints after advancing
one line from the top of the body area on the second page. Therefore we have skipped the first line in the body area.
Normally you would print every line with (+1) and would not see this. I wrote this code in this
way in order to show that the blank line is really the first line in the body.
Timing of printing events
Before wrapping up this discussion of the basic structure of the page, let's look at how and when the sections are produced.
We might assume that the heading is written, then the body, and finally the footing. But step through this sample
program in the debugger and you see that the flow of control doesn't work
like that. Here is the actual order of events:
BEGIN-PROGRAM
PRINT (the top line and 51 numbered lines in the body)
- The next
PRINT (for body line 52) is reached but is not executed
BEGIN-HEADING, PRINT (2 lines), and END-HEADING
BEGIN-FOOTING, PRINT (2 lines), and END-FOOTING
- We now begin page 2
PRINT for line 52 is finally executed
PRINT for the rest of the lines, which all fit on the page
END-PROGRAM
BEGIN-HEADING, PRINT (2 lines), and END-HEADING
BEGIN-FOOTING, PRINT (2 lines), and END-FOOTING
You can see that END-PROGRAM is not really the end—some code continues to execute after
that point. More importantly, note that the page heading is printed after the body area is completed, not before. This is important to know
because we often print variable information in the heading. For example, suppose that you sort your data by
department and you want to print the department name in the heading. Since the heading is printed only when the
page is completed (for example, if you issue a NEW-PAGE to start a new department), the value of the
department name for the current row's data (&variable) may be wrong! You need to save the department name in
a separate string variable ($variable) and use that instead. There are also ways of handling this with ON-BREAK ,
but that's a big topic that is out of scope for these posts, where we'll be focusing more on the presentation aspects.
In the next post we'll cover the SQR print grid and positioning.
|