XFRX
Developer’s guide
© 2007 Martin Haluza
EQEUS.COM
XFRX version: 12.3
Last update: 16:34, June 5, 2007
The latest version of this document is available at: http://www.eqeus.com.
Trademarks: Microsoft, Visual FoxPro, .NET, Visual C#, ASP.NET, Word, Excel and ActiveX are either trademarks or registered trademarks of Microsoft Corporation.
5.1 How XFRX handles different version of Visual FoxPro
5.2 Differences between XFRX for VFP 8.0 and XFRX for VFP 9.0
5.3 Distributing XFRX with other applications
5.4 Two versions of XFRXLIB.FLL
6.1 Running XFRX in VFP 5.0, 6.0, 7.0 and 8.0
6.3 Using THISFORM and THIS references
6.4 Displaying progress bar in VFP 8.0
6.5 Displaying progress bar in VFP 9.0
6.6 Canceling report generation in progress
6.9 Zipping the generated files
8.4 Appending generated output to existing PDF Documents
10 Flow layout document option
12 Generating OpenOffice documents (ODF)
13.1 HTML page size adjustment
14.3.1 Generating sheet per page
14.3.2 Generating sheet per start-each-group-on-a-new-page groups
14.5 Hiding the Excel sheet grid
14.6 Leaving the fields content in Excel cells
14.7 How to invoke the XLS output
14.9 How to achieve the best results
14.10 Numeric field picture format in Excel
15 Converting reports to plain text
15.4 Characters per inch setting
16.1 Converting reports to XFF files
16.2 Initializing the XFRX#DRAW class instance
16.3 Creating temporary XFF files
16.4 Converting XFF files to other output formats
16.5.1 Displaying printer properties dialog
16.5.2 Using custom printer settings when printing.
17 Drawing custom objects with XFRX#DRAW
17.1 Drawing custom objects to existing XFF files
17.2 Drawing custom objects during report generation process
17.2.2 Rectangle-bound scripts
17.3.1 XFF document navigation
17.3.5 Tooltips, hyperlinks and bookmarks
18.1 Setting up the XFRX previewer
18.1.1 Common methods and properties
18.1.2 Using frmMPPreviewer class
18.1.3 Using cntXFRXMultiPage class
18.2 Printing from the previewer
18.3 Exporting reports from the previewer
19 Implementing custom event hyperlinks (drilldown) in the XFRX previewer
19.1 Setting up custom event hyperlinks
19.2 Accessing the calling previewer
19.3 Drilldown solution example
20 Converting reports to pictures
21 Chaining listeners in VFP 9.0
22 Running XFRX in a web-based environment
23.2 Properties and methods common in XFRXListener and XFRXSession classes
XFRX is a tool for transforming Visual FoxPro reports to electronic formats. It can be incorporated into Visual FoxPro applications to provide the following functionality:
XFRX is a royalty-free product. It can be added to Visual FoxPro applications without any additional costs. Please read the License chapter for more details.
XFRX is available for Visual FoxPro 5.0, 6.0, 7.0, 8.0 and 9.0. XFRX contains its own report engine which is used in VFP 8.0 and earlier. In VFP 9.0, XFRX plugs into the new reporting architecture of the native report engine.
The differences between XFRX for VFP 5.0, 6.0, 7.0 and 8.0 and XFRX for VFP 9.0 are described in detail in this document.
Please note: To make the text easier to read, these differences are described as differences between VFP 8.0 and VFP 9.0. If VFP 8.0 is mentioned further in the text, it applies for VFP 5.0, 6.0 and 7.0 as well.
The basic architecture is described in the following schema:

