Reports and Documents

If you do need to create of modify documents and reports, the following should be useful.

OpenVPMS uses two 'vehicles' to generate printed (or pdf) output: OpenOffice (specifically its 'soffice' component) and JasperReports. Note that since OpenOffice can handle Microsoft Word documents, you can happily use Word rather than Open Office Writer to prepare letters and forms.

Which of these two is used depends on the document content set for the document template. (See Administration|Templates and Create/Edit Template.) If the document content is a .jrxml file, then JasperReports is used, if it is an .odt or .doc or .docx file then OpenOffice is used.

To create and edit the .jrxml files you use JasperSoft's iReports, specifically version 5.0.4. (The use of later versions is possible but the compatibility mode option needs to be enabled.)

Note that JasperReports is used for any document that has more complex datasets such as invoices, statements, reports etc as these typically have multiple rows of data and require groupings and other data processing functions not available in OpenOffice. These are also rarely changed except during implementation.

OpenOffice is used for customer, supplier and patient documents. These are more likely to be modified and added to by the practice so a standard word processor editor is more appropriate.

The reports and forms/letters/documents get data in two ways:

  • Reports (ie things run from the Reporting|Reports menu) are all handled by JasperReports. These MUST have their Report Type set to 'Report' in their document template. The report parameters (if any) are passed as 'Parameters' and the 'datasource' is set to access the MySQL database.  The report then uses SQL to extract the required information from the MySQL database. Selection criteria and other parameters are entered via a report criteria screen.
  • Forms, letters, and system documents (ie invoices etc) may be handled by either JasperReports (for the complicated ones) or OpenOffice. For these the Report Type in their document templates will always be other than 'Report', eg 'Customer Invoice', 'Patient Letter', etc. In both cases an appropriate dataset is made available - and this is determined by the Report Type. For OpenOffice (or M/S Word) this is accessed via merge fields, ie the facility that is commonly used in word processors to do mail merge. For JasperReports, the 'datasource' is set to access this dataset. In both cases the field names are the same. Note that the term 'field name' is a little misleading - as well as things that look like names such as and patient.entity.species, you can use more complicated expressions like [openvpms:get(party:getPatientOwner(.),'lastName')] and [macro:eval('standardConditions')]. Expressions are always enclosed by square brackets.

    The available field names are documented here; the available expressions here.

    Input parameters (commonly user input to letters) are entered via a parameter input screen.


Open Office Notes
The simplest way to generate a new .odt template is to use the sample templates included in the distribution.  These call out almost all the available fields and you can copy the required fields from the sample document.

Microsoft Word Notes
The simplest way to generate a new .doc (or .docx) template is to use the sample templates included in the distribution.  These call out almost all the available fields and you can copy the required fields from the sample document.

