Delphi & C++ Builder components library
and Software development
 
 
 

XMLReport - export data to DOCX or ODT file according report template

It uses prepared template file in DOCX or ODT format with special TAGs and fill data into it instead of TAGs. Result is again file in the same format but filled by data from variables, datasets etc.

See example of report template Employee_list2.docx or Employee_list2.odt (on each page is one example of report) and the result of report Result.docx or Result.odt.

User can use any editor to prepare DOCX or ODT template (I recommend OpenOffice, LibreOffice or Google Docs). MS Word can be used too but see important instruction for setting of MS Word to prepare correct template file.

XML Report uses rzip.dll to extract and update of XML content from DOCX and ODT file. This DLL must be provided together with application which use XMLReport. Download rzip.dll (Chrome can blocked download as possible malicious file, then please confirm download).

List of special tags which can be used inside of DOCX or ODT template file:
(X) in tags specify one dataset, datasets are passed as parameter and are marked by character from A to Z

 

FIELD tags

FIELDS tags is used for inserting of field value from selected dataset (X) and current record

<<X.FieldName>>

Insert value of specified field in their default format, example: <<A.LastName>>

<<X.FieldName:Format>>

Insert value of specified field in specified format, Format has the same format string as in Delphi
example: <<A.Salary:# ##0.00>> <<A.OrderDate:mm/dd/yy>>

<<X.FieldName:Width:Format>>

Width is used for TXT template and must starts by < (left alignment) or > (right alignment), field value is extended by separators to specified width
Example: <<A.Name:>20>> - name extended to 20 characters and aligned to left; <<A.Phone:>12>> - phone extended to 12 characters and aligned to right

<<X.#FieldIndex>> <<X.#FieldIndex:Format>>

Insert value of field specified by their index, example: <<A.#2>>

Special format strings:

if Format is set to string LABEL then "Display Label" of the field is inserted (instead of field value)

Special format string composed from one or more parts separated by semicolon can be used for graphics field:

  • W=number - define max width of picture in pixels
  • H=number - define max height of picture in pixels
  • Wcm=number - define max width of picture in centimeters
  • Hcm=number - define max height of picture in centimeters
  • Winch=number - define max width of picture in inches
  • Hinch=number - define max height of picture in inches
  • Rotate=number - define angle of rotation
  • Enlarge - define that smaller pictures than defined W or H will be enlarged
  • Quality - define quality of inserted picture (10..100, 100=full quality; Auto=automatic resize)
  • SaveAsJPG - define that all pictures will be saved in report in JPG format
  • SaveAsPNG - define that all pictures will be saved in report in PNG format
Example: <<A.Photo:Wcm=5;Hcm=5;Rotate=90>>; <<A.Photo:Winch=5;Hinch=5;Quality=50>>
 

VARIABLES tags:

<<VariableName>>

insert value of variable from list of variables which is defined in property Variables, OnUserCalc events is called if variable is not found in variable list
Example: <<UserName>>
 

CALCULATION tags:

CALCULATION tags are used for evaluating and/or inserting of any numeric expression

<<=expression:Format>>

expression can contain:
  • signs: + - * /
  • any number of brackets: ( )
  • number constant
  • Field value: X.Field (value of the field must have number format)
  • user defined variables (value of the variable must have number format)
  • result of aggregation function: FuncName[X.Field] or FuncName[CalcName], where FuncName can be one of Sum, Max, Min, Count, Avg or GrandSum, GrandMax, GrandMin, GrandCount, GrandAvg; each X.Field or CalcName must be defined in CALC part of SCAN tags before using in aggregation functions
Example: <<=B.Salary*1.2>> <<=B.Salary*1.3:# ##0.00>> <<=(Sum[A.Salary]+Sum[A.Bonus])/2:# ##0>>

<<ResetCalc>>

reset all aggregation fields to 0
 

SCAN tags

Scan tags are used for repeating some part of report for more dataset records.

<<Scan(X);While(condition);SkipIf(condition); MinRows(number); MaxRows(number); NewLine;NewCol;NewPage;Sep(string); NoIfEmpty;NoFirst; Calc(X.Field1,X.Field2,CalcAvg=(X.Field1+X.Field2)/2,...)>>

  • defines first point and conditions of scan function
  • scan loop is finished when While condition come false
  • scan loop skip record if SkipIf condition is true
  • MinRows define minimum number of printed rows (if dataset has less records empty records are printed)
  • MaxRows define maximum number of printed rows (scan loop is finished after defined number of records)
  • NewLine insert new line after each record
  • NewCol insert new column after each record
  • NewPage insert new page after each record
  • Sep(string) insert defined string as separator after each record
  • scan loop do not move to first record if NoFirst is used
  • Calc defines list of Fields or Named expression for aggregation function, for each listed field or expression will be calculated following values: Sum, Min, Max, Avg, Count and GrandSum, GrandMin and so on

