TechTricks
Technical answers from the trenches 
 
 
 
 

     
   
Creating Quick Reports
 
   
 Posted: 03 May 2001
 
   
 
 Applies to: Paradox 5.0 and later
 
   
 
Audience: Everyone
 
       
   

Introduction

If you've worked with interactive Paradox for any length of time, you've probably noticed that Table windows let you press Shift+F7 to print a quick (or "instant") report. Unfortunately, you can't do this in Form windows. This article shows how you can add this functionality to your Paradox applications using ObjectPAL.

The basic idea involves creating a template report, one containing a blank table frame. When the user triggers your code, it determines the table underlying the active object, adds that to your template report's datamodel, binds the table frame to that table, and then resizes the columns in the tableframe to fit accordingly, as shown in the following code:

method doQuickReport()
; -------------------------------------------------------------------------
; Creates a quick report for the table underlying the active object.
; -------------------------------------------------------------------------
var
   astrObjs  array[] String  ; holds objects in a table frame
   fmActive  Form            ; pointer to the calling form

   rptQuick  Report          ; the quick report itself.
   siCounter SmallInt        ; loop counter

   strValue,                 ; use to hold different values.
   strTitle  String          ; form's title

   uiTarget  uiObject        ; used to resize fields in table frame
endVar

   ; first, make sure the active object has a tablename property.
   try
      strValue = active.TableName
   onFail
      ; not data aware
      beep()
      return
   endTry

   if strValue = "" then ; (e.g. the object is not bound)
      beep()
      return
   endIf

   fmActive.attach()
   strTitle = fmActive.getTitle()

   ; update the template report
   if not rptQuick.load( ":priv:quickrpt", winStyleHidden ) then
      errorShow( "Can't Print Report",
                 "Use [>>] for details..." )
   else
      sleep()
      rptQuick.setTitle( strTitle + " Report" )
      rptQuick.txtRptTitle.Text = strTitle
      rptQuick.dmAddTable( strValue )
      rptQuick.tfMaster.tableName = strValue
      rptQuick.tfMaster.showAllColumns = TRUE

      ; reduce the columns to something to grow from
      for siCounter from 1 to rptQuick.tfMaster.nCols
         rptQuick.tfMaster.CurrentColumn = siCounter
         rptQuick.tfMaster.ColumnWidth = 360
      endFor

      ; tell each field object to fit width (and, yes,
      ; this looks like the only way to do it reliably.)

      uiTarget.attach( rptQuick, "tfMaster" )
      strValue = uiTarget.getProperty( "firstRow" )
      uiTarget.attach( rptQuick, strValue )
      uiTarget.enumObjectNames( astrObjs )
      for siCounter from 2 to astrObjs.size() ; skip record itself
         uiTarget.attach( rptQuick, astrObjs[ siCounter ] )
         uiTarget.fitWidth = TRUE;
      endFor

      rptQuick.DesignModified = FALSE

   endIf

endMethod

As you can probably tell, this particular example involves some design assumptions about the template report. Specifically:

  • The name of the tableframe is tfMaster.

  • A text box named txtRptTitle in the report header should display the name of the active form, plus the word "Report." For example, if your form's caption says "Customer Information," the caption of the quick report should be "Customer Information Report."

  • You want to print all fields and all records.

You can use this in a variety of ways. For example, you can create the initial set of reports in a database system by adding a little bit of code to save the report to a new name (provided you're not using Runtime, which cannot save changes to a report). You can also use this to create specific types of reports. For example, suppose you've carefully designed a template report ideal for printing to a file.

You can also use this approach while respecting any filters, ranges, or other environmental conditions (such a current index). Here's one way to do that:

method doQuickReport()
; -------------------------------------------------------------------------
; Creates a quick report for the table underlying the active object.
; -------------------------------------------------------------------------
var
   astrObjs  array[] String  ; holds objects in a table frame
   fmActive  Form            ; pointer to the calling form

   rptQuick  Report          ; the quick report itself.
   siCounter SmallInt        ; loop counter

   strValue,                 ; use to hold different values.
   strTitle  String          ; form's title

   tcActive  tCursor         ; current data view
   uiTarget  uiObject        ; used to resize fields in table frame
endVar

   ; first, make sure the active object has a tablename property.
   try
      tcActive.attach()
   onFail
      ; not data aware
      beep()
      return
   endTry

   ; save current view into a snapshot.
   strValue = ":priv:answer.db"
   tcActive.instantiateView( strValue )
   tcActive.close()

   fmActive.attach()
   strTitle = fmActive.getTitle()

   ; update the template report
   if not rptQuick.load( ":priv:quickrpt", winStyleHidden ) then
      errorShow( "Can't Print Report",
                 "Use [>>] for details..." )
   else
      sleep()
      rptQuick.setTitle( strTitle + " Report" )
      rptQuick.txtRptTitle.Text = strTitle
      rptQuick.dmAddTable( strValue )
      rptQuick.tfMaster.tableName = strValue
      rptQuick.tfMaster.showAllColumns = TRUE

      ; reduce the columns to something to grow from
      for siCounter from 1 to rptQuick.tfMaster.nCols
         rptQuick.tfMaster.CurrentColumn = siCounter
         rptQuick.tfMaster.ColumnWidth = 360
      endFor

      ; tell each field object to fit width (and, yes,
      ; this looks like the only way to do it reliably.)

      uiTarget.attach( rptQuick, "tfMaster" )
      strValue = uiTarget.getProperty( "firstRow" )
      uiTarget.attach( rptQuick, strValue )
      uiTarget.enumObjectNames( astrObjs )
      for siCounter from 2 to astrObjs.size() ; skip record itself
         uiTarget.attach( rptQuick, astrObjs[ siCounter ] )
         uiTarget.fitWidth = TRUE;
      endFor

      rptQuick.DesignModified = FALSE

   endIf

endMethod

As you can see, this version isn't vastly different from the previous one. The main changes focus on making a copy of the data being displayed before printing the report. Other approaches are certainly possible.

We're often told to work smarter. This technique shows one way you can do so using Paradox.

 

       

Top

Feedback About Paradox Delphi Assorted Web Stuff
 
 
Copyright © 2000-2004, techtricks.com; All Rights Reserved.
Acknowledgements, Disclaimers, Terms and Conditions.
Article last updated on 31 May 2003

 

Other Sites: Paradox, Delphi, Perl, Web Stuff, and More


 

[- End -]