Using XFF files

XFRX is able to save the generated report to a binary file (XFF file). This file can be any time later used to:

  • Transform the stored report output to any of the target formats supported by XFRX (PDF, Word, HTML, Excel, TXT, etc.)
  • Print the stored report output
  • Preview the stored report output in the XFRX previewer

You can also modify the content of existing XFF files or create new XFF files from scratch, bypassing the reporting engine altogether.









Converting reports to XFF files

To create a XFF file, send "XFF" as the target parameter and the name of the file as the output name parameter of the SetParams().

Example: Creating a XFF file

VFP 8.0 approach
LOCAL m.loSession
m.loSession= xfrx("XFRX#INIT")
IF m.loSession.SetParams("output.xff",,,,,,"XFF") = 0
   m.loSession.ProcessReport("report")
   m.loSession.finalize()
ENDIF
VFP 9.0 approach
LOCAL m.loObj
m.loObj = xfrx("XFRX#LISTENER")
iF m.loObj.SetParams("output.xff",,,,,,"XFF") = 0
   REPORT FORM myreport OBJECT m.loObj
ENDIF

By default, .XFF extension (XFrx File) is added to the output file. The XFF file is internally stored as a normal DBF file, and because Memo fields are used for some of its columns, another file with the same name and .FPT extension is created.

Initializing the XFRX#DRAW class instance

