Introduction
dB2K offers a built in “ReportViewer” class which is defined in the online help as “A control to display a report on a form”. It does what it says and will display a report (.REP file) on screen. It is not horribly functional on its own though, and putting it to proper use requires some enhancements. To make life easier for us, Ken Mayer created a form called Preview.wfm.
Preview.wfm uses a ReportViewer object and allows reports to be viewed on-screen. It also provides pushbuttons for printing and traversing pages and even allows for passing parameters to your report. Preview.wfm is among the many helpful, useful and downright handy pieces of dB2K code contained in the dBASE Users’ Function Library Project (dUFLP). The library is available for download from Ken Mayer’s web site.
As a novice dB2K user, I had a difficult time making my reports work with the PREVIEW utility when I wanted to pass parameters to the report. Then, one day, I finally “got it”. Since others have had many of the same questions as I, it seemed worthwhile to provide an example here in the dBulletin. Please keep in mind that I am a novice. This is my way of doing it, but better ways may exist. I hope you find the examples helpful.
What I wanted to accomplish
I am re-writing an old DOS application designed to keep track of video tapes for a video rental store. The data and the reporting needs are fairly simple. I wanted the user to have the following options:
To
see a sample PREVIEW form (from clicking the “Screen” button), click
here.
To handle the pushbuttons, I only had to create four methods for this form.
PBCancel_onClick()
The
PBCancel_onClick() method
doesn’t leave much to talk about. Since all it is supposed to do is close
the form, I typed form.close()
in
the method. ’Nuff said.
Function PBCancel_onClick form.close() return |
|
PBPrint_onClick()
The
PBPrint_onClick() method
is straightforward. It establishes an instance of the report, gets the
parameter array, sends the array to the report by creating a report property
called PARAMS,
sets the report to go to the printer and then prints it. Comments in the
code explain what each step does.
Function PBPrint_onClick // method of RepDialog.WFM local r, aParam // instantiate
report for sending to printer
// get the parameter
array to pass to the report
// pass aParams
array to report
// setting the
output property to 1 directs the report to printer
// print report
return |
|
PBPreview_onClick()
Like
PBPrint_onClick(),
the PBPreview_onClick() method
gets a parameter array from ParamSetup().
However, it then passes the array along to the
Preview.wfm form
(rather than the report itself) and
Preview.wfm takes
over from there.
Function PBPreview_onClick // Method of RepDialog.wfm // Revised 01/28/2001 // get the parameter
array to pass to the report
// That's all
we have to do. Preview.wfm takes care of the rest
// Note: I don't
know why but calling PreviewForm()
// so instead,
call it this way
// The parameters
above are:
return |
|
ParamSetup()
I allow the user to send the report directly to the printer or to view the report using Preview.wfm. Since both PBPrint_onClick() and PBPreview_onClick() require the same array setup, I’m using ParamSetup() to fill the bill. If you were offering only a single choice (just the ‘Screen’ pushbutton for example), you wouldn’t need a separate setup method. You could instead just include the ParamSetup() steps within the onClick() method for the ‘Screen’ pushbutton.
First, ParamSetup() establishes an array to contain the parameters. (Please note: The ReportViewer base class uses an associative array by default. For compatibility, ParamSetup() also uses an associative array.)
Next, ParamSetup() checks the group of radio buttons on the form to determine how the user wants to sort the report data.
Then, it changes the text of the report title based on this information.
Last,
it looks at the date entered by the user (if any). If available, it sets
the value of the RecDateStart array
element to use as a filter). Easy to understand, yes? I hope so. If not,
please drop me an email to let me
know what you don’t understand. I’ll try to explain it more thoroughly
and I’ll use your comments to refine this page.
Function ParamSetup() // Method of RepDialog.wfm // this sets up the parameter array and passes it back to // the calling method [PBPrint_onClick() or PBPreview_onClick()] // setup associative
array for passing to tapelist.rep
// Set value
of array's "SortChoice" element
// Set title
according to above choice
// Set date
filter element in aParams
return aParams |
|
Ok, we’re almost done. The last thing I need to talk about is the report itself and how it uses the parameter array to change the report to your liking. Report objects have a built-in method called Render(). This method, when called, simply prints the report by default. It doesn’t check for any kind of parameters passed by the user. So, in order to make this parameter array work, we need to create our own version of Render().
We do this by overriding the built-in Render() method. In brief, to do this, open the report in design mode and click Method|New Method on the menu. This will allow you to type your own Render() method which will be called Form_Render(). Take note that when the source editor opens, dB2K will give your intended method a default name other than Form_Render(). Be sure you change the name of the method to Form_Render().
Here
is what my Form_Render() method
looks like. Don’t forget that this method is in the REPORT (.rep),
not in the report dialog form like the previous methods.
Function Form_Render // method of TapeList.rep // overridden render method // We only want this code to run once (just for the filter setup, etc). // Note that except for the call to super::render() at the bottom, // this code only runs if hasn't been called previously // Check for
existence of the runOnce logical property
// Check for existence of a ReportViewer object
endif
// if we have a params array, we need to set parameters for the report
if this.params ["RecDateStart"] # null
// Add subtitle listing presence of filter
if this.cSort # null
endif // if params SortChoice # null endif // if type ( "this.params") == "O" endif // if type this.runonce # L return super::render() |
|
This is a somewhat long method but really not too difficult to understand if we break it down into separate parts. Once you get past the this.runOnce part, here is what happens:
This is my first attempt at writing any kind of technical document. So, if you have any questions in reference to this document or if you wish to offer constructive criticism as to how I could make it better, please drop me an email. I would like to hear from you.
Please note that I cannot supply any kind of technical support for dB2K or any other software product. Nor can I offer general programming assistance except for that which I might post in the dB2K newsgroups.
Steve
Hawkins
dB2K
programmer-in-training
SeHawk
Services
dB2K
- the only way to fly