Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


When XFRX is run, it returns an instance of one of three classes, depending on a parameter passed. The available parameters are:

  1. “XFRX#INIT”
    Running XFRX with this parameter will return the XFRXSession class instance, which is the main class that controls the behavior of XFRX in VFP 5, 6, 7 and 8.
  2. “XFRX#LISTENER”
    This option is available in Visual FoxPro 9 only and returns an instance of XFRXListener class.
  3. “XFRX#DRAW”
    This option returns an instance of XFRX#DRAW class. This class is used for working with XFF files. Please see Initializing the XFRX#DRAW class instance chapter na stránce 44 for more information.
Warning
titleImportant 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:

Code Block
languagevb
linenumberstrue
LOCAL m.loSession
m.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.


Table of Contents
maxLevel2


 

  Running XFRX in VFP 5.0, 6.0, 7.0 and 8.0

Info
titlePlease 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.

  1. Call XFRX with "XFRX#INIT" as a parameter to obtain the XFRXSession object:

    Code Block
    languagetext
    firstline1
    linenumberstrue
    LOCAL m.loSession
    m.loSession=XFRX("XFRX#INIT")


  2. Call SetParams method to set the document generation parameters. (Please see page 80 for details and full parameter list).
  3. If SetParams return 0 (zero), call ProcessReport method for each report to process. (Please see page 91 for details and full parameter list).
  4. After all reports are processed, call Finalize method to finish the document generation process.
  5. 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
languagevb
linenumberstrue
USE demoreps\invoices ORDER customer
LOCAL m.loSession, m.lnRetval
m.loSession= xfrx("XFRX#INIT")
m.lnRetVal = m.loSession.SetParams("output.pdf",,,,,,"PDF")
IF m.lnRetVal = 0
   m.loSession.ProcessReport("report1")
   m.loSession.ProcessReport("report2")            
   m.loSession.finalize()
ELSE
   ? m.lnRetVal
ENDIF

Running XFRX in VFP 9.0

In VFP 9.0, the standard object-assisted mode is used to run XFRX:

  1. Call XFRX.APP with "XFRX#INIT" as a parameter to obtain the XFRXListener object:

    Code Block
    languagetext
    loListener=XFRX("XFRX#LISTENER")


  2. Now there are two options you can choose from:
    1. 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).
    2. 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).
  3. 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.
  4. 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.

 

Info
titleNote

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
languagevb
linenumberstrue
USE demoreps\invoices ORDER customer
LOCAL m.loSession, m.lnRetval
m.loSession = XFRX("XFRX#LISTENER")
m.lnRetval = loSession.SetParams("output.pdf",,,,,,"PDF")
IF m.lnRetval = 0
   REPORT FORM report1 OBJECT m.loSession NOPAGEEJECT
   REPORT FORM report2 OBJECT m.loSession
ELSE
   ? m.lnRetval
ENDIF
Example 3
Code Block
languagevb
linenumberstrue
USE demoreps\invoices ORDER customer
LOCAL m.loSession, m.lnRetval
m.loSession = XFRX("XFRX#LISTENER")
m.lnRetval = m.loSession.SetParams("output.pdf",,,,,,"PDF")
IF m.lnRetval = 0
   REPORT FORM report1 OBJECT m.loSession NOPAGEEJECT
   REPORT FORM report2 OBJECT m.loSession NOPAGEEJECT
   m.loSession.finalize()
ELSE
   ? m.lnRetval
ENDIF
Example 4
Code Block
linenumberstrue
USE demoreps\invoices ORDER customer
LOCAL m.loSession, m.lnRetval
m.loSession = XFRX("XFRX#LISTENER")
m.loSession.targetType = "PDF"
m.loSession.targetFileName = "output.pdf"
m.lnRetval = m.loSession.SetParams()
IF m.lnRetval = 0
   REPORT FORM report1 OBJECT m.loSession NOPAGEEJECT
   REPORT FORM report2 OBJECT m.loSession
ELSE
   ? m.lnRetval
ENDIF

Using THISFORM and THIS references

Info
titleNote

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

