XFRX

Developer’s guide

 

© 2005 Martin Haluza

EQEUS.COM

 

 

 

 

 

 

 

XFRX version: 10.2

Document version: 1.2

Last update:  12:05, April 20, 2005


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.

1         Contents

 

1      Contents. 2

2      What’s new in this document. 5

3      Introduction.. 6

4      Installation.. 7

4.1       How XFRX handles different version of Visual FoxPro. 7

4.2       Differences between XFRX for VFP 8.0 and XFRX for VFP 9.0.. 8

4.3       Distributing XFRX with other applications. 8

5      Running XFRX.. 9

5.1       Running XFRX in VFP 5.0, 6.0, 7.0 and 8.0.. 9

5.2       Running XFRX in VFP 9.0.. 10

5.3       Using THISFORM and THIS references. 11

5.4       Displaying progress bar in VFP 8.. 12

5.5       Displaying progress bar in VFP 9. 12

5.6       Canceling report generation in progress. 13

5.7       Printing page ranges. 13

5.8       User-defined page size. 13

5.9       Zipping the generated files. 14

6      Interactive features. 15

6.1       Hyperlinks. 15

6.2       Bookmarks. 16

6.3       Document properties. 17

7      PDF specific features. 18

7.1       PDF Encryption.. 18

7.2       PDF Font Embedding. 18

7.3       Object rotation.. 19

7.4       Appending generated output to existing PDF Documents. 19

8      Word specific features. 20

8.1       Password protection.. 20

8.2      Word document splitting. 20

9      Flow layout Word document option.. 21

9.1       Running the conversion.. 21

9.2       How it works. 21

9.3       Page headers and footers. 22

9.4       Deficiencies. 22

10        HTML specific features. 24

10.1     HTML page size adjustment. 24

11     Excel specific features. 25

11.1      General notes. 25

11.2     How it works. 25

11.3     Handling page breaks. 25

11.3.1       Generating sheet per page. 25

11.3.2      Generating sheet per start-each-group-on-a-new-page groups. 26

11.4     Defining sheet names. 26

11.5      Hiding the Excel sheet grid. 26

11.6     Leaving the fields content in Excel cells. 26

11.7      How to invoke the XLS output. 26

11.8     XLS cells adjustment. 27

11.9     How to achieve the best results. 27

11.10       Numeric field picture format in Excel 29

12    Converting reports to plain text. 31

12.1     Limitations. 31

12.2     How it works. 31

12.3     Horizontal lines. 32

12.4     Characters per inch setting. 32

13    Using XFF files. 34

13.1     Creating XFF files. 34

13.2     Initializing the XFFWriter class instance. 34

13.3     Creating temporary XFF files. 35

13.4     Converting XFF files to other output formats. 35

13.5     Printing XFF files. 36

13.6     Previewing XFF files. 36

14    XFRX previewer. 37

14.1     Adding the previewer container to a form... 37

14.2     Previewing XFF files. 37

14.2.1      VFP 8.0 approach.. 37

14.2.2      VFP 9.0 Approach.. 38

14.3     Printing from the previewer. 39

14.4     Previewer localization.. 39

15    Converting reports to pictures. 41

16    Chaining listeners in VFP 9. 42

17    Running XFRX in a web-based environment. 43

18        Reference. 44

18.1     XFRX Output Target Types. 44

18.2     Methods common in XFRXListener and XFRXSession classes. 45

18.3     XFRXListener class. 52

18.4     XFRXSession class. 53

18.5     XFFWriter class. 54

18.6     XFCont class. 56

19    XFRX License. 57

20       Frequently asked questions. 58

2         What’s new in this document

 

Date

XFRX version

Document modifications

March 28, 2005

10.2

New chapters:

Defining sheet names in XLS documents (page 26)

Hiding the Excel sheet grid (page 26)

Leaving the fields content in Excel cells (page 26)

Printing XFF files, chapter Printing XFF files (page 36)

 

Updated chapters:

Handling page breaks in XLS output (page 25)

Using XFF files (page 34)

XFRX previewer (page 37)

XFFWriter class reference  (page 54)

 

December 29, 2004

10.1

New chapters:

Appending generated output to existing PDF Documents on page 19.

3         Introduction

XFRX is a tool for transforming Visual Foxpro reports to electronic formats. It can be incorporated into Visual Foxpro applications and used to provide end users with an option to:

XFRX is a royalty-free product, so it can be added to Visual Foxpro applications without any additional costs. Please read the License 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.

 

4         Installation

 

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

 

