Browse DevX
Sign up for e-mail newsletters from DevX


Extending the Visual FoxPro 9 Reporting System : Page 2

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

New Reporting Syntax
Visual FoxPro 9 supports running reports using the old report engine; you use the REPORT command just as you did before (although, as you'll see in a moment, you can use a new command to override the behavior of REPORT). To get new-style reporting behavior, use the new OBJECT clause of the REPORT command. The OBJECT clause supports two ways of using it: by specifying a report listener and by specifying a report type. Microsoft refers to this as object-assisted reporting.

A report listener is an object that provides new-style reporting behavior. Report listeners are based on a new base class in Visual FoxPro 9 called ReportListener. To tell Visual FoxPro 9 to use a specific listener for a report, instantiate the listener class and then specify the object's name in the OBJECT clause of the REPORT command. Here's an example:

loListener = createobject('MyReportListener') report form MyReport object loListener

If you'd rather not instantiate a listener manually, you can have Visual FoxPro do it for you automatically by specifying a report type:

report form MyReport object type 1

The defined types are:

  • 0 for outputting to a printer
  • 1 for previewing
  • 2 for page-at-a-time mode but not to send the output to a printer
  • 3 for all-pages-at-once mode but not invoke the preview window
  • 4 for XML output
  • 5 for HTML output.
You can also use other, user-defined types.

When you run a report this way, the application specified in the new _REPORTOUTPUT system variable (ReportOutput.APP in the Visual FoxPro home directory by default) is called to determine which listener class to instantiate for the specified type. It does this by looking for the listener type in a listener registry table built into the APP (although you can also tell it to use an external table). If it finds the desired class, it instantiates the class and gives a reference to the listener object to the reporting engine. Thus, using OBJECT TYPE SomeType in the REPORT command is essentially the same as:

loListener = .NULL. do (_ReportOutput) with SomeType, loListener report form MyReport object loListener

During the run of a report, Visual FoxPro exposes reporting events to objects based on the ReportListener base class as they happen. The Visual FoxPro Help file has complete documentation on the properties, events, and methods (PEMs) of ReportListener, but I'll only discuss the most useful ones in this article.

Table 1 lists the most commonly used properties of the ReportListener class.

Table 1: Some useful properties of the ReportListener class.




The data session ID for the report's data


The data session ID for the FRX cursor


The handle for the GDI+ graphics object used for rendering


The type of report output the listener produces. The default is -1, which specifies no output, so you'll need to change this to a more reasonable value. The values are the same as those specified in the OBJECT TYPE clause of the REPORT command.


The number of pages rendered


.T. (the default is .F.) to suppress progress information

Table 2 lists the most commonly used events and methods of ReportListener.

Table 2: Some useful events and methods of the ReportListener class.




Fires before the FRX is loaded and the printer spool is opened


Fires after the report has been run


Fires after the FRX has been loaded but before the report has been run


Fires after the report has been run


Fires before a band is processed


Fires after a band is processed


Fires before a field is rendered


Fires as an object is being rendered


Outputs the specified rendered page to the specified device

ReportListener Subclasses
The FFC (FoxPro Foundation Classes) subdirectory of the Visual FoxPro home directory includes _ReportListener.VCX, which contains some subclasses of ReportListener that have more functionality than the base class. The most useful of these is _ReportListener.

The _ReportListener class lets you chain listeners by providing a Successor property that may contain an object reference to another listener.
One of the most important features of _ReportListener is support for successors. You may want to use more than one report listener when running a report. For example, if you want to both preview a report and output it to HTML at the same time, more than one report listener must be involved. _ReportListener allows chaining of listeners by providing a Successor property that can contain an object reference to another listener.

For example, suppose ListenerA and ListenerB are both subclasses of _ReportListener that each perform some task, and you want to use both listeners for a certain report. Here's how you can chain these listeners together:

loListener = createobject('ListenerA') loListener.Successor = createobject('ListenerB') report form MyReport object loListener

The report engine only communicates with the listener specified in the REPORT or LABEL command, called the lead listener. As the report engine raises report events, the lead listener calls the appropriate methods of its successor; the successor calls the appropriate methods of its successor, and so on down the chain. This type of architecture is known as a chain of responsibility, as any listener in the chain can decide to take some action or pass the message on to the next item in the chain.

Another interesting capability of _ReportListener is chaining reports. The AddReport method adds a report to the custom ReportFileNames collection. You pass this method the name of a report and optional report clauses to use (such as the RANGE clause) and a reference to another listener object. The RemoveReports method removes all reports from the collection. RunReports runs the reports; pass it .T. for the first parameter to remove reports from the collection after they're run and .T. for the second parameter to ignore any listeners specified in AddReport. Here's an example that runs two reports as if they were a single report:

loListener = newobject('_ReportListener', ; home() + 'ffc\_ReportListener.vcx') loListener.ListenerType = 1 loListener.AddReport('MyReport1.frx', ; 'nopageeject') loListener.AddReport('MyReport2.frx') loListener.RunReports()

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