I.T. Discussion Community!
-Collapse +Expand
Paradox
Search Paradox Group:

Advanced
-Collapse +Expand Paradox To/From
To/FromCODEGuides
-Collapse +Expand Paradox Store
PRESTWOODSTORE

Prestwood eMagazine

April Edition
Subscribe now! It's Free!
Enter your email:

   ► KBDesktop Data...Paradox & Ob...P9 Book: Pow...   Print This     
  From the June 2015 Issue of Prestwood eMag
 
Paradox P9 Book: Power Programming:
Power: Chapter 12, Handling Reports
 
Posted 16 years ago on 3/22/2003 and updated 9/30/2009
Take Away:

Chapter 12, "Handling Reports" from Paradox 9 Power Programming by Mike Prestwood.

KB100205



A report is a tool for printing data to get an organized, formatted hard copy of your data. You can communicate data with presentation-quality reports. Paradox's built-in report writer is a high-quality tool that will suffice for the majority of your printouts. With the combination of reports and queries--and the ObjectPAL commands that enable you to use them--you can add sophisticated printing capabilities to your applications.

Using Reports in ObjectPAL

For manipulating reports, ObjectPAL offers the report object. The report object (or variable) is a handle to a report window. With a report variable, you can attach to an already opened report or you can open a report. After the handle is established, you can manipulate the report. If you browse the online help and explore the Form object type, Report type, and TableView object type, you will see that many methods and procedures are shared among them.

Opening a Report

The next bit of code demonstrates opening a report and setting the title of the report. To achieve a smooth opening of the report, note that WinStyleDefault + WinStyleHidden is used along with the show() method. Change working directories to Paradox's Samples directory and type lines 3--9 into the pushButton event of a button.

 1: ;Button :: pushButton
 2: method pushButton(var eventInfo Event)
 3: var
 4: r Report
 5: endVar
 6:
 7: r.open("Customer", WinStyleDefault + WinStyleHidden)
 8: r.setTitle("New report title")
 9: r.show() ;You can also use bringToTop().
10: endMethod

Printing Reports

The first step in learning how to handle reports with ObjectPAL is learning how to print an existing report. The next two examples demonstrate how to use the print() and open() report methods.

Suppose that you want to create two buttons on a form. The first button directly prints an existing report with no interaction from the user. The second button previews the report and prompts the user with the Print File dialog box.

Step By Step

Change your working directory to Paradox's Samples directory. Create a new form and place two buttons on it. Label the first button Print Report and the second Open then Print Report, as shown here:

Illustration 1

[Need Image Here]

Add lines 3--7 to the pushButton event of the Print Report button. Line 4 declares r to be a Report variable. In this case, r is a temporary variable, alive only for the duration of the method. This is important to note because, with display managers, the existence of the object (the report, in this case) does not close when the variable is destroyed. This is not true with all objects. For example, OLE and TCursor objects automatically close when the variable is destroyed. To optimize this form, you can combine these two declarations into a single declaration higher up in the containership path. In line 7, print() is used to print the report without first previewing it. You do not need to open the report first.

1: ;Button :: pushButton
2: method pushButton(var eventInfo Event)
3: var
4: r Report
5: endVar
6:
7: r.print("Customer")
8: endMethod

Add lines 3--8 to the pushButton event of the Open then Print Report button. Lines 7 and 8 on the second button use open() to open the report to preview it, and use print() to display the Print File dialog box.

1: ;Button :: pushButton
2: method pushButton(var eventInfo Event)
3: var
4: r Report
5: endVar
6:
7: r.open("Customer")
8: r.print()
9: endMethod

Check your syntax, save the form as REPORT1.FSL, run the form, and press the Open then Print Report button (see Figure 12-1).

Figure 1: The Open then Print Report button previews a report and displays the Print File dialog box

[Need Image Here]

Printing a Report Based on the Current Record

In general, reports deal only with a set of data. They step through the master table one record at a time and print the report information once for every record. Often, you need to print a report based on a subset of the table or even just a single record. There are several techniques for doing this in Paradox, including using a query and using ObjectPAL. Both are demonstrated in this section. The query technique takes two steps. First, execute a query. Then, print a report that is based on the answer table for the query. In the following example, you print a report based on only the current record.