4.1        How XFRX handles different version of Visual FoxPro

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

 

4.2        Differences between XFRX for VFP 8.0 and XFRX for VFP 9.0

As written in the previous paragraph, XFRX for VFP 9.0 uses the native report engine, which results in the following advantages:

  1. The layout of the documents produced by XFRX for VFP 9.0 should generally be more exact as the same engine is used both for printing and for document generation.
  2. XFRX for VFP 9.0 is approximately twice as fast as XFRX for VFP 8.0.
  3. Variables declared as LOCAL are not visible in XFRX for VFP 8.0.
  4. XFRX for VFP 8.0 has some restrictions in handling the data environment. It is able to set up the data environment, open tables, setup relations and fire the data environment methods, but the data environment instance itself is not available. This restriction does not apply to VFP 9.0.
  5. XFRX for VFP 9.0 is able to display any content of general fields, including ActiveX components. XFRX for VFP 8.0 is able to extract just BMP and JPEG pictures from the general fields.
  6. XFRX for VFP 8.0 does not support multicolumn layout where records are laid from left to right (rather than from top to bottom). This limitation does not apply for VFP 9.0.

 

4.3        Distributing XFRX with other applications

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.

5         Running XFRX

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 XFFWriter class. This class is used for working with XFF files. Please see Initializing the XFFWriter class instance chapter on page 34 for more information.

 

Important note: The evaluation version of XFRX cannot be included into VFP projects, it makes VFP crash. The 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.

 

5.1        Running XFRX in VFP 5.0, 6.0, 7.0 and 8.0


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.

 

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

    loSession=XFRX("XFRX#INIT")

  2. Call SetParams methods to set the document generation parameters. (Please see page 45 for details and full parameter list).
  3. If SetParams return 0 (zero), call ProcessReport method for each report to process. (Please see page 53 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

 

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

 

5.2        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:

    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 45 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 52 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.

 

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

 

5.3        Using THISFORM and THIS references

Note: This paragraph applies to VFP 8 only. THISFORM and THIS references are handled properly by the native report engine in VFP 9.

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

5.4        Displaying progress bar in VFP 8

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.

 

5.5        Displaying progress bar in VFP 9

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

 

5.6        Canceling report generation in progress

Note: This paragraph applies both to VFP 9 and VFP 8.

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

 

5.7        Printing page ranges

Note: This paragraph applies to VFP 8 only. In VFP 9, 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")

 

5.8        User-defined page size

Note: This paragraph applies both to VFP 8 and VFP 9.

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 on page 24.

5.9        Zipping the generated files

Note: This paragraph applies both to VFP 8 and VFP 9.

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 on page 45) or, with an equivalent behavior, by the three parameters of ZipDocument() method of XFRXListener class (reference on page 52).

 

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:

 

loSession.SetParams("invoices.pdf",,.T.,,,,"PDF","archive.zip", .t., .t.)

6         Interactive features

The generated documents can include hyperlinks for faster navigation, PDF documents can also include bookmarks. The hyperlinks and bookmarks are controlled via Comment field of labels and fields.

 

Please note: In the beta version of VFP 9 there is a bug that makes it impossible to store anything into fields’ comment. Because XFRX uses the comment field to define hyperlinks and bookmarks, the “User data” field is now used for this purpose. In the final version, XFRX for VFP 9 will work both with comment and user data field.

6.1        Hyperlinks

Note: This paragraph applies both to VFP 9 and VFP 8.

The hyperlinks are controlled via Comment field of report labels or fields.
To create a link, you need a source field (the underlined text you will navigate from) and a target field (the place where you get when you click on a hyperlink).

o       Creating source fields

Enter the following text into the comment of the source field:

#UR A HREF=<destination name>

 

The destination name is an expression, which is evaluated at the time of report generation. You can navigate to other fields in the same document, or to any URL. The destination names of other fields in the same document has to be preceeded with #.

 

Examples:

#UR A HREF="#top"

Navigates to the beginning of the document. "top" is a reserved word. Do not name target fields are "top".

 

#UR A HREF="#custlist"

Navigates to the field whose destination name is "custlist".

 

#UR A HREF="#"+customer.id

Navigates to the field whose destination name is eval(customer.id)

 

#UR A HREF="http://www.eqeus.com"

Navigates to Eqeus.com homepage

 

o       Creating target fields


To add a destination name to a (target) field, add the following text into the comment:

#UR A NAME=<destination name>

 

Example:

#UR A NAME=customer.id