FoxPro report – The FoxPro report definition, stored in .FRX, .FRT files
Report engine – The reporting engine that processes the report definition. XFRX for VFP 8.0 and earlier contains its own report engine. In VFP 9.0, XFRX plugs into the new reporting architecture and the native report engine is used.
Scripts – Methods or code snippets written in VFP. The scripts call methods of XFRX#DRAW class to “draw” to the generated document.
You can find more information about using scripts in Drawing custom objects with XFRX#DRAW chapter on page 45.
Custom object scripts – scripts linked to a rectangle object on a report. When the rectangle is being processed, the script is invoked instead of rendering the actual rectangle. The custom object scripts can alternatively be converted to pictures.
When these scripts are processed, the controlling table of the report is available, so these scripts are ideal for generating graphs or other data based graphics objects.
Page bound scripts – scripts invoked on each page, drawing either “above” of “below” the page content. These scripts are suited for watermarks.
Custom scripts – you can modify the generated reports, too. You can add text, graphics, new pages, hyperlinks, bookmarks, etc. You can even create new documents from scratch, bypassing the report engine altogether.
XFF File – an internal file that stores the generated reports. These files can be modified, stored to disk, previewed on screen, printed or converted to any of the target formats. You can find more information about XFF files in Using XFF files chapter on page 41.
XFRX#DRAW class – the class that wraps XFF files.
XFRX previewer – The XFF files can be
previewed in an advanced report previewer that comes with XFRX. The previewer can
be localized and allows for search the document and supports hyperlinks and
bookmarks.
You can find more information about using the previewer in XFRX previewer chapter on page 51.
Printer – XFRX is also able to print the
XFF files. Please find more information about printing in Printing XFF files chapter on page 43.
Evaluation version quick tip: For a quick preview of the capabilities of XFRX, unpack the whole zip archive to an empty directory and run DEMO.SCX.
XFRX consist of the following parts:
The installation is very easy: simply unpack the zip archive and make sure the files are accessible from VFP (they can either be placed in a local directory or the path can be set via the SET PATH command).
XFRX for VFP 8 contains its own report engine that mimics the behavior of the native Visual FoxPro report engine.
XFRX for VFP 9 is implemented as an XFRXListener class, a descendant of UtilityReportListener class (please see _REPORTLISTENER.VCX in FFC for more information about the basic report listener classes provided by FFC). The XFRXListener class complies with the object-assisted reporting standards introduced in VFP 9 and perfectly fits into the new open architecture. You can use it alone or in combination with other report listeners provided with the product or by third parties.
About 95% of XFRX is written in Visual FoxPro and, to make the deployment as easy as possible, all its source code (without the visual classes for the report previewer container) is in one PRG file, both for VFP 8.0 and VFP 9.0: XFRX.PRG. This PRG file is the same for all VFP versions.
If you purchase XFRX without source codes, you will be able to download XFRX.FXP compiled in the VFP version you are using.
If you purchase the source code, before you add XFRX.PRG into your project and compile it, you need to enable (uncomment) one of the #DEFINE commands at the beginning of XFRX.H, which determines the VFP version you are using.
Example: If XFRX is used in VFP 8.0, the beginning of XFRX.H would look
like this:
*#DEFINE VFP5
*#DEFINE VFP6
#DEFINE VFP8
*#DEFINE VFP9
(Please note there is not a constant for VFP 7.0. If you are using VFP 7.0, uncomment the VFP6 constant).
As written in the previous paragraph, XFRX for VFP 9.0 uses the native report engine, which results in the following advantages:
The best way to distribute XFRX is to include XFRX.FXP (or XFRX.PRG, if you purchased the source code option) into the target application’s exe (add it to your project, to the section where your PRGs are). This way, you won’t have to distribute this file and, more importantly, XFRX will be able to access the reports and other resource files (pictures, tables, etc.) built into the exe as well.
If you are using the XFRX previewer, add the appropriate files from the XFRXLIB directory to your project as well.
The support libraries (XFRXLIB.FLL, HNDLIB.DLL and ZLIB.DLL) cannot be included in the exe and need to be distributed along with the application. They need to be located either in the same directory where the main EXE is or in a directory defined in SET PATH command.
There are two versions of XFRXLIB.FLL available that you can use with XFRX. The reason of this is that the “normal” XFRXLIB.FLL version requires three other DLL libraries from Microsoft to be installed on the target computers: gdiplus.dll, msvcr71.dll and msvcp71.dll. If you try to use XFRX with XFRXLIB.FLL without these DLLs installed, SetParams method will return -6, “xfrxlib.fll cannot be loaded (it is missing or invalid)”.
All of these dll libraries can be downloaded from Eqeus or Microsoft website:
These libraries can be distributed with your application (they are also distributed with VFP 9.0), but sometimes you may not need the gdiplus features in XFRXLIB.FLL and it may be easier to use a no-gdi+ version of XFRXLIB.FLL. This library is located in the NOGDIP subdirectory in the evaluation as well as commercial version package.
The following table indicates features not available in the no-GDI+ version if XFRXLIB:
|
|
GDI+ version |
No-GDI+ version |
|
Exporting reports as pictures |
Yes |
No |
|
Printing |
Yes |
No |
|
Supporting BMP and JPG pictures in PDF |
Yes |
Yes |
|
Supporting other picture formats in PDF |
Yes |
No |
|
Converting report pictures to defined DPI |
Yes |
No |
|
Exporting contents of general fields in VFP 9 |
Yes |
No |
|
Exporting BMP and JPG pictures from general fields in VFP 8 |
Yes |
Yes |
|
Binary comparison of images to reduce the size of PDF documents |
Yes |
Yes |
When XFRX is run, it returns an instance of one of three classes, depending on a parameter passed. The available parameters are:
Important note: The evaluation version of XFRX cannot be included into VFP projects, it makes VFP crash. To avoid this please invoke XFRX via macro substitution:
loSession = EVALUATE("xfrx('XFRX#INIT')")
This way XFRX.APP does not get into the project and you will be able to compile your application without problems.
Please note: To make the text easier to read, the
differences between XFRX for VFP 5.0, 6.0, 7.0, 8.0 and XFRX for VFP 9.0 are
further in the text described as differences between VFP 8.0 and VFP 9.0. If
VFP 8.0 is mentioned, the described feature applies for VFP 5.0, 6.0 and 7.0 as
well.
Example 1:
This code merges two reports – report1 and report2 – into a single PDF document, output.pdf
use demoreps\invoices order customer
local loSession, lnRetval
loSession= xfrx("XFRX#INIT")
lnRetVal = loSession.SetParams("output.pdf",,,,,,"PDF")
If lnRetVal = 0
loSession.ProcessReport("report1")
loSession.ProcessReport("report2")
loSession.finalize()
Else
? lnRetVal
Endif
In VFP 9.0, the standard object-assisted mode is used to run XFRX:
Note: Even in VFP 9.0, you can initialize the XFRXSession class via “XFRX#INIT” parameter and use the XFRX’s own engine, rather than the native one.
The following examples all do exactly the same (and they also do exactly the same as the example 1 above), showing various ways of calling XFRX in VFP 9.0:
Example 2:
use demoreps\invoices order customer
local loSession, lnRetval
loxfrx = XFRX("XFRX#LISTENER")
lnRetval = loxfrx.SetParams("output.pdf",,,,,,"PDF")
IF lnRetval = 0
REPORT FORM report1 OBJECT loxfrx NOPAGEEJECT
REPORT FORM report2 OBJECT loxfrx
ELSE
? lnRetval
endif
Example 3:
use demoreps\invoices order customer
local loSession, lnRetval
loxfrx = XFRX("XFRX#LISTENER")
lnRetval = loxfrx.SetParams("output.pdf",,,,,,"PDF")
IF lnRetval = 0
REPORT FORM report1 OBJECT loxfrx NOPAGEEJECT
REPORT FORM report2 OBJECT loxfrx NOPAGEEJECT
Loxfrx.finalize()
ELSE
? lnRetval
endif
Example 4:
use demoreps\invoices order customer
local loSession, lnRetval
loxfrx = XFRX("XFRX#LISTENER")
loxfrx.targetType = "PDF"
loxfrx.targetFileName = "output.pdf"
lnRetval = loxfrx.SetParams()
IF lnRetval = 0
REPORT FORM report1 OBJECT loxfrx NOPAGEEJECT
REPORT FORM report2 OBJECT loxfrx
ELSE
? lnRetval
endif
Note: This paragraph applies to VFP 8.0 only. THISFORM and THIS references are handled properly by the native report engine in VFP 9.0.
XFRX supports using THISFORM and THIS in the expressions of the report fields. However, being normal VFP application, XFRX cannot access THISFORM and THIS objects directly. Instead, THISFORM object has to be explicitly sent to XFRX via setThisform() method, THIS needs to be sent via setThis() method. The use is very simple.
If you have THISFORM in your report, call xfrxSession.setThisform(THISFORM) before calling ProcessReport(). If you are using THIS, call xfrxSession.setThis(THIS).
XFRX provides a simple hook so that any progress bar tool could be used for displaying the progress during the document generation process. All you have to do is to create an object which contains updateProgress() method and pass it to XFRX. During the generation process, XFRX calls updateProgress() method either after each page or after each record is processed.
This is a simple example of displaying the generation progress in a wait window:
loSession=xfrx("XFRX#Init")
loProgress = createobject("progress")
lnRetVal = loSession.SetParams("document",,,,,,"PDF")
if lnRetVal = 0
loSession.setProgressObj(loProgress,2)
loSession.ProcessReport("myReport")
loSession.finalize()
endif
define class progress as custom
procedure updateProgress
lpara ta,tb, tc
wait window nowait "Page #:
"+allt(str(tb))+" Report #: "+allt(str(ta))+"
("+allt(str(tc))+"%)"
enddef
The progress
object is attached to XFRX with setProgressObj() method. This method takes two
parameteres - the first one is the progress object, the second defines the
information the updateProgress() will be getting. It can contain two values: 1
- only page number and report number will be provided in updateProgress()
method, or 2 - page number, report number and percentage progress within the
current report will be provided. Using the percentage progress information is
more accurate and more suitable for progress bar visualization, but to provide
this, XFRX has to calculate the number of records in the processed table,
which, sometimes, can be very time demanding. In this cases, 1 can be used not
to calculate the number of records.
The updateProgress method takes three parameteres: current report number,
current page number and actual percentage progress within the current report.
In VFP 9.0, the XFRXListener object can be chained together with another listener which would take care of the progress bar displaying. One of the possible ways to do this is to use the UpdateListener class, which is shipped with VFP 9.0, in FFC.
Example:
This sample code creates an instance of the UpdateListener class and chains it with XFRXListener:
loxfrx = XFRX("XFRX#LISTENER")
SET CLASSLIB TO (HOME()+"FFC\_reportlistener.vcx")
loUpdate = CREATEOBJECT("updatelistener")
loUpdate.thermFormCaption = "Report in progress ..."
loxfrx.successor = loUpdate
lnRetval = loxfrx.setparams("output.pdf",,,,,,"PDF")
IF lnRetval == 0
REPORT FORM (lcReportName) OBJECT loxfrx NOPAGEEJECT
loxfrx.finalize()
ELSE
? lnRetval
endif
Note: This paragraph applies both to VFP 9.0 and VFP 8.0
The report generation process in progress can be canceled by setting the global variable gnStopXFRX to 1. For example, you can, for example, use it this way:
ON KEY LABEL Ctrl+C gnStopXFRX = 1
Note: This paragraph applies to VFP 8 only. In VFP 9.0, please use the RANGE clause of the REPORT FORM command to achieve the same.
To define the page range, call setPageRange() method before calling calling ProcessReport(). There are two possible ways how to call the setPageRange() method:
loSession.setPageRange(5,10)
loSession.setPageRange("1,4,10-20,25")
Note: This paragraph applies both to VFP 80. and VFP 9.0
You can define the page size of the generated document. The user-defined page size will override the page size stored in the report. To define the user-defined page size, call setPaperSize() method with paper width and paper height as parameters:
setPaperSize(nUDPaperWidth, nUDPaperHeight)
The unit is Inch * 10000.
See also: HTML page size adjustment na stránce 31.