Using a Query to Print a Report Based on the Current Record

Suppose that you want to print a report based on the current record. This example uses an embedded query to generate a table with a single record in it. It also demonstrates using a temporary table to control the report.

    Step By Step

    Create a query with all the fields checked based on ORDERS.DB and run it. This generates an ANSWER.DB table in your private directory, which is used in step 2.

    Change your working directory to Paradox's Samples directory and create a new form with the :PRIV:ANSWERS.DB, ORDERS.DB, and LINEITEM.DB tables in the data model.

    Link the :PRIV:ANSWERS.DB table to the Orders table in a 1:1 relationship.

    Link the Orders table to the Lineitem table in a 1:M relationship. Place a button on the form and label it Print Current Invoice. Note that you must initially create the :PRIV:ANSWER.DB table in order to link it.

    Add lines 3--19 to the pushButton event of the Print Current Invoice button. If you would rather view the report on the screen then print it, substitute r.open("ORDER") for line 19 below. Line 9 takes the value from the Order_No field and puts it in the s variable. Lines 10--16 make up the query; line 14 uses the s variable. Line 18 executes the query, and line 19 prints the report. Because the report is based on the table created by the query executed in line 19, it consists of only one record.

     1: ;Button :: pushButton
     2: method pushButton(var eventInfo Event)
     3: var
     4: r Report
     5: q Query
     6: s String
     7: endVar
     8:
     9: s = Order_No.value
    10: q = Query
    11: ANSWER: :PRIV:ANSWER.DB
    12:
    13: ORDERS.DB | Order No |
    14: | Check ~s |
    15:
    16: EndQuery
    17:
    18: executeQBE(q)
    19: r.print("ORDER") ;To see report, use r.open("ORDER") instead.
    20:
    endMethod

    Check your syntax, save the form as REPORT2.FSL, and run it. Move to the record that you want to print, and click the button.

    Fully Controlling a Report

    An alternate and perhaps easier technique to print the current record and maintain full control of a report is to use setGenFilter(), setMenu(), and wait(). setGenFilter() is used to filter the data down to the current invoice. setMenu() is used to keep the user from using other menu options. Finally, wait() is used so that the user doesn't stray from the report. Following is the code in full for you to study:

     1: ;btn :: pushButton
     2: method pushButton(var eventInfo Event)
     3: var
     4: r Report
     5: m Menu
     6: pop PopUpMenu
     7: dynFilter DynArray[] String
     8: endVar
     9:
    10: ;Load the report hidden.
    11: if not r.load(":INVOICE:INVOICE", WinStyleDefault + WinStyleHidden) then
    12: errorShow()
    13: return
    14: endIf
    15:
    16: ;Apply filter.
    17: dynFilter["Order No"] = String(Order_No.value)
    18: r.Order_No.setGenFilter(dynFilter)
    19: r.run()
    20:
    21: ;Give the user only a simple menu.
    22: pop.addText("&Print...", MenuEnabled, MenuFilePrint)
    23: pop.addText("&Printer Setup...", MenuEnabled, MenuFilePrinterSetup)
    24: pop.addText("&Close", MenuEnabled, MenuControlClose)
    25: m.addPopUp("&File", pop)
    26: r.setMenu(m)
    27:
    28: ;Show report and wait.
    29: r.maximize()
    30: r.wait()
    31:
    endMethod

    Caution: Line 17 in the above code works fine if the field's display attributes do not display the thousands separator. If you are having trouble adopting the above code to your application and cannot adjust the display attributes for the field, then strip out the thousands separator using ObjectPAL's format() method. For example, replace line 17 above with dynFilter["Order No"] = format("EI",Order_No.Value).

    Manipulating the Printer Before You Print

    ObjectPAL offers the capability to manipulate the printer before you print. The System type procedures printerGetInfo(), printerGetOptions(), printerSetCurrent(),printerSetOptions(), and enumPrinters(). For example, to get a listing of all the available printer setups, type lines 3--8 into the pushButton event of a button.

    1: ;btn :: pushButton
    2: method pushButton(var eventInfo Event)
    3: var
    4: arPrinters Array[] String
    5: endVar
    6:
    7: enumPrinters(arPrinters)
    8: arPrinters.view("Available Printer Setups")
    9: endMethod

    In addition to these System type procedures, the Report type print() method can control the printer.

    Using the reportPrintInfo Variable

    Another option for changing printer orientation is to set reportPrintInfo.orient = PrintLandscape. The following code fragment prints a report called Customer.rsl in landscape orientation.

    1: var
    2: r Report
    3: rpi ReportPrintInfo
    4: endVar
    5:
    6: rpi.orient = PrintLandscape
    7:
    8: rpi.name = "Customer"
    9: r.print( rpi )

    Paper size cannot be set this way, but the number of copies, page incrementing, and starting and ending pages can be set--if the printer driver supports these features. To find out whether your printer driver supports these features, select File | Printer Setup: . If the Printer Setup dialog box provides fields for you to specify the number of copies, starting and ending pages, or page incrementing, then your printer driver does handle these features; otherwise, it does not.

    You also can use this technique to change the master table of a report. The following code demonstrates this technique:

    1: var
    2: r Report
    3: rpi ReportPrintInfo
    4: endVar
    5:
    6: rpi.name = "MYREPORT"
    7:
    8: rpi.masterTable = "OTHER.DB"
    9: r.print(rpi)

    Using a Custom Toolbar with a Report

    Other than menus that use the standard menu constants, you can't use user-defined pull-down menus with a report, because reports don't have ObjectPAL. Specifically, reports don't have a menuAction event to which you can add code. There is, however, an alternative solution. Create a small toolbar-style dialog box, then open the dialog box over the report. That is, after you preview the report, open the dialog box. Because dialog boxes are always on top, the options that you put on the dialog box are always seen; therefore, they are always active. In the following example, you launch a report and a dialog box from a button.

    Adding a Toolbar to a Report

    Suppose that you want to launch a report and a dialog box from a button and have the dialog box control the report. Because the second form is a dialog box, it always stays on top of the report and gives the user easy control over the report.

      Step By Step

      Change your working directory to Paradox's Samples directory. Create a new form or open an existing one, and place a button on it. Label the button Go, set the title of the form to Report Form (see the illustration shown next), and save the form as REPORT3.FSL.

      Illustration 2

      [Image Here] 

      Add lines 3--19 to the pushButton event of the Go button on the main form and save it as REPORT3.FSL. Lines 4 and 5 on the Go button of the first form declare f as a Form variable and r as a Report variable. Lines 8--13 use a Report variable to either open the report or attach to it and bring it to the top if it's open. Line 12 specifically sets a title when the report is opened. This is done so that later you can attach a Report variable to the open report. Lines 15--19 either open the small dialog box form or attach a Form variable to it and move to the small dialog box.

       1: ;Button :: pushButton
      2: method pushButton(var eventInfo Event)
      3: var
      4: f Form
      5: r Report
      6: endVar
      7:
      8: if r.attach("Report 1") then
      9: r.bringToTop()
      10: else
      11: r.open("Customer")
      12: r.setTitle("Report 1")
      13: endIf
      14:
      15: if f.attach("Options") then
      16: f.moveTo()
      17: else
      18: f.open("REP-MENU")
      19: endIf
      20: endMethod

      Now, create another new form with four buttons on it, set the form title to Options, make it a dialog box, and save it as REP--MENU.FSL. Label the four buttons Design, Maximize, Go to page 5, and Close, as shown here:

      Illustration 3

      [Image Here]

      Open the REP--MENU.FSL form that you created in step 2 and add line 3 to its Var window of the Page object. Line 3 on the dialog box form declares r as a Report variable. The r Report variable is used throughout the dialog box to deal with the open report.

      1: ;Page :: Var
      2: Var
      3: r Report
      4: endVar

      Add lines 3--8 to the open event of the page object of the REP--MENU.FSL form.

      1: ;Page :: open
      2: method open(var eventInfo Event)
      3: if r.attach("Report 1") then
      4: r.bringToTop()
      5: else
      6: msgStop("Startup Error!",
      "This form is only for use with Report3.fsl")
      7: close()
      8: endIf
      9: endMethod

      Add line 3 to the pushButton event of the Design button on the REP--MENU.FSL form.

      1: ;Button :: pushButton
      2: method pushButton(var eventInfo Event)
      3: r.design()
      4: endMethod

      Add line 3 to the pushButton event of the Maximize button on the REP--MENU.FSL form.

      1: ;Button :: pushButton
      2: method pushButton(var eventInfo Event)
      3: r.maximize()
      4: endMethod

      Add line 3 to the pushButton event of the Move to page 5 button on the REP--MENU.FSL form.

      1: ;Button :: pushButton
      2: method pushButton(var eventInfo Event)
      3: r.moveToPage(5)
      4: endMethod

      Add lines 3 and 4 to the Close button on the REP--MENU.FSL form.

      1: ;Button :: pushButton
      2: method pushButton(var eventInfo Event)
      3: r.close()
      4: close()
      5: endMethod

      Add lines 3--5 and 12--16 to the depart event of the REP--MENU.FSL form.

       1: ;Form :: depart
      2: method depart(var eventInfo MoveEvent)
      3: var
      4: f Form
      5: endVar
      6:
      7: if eventInfo.isPreFilter() then
      8: ;This code executes for each object on the form
      9: else
      10: ;This code executes only for the form
      11: if f.attach("Report Form") then
      12: f.moveTo()
      13: else
      14: f.open("REPORT3")
      15: endIf
      16: endIf
      17: endMethod

      Check your syntax and save both forms. Close the REP--MENU form and run the first REPORT3.FSL form. Click the Go button. The report opens first, and the dialog box opens on top of it. You can select either the pull-down menus or the buttons from the dialog box form that you created. It doesn't matter whether the report or the dialog box is active (see Figure 12-2).

      Figure 2: REP--MENU.FSL and a report; the form always stays above the report because it's a dialog box

      [Image Here]

      Summary

      In this chapter, you learned about using reports and integrating them into your application. You learned how to run a report using the open() method, how to print a report with the print() method, and how to control a report with a query and with setGenFilter() and setMenu(). You also learned how to manipulate the printer before you print.

      More Info

      Article:  A 10 Minute Paradox Reports Quick Start

      Linked Message Board Threads

       Setting up a report to use a specific paper tray in Paradox Reports MB Topic (2 replies)
       Using the function in QBE & SQL MB Topic (3 replies)
       First page of report printed for day is garbage in Paradox Reports MB Topic (2 replies)
       fields in reports change on their own in Paradox Reports MB Topic (0 replies)
       Report Printing 2 duplicate rows in Paradox Reports MB Topic (1 replies)
       Exporting text file from report in Paradox to/from Other Data Sources MB Topic (1 replies)
       Insert image in report? in Paradox Reports MB Topic (1 replies)
       Supress line in reports in ObjectPAL MB Topic (5 replies)
       Passing Variables to Report in Paradox Reports MB Topic (4 replies)
       setRange/getRange in ObjectPAL MB Topic (5 replies)

      Comments

      0 Comments.
      Share a thought or comment...
       
      Write a Comment...
      ...
      Sign in...

      If you are a member, Sign In. Or, you can Create a Free account now.


      Anonymous Post (text-only, no HTML):

      Enter your name and security key.

      Your Name:
      Security key = P1222A1
      Enter key:
      KB Post Contributed By Mike Prestwood:

      Mike Prestwood is a drummer, an author, and creator of the PrestwoodBoards online community. He is the President & CEO of Prestwood IT Solutions. Prestwood IT provides Coding, Website, and Computer Tech services. Mike has authored 6 computer books and over 1,200 articles. As a drummer, he maintains play-drums.com and has authored 3 drum books. If you have a project you wish to discuss with Mike, you can send him a private message through his PrestwoodBoards home page or call him 9AM to 4PM PST at 916-726-5675 x205.

      Visit Profile

       KB Article #100205 Counter
      15147
      Since 4/2/2008
      Follow PrestwoodBoards on: 


      ©1995-2019 PrestwoodBoards  [Security & Privacy]
      Professional IT Services: Coding | Websites | Computer Tech