This field will be a target field for source fields with HREF="#"+customer.id

 

6.2        Bookmarks

Note: This paragraph applies both to VFP 9 and VFP 8.

Note 2: Bookmarks are currently supported in PDF and HTML documents


Bookmarks (document outline) serves as a "visual table of contents" to display the document structure. Users use this to interactively navigate in the document. To add a report field into the document outline simply put the following into the field's comment:

 

#UR OUTLINE=<outline_name>

 

The outline_name is an expression, which is evaluated at the time of report generation and the result is used as the bookmark item. If users click the bookmark, they will navigate to the corresponding report field.

 

Example:

In a report with a list of invoices grouped by customers, bookmarks containing the list of customer can be created by adding

 

#UR OUTLINE=invoices.customerName

 

into the comment of a customer name field (or any other field you want to navigate to, e.g. the first field on a page with the customer).

 

To enable bookmarks in the HTML output, call

 

loSession.SetOtherParams("PRINT_BOOKMARKS",.t.)

 

before calling loSession.ProcessReport()

With bookmarks enabled, XFRX will generate three HTML pages (three files): the main page defining the page frames, the bookmark page and the page with the report output.

6.3        Document properties

Note: This paragraph applies both to VFP 9 and VFP 8. The set… methods are implemented both in XFRXListener and XFRXSession classes.

The following methods can be called to set various document properties. When generating a Word document, all document properties have to be set before the first report is processed. When exporting to PDF, the properties have to be set before Finalize() method is called.

 

 

   loSession.setAuthor(<author>)

   loSession.setTitle(<title>)

   loSession.setSubject(<subject>)

   loSession.setKeywords(<keywords>)

 

 

   loSession.setCreator(<creator>)

   loSession.setProducer(<producer>)

 

 

   loSession.setComments(<comments>)

   loSession.setCategory(<category>)

   loSession.setManager(<manager>)

   loSession.setCompany(<company>)

 

7         PDF specific features

7.1        PDF Encryption

Note: This paragraph applies both to VFP 9 and VFP 8. The setPasswords method is implemented both in XFRXListener and XFRXSession classes.

PDF documents can be encrypted. To set the encryption on, call setPasswords method:

 

   loSession.setPasswords(tcOwnerPassword, tcUserPassword)

 

The user password can be empty. If the owner password is empty, a random string will be generated as the password.
The owner can do anything with the document. The user permissions can be set using the setPermission method:

 

   loSession.setPermissions(tlPrintDocument, ;

                             tlModifyDocument, ;

                                    tlCopyTextAndGraphics, ;

                                    tlAddOrModifyAnnotations)

The default values of the permissions is .F. (false).

 

7.2        PDF Font Embedding

Note: This paragraph applies both to VFP 9 and VFP 8. The method is implemented both in XFRXListener and XFRXSession classes.

XFRX supports both whole font and font subset embedding.

To embed all characters of all used fonts, call:

 

loSession.setEmbeddingType(2)

 

before running the report.

To embed only the characters used, call:

 

loSession.setEmbeddingType(3)

 

Embedding only subset of fonts (characters used in the document) significantly reduces the size of the generated file.

To select which font to embed (e.g. when you need just to embed the barcode font, or font that is not installed on the pc the document will be sent to), add “#UR INCLUDEFONT” (without the quotation marks) to the comments of a field that uses the font (in the report). Add “#UR INCLUDEFONT SUBSET” comment to include the font subset.

 

 

7.3        Object rotation

Note: This paragraph applies both to VFP 9 and VFP 8.

To rotate a text or a picture in PDF output, add “#UR ROTATE” (without the quotation marks) to the comment of the report field. The text or the picture will rotate anticlockwise by the entered angle, e.g. to print vertically, add: “#UR ROTATE 90”.

7.4        Appending generated output to existing PDF Documents

Note: This paragraph applies both to VFP 9 and VFP 8.

From version 10.1, XFRX is able to append the generated report to an existing PDF document. It is possible to append the report at the end of the document or at an arbitrary position within the document: with either inserting the new pages or replacing the pages in the existing PDF document.

In XFRX for VFP 8 this feature is controlled by a new parameter of SetParams(…) method: tuAppend. Please see the SetParams method reference on page 45 for more information about setting this parameter.

In XFRX for VFP 9 you can interchangeably use the new parameter of SetParams(…) method or AppendToFile property of the XFRXListener class.