(Please see the XFRX#DRAW class reference).

XFRX methods do not work with the XFF file directly, but always via the XFRX#DRAW class, which represents a wrapper around the XFF file. To create an instance of this class, call XFRX with “XFRX#DRAW” parameter. Then call openDocument(tcXFFFileName) to attach the XFRX#DRAW object to an existing XFF file:

LOCAL m.loXFF
m.loXFF = xfrx("XFRX#DRAW")
IF m.loXFF.openDocument("output.xff")
   
ELSE
   ? "XFF file cannot be open"
ENDIF

You can also create an empty XFF file by calling CreateDocument(tcXFFFileName) method.

Creating temporary XFF files

Sometimes you may want to create the XFF file just in memory, use it in your application (e.g. for report previewing and printing) and release it afterwards.

To do this, leave the XFF file name empty. In this case a temporary XFF file will be created and you will be able to access its XFRX#DRAW class instance. The way how to access the instance differs in VFP 8.0 and VFP 9.0.

VFP 8.0 approach

In VFP 8.0, the instance is returned by the Finalize() method of the XFRXSession class:

LOCAL m.loSession, m.loXFF
m.loSession= xfrx("XFRX#INIT")
IF m.loSession.SetParams(,,,,,,"XFF") = 0
   m.loSession.ProcessReport("report")
   m.loXFF = m.loSession.finalize()
ENDIF
*
* now the loXFF instance can be used as if the XFF file was opened
* with the openDocument method call
*

VFP 9.0 approach

In VFP 9.0, the instance is stored in oxfDocument property of the XFRXListener class:

LOCAL m.loObj, m.loXFF
m.loObj = xfrx("XFRX#LISTENER")
 
m.loObj.targetType = "XFF"
m.loObj.targetFileName = "" && output to a temporary file
 
REPORT FORM report OBJECT m.loObj
 
m.loXFF = m.loObj.oxfDocument

Converting XFF files to other output formats

To process the stored report, you need to initialize a XFRX#DRAW object, link it to the stored file and send it as a parameter of TransformReport method of XFRXListener class (in VFP 9.0) or XFRXSession class (in VFP 8.0) instance.

ExampleTransforming a stored XFF file to a PDF document.

VFP 8 approach:

LOCAL m.loSession, m.loXFF, m.lnRetVal
m.loSession= xfrx("XFRX#INIT")
m.loXFF = xfrx("XFRX#DRAW")
IF m.loXFF.openDocument("output.xff")
   m.lnRetVal = m.loSession.SetParams("output.pdf",,,,,,"PDF")
   IF m.lnRetVal = 0
      m.loSession.TransformReport(m.loXFF)
   ENDIF
ENDIF

VFP 9 approach:

LOCAL m.loSession, m.loXFF, m.lnRetVal
m.loObj = xfrx("XFRX#LISTENER")
m.loXFF = xfrx("XFRX#DRAW")
IF m.loXFF.openDocument("output.xff")
   m.lnRetVal = m.loObj.SetParams("output.pdf",,,,,,"PDF")
   IF m.lnRetVal = 0
      m.loObj.transformReport(m.loXFF)
   ENDIF
ENDIF

Printing XFF files

To send the content of a XFF file to a printer, call printDocument method of the XFRX#DRAW class instance. The name of the printer, job name and page range can be sent as parameters.

Please see the full parameter list and further details in the XFRX#DRAW class reference.

Example: Printing an XFF file

m.loXFF.printDocument(getprinter(),"xfrx – invoice", "1,2,4-10")

Displaying printer properties dialog

A printer properties dialog for a given printer can be invoked via _xfPrinterProperties function, returning the printer properties structure as a string.

This string can be saved as a user preference and sent to XFRX as the 5th parameter of PrintDocument method when printing. This functionality is similar to SYS(1037) introduced in VFP 9.0, with two differences/improvements:

  • The page setup and printer selection dialogs are skipped, which saves two clicks for the users and preempts confusions in case the printer has already been selected. (Very often, there is a printer selection box in the "main" form and a button to invoke printer properties).
  • This implementation works in earlier versions of Visual FoxPro, too (from VFP 5.0)

The _xfPrinterProperties method takes 3 parameters:

tcPrinterName - the printer name

tcTag2 - the DEVMODE structure to use as a default (if not specified, the default printer settings will be used)

tlShowProperties - if set to .T., the printer properties dialog box will show up. If OK button is clicked, the DEVMODE structure with selected printer settings will be returned. If Cancel button is clicked, an empty string will be returned.
If this parameter is set to .F., the dialog will not be displayed and the default printer setting will be returned.

by ref tnRetVal - Value indicate a problém (since XFRX 15.7)

  • -3 Printer name is not valid 
  • -2 Cannot  get DEVMODE size for specified printer
  • -1 Cannot  get DEVMODE for specified printer

Example:

SET PROCEDURE TO xfrx ADDITIVE && this is required as the function is implemented inside XFRX.FXP
LOCAL m.lnRetVal, m.lcPrinter, m.lcTag2
m.lcPrinter = GETPRINTER() && select a printer
m.lcTag2 = _xfPrinterProperties(m.lcPrinter, "", .F.) && do not show the dialog, return the default settings
m.lcTag2 = _xfPrinterProperties(m.lcPrinter, m.lcTag2, .T.) && show the dialog box now
m.lcTag2 = _xfPrinterProperties(m.lcPrinter, m.lcTag2, .T.,,@m.lnRetVal) && show the dialog box now

DO CASE
   CASE EMPTY(m.lcTag2) AND m.lnRetVal=0
        && CANCEL button was clicked
 
   CASE EMPTY(m.lcTag2) AND m.lnRetVal<0
        && Some error
   OTHERWISE
       && OK button was clicked
ENDCASE

Using custom printer settings when printing

The printer settings structure can be sent to PrintDocument method as the fifth parameter. If this parameter is empty, the default printer settings are used.

The printer settings structure can be retrieved by _xfPrinterProperties procedure (see the previous chapter), or, if the printer settings are saved with the report, it is stored in Tag2 field in the first record of the FRX file.

Example:

m.loXFF.printDocument(lcPrinter, "job name", 1, 3, lcTag2)

Changing custom printer settings

Since XFRX 17.0 you can use class _XFRX_DEVMODE_WRITER for changing some printer properties.

Example:

LOCAL m.loDEVMODE, m.lcTAG2, m.lcPrinter
m.lcPrinter=SET("PRINTER",2)
m.lcTAG2 = _xfPrinterProperties(m.lcPrinter, "", .F.) && do not show the dialog, return the default printer settings
m.loDEVMODE=CREATEOBJECT("_XFRX_DEVMODE_WRITER",m.lcTAG2) && read DEVMODE structure
m.loDEVMODE.SetField("DM_ORIENTATION",2) && set some field - orientation landscape
=m.loDEVMODE.Write() && recreate DEVMODE structure
m.lcTAG2 =m.loDEVMODE.cDEVMODE
m.loXFF.printDocument(m.lcPrinter, "job name", 1, 3, m.lcTAG2)

Previewing XFF files

Please see chapter Previewing XFF files  for more information about previewing XFF files in the advanced report previewer that comes with XFRX.