3.1 Running XFRX in VFP 5.0, 6.0, 7.0 and 8.0
Info | ||
---|---|---|
| ||
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. |
Call XFRX with "XFRX#INIT" as a parameter to obtain the XFRXSession object:
Code Block language text loSession=XFRX("XFRX#INIT")
- Call SetParams method to set the document generation parameters. (Please see page 80 for details and full parameter list).
- If SetParams return 0 (zero), call ProcessReport method for each report to process. (Please see page 91 for details and full parameter list).
- After all reports are processed, call Finalize method to finish the document generation process.
- You can also call ResetPageNo() method if you need to reset the page number in between reports.
Example 1
This code merges two reports – report1 and report2 – into a single PDF document, output.pdf
Code Block | ||||
---|---|---|---|---|
| ||||
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 |
Running XFRX in VFP 9.0In VFP 9.0, the standard object-assisted mode is used to run XFRX:
Call XFRX.APP with "XFRX#INIT" as a parameter to obtain the XFRXListener object:
Code Block language text
loListener=XFRX("XFRX#LISTENER")
- Now there are two options you can choose from:
- Call loListener’s SetParams method that has exactly the same parameters and return values as the one in XFRXSession class. (Please see page 80 for details and full parameter list).
- Or, you can fill in individual properties of loListener and run SetParams method without any parameters to make sure you can proceed to the next step. (Please see page 90 for full list of properties available).
- Call the native REPORT FORM command with the new OBJECT clause for each report to process. If more reports are merged, include NOPAGEEJECT clause with each REPORT FORM call but the last one.
- Alternatively, you can leave the NOPAGEEJECT clause in the last REPORT FORM command as well (which may be useful is some scenarios) and call loListener.finalize() to finish the document generation.
Call XFRX.APP with "XFRX#INIT" as a parameter to obtain the XFRXListener object:
Code Block | ||
---|---|---|
| ||
loListener=XFRX("XFRX#LISTENER") |
- Call loListener’s SetParams method that has exactly the same parameters and return values as the one in XFRXSession class. (Please see page 80 for details and full parameter list).
- Or, you can fill in individual properties of loListener and run SetParams method without any parameters to make sure you can proceed to the next step. (Please see page 90 for full list of properties available).
Info | ||
---|---|---|
| ||
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
Code Block | |
---|---|
|
| |||
USE demoreps\invoices order customer
local loSession, lnRetval
loxSession = XFRX("XFRX#LISTENER")
lnRetval = loSession.SetParams("output.pdf",,,,,,"PDF")
IF lnRetval = 0
REPORT FORM report1 OBJECT loSession NOPAGEEJECT
REPORT FORM report2 OBJECT loSession
ELSE
? lnRetval
ENDIF |
Example 3
Code Block |
---|
use demoreps\invoices order customer
local loSession, lnRetval
loSession = XFRX("XFRX#LISTENER")
lnRetval = loSession.SetParams("output.pdf",,,,,,"PDF")
IF lnRetval = 0
REPORT FORM report1 OBJECT loSession NOPAGEEJECT
REPORT FORM report2 OBJECT loSession NOPAGEEJECT
Loxfrx.finalize()
ELSE
? lnRetval
endif |
Example 4
Code Block |
---|
use demoreps\invoices order customer
local loSession, lnRetval
loSession = XFRX("XFRX#LISTENER")
loSession.targetType = "PDF"
loSession.targetFileName = "output.pdf"
lnRetval = loSession.SetParams()
IF lnRetval = 0
REPORT FORM report1 OBJECT loSession NOPAGEEJECT
REPORT FORM report2 OBJECT loSession
ELSE
? lnRetval
endif |
Using THISFORM and THIS references
Info | ||
---|---|---|
| ||
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 THISFORM and THIS in the report field expressions. However, being a 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. If you have THISFORM in your report, call xfrxSession.setThisform(THISFORM) before calling ProcessReport(). If you are using THIS, call xfrxSession.setThis(THIS).
3.4GDI+ compatible word wrapping algorithm
Since the introduction of VFP 9.0 we are experiencing layout compatibility issues between the old reporting engine (pre-VFP 9.0) and the new reporting engine (VFP 9.0). [Please seeGuide to Reporting Improvements VFP 9.0 help topic for more information.]
With XFRX we are experiencing a similar problem - while the pre-VFP 9.0 report engine inside XFRX is using GDI for wordwrapping and layout calculation, the VFP 9.0 report that is used in XFRX for VFP 9.0 is using GDI+. Moreover, XFRX is using GDI+ for printing, output to pictures and previewing. The main difference between using GDI and GDI+ is text width. Each text element is slightly wider with GDI+, which can result in element content being cut, earlier wrapping longer stretched fields. Here is a summary:
XFRX ver. 12.3 and earlier
VFP 9.0
VFP 8.0 and earlier
Output to PDF and other output formats
GDI
GDI
Report engine
GDI+
GDI
Report previewer
GDI+
GDI+
Printing out of XFRX
GDI+
GDI+
Although converting everything to GDI+ would ease the complexity, it would bring another problem - "old" reports might need to be modified. So, instead, the latest XFRX version now contains both GDI and GDI+ wordwrapping algorithms and you can choose which one is going to be used. By default GDI+ is used in VFP 9.0 in the listener mode and GDI is used in VFP 8.0 earlier. There is probably no reason to switch to GDI in VFP 9.0 but it might sometimes be useful to switch to GDI+ as printing and previewing is still in GDI+:
XFRX ver. 12.4 with wordwrapping set to GDI+
VFP 9.0
VFP 8.0 and earlier
Output to PDF and other output formats
GDI+
GDI+
Report engine
GDI+
GDI+
Report previewer
GDI+
GDI+
Printing out of XFRX
GDI+
GDI+
XFRX ver. 12.4 with wordwrapping set to GDI
VFP 9.0
VFP 8.0 and earlier
Output to PDF and other output formats
GDI
GDI
Report engine
GDI+
GDI
Report previewer
GDI+
GDI+
Printing out of XFRX
GDI+
GDI+
To set the wordwrapping algorithm manually then, before running your reports, create a public or private variable _xfrx_WordWrapAlgorithm and set it to 1 for GDI mode and 2 for GDI+ mode.
3.5 XFRX ver. 12.3 and earlier | ||
VFP 9.0 | VFP 8.0 and earlier | |
Output to PDF and other output formats | GDI | GDI |
Report engine | GDI+ | GDI |
Report previewer | GDI+ | GDI+ |
Printing out of XFRX | GDI+ | GDI+ |
XFRX ver. 12.4 with wordwrapping set to GDI+ | ||
VFP 9.0 | VFP 8.0 and earlier | |
Output to PDF and other output formats | GDI+ | GDI+ |
Report engine | GDI+ | GDI+ |
Report previewer | GDI+ | GDI+ |
Printing out of XFRX | GDI+ | GDI+ |
XFRX ver. 12.4 with wordwrapping set to GDI | ||
VFP 9.0 | VFP 8.0 and earlier | |
Output to PDF and other output formats | GDI | GDI |
Report engine | GDI+ | GDI |
Report previewer | GDI+ | GDI+ |
Printing out of XFRX | GDI+ | GDI+ |
Text output trimming
In VFP 9.0 the trim mode is controlled by the "Trim mode for character expressions" setting on the "Format" tab in the "Field Properties" form.
In pre-VFP 9.0 version the trimming is controlled by a special string in fields comment: #UR TRIM=, followed by the trim mode code:
Code
Description
0
Default trimming in pre-VFP 9.0 versions - trim to nearest word
1
Trim to nearest character
2
Trim to nearest word
3
Trim to nearest character, append ellipsis
4
Trim to nearest word, append ellipsis
5
Show inner path as ellipsis
Example: #UR TRIM=3 wraps to the nearest character and appends ellipsis
3.6 In pre-VFP 9.0 version the trimming is controlled by a special string in fields comment: #UR TRIM=, followed by the trim mode code:
Code | Description |
0 | Default trimming in pre-VFP 9.0 versions - trim to nearest word |
1 | Trim to nearest character |
2 | Trim to nearest word |
3 | Trim to nearest character, append ellipsis |
4 | Trim to nearest word, append ellipsis |
5 | Show inner path as ellipsis |
Displaying progress bar in VFP 8.0
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:
Code Block |
---|
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.
Displaying progress bar in VFP 9.0
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:
Code Block |
---|
LOCAL loSession, loUpdate
loSession = XFRX("XFRX#LISTENER")
SET CLASSLIB TO (HOME()+"FFC\_reportlistener.vcx")
loUpdate = CREATEOBJECT("updatelistener")
loUpdate.thermFormCaption = "Report in progress ..."
loSession.successor = loUpdate
lnRetval = loSession.setparams("output.pdf",,,,,,"PDF")
IF lnRetval == 0
REPORT FORM (lcReportName) OBJECT loSession NOPAGEEJECT
loSession.finalize()
ELSE
? lnRetval
endif |
Canceling report generation in progress
Info | ||
---|---|---|
| ||
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:
Code Block |
---|
ON KEY LABEL Ctrl+C gnStopXFRX = 1 |
Printing page ranges
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:
setPageRange(tnFrom, tnTo)
tnFrom and tnTo define the from-to range. If tnTo is empty, the total number of pages is used
Example:
Code Block loSession.setPageRange(5,10)
- setPageRange(tcRange)
tcRange is a string, which can contain page numbers and page ranges delimited by commas, the page range is defined as "from-to".
Example:
Code Block loSession.setPageRange("1,4,10-20,25")
3.10 setPageRange(tnFrom, tnTo)
tnFrom and tnTo define the from-to range. If tnTo is empty, the total number of pages is used
Example:
Code Block |
---|
loSession.setPageRange(5,10) |
tcRange is a string, which can contain page numbers and page ranges delimited by commas, the page range is defined as "from-to".
Example:
Code Block |
---|
loSession.setPageRange("1,4,10-20,25") |
User-defined page size
Info | ||
---|---|---|
| ||
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:
Code Block |
---|
setPaperSize(nUDPaperWidth, nUDPaperHeight) |
The unit is Inch * 10000.
See also: HTML page size adjustment na stránce 34.
3.11Zipping the generated files
Info | ||
---|---|---|
| ||
This paragraph applies both to VFP 8.0 and VFP 9.0 |
The generated file can be automatically zipped. This feature is controlled by the last three parameters of SetParams() method of XFRXSession and XFRXListener classes (see the reference na stránce 80) or, with an equivalent behavior, by the three parameters of ZipDocument() method of XFRXListener class (reference na stránce 90).
Example:
With the following SetParams parameters, XFRX first creates "invoices.pdf", then creates "archive.zip" (if it doesn't exist) and adds "invoices.pdf" into the archive. Then the original "invoices.pdf" will be deleted:
Code Block |
---|
loSession.SetParams("invoices.pdf",,.T.,,,,"PDF","archive.zip", .t., .t.) |
Session