Understanding the Report Output Application

The default Report Output Application (ReportOutput.app) fulfills the standard responsibilities of an application designated in the _REPORTOUTPUT variable.

  • It accepts two parameters, expecting a numeric value as the first parameter.

  • It stores an object reference to an instance of a ReportListener-derived class to the variable it received as the second parameter.

  • The class for which it supplies an instance is determined by the value in the first parameter.

  • If successful in obtaining an object reference to an appropriate class, it assigns the value of the first parameter to the object's OutputType property.

Note

For full information on the requirements for a Report Output Application, refer to _REPORTOUTPUT System Variable.

This topic covers details of the default Report Output Application's implementation of these requirements. It also describes some additional functionality supplied by the default Report Output Application.

ReportOutput.app ReportListener Reference Collection

You can explicitly assign a ReportListener object reference to a variable, if you call the Report Output Application using the following syntax:

LOCAL loRef
do (_REPORTOUTPUT) with <N>, loRef
IF ISNULL(loRef)
   * the Report Output Application did
   * not recognize the value <N>
ELSE 
   ? loref.outputtype
   ? loref.class
ENDIF

However, in many cases, ReportOutput.app provides a ReportListener object reference without your explicitly assigning the reference to a variable. This situation occurs if you have set the value of SET REPORTBEHAVIOR to 90, or if you use the OBJECT TYPE<N> clause on your REPORT FORM or LABEL command.

ReportOutput.app maintains a public variable, _oReportOutput, derived from the Collection class. It stores references to the ReportListener-derived objects, for which it has provided references, in this collection. The collection scopes ReportListener references globally, so that they can be successfully re-used for multiple reports, regardless of how or where you ask for the reference.

Providing consistent ReportListener scope, using ReportOutput.app's reference collection or a similar strategy, is required to support chaining multiple reports in one output result. The reference collection also provides a convenient mechanism for retrieval of these object references, before and after the report run.

You can retrieve the object reference from the collection by using the string value of the appropriate OutputType as the collection key:

#DEFINE PRINT_MODE 0
REPORT FORM ? OBJECT TYPE PRINT_MODE 
LOCAL loRef
loRef = _oReportOutput[TRANSFORM(PRINT_MODE)]
? loRef.OutputType  && will be 0
? loRef.PageTotal && will be the total of pages 
                  && from the last print run

For more information, see How to: Use the Report Output Application's Reference Collection.

Important

ReportOutput.app reserves the right to use additional key values in this collection for other uses besides ReportListener object references. For example, if you designate a custom Report Output registry table, it stores the name of this table in the reference collection. For more information, see How to: Specify an Alternate Report Output Registry Table.

ReportOutput.app Extended Parameters

ReportOutput.app extends the use of the two required _REPORTOUTPUT parameters, provides default behavior if the second parameter is not included, and adds an optional third parameter. The following represents appropriate syntax for ReportOutput.app

DO ReportOutput.app WITH ;
   nListenerType [,eListenerReference [,eUnload]]

This section describes ReportOutput.app's treatment of each parameter.

First Parameter: nListenerType

When evaluating its nListenerType parameter, ReportOutput.App accepts all numbers greater than or equal to -1, the default value of ReportListener's ListenerType property, as instructions to provide a ReportListener reference of appropriate type.

Note

If nListenerType is a number but is not an integer value, ReportOutput.app accepts the value but uses the integer portion of the received value as the type requested.

If nListenerType is -1, it provides a reference to an object instanced from the ReportListener baseclass. If it is greater than -1, ReportOutput.app begins an evaluation process to determine what ReportListener-derived class should provide the reference, as follows:

  • ReportOutput.app first checks to see if it has a cached reference to an object previously provided for this value. If it finds one, it re-uses this reference.

  • If no cached reference is available, ReportOutput.app checks its registry table for any user instructions that match this value. The registry table is described in a later section of this topic.

  • If there are no user instructions available, it uses built-in defaults listed in the following table.

nListenerTypevalue Default class providing ReportListener reference

0

ReportListener User Feedback Foundation Class

1

ReportListener User Feedback Foundation Class

2

ReportListener Baseclass

3

ReportListener Baseclass

4

ReportListener XML Foundation Class

5

ReportListener HTML Foundation Class

999

ReportListener Debug Foundation Class

Note