<<ScanEntry(X)>>

defines start point of repetition, this tag is optional

<<ScanFooter(X)>>

defines stop point of repetition, this tag is optional

<<EndScan(X)>>

defines last point of scan function

Typical use:

Example 1 - simple loop:
<<Scan(B)>>
body of table - is repeated for each record
<<EndScan(B)>>

Example 2 - full loop:
<<Scan(B)>>
Header col1Header col2
<<ScanEntry(B)>>
Data col1Data col2
<<ScanFooter(B)>>
Footer col1Footer col2
<<EndScan(B)>>

Example 3 - full loop with conditions:
<<Scan(B);SkipIf(B.Retired);Calc(Salary,Bonus)>>
any header
<<ScanEntry(B)>>
body of table - is repeated for each record
<<ScanFooter(B)>>
any footer
<<EndScan(B)>>

Note: If any of scan tag is alone in the line, whole line will be removed

ODT format do not support joining of tables without text between them so new possibility for scan inside table is possible. Simply define scan tag before table and specify which rows is header or footer and specify condition for each row to show. Row is always shown if condition is not specified.

<<Scan(B);While(condition);SkipIf(condition);Calc(...); TblRow1(condition for row1);TblRow2(condition for row2);TblRow3(condition for row3)...>>

Example for table scan (simple table with header, one datarow to repeat and footer):

<<Scan(B);TblRow1(Header);TblRow2();TblRow3(Footer)>>
Header col1Header col2
Data col1Data col2
Footer col1Footer col2
<<EndScan(B)>>

Example for table scan (table with header, one datarow to repeat for man, another for woman, one footer):

<<Scan(B);TblRow1(Header);TblRow2(A.Sex="Male");TblRow3(A.Sex="Female");TblRow4(Footer)>>
Header col1Header col2
Data col1 for manData col2 for man
Data col1 for womanData col2 for woman
Footer col1Footer col2
<<EndScan(B)>>

Then report keeps only one table but repeat and fill by data each rows according defined condition for it.

 

RECORD MOVE tags

This tags can be used for moving dataset to another record. Usually is not necessary to use it.

<<Next(X)>>

<<Prev(X)>>

<<First(X)>>

<<Last(X)>>

Use bookmark tags to store and restore active record during report:

<<GetBookmark(X)>>

<<GotoBookmark(X)>>

 

IF and IIF tags

IF or IIF tags is used for inserting any text or dataset field dependently on any condition
IF tag is global, it means IF tag is processed before all scan function
IIF tag is inline tag, it means IIF tag is processed inside current scan, i.e. for each record (it is important if you use dataset value inside condition)

<<If(condition)>>...block if true...<<ElseIf>>...block if false...<<EndIf>>

<<IIf(condition)>>...block if true...<<ElseIIf>>...block if false...<<EndIIf>>

Note:

"ElseIf" tag and "block if false" is optional
 

CASE tags

Case tag can be used similar as IF but offer more conditions and results in one tag

