Browse DevX
Sign up for e-mail newsletters from DevX


Extending the Visual FoxPro 9 Reporting System : Page 4

In this article, you'll learn about Visual FoxPro 9's report listener concept, how it receives events as a report runs, and how you can create your own listeners to provide different types of output in addition to print and preview.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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.

Listing 1 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 calls SetupEffectsForObject, 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).

However, EvaluateContents 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.)

The ORDERDATE 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.
The Execute method of DynamicForeColorEffect changes the color of the field by setting the PenRed, PenGreen, 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 is 3 (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.

Running TestDynamicFormatting.PRG results in the output shown in Figure 1.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date