In the table, notice that a single ReportListener class may handle multiple nListenerType values. ReportOutput.app assigns the nListenerType value it receives to the object's OutputType property. This property value assignment is part of the specified requirements for any Report Output Application. If the object is an instance of a ReportListener-derived class, ReportOutput.app expects the object to decide whether to re-assign its own ListenerType property based on OutputType, or maintain the values separately. If the object is an instance of the ReportListener baseclass, ReportOutput.app also assigns the nListenerType value to the object's ListenerType property. For more information, see OutputType Property (Visual FoxPro) and ListenerType Property.

ReportOutput.app reserves all nListenerType values less than -1 to expose additional functionality beyond its specified responsibility to provide ReportListener references. Two such values, -100 and -200, are covered in a later section of this topic.

Second Parameter: eListenerReference

ReportOutput.app treats its second parameter, eListenerReference as optional. If it is not received, ReportOutput.app simply caches a reference to an instance of the appropriate ReportListener class in its reference collection. This behavior gives you the opportunity to set up various ReportListener references before you need them for reporting.

If it receives its eListenerReference parameter, ReportOutput.app accepts either a declared variable, as shown in the example in the last section, or as a string representing the variable. If you provide a string to represent the variable, and if the variable represented by the string does not already exist, ReportOutput.app initializes the variable as PUBLIC.

You can also use a string to ReportOutput.app in the eListenerReference parameter if you want to assign a ReportListener to an object member. For example:

#DEFINE PREVIEW_MODE 1
Ox = CREATEOBJECT("custom")
Ox.addProperty("myReportListener")
DO (_REPORTOUTPUT) WITH PREVIEW_MODE, "ox.myReportListener"
REPORT FORM ? OBJECT ox.MyReportListener
? ox.myReportListener.Name

If the object member does not exist but ReportOutput.app can verify that the object exists, the member is created. It is capable of drilling down into object containership hierarchies for this purpose. For example:

#DEFINE PREVIEW_MODE 1
Ox = CREATEOBJECT("form")
Ox.addobject("myChildObject","custom")
DO (_REPORTOUTPUT) WITH PREVIEW_MODE, "ox.myChildObject.RL"
REPORT FORM ? OBJECT ox.myChildObject.RL
? ox.myChildObject.RL.PageTotal

Third Parameter: eUnload

You can release a ReportListener reference from ReportOutput.app's reference collection explicitly, as follows:

#DEFINE PRINT_MODE 0
_oReportOutput.Remove[TRANSFORM(PRINT_MODE))

However, ReportOutput.app provides a third parameter so you can ask the application to manage this reference for you, without addressing the collection directly. The parameter allows you to explicitly release the reference or to release and immediately receive a new instance, as shown in the following example.

#DEFINE PRINT_MODE 0
#DEFINE OUTPUTAPP_LOADTYPE_RELOAD 2
   DO (_reportoutput) WITH ;
      PRINT_MODE , ox, OUTPUTAPP_LOADTYPE_RELOAD

The following are the recognized values for the eUnload parameter.

eUnloadParameter Value Usage

Not passed, logical False (.F.), or passed but not logical or numeric type.

Ignored. ReportOutput.app provides standard behavior: it loads a ReportListener or performs other activity as determined by nListenerType value.

Logical True (.T.) or numeric value 1.

ReportOutput.app does not provide a ReportListener object reference. It checks for a ReportListener object using a key determined by nListenerType, and removes this ReportListener from its collection if found.

All numeric values greater than 1.

ReportOutput.app removes a reference for a ReportListener object from its collection, if found, and then re-loads the appropriate reference. It stores this reference to the variable indicated in the eListenerReference parameter.

ReportOutput.app ReportListener Registry Table

ReportOutput.app provides default ReportListener object references according to the table listing nListenerType values and class names in the previous section. You can use a registry table to override these settings.

ReportOutput.app leverages the same configuration or registry table structure as the ReportListener Foundation Classes use to store their configuration information. The following code shows you the base structure of this table. You can add fields to this table of any type, and the order of the fields is not significant to Report Output Application components or the Foundation Classes.

CREATE TABLE (CONFIG_TABLE_NAME) ;
   (objtype i, ;
    objcode i, ;
    objname v(60), ;
    objvalue v(60), ;
    objinfo m)    

Both ReportOutput.app and the ReportListener Foundation Classes provide facilities to create the table for you. For more information on creating the table and designating it as your Report Output Application registry table, see How to: Specify an Alternate Report Output Registry Table.

Note