Notes:

  1. It's not guaranteed that XFRX will be able to append to any PDF document. It works fine with PDF documents generated by XFRX and we've successfully tested PDFs from other sources, too, but the PDF specification allows for some internal structures that XFRX wouldn't be able to decode. (To be precise: XFRX doesn’t support linearized PDF documents and documents that use page tree structures).
  2. Because of the way the PDF file is constructed, the size of the PDF document never shrinks, even if the number of pages in the resulting PDF document is smaller than in the original one.

 

8         Word specific features

8.1        Password protection

Note: This paragraph applies both to VFP 9 and VFP 8. The setPasswords method is implemented both in XFRXListener and XFRXSession classes.

To add passwords to Word documents, call SetPasswords() method before calling ProcessReport():

 

loSession.setPasswords(tcReadPassword, tcWritePassword, tlRequirePassword)

 

You can omit either tcReadPassword or tcWritePassword. tlRequirePassword is optional (default value is .F.). If set to .T., Word will ask for the password even when the document is being opened first time after the generation (if tlNotOpenViewer parameter of SetParams method is set to .F.).

8.2        Word document splitting

Note: This paragraph applies to  VFP 8 only.

When the generated documents are very long, Word application has problem with the conversion - it takes very long to convert it. To avoid this problem, XFRX can split the generated document into more smaller documents. To set this up, call SplitDocument() method before calling ProcessReport():

 

loSession.SplitDocument(tnPages)

 

tnPagesp is the number of pages each of the resulting documents would have.

 

9         Flow layout Word document option

 

Note: This chapter links to several sample documents at our web site. If you are reading an electronic version of this document, simply click the hyperlinks to download them. If you are reading a printed version, here are the addresses:

http://www.eqeus.com/xfrxmanual/example1.doc

http://www.eqeus.com/xfrxmanual/example2.doc

http://www.eqeus.com/xfrxmanual/example3.doc

http://www.eqeus.com/xfrxmanual/example4.doc

 

There are two output options that produce Word documents – Absolute positioned layout (DOC) and Flow layout (FDOC). The generated documents often look the same, but the algorithms behind these options are completely different. The absolute positioned layout always looks like the original report, but is hard to edit and bigger in size. The flow layout may not always look exactly the same, but it is a 'real' Word document - easily editable, with styles, page headers and footers, paragraphs and tab stops, which is also shorter in size and faster to open.

This chapter describes the Flow layout (FDOC) output option – how it works and how it differs from the Absolute positioned layout (DOC).

9.1        Running the conversion

Flow layout Word option is implemented as a new target type, so simply send “FDOC” as the tcTarget parameter of the SetParams() method.

9.2         How it works

The logic is similar to the way how plain text option works. During the generation process, XFRX takes each section – one by one – and tries to split it to individual lines. Then each line is added to the output, respecting the vertical position of the line on the paper and horizontal positions of individual objects. Vertically misaligned objects are moved down to the closest baseline.

 

Example 1:

This report definition:

 

 

will be split to three lines and the resulting document will look like this:

(download example1.doc


As you can see all objects are aligned to the same baseline and the horizontal position is set by a tab stop (left, right or center, depending on the field’s alignment). If you add any graphics or pictures, these are added to the document and linked to the paragraph it starts at, so if you add contents above the graphics, it will move down along with the corresponding paragraph.

 

If XFRX cannot create distinct lines or if the text objects overlap one another, the overlapping text object is placed at the exact position as a textbox.

 

Example 2:

 >> converts to >>  

(download example2.doc)

 

9.3        Page headers and footers

Page headers and footers defined in the report are converted to page headers and footers in the Word document, so for example, if you add a line in the middle of a page, the page footer will not move to the next page header, but stay in place.

9.4         Deficiencies

Even though most reports are converted without problems, there are certain scenarios when the output wouldn’t look as expected. As stated above, all fields in one line are aligned to the same baseline. In some reports, this can cause a problem, for example:

 >> converts as >> 

(download example3.doc)

 

Not only is the “two” text too below, it is also printed over the “three” one (“three” is placed too high to be on a separate line, so it is converted as a textbox). In this case, you may want to tell the engine that “two” and “three” objects should always be treated as absolute positioned textboxes.

To do this, add “#UR POSITIONABSOLUTE” as a comment of these fields:

 

 

And the resulted Word document would be generated as:

 

(download example4.doc)

 

10   HTML specific features

10.1   HTML page size adjustment

Note: This paragraph applies both to VFP 9 and VFP 8. The ShrinkHeight method is implemented both in XFRXListener and XFRXSession class.

When generating HTML documents, XFRX makes the page a bit shorter by default (by 1.65 inches). This is to suppress the bottom of a page to wrap to a new page when printing from the Internet Explorer. Two lines are added to the printed page - at the top and bottom of the page - as header and footer. By calling ShrinkHeight() method, you can either suppress this behaviour by calling:

 

ShrinkHeight(0)

or set your own value by which the page will be shrinked. The unit is Inch * 10000, so to make the page shorter by 2 inches, call:

 

ShrinkHeight(20000)

 

The value sent by ShrinkHeight() method is applied to all output types, not just HTML.

 

See also: User-defined page size on page 13.

11   Excel specific features

11.1   General notes

The output to the Excel format is similar to the flow layout formats. The other formats use absolutely positioned textboxes for each report label or textbox, containing the generated text output. The XLS output, on the other hand, puts the generated text directly into the cells on the Excel sheet and sets the height of the rows and width of the columns to achieve the desired layout. Lines and rectangles, too, are added as cells' borders, rather than graphics over the sheet.

There are many advantages in this approach: the generated documents are smaller and much easier to be modified - all numeric fields can be used in calculations, it's no problem to add rows or columns, change cell attributes, etc.

There are, however, downsides, too: The fields cannot overlap, so something like this:

in the report won't convert correctly, and, as each Excel cell has a margin inside that cannot be suppressed, some fields might have to be made a little wider to accommodate the whole content.

With XFRX, the reports will probably need some tweaking, especially the complicated ones, but the result will be a normal Excel document, as if someone created it manually.

11.2   How it works

XFRX makes use of the possibility to merge more Excel cells together. Wherever a label or textbox should start or finish, XFRX creates a row and a column. To achieve the best looking results, it is a good thing to align the labels and textboxes both vertically and horizontally - result of which is a clearer document with fewer rows and columns. (Please see more about this below, in How to achieve the best results? paragraph.)

11.3   Handling page breaks

By default, XFRX does not break pages in the XLS output the same way as in other output formats – it is run in the plain mode instead, which means the output is one sheet - as long as it needs to be, with a page header on the top and a page footer at the bottom.

If more reports are processed, each report creates one sheet in the output document.

 

There are two options you can use to modify the way the page breaks are handled:

11.3.1       Generating sheet per page

To enable this option, call SetOtherParams method to set the “SHEET_PER_PAGE” parameter to .T.:

 

loSession.SetOtherParams("SHEET_PER_PAGE",.t.)

 

This will switch off the “plain” mode and the page breaks will correspond to other output options. Each page will be generated as a new sheet in the Excel document.

 

Please see more information about the SetOtherParams method in Methods common in XFRXListener and XFRXSession classes reference on page 45.

11.3.2       Generating sheet per start-each-group-on-a-new-page groups

To enable this option, call SetOtherParams method to set the “SHEET_PER_NP_GROUP” parameter to .T.:

 

loSession.SetOtherParams("SHEET_PER_NP_GROUP",.t.)

 

This option combines the plain mode and the sheet-per-page mode. The report runs in the plain mode but a new sheet is generated for each report group with “Start each group on a new page” flag set to .T.

11.4   Defining sheet names

There are two ways how to define sheet names. You can define a static text via NEXT_SHEET_NAME parameter, or you can use the NEXT_SHEET_NAME_EXPR parameter to define an expression, which will be evaluated at the bottom of each sheet and the result will be used as the new sheet name.  The latter option is useful if more sheets are generated during one report run.

Please see more information about SetOtherParams method in Methods common in XFRXListener and XFRXSession classes reference on page 45.

11.5   Hiding the Excel sheet grid

The background grid is visible by default. To hide it, please set DISPLAY_GRID_LINES parameter to false:

 

loSession.SetOtherParams("DISPLAY_GRID_LINES",.F.)

 

11.6   Leaving the fields content in Excel cells

By default, the content of non-stretchable fields is cut according to the size of the field, but you can optionally leave the full content of the field in the Excel cell. To enable this option, set the LEAVE_FULL_FIELD_CONTENT parameter to .T.:

 

loSession.SetOtherParams("LEAVE_FULL_FIELD_CONTENT",.T.)

 

11.7   How to invoke the XLS output

It is pretty much the same as with the other targets:

 

local loSession, lnRetval

loSession= xfrx("XFRX#INIT")

loSession.initLog()

lnRetVal = loSession.SetParams("output.xls",,,,,,"XLS")

If lnRetVal = 0

      loSession.SetOtherParams("NEXT_SHEET_NAME","first") && the name of the sheet, optional

      loSession.ProcessReport("report1")

      loSession.SetOtherParams("NEXT_SHEET_NAME","second")

      loSession.ProcessReport("report2")

      loSession.finalize()

ENDIF

 

This example creates a two sheet document. As you can see, SetOtherParams() method can be used to define the sheet names. If it is not called, the default names are "sheet1", "sheet2", etc.

11.8   XLS cells adjustment

When XLS document is generated, the vertical and horizontal coordinates of objects are adjusted - if the difference between two coordinates is smaller than a certain value, the coordinates are 'aligned'. This approach significantly reduces the number of rows and columns in the generated document.

It is possible to define this minimal difference. The greater the number is, the lesser number of rows/columns is generated, but if the number is too big, fields might get overlapped and could be left out.

Call SetOtherParams method with "HORIZONAL_ADJUSTMENT" or "VERTICAL_ADJUSTMENT" to define the minimal horizontal and/or vertical difference.

Example:

loSession.SetOtherParams("HORIZONTAL_ADJUSTMENT",1000) && default value = 76

loSession.SetOtherParams("VERTICAL_ADJUSTMENT",1000) && default value = 180

11.9   How to achieve the best results

  1. Align the fields.
    Have a look at the following document: (http://www.eqeus.com/xls1.xls)
    Columns B and C are almost invisible (if you make them wider, you can see that customer names start at column B, "Customer List" starts at column C and "Customer" starts at column D - which is something that we don't notice in normal report but have better result in the XLS output if the fields are aligned), row 4 is very narrow, and between each customer, there's added a very thin row, too.

    "Fixing" this is very simple - we aligned the "Customer", "Customer List" labels and the customer textbox, moved the line below the header a little bit higher so it lands on the cells below the "Customer" and "Total" captions. We also aligned the textboxes vertically.
    The resulting document looks much better: (http://www.eqeus.com/xls2.xls)

  2. Problem with label width
    The size of a label cannot be modified in the report designer - it always takes the size of the text entered. However, as we mentioned before, the Excel cells have little margins inside, so if we create a cell as wide as the label and put the text into it, the whole text wouldn't fit in - the last character or two disappear!
    XFRX takes care of this and makes the cell a bit wider, but this can bring another problem - if there is another label or a text field near the right edge of the label, increasing the width can result in overlapping the other label or the text field, result of which would be that one of the two labels disapper (there can be only one thing inside the cell). So please be careful about this and make sure there is enough space between the labels.

  3. Variable labels widths
    As the width of the label depends on its content, we cannot align both right and left edges of more labels and sometimes it might be better to replace labels with textboxes. For example, if there are many labels in a column, all left aligned like this:


    When creating the Excel document, XFRX will create a column for the right edge of each label:



    However, if the labels are converted to textboxes, we can align them:



    And the result might look better:

    It is actually quite easy to convert all labels to textboxes, just open the report in FoxPro and replace the object type:

USE report.frx
REPLACE objtype WITH 8 ALL FOR objtype = 5
USE

11.10   Numeric field picture format in Excel

The format definition of numeric cells in Excel is different from the format syntax used in Foxpro. XFRX is now able to convert the simple format definitions and allows for user-defined implicit and/or explicit Excel-type format definitions.
In Visual Foxpro, the numeric field is converted to its text representation based on an explicit format definition (format field in the report expression definition) or field's decimal places and SET DECIMAL setting.

When a numeric field is transformed to an Excel cell, the following algorithm is used:

  1. If there is an explicit XLS format defined, use it.


To define an explicit XLS format for a numeric field, add:

#UR XLSF= (expression)

to the field's comment.


Example 1:
#UR XLSF="General"

The "General" formatting - no special formatting, the number of decimal places is determined by the field's value

 

Example 2:

#UR XLSF="Standard"

The "Standard" formatting - two decimal places, thousand and decimal separators will be used according to the Excel defaults

 

Example 3:

#UR XLSF="#0.00"

Two decimal places, no leading zeros

 

Example 4:

#UR XLSF="#0.00;[red]#0.00"

Two decimal places, display negative numbers in red

  1. If the field contains a format definition, try to look up the format in a conversion table.

A conversion table can be populated programmatically when XFRX is executed so that the formats that are often used and cannot by converted automatically by XFRX would not require an explicit definition in each field in the report.

To add an entry to the conversion table, use addXLSFormatConversion method of XFRXSession class.


Example 5:
loSession.addXLSFormatConversion("@L 999999.99","000000.00")

  1. If the field contains a format definition a