GDI+ 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 see Guide 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, see Changes in Functionality for the Current Release VFP 9.0 help topic for more information. 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.

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

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
languagevb
linenumberstrue
LOCAL m.loSession, m.loProgress, m.lnRetVal
m.loSession=xfrx("XFRX#Init")
m.loProgress = CREATEOBJECT("progress")
m.lnRetVal = m.loSession.SetParams("document",,,,,,"PDF")
IF m.lnRetVal = 0
   m.loSession.setProgressObj(loProgress,2)
   m.loSession.ProcessReport("myReport")
   m.loSession.finalize()
ENDIF

DEFINE CLASS progress AS CUSTOM
   PROCEDURE updateProgress
      LPARAM m.ta, m.tb, m.tc
      WAIT WINDOW NOWAIT "Page #: "+allt(str(m.tb))+" Report #: "+allt(str(m.ta))+" ("+allt(str(m.tc))+"%)"
   ENDPROC
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
languagevb
linenumberstrue
LOCAL m.loSession, m.loUpdate
m.loSession = XFRX("XFRX#LISTENER")
SET CLASSLIB TO (HOME()+"FFC\_reportlistener.vcx")
m.loUpdate = CREATEOBJECT("updatelistener")
m.loUpdate.thermFormCaption = "Report in progress ..."
m.loSession.successor = m.loUpdate
m.lnRetval = m.loSession.setparams("output.pdf",,,,,,"PDF")
IF lnRetval == 0
   REPORT FORM (m.lcReportName) OBJECT loSession NOPAGEEJECT
   m.loSession.finalize()
ELSE
   ? m.lnRetval
ENDIF

Canceling report generation in progress

Info
titleNote

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
    m.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
    m.loSession.setPageRange("1,4,10-20,25")


User-defined page size

Info
titleNote

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.

Zipping the generated files

Info
titleNote

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
m.loSession.SetParams("invoices.pdf",,.T.,,,,"PDF","archive.zip", .t., .t.)

 

Old multiline behavior

 XFRX 15.0.3 fixes a bug with a wrong multiline height calculation - the object height does not equal with object height in VFP native preview. if you need the previous multiline height calculation set the lOldMultiLineBehavior property to true.

Code Block
m.loSession.lOldMultiLineBehavior = .T.

 

XFRX#INIT and multiband support

If you have a report with multiple detail bands and you need to run it in the pre-VFP9 calling syntax (eg. you need export a report in your dll application), set lMultiDetailBehavior property on. This feature is experimental. 

Info

This property is obsolete since XFRX 17.0. XFRX 17.0 support multiple detail bands.


Code Block
m.loSession.MultiDetailBehavior = .T.
 


XFRX#LISTENER and PREVIEW (XFRX 15.3)

Supports for PREVIEW clause for XFRX#LISTENER in REPORT command.
Simply way: 

 

Code Block
linenumberstrue
LOCAL m.loSession, m.lnRetVal
SET CLASSLIB TO (HOME()+"ffc\_reportlistener") ADDITIVE 
SET CLASSLIB TO xfrxlib\xfrxlib ADDITIVE 
 
m.loSession=EVALUATE([XFRX("XFRX#LISTENER")])
m.lnRetVal = m.loSession.SetParams(,,   ,,,,"PREVIEWFRM")
IF m.lnRetVal = 0
   REPORT FORM (lcPath+"_reports\test") OBJECT m.loSession PREVIEW
ELSE
   ?m.loSession.ErrorMessage(m.lnRetVal)   
ENDIF


 Creates form previewer:

Code Block
linenumberstrue
LOCAL m.loSession, m.lnRetVal
SET CLASSLIB TO (HOME()+"ffc\_reportlistener") ADDITIVE 
SET CLASSLIB TO xfrxlib\xfrxlib ADDITIVE 

m.loSession=EVALUATE([XFRX("XFRX#LISTENER")])

m.lnRetVal = m.loSession.SetParams(,,   ,,,,"PREVIEWFRM")
IF m.lnRetVal = 0
   m.loSession.oPreviewFRM = CREATEOBJECT("frmMPPreviewer")
   m.loSession.oPreviewFRM.WindowType=0 && or another settings

   REPORT FORM (lcPath+"_reports\test") object m.loSession PREVIEW
ELSE
   ?m.loSession.ErrorMessage(m.lnRetVal)   
ENDIF 

 

Running XFRX in MTDLL 

Please, read informations about  PROGCACHE key in  "Special Terms for Configuration Files"  Visual FoxPro Help.