ReportOutput.app and the ReportListener Foundation Classes use this table structure differently, and require different indexes. However, it does not matter which component creates the table, or if you create it as a blank table, as shown in the sample code above. Each component will create any records and indexes it needs, if pointed to that table.

ReportOutput.app reserves the range 100-999 for Objtype field values in the configuration table. It uses an Objtype field value of 100 to represent ReportListener class registry records. The following table shows you ReportOutput.app's use of records in the table for ReportListener registry purposes.

Field Usage Remarks

OBJTYPE

100

A value of 100 in this field identifies a ReportListener registry record.

OBJCODE

nListenerType

The values in this field are matched against the first parameter you supply to ReportOutput.app.

OBJNAME

Class to instantiate

This class name may be ReportListener (the base class).

OBJVALUE

Class library (.vcx) or procedure file (.prg) holding the class definition.

This value may be blank, if the class name is ReportListener.

OBJINFO

Module/Application containing library.

This value may be blank, if the class library or procedure file is bound into your application.

ReportOutput.app specifies an Objtype field value of 110 to store other configuration information for its own use. It uses records with an Objtype value of 110 and an Objcode value of 1 for filtering the ReportListener registry records based on user-specified criteria. Records with an Objtype value of 110 and any other Objcode values are reserved for other configuration uses by ReportOutput.app, but are not currently used.

The following table describes ReportOutput.app's usage of registry table fields for filter records.

Field Usage Remarks

OBJTYPE

110

A value of 110 in this field identifies a ReportOutput.app configuration record.

OBJCODE

1

A value of 1 in this field, for records with an Objtype value of 110, is a filter record.

OBJNAME

not used

Filter records ignore this field.

OBJVALUE

not used

Filter records ignore this field.

OBJINFO

Filter expression

The expression you put in this field is included in a LOCATE expression when searching the registry table for an appropriate class to provide for a given nListenerType value. The LOCATE command is constructed as follows:

#DEFINE OUTPUTAPP_OBJTYPE_LISTENER    100
   LOCATE FOR ObjType = ;
   OUTPUTAPP_OBJTYPE_LISTENER AND ;
   (ObjCode = iType)  ;
   &cFilter ;
   AND (NOT DELETED())

For more information, see How to: Register Custom ReportListeners and Custom OutputTypes in the Report Output Registry Table.

ReportOutput.app Return Values

A Report Output Application must be modal, because it is required to return a value to Visual FoxPro's Report Engine as part of the Engine's processing of a REPORT FORM or LABEL command. Visual FoxPro receives this return value using the parameter eListenerReference, which is passed by reference; the native engine does not recognize a return value from ReportOutput.app.

However, ReportOutput.app does provide a return value if you call it as a function, representing success or failure in the task indicated by your nListenerType parameter:

? ReportOutput(5, "oRL")
* returns .T.
DISPLAY MEMO LIKE oRL
* Shows that the call above
* declares the variable oRL PUBLIC if
* it is not already in scope, 
* because it was passed as a string
* stores a reference to the HTMLListener
* Foundation class in this variable.
? ReportOutput(25,"oRlx")
* returns .F.
DISPLAY MEMO LIKE oRLx
* Shows that the call above does
* not declare the variable oRLx

ReportOutput.app Compile-time Adjustments

ReportOutput.app's source code is available in a zip file in the XSource folder in your Visual FoxPro \Tools directory. For more information, see XSource Folder.

You can include the source code for ReportOutput.app in your applications. For more information, see Including Report Files for Distribution. When you follow this practice, you can edit the Report Output defined constants, found in the ReportOutput.h header file, to tune your application's reporting behavior.

The table below provides a sample of the kinds of items available in the header file for adjustment.

#DEFINEd constant Default value Edit this setting to change:

OUTPUTAPP_INTERNALDBF

"_ReportOutputConfig"

Name of built-in registry table.

OUTPUTAPP_EXTERNALDBF

"OutputConfig"

Default name of registry table on disk.

OUTPUTAPP_REFVAR

_oReportOutput

Name of public variable for the reference collection.

OUTPUTAPP_BASELISTENER_CLASSLIB

"Listener.VCX"

Class library holding default ReportListener classes.

OUTPUTAPP_CLASS_PRINTLISTENER

"UpdateListener"

Class name used by default to handle eListenerType value 0 (print).

See Also

Concepts

Considerations for Creating New Report Output Types

Other Resources

ReportListener Foundation Classes