Note that although Word supports conditional fields, these are not implemented by the Open Office component used by OpenVPMS. Hence if you need conditional fields (eg to switch between 'him' and 'her' based on the patient's sex) then you will either need to use .odt templates. Alternatively you use the macro:eval function to run a macro that will return his or her depending on the sex.

iReports Notes
The following is not intended to be 'how to use iReports' but rather a set of notes that may help you when you are examining an existing report and trying to understand how it works.

Field names: For reports, when the datasource is the MySQL database, the field names are the names of the fields returned by the SQL query. Otherwise the datasource is a data collection and the field names are used the access the data collection - either via simple archetype dot notation (eg, or via xpath expressions enclosed in square brackets (eg [party:getPartyFullName(.)] ).  While the former feels quite normal - ie using $F{} is a reasonable syntax, the latter appears peculiar - $F{[party:getPartyFullName(.)]} does not look like a normal way to access something.  However, it works - what is happening is that the OpenVPMS code examines the name of the field, sees that it starts with '[' and ends with ']' and knows to interpret the contents as an xpath expression.

Sorting and Grouping: The Grouping facility assumes that the records are appropriately sorted. That is, if you use grouping to organise the output by patient/date/product type then the data must be sorted in this order - defining the groups does not do the sorting for you. For SQL based reports, you do the sorting in the SQL query. Otherwise you can do it either in the datasource specification (see below) or using the inbuilt facility - this is accessed via the Report Query icon on the Designer view, and then pressing the 'Sort Options...' button.

Note that using the inbuilt sort, you can sort using fields (including ones that are xpath expressions) and variables, whereas in the datasource specification (see below) you can only sort by node names.

Sub-reports: [Note that although JasperReports support sub-reports anywhere in the report, the OpenVPMS implementation only supports sub-reports in either the Detail or Summary bands.] When using sub-reports you must specify the datasource for the sub-report in the main report. If the main report is using the MySQL database as the datasource, then the datasource part of the sub-report field in the main report will be set like the following:

However, if the main report is not using MySQL as the datasource (ie this is the sub-report for Customer Invoices or Customer Statements) then the datasource part of the sub-report field in the main report will be set like the following:

The datasource expression can also have a second argument as follows:

 $P{dataSource}.getDataSource("items", new String[]{"", "target.startTime"}) 

Here, the first argument "items" specifies the node in the report's data source (eg act.customerAccountChargesInvoice for an invoice), and hence this accesses the invoice's items. The strings in the second argument specify the names of the nodes to sort the data by. Note that these must be node names, they cannot be xpath expressions.

Now the 'items' node of the act.customerAccountChargesInvoice archetype is a collection of actRelationship.customerAccountInvoiceItem archetypes, and in these the node named 'target' is the collection of act.customerAccountInvoiceItem archetypes which are the invoice line items.

Hence in the sub-report, the field names are where xxx is the node within the act.customerAccountInvoiceItem archetype.

NOTE that the Subreport Expression contains the name of the Content of subreport - not the template name.  Hence if you upate say the Invoice Items template with a modified content file (say InvoiceItems-BE-1.jxrml) then the Invoice template will not be able to find the items content because you have changed its name. That is, if you are editing the content of a subreport, you must not change the name of the content file.

Furthermore you should not have multiple templates that have content of the same name - IF one of the templates is a subreport. This is because when the subreport content is used when the report is run, it is highly likely that the wrong one will used since there are multiple content files with the same name.

iReports Preview: If you building a report that uses the MySQL datasource, then you can use iReports Preview facility. To set this up you need to add the datasource. Click the Report Datasources button:

Now press New to create a new 'Database JDBC connection' and then set the details as follows:

Note that if you are developing a report that uses subreports, then for previewing to work, the 'Subreport Expression' parameter needs to be like:
  $P{SUBREPORT_DIR} + "RPT Practice Summary_CountInvoicedCustomers.jasper"
whereas, for production use in OpenVPMS, it needs to be like:
  "RPT Practice Summary_CountInvoicedCustomers.jrxml"


Email Letterhead Support
If reports and documents are set up to be printed on letterhead paper, then if they are emailed rather than printed, one needs a facility to insert the letterhead when the item is being emailed but not if it is being printed.

This is achieved through the IsEmail property which is supported for OpenOffice and JasperReports templates.

To use it in OpenOffice templates:

  1. Create a new field by going Insert -> Fields -> Other -> User Field
  2. In Name, enter "IsEmail" (without quotes)
  3. In Value, enter "unset" (without quotes)
  4. Click on the green tick
  5. Create a section to display when printing by going Insert ->Section
  6. Name it "Print Letterhead"
  7. Tick the Hide box
  8. Enter: IsEmail == "true" in the With Condition box
  9. Click OK
  10. Repeat 5-9 for a section named "Email Letterhead" but enter IsEmail == "false" in the With Condition Box.

The "cartrophen first reminder.odt" and "desex first reminder.odt" templates in the release distribution demonstrate this. 

To use it in JasperReports templates:

  1. Add a Boolean parameter, IsEmail
  2. For elements that should only be displayed when emailing, set their "Print When Expression" expression to: $P{IsEmail}.equals(Boolean.TRUE)
  3. For elements that should only be displayed when printing/previwing, set their "Print When Expression" expression to: $P{IsEmail}.equals(Boolean.FALSE)

Any of the JasperReports in the release distribution illustrate this.

Syndicate content