The Report Builder architecture defines a framework into which you can plug your own classes to handle specific builder actions, such as responding to report designer events. Additionally, the report builder also allows you to replace the Expression Builder dialog box with your own implementation, by registering a class in the report builder's event handler registry table.
This topic describes the process of plugging in your own class to replace the expression builder dialog box, and also gives a more comprehensive example class that demonstrates how to create a Data Environment-aware expression builder.
![]() |
---|
If you have not already done so, create an editable copy of the report builder's internal event handler registry table, as described in How to: Add Your Own Handler to the Report Builder's Registry. |
![]() |
---|
This topic assumes that the _REPORTBUILDER system variable is set to the default Report Builder application. If it is empty, or has been set to a third-party report builder, then the procedures described below probably will not apply. For more information, see _REPORTBUILDER System Variable. |
To create a GetExpression wrapper class
-
Create or edit a programmatic class library:
MODIFY COMMAND c:\temp\mylibrary.prg
-
Define a class that implements the GetExpression wrapper API, as documented in Report Builder Event Handler Registry Table. You can use the simple example shown here as a template. This example replaces the label caption editor with a simple input box.
-
Save your changes.
В | ![]() |
---|---|
DEFINE CLASS MyGetExpressionWrapper AS Custom PROCEDURE GetExpression( cDefaultExpr, cDataType, ; cCalledFrom, oEvent ) LOCAL cNewValue * Switch to the designer datasession, where tables * may be open: SET DATASESSION TO (oEvent.DefaultSessionID) DO CASE CASE m.cCalledFrom = "LabelCaption" * Specify special handling for label captions: cNewValue = INPUTBOX("Enter the label caption") OTHERWISE * All other expression builders will use the default: GETEXPR "Enter the label caption" TO cNewValue ; TYPE cDataType DEFAULT cDefaultExpr ENDCASE * Restore to the private builder datasession: SET DATASESSION TO (oEvent.FrxSessionID) RETURN cNewValue ENDPROC ENDDEFINE |
To register your class as in the handler registry table
-
Open the Report Builder Options dialog box:
DO (_REPORTBUILDER)
-
Click Explore Registry.
-
Locate the record with Type = "G".
-
Edit the record so that Class =
"MyGetExpressionWrapper"
and Library="c:\temp\mylibrary.prg"
-
Click OK to save your changes.
To test your changes
-
Open a report or label layout in the designer.
-
Double-click on a label control to display the Properties dialog box.
-
Click on the ellipsis (…) next to the label caption text box to invoke the custom expression builder provided by your class.
Example
By design and by default, the Expression Builder dialog box invoked by ReportBuilder.App does not show tables that are not open in the designer's data session. Tables and cursors included in the report layout's data environment are not available. This is a change from how the designer's Expression Builder behaved in earlier versions (and still does when _REPORTBUILDER = ""
).
This example shows how you can define an alternative wrapper class that inspects the data environment, opens the tables in a private data session and then invokes the standard GETEXPR dialog box, to duplicate the original behavior of the report designer's Expression Builder.
You can save this class to a procedure file, and register it for use in the report builder, as described above.
В | ![]() |
---|---|
DEFINE CLASS GetExpressionWithDE AS Session DataSession = 2 && private PROCEDURE GetExpression LPARAMETERS lcDefaultExpr, lcDataType, lcCalledFrom, loEvent LOCAL lCurSel, lcNewExpr, liPrivateSession LOCAL liLines, i, iTableCount, lcAlias, lcSource *---------------------------------------------- * Save this before it changes: *---------------------------------------------- liPrivateSession = THIS.DataSessionId *---------------------------------------------- * Scan the data environment and open tables: *---------------------------------------------- SET DATASESSION TO (loEvent.FrxSessionId) lCurSel = SELECT() iTableCount = 0 SELECT expr FROM frx WHERE objtype = 26 ; INTO CURSOR environCursors SELECT environCursors SCAN liLines = ALINES(laValuePairs, environCursors.expr ) FOR i = 1 TO liLines DO CASE CASE LEFT(UPPER(laValuePairs[i]),5) == "ALIAS" lcAlias = THIS.GetValue( laValuePairs[i]) CASE LEFT(UPPER(laValuePairs[i]),7) == "CURSORS" lcSource = THIS.GetValue( laValuePairs[i]) ENDCASE ENDFOR lcSource = EVL(lcSource,"") DO CASE CASE FILE(lcSource) CASE FILE(FORCEEXT(lcSource,"DBF")) lcSource = FORCEEXT(lcSource,"DBF") CASE FILE(JUSTFNAME(lcSource)) lcSource = JUSTFNAME(lcSource) CASE FILE(FORCEEXT(JUSTFNAME(lcSource),"DBF")) lcSource = FORCEEXT(JUSTFNAME(lcSource),"DBF") ENDCASE IF FILE(lcSource) lcAlias = EVL( lcAlias, "Cursor"+TRANSFORM(i)) SET DATASESSION TO (liPrivateSession) IF NOT USED(lcAlias) TRY IF EMPTY(ALIAS()) USE (lcSource) ALIAS (lcAlias) ; NOUPDATE SHARED ELSE USE (lcSource) ALIAS (lcAlias) ; IN 0 NOUPDATE SHARED ENDIF iTableCount = iTableCount+1 CATCH WHEN .T. ENDTRY ENDIF SET DATASESSION TO (loEvent.FrxSessionID) ENDIF ENDSCAN USE IN environCursors SELECT (lCurSel) IF iTableCount > 0 SET DATASESSION TO (liPrivateSession) ELSE SET DATASESSION TO (loEvent.DefaultSessionID) ENDIF *----------------------------------- * Display the GETEXPR dialog: *----------------------------------- GETEXPR TO lcNewExpr TYPE lcDataType DEFAULT lcDefaultExpr *----------------------------------- * Clean up and exit: *----------------------------------- SET DATASESSION TO (liPrivateSession) CLOSE DATA SET DATASESSION TO (loEvent.FrxSessionID) RETURN lcNewExpr ENDPROC PROTECTED PROCEDURE GetValue LPARAMETER lcValuePair LOCAL liPos, lcReturn lcReturn = "" IF NOT EMPTY(lcValuePair) liPos = AT("=",lcValuePair) IF EMPTY(liPos) RETURN "" ENDIF lcReturn =CHRTRAN(ALLTRIM(SUBSTR(lcValuePair,liPos+1)),["'],[]) ENDIF RETURN lcReturn ENDPROC ENDDEFINE |
See Also
Tasks
How to: Configure the Report Builder's Event HandlingHow to: Specify an Alternate Report Event Handler Table
Reference
Event Handler Registry Dialog Box (Report Builder)Report Builder Options Dialog Box (Report Builder)
Report Builder Event Handler Registry Table