Larry Teames On Reports

by Larry Teames

Published 1999-08-31    Printer-friendly version

This column is part of a series in which I illustrate approaches to common reporting situations. To make it easier for you to follow and later review what I cover, I have created a small dictionary (BREAKS.DCT), and the TPS files to go with it (LETTERS.TPS, BREAK1.TPS, and BREAK2.TPS). These files and the application I create for each column are available for download. This month's application file is CMEX2.APP.

I'm using Clarion5 (ABC) to build the example applications, but in most cases, I use the legacy embeds when placing source code in the report procedures because of their more descriptive names.

Working with Letterhead stationary

This month I've built a report that allows the user to print a letter (the body text and recipient are selected at runtime) using letterhead stationary for the first page, and plain stock for the remaining pages. I've elected to do this "one recipient at a time" to accommodate the simplest scenario, in which the user places one letterhead page and several stock pages in the printer's paper bin before printing.

Because all letterhead stationary doesn't extend the preprinted portion the same distance down the page, I'll need a way to allow the user to control how far down on the first page printing will begin. However, I want to start printing at the top of each subsequent page.

The Approach

First I created a standard ABC report procedure, where I specified the BREAK1 file as the primary file and the LETTERS file as an Other file. I set this procedure up so that the user selects the desired letter text (from the LETTERS file) and then selects the desired recipient (from the BREAK1 file). I also decided to use a simple INI file-based approach to control the distance I need to skip to start printing below the preprinted part of the letterhead stock.

Formatting The Report

First I went into the report formatter and deleted the automatically generated Page Header, Page Footer, and Form bands. I don't need these bands for this report, and they will only complicate things by trying to automatically print.

Next I set the width of the report (the Detail Area) to 7½ inches to allow for a ½ inch margin on each side. Then I set the Y-position of the report to ½ inch from the top of the page, and the height to a little over 9½ inches.

Finally, I set the default font for the report to Arial Regular 10pt.

Creating And Populating The Bands

To have this report operate the way I wanted I needed three detail bands, so I created two additional detail bands. I renamed the original band from Detail to SpacerBand, and also gave it a field equate (FEQ) label of ?SpacerBand. I named the second band HeaderBand (with the FEQ ?HeaderBand), and the third band I named Detail (?DetailBand).

SpacerBand will be blank when printed, and is used primarily to push the subsequent bands down below the preprinted part of the letterhead stock. I say primarily, because I also used it as the "home" of the textbox control containing the memo (LET:LetterText) from the LETTERS file. Note that when I populated this control I left it set to default height and width and didn't concern myself with where on the band I placed it. This is because this control will be used indirectly to supply text lines for the letter, but will not actually be printed (I hide it at runtime). This band was a convenient place to put the control where it would not be in my way while working with the other bands and controls.

HeaderBand is used to print the letter recipient's information from the selected BREAK1 record. There's no trickery with this band. It's simply made tall enough to allow for the controls that contain the recipient information.

DetailBand is used to print the text from the memo field. However, this is done one text line at a time. This approach allows me to have the letter automatically flow from one page to the next, regardless of the number of lines entered into the memo. After renaming this band, I populated a STRING control, made it as wide as I wanted each text line to be, then renamed it ?TextLine. Note that this is a simple string control, not a FEQ for a variable. Finally, I changed the text of the string to something that would remind me of its intended use.

How it works

Now let's look over the code that makes this report work. After selecting the desired LETTERS record and recipient (BREAK1), and opening the report, I set up the report with various runtime changes. In the After Opening Report embed I placed the code in Listing 1 (the comments describe what the code is doing):

Listing 1. The After Opening Report embed code.
SETTARGET(REPORT)   
! Following FEQs are in the REPORT
! Get the letterhead skip area
IF GETINI('Letter-Standard','SkipForLetterhead','NotFound'|
  ,'.\CMEX.INI') <> 'NotFound'                       
   ! Reduce by report's printable area offset
   LHSkip# = INT(GETINI('Letter-Standard','SkipForLetterhead',|
     'NotFound','.\CMEX.INI')) - REPORT{PROP:YPOS}   
   ! if result is less than zero set skip height to zero
   IF LHSkip# < 0                        
      LHSkip# = 0                       
   END
   ! Set "spacer" detail height to skip height
   ! and maxheight to that same height
   ?SpacerDetail{PROP:HEIGHT} = LHSkip#          
   ?SpacerDetail{PROP:MAXHEIGHT} = LHSkip#     
END
! Set textbox width to fixed string length
?LET:LetterText{PROP:WIDTH} = ?TextLine{PROP:WIDTH}     
! Ensure the textbox is hidden
?LET:LetterText{PROP:HIDE} = True             
! Ensure the textbox is set to DEFAULT height
?LET:LetterText{PROP:NOHEIGHT} = True              
! Ensure Detail band set to DEFAULT height
?Detail{PROP:NOHEIGHT} = True           
! Ensure string ctl ypos set to zero     
! and its height set to same as textbox lines
?TextLine{PROP:YPOS} = 0              
?TextLine{PROP:HEIGHT} = ?LET:LetterText{PROP:LINEHEIGHT}
! Reset to default target (ie. window)
SETTARGET                         

After setting these report characteristics, I used the Embeditor to find the generated print statements and omit them from the compile. I then followed the omitted code with custom code to do the printing in the way I needed it, as shown in Listing 2.

Listing 2. Overriding the default print behavior.
! Omit the generated print statements 
! for all bands print behavior.
OMIT('--omit to here--')    
PRINT(RPT:SpacerDetail)
PRINT(RPT:HeaderDetail)
PRINT(RPT:detail)
! Start of "After Printing Detail Section"
! [Priority 4000]
!--omit to here--
! Print the "spacer" band to get past letterhead, logo, etc.  
PRINT(RPT:SpacerDetail)   
! Print the address, salutation, etc.
PRINT(RPT:HeaderDetail)    
! Loop thru all lines of the textbox. For each line
! set the string to the next line of the textbox
! and print that line.
LOOP L# = 1 TO REPORT$?LET:LetterText{PROP:LINECOUNT}  
  REPORT$?TextLine{PROP:TEXT} = |
    REPORT$?LET:LetterText{PROP:LINE,L#}    
  PRINT(RPT:Detail)             
END

That's all there is to it! As you can see, there wasn't much to code once I decided what I wanted to do and decided how I would need to approach it.

As I've stated in past articles, the best way to control the report engine is to eliminate any undesirable automatic print engine functionality whenever possible. In this example the key was to not print the memo in a textbox (which is the approach typically used). Instead, I broke the memo down into individually printed lines of text so I would get automatic page overflow as each page is filled.

If you have a particular reporting question or problem that you'de like to see covered in a future column, please email me at lteames@cpcs-inc.com with your request. I can't promise that I'll be able to use every request I receive, but I'll try my best.

Until next month, Happy Reporting!

Download the example application


Larry Teames is an independent software developer, and one of the four founding members of Team TopSpeed. He is also president of Creative PC Solutions, Inc. which markets the popular Clarion 3rd party product Creative Reporting Tools.

Printer-friendly version

Reader Comments

To add a comment to this article you must log in.

 
 

Search

 

Advanced Search
Topical Index

Related Articles

Subscribe to
ClarionMag

One year: $189

(includes all back issues since '99)

Renewals from $139

Two years: $289

Renewals from $239

More Info

Subscribe Now!

ClarionMag Blog

RSS Feeds

Updates via Email

Enter your Email


Powered by FeedBlitz

Quick Links