Creating Your Own Listeners
Because report listeners are a class, you can create subclasses that alter the behavior of the reporting system when a report runs.
|The key to changing the way a field appears in a report is the EvaluateContents method.|
For example, one thing I've always wanted is a way to dynamically format a field at runtime. Under some conditions, I may want a field to print with red text, and under others, I want it in black. Perhaps a field should sometimes be bold and the rest of the time not.
The key to changing the way a field appears in a report is the EvaluateContents
method. This method fires for each field object just before it's rendered, and gives the listener the opportunity to change the appearance of the field. The first parameter is the FRX record number for the field object being processed and the second is an object containing properties with information about the field object. (See the Visual FoxPro Help file for a list of the properties this object contains.) You can change any of these properties to change the appearance of the field in the report. If you do so, set the Reload property of the object to .T.
to notify the report engine that you've changed one or more of the other properties.
shows some code (TestDynamicFormatting.PRG) defining a subclass of _ReportListener, called EffectsListener, that handles different types of effects that may be applied to fields in a report. These effects are applied by effect handler objects, which are stored in a collection in the oEffectsHandlers
property of EffectsListener. Each effect handler object handles a single effect
As the report is processed, the listener needs to determine which fields will have effects applied to them. It does that in the EvaluateContents
method by looking at each field as it's about to be rendered. EvaluateContents
, which calls the GetEffect
method of each effect handler to let it decide whether to apply an effect to the field. GetEffect
looks in the USER
memo of the field's record in the FRX for a directive indicating what type of effect to apply. If a particular handler is needed for the field, a reference to the handler is added to a collection of handlers that processes the field (as a field may have more than one effect applied to it).
fires for every field in every record, and there really isn't a need to check for the effects more than once for a particular field (doing so would slow down the performance of the report). So, BeforeReport
creates an array with as many rows as there are records in the FRX.
If the first column of the array is the default .F.,
the listener hasn't checked for the effects of the field being rendered yet, so EvaluateContents
does that and then sets the first column of the array to .T.
so the FRX record isn't examined again.
After determining whether there are any effects to be applied to the field, EvaluateContents
then goes through the collection of effect handlers for the field, calling the Execute
method of each one to have it do whatever is necessary.
DynamicForeColorEffect is one of the effect handlers. It looks for a directive in the USER
memo of a field in the report with the following format:
*:EFFECTS FORECOLOR = expression
(You can access the USER
memo of an object in a report from the Other
page of the properties dialog box for that object.)
field of the TestDynamicFormatting
report used in Listing 1
has the directive in the following snippet in its USER
memo; it tells EffectsListener that the DynamicForeColorEffect object should adjust the color of the field so it displays in red if the date shipped is more than ten days after it was ordered or black if not:
*:EFFECTS FORECOLOR = iif(SHIPPEDDATE > ORDERDATE +
10, rgb(255, 0, 0), rgb(0, 0, 0))
|Figure 1: TestDynamicFormatting Report. The code in Listing 1 produced this report, which shows dynamic formatting for the Shipped Date and Ship Via columns.|
method of DynamicForeColorEffect changes the color of the field by setting the PenRed
, and PenBlue
properties of the field properties object that was passed to EvaluateContents
to the appropriate colors and sets Reload to .T.
, which tells the report engine that changes were made.
DynamicStyleEffect uses a similar directive to change the font style. The style to use must be a numeric value: 0
is normal, 1
is bold, 2
is italics, and 3
is bold and italics. The SHIPVIA
field in the TestDynamicFormatting
report has the following directive in USER
, which causes the field to display in bold if SHIPVIA
(which, because of the expression for the field, actually displays as Mail)
or normal if not:
*:EFFECTS STYLE = iif(SHIPVIA = 3, 1, 0)
DynamicStyleEffect works the same as DynamicForeColorEffect, but changes the Style
property of the field properties object.
results in the output shown in Figure 1