JavaScript Editor js editor     Web development 

Main Page

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

  1. Create or edit a programmatic class library:

    MODIFY COMMAND c:\temp\mylibrary.prg

  2. 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.

  3. Save your changes.

В Copy Code
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")
         * All other expression builders will use the default:
         GETEXPR "Enter the label caption" TO cNewValue ;
            TYPE cDataType DEFAULT cDefaultExpr
      * Restore to the private builder datasession:
      SET DATASESSION TO (oEvent.FrxSessionID)
      RETURN cNewValue

To register your class as in the handler registry table

  1. Open the Report Builder Options dialog box:


  2. Click Explore Registry.

  3. Locate the record with Type = "G".

  4. Edit the record so that Class = "MyGetExpressionWrapper" and Library= "c:\temp\mylibrary.prg"

  5. Click OK to save your changes.

To test your changes

  1. Open a report or label layout in the designer.

  2. Double-click on a label control to display the Properties dialog box.

  3. Click on the ellipsis (…) next to the label caption text box to invoke the custom expression builder provided by your class.


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.

В Copy Code
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
        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])

        lcSource = EVL(lcSource,"")

        DO CASE
        CASE FILE(lcSource)
        CASE FILE(FORCEEXT(lcSource,"DBF"))
           lcSource = FORCEEXT(lcSource,"DBF")
        CASE FILE(JUSTFNAME(lcSource))
           lcSource = JUSTFNAME(lcSource)
           lcSource = FORCEEXT(JUSTFNAME(lcSource),"DBF")

        IF FILE(lcSource)
           lcAlias = EVL( lcAlias, "Cursor"+TRANSFORM(i))
           SET DATASESSION TO (liPrivateSession)
           IF NOT USED(lcAlias)
                 IF EMPTY(ALIAS())
                    USE (lcSource) ALIAS (lcAlias) ;
                       NOUPDATE SHARED
                    USE (lcSource) ALIAS (lcAlias) ;
                       IN 0 NOUPDATE SHARED
                 iTableCount = iTableCount+1
              CATCH WHEN .T.
           SET DATASESSION TO (loEvent.FrxSessionID)
     USE IN environCursors
     SELECT (lCurSel)
     IF iTableCount > 0
        SET DATASESSION TO (liPrivateSession)
        SET DATASESSION TO (loEvent.DefaultSessionID)

     * Display the GETEXPR dialog:
     GETEXPR TO lcNewExpr TYPE lcDataType DEFAULT lcDefaultExpr

     * Clean up and exit:
     SET DATASESSION TO (liPrivateSession)
     SET DATASESSION TO (loEvent.FrxSessionID)
     RETURN lcNewExpr

     LPARAMETER lcValuePair
     LOCAL liPos, lcReturn
     lcReturn = ""
     IF NOT EMPTY(lcValuePair)
        liPos = AT("=",lcValuePair)
        IF EMPTY(liPos)
           RETURN ""
        lcReturn =CHRTRAN(ALLTRIM(SUBSTR(lcValuePair,liPos+1)),["'],[])
     RETURN lcReturn


See Also

JavaScript Editor js editor     Web development