<<Case(SourceValue;ValueToCompare1,Result1:Format;ValueToCompare2,Result2:Format;....;#ELSE#,ResultElse))>>

  • SourceValue is merged with ValueToCompare1 (2...x) and used as condition, if condition is valid then Result1 (2...x) is used
  • SourceValue can be any field, variable or calculation (without = in the beggining)
  • ValueToCompare can be any constant, variable, field or calculation
  • SourceValue or ValueToCompare must contain any sign for comparison: = ; == ; <> ; > ; < ; >= ; <= , see CONDITIONS description
  • set ValueToCompare to #ELSE# to use ResultElse in any case

Example:

  • <<Case(A.Salary;<3000,Bellow 3000;<=5000,middle range (3000-5000);<10000,high;#ELSE#,very high)>>
  • <<Case(A.EmploTypeID=;1,internal;2,external;#ELSE#,unknown type)>>
  • <<Case(A.BirthDate;<#19000101#,error date;>#20200101#,error date;#ELSE#,A.BirthDate)>>
 

CONDITIONS:

Conditions can be used in SCAN tags (While or SkipIf) or in IF and IIF tags.
Condition can contain:
  • signs: = ; == ; <> ; > ; < ; >= ; <=
  • boolean field: X.Retired
  • text field: X.Field
  • text constant: "text"
  • datetime constant: #YYYYHHMM# or #YYYYHHMMhhmmss#
  • any expression (see above)
  • any number of brackets: ( )
  • logical operations: and or not
  • test if dataset is empty: X.0
  • test if dataset is eof : X.@

example of some conditions:

  • A.Name="Carl"
  • A.Salary>30000
  • A.Salary>30000 and B.State<>"NY"
  • (not A.Retired) and (B.State="NY" or B.State="WA")
 

SPECIAL tags

<<SepList("sep",X.Field1,X.Field2,...)>>

insert list of values separated by text defined in first parameter "sep", it is usefull in creating separated list of any fields, because this function skips empty fields

<<FirstValue(X.Field1,X.Field2,...)>>

display first not empty value from list

<<Picture(VariableName:Format)>>

insert external graphic file to report, VariableName define Variable, which must contain full path to graphic file (see VariableTags description), Format has the same possibility as for graphic fields

<<BarCode(expression):Format>>

Insert BarCode picture, expression defines displayed code and can be fieldtag, variable or constant (eg. "123")

Format can be made up from more parts divided by ;

Type=string - define type of barcode from following CodeEANAuto (auto detection according text length), CodeEAN8, CodeEAN13, Code_2_5_interleaved, Code_2_5_industrial, Code_2_5_matrix, Code39, Code39Extended, Code128A, Code128B, Code128C, Code93, Code93Extended, CodeMSI, CodePostNet, CodeCodabar, CodeUPC_A, CodeUPC_E0, CodeUPC_E1, CodeUPC_Supp2, CodeUPC_Supp5, CodeEAN128A, CodeEAN128B, CodeEAN128C

ShowCode - defines showing of numeric code

FontName - define font for numeric code + all tags for Pictures included Rotate, Wmax, Hmax and Quality (Quality should be 100 for barcode)

all tags for Pictures included Rotate, Wmax, Hmax and Quality (Quality should be 100 for barcode)

<<InsertFile(FileName)>>

insert content of external file to possition of tag, text is converted to XML format

<<InsertXMLFile(FileName)>>

insert content of external file to possition of tag, content is not converted to XML format

<<DefVar(VariableName,Value)>>

define variable which can be used everywhere in report, value can be any constant ("text") or expression

<<Info(Name=Value)>>

tag Info is used for backward communication from report to application
all Info tags are processed before any other action, so this tags can be anywhere in RTF template
tag body (Name=Value) will be added to property ExtendedInfo and event OnInfo will be called, so application can make any action according ExtendedInfo content

Example:

this tag can be used for specifying of active printer and application can process it
<<Info(Printer=HP Laser Jet 5L)>>

<<ListAllFields>>

insert list of all dataset fields name, it is usefull only during creating new report
 

STRING functions and tags

String functions can be used in calc tags or as parameter in string routine

=StrLen[expression]

- evaluate expression and returns its length

=StrPos[expression;substring]

- evaluate expression and returns position of substring in expression

=StrPosCS[expression;substring]

- same as StrPos but case sensitive String tags can be used as common tags anywhere in report

<<Str_Part(expression,from,count)>> or <<Str_Part(expression,startstr,endstr)>>

- evaluate expression and return part of it - e.g.: A.email = name@company.com
  • <<Str_Part(A.email,1,"@")>> returns "name"
  • <<Str_Part(A.email,"@",255)>> returns "@company.com"
  • <<Str_Part(A.email,"@",".")>> returns "@company"
  • <<Str_Part(A.email,=StrPos[A.email,"@"]+1,".")>> returns "company"
  • <<Str_Part(A.email,=StrLen[A.email]-3,4)>> returns ".com"

<<Str_PartCS(expression,from,count)>>

- same as Str_Part but case sensitive

<<Str_Replace(expression,oldsubstr,newsubstr)>>

- evaluate expression and replace all oldsubstr by newsubstr - e.g.: A.email = name@company.com ; A.LastName = "King"
  • <<Str_Replace(A.email,"@","(at)")>> returns "name(at)company.com"
  • <<Str_Replace(A.email,"name",A.Lastname)>> returns "King@company.com"
  • <<Str_Replace(A.email,Str_Part(A.email,1,"@"),A.Firstname)>> returns "King@company.com"

<<Str_ReplaceCS(expression,oldsubstr,newsubstr)>>

- same as Str_Replace but case sensitive

<<Str_Upper(expression)>>

- evaluate expression and change to uppercase

<<Str_Lower(expression)>>

- evaluate expression and change to lowercase

<<Str_Proper(expression)>>

- evaluate expression and change to propercase (first letter uppercase)

<<Str_Trim(expression)>>

- evaluate expression and trim spaces

Go back