Questions?

Subscribe to out mailing list Google group:

Printing

Printing in sqlkit uses the oootemplate module that is distributed along with sqlkit but could be used in a totally independent way and does not depend in any way on other parts of sqlkit.

OpenOffice.org template

This module makes it possible to use an oasis .odt document as a template to produce documents via the use of an openoffice server (i.e. an istance of openoffice that listens for connections by clients).

It uses the uno module that comes with openoffice. In the following image you can see how the template looks before rendering and how the pdf produced looks. The red circle stresses the marker that makes the template produce many lines for each input line: one for each object in context.

../_images/ootemplate-colors.png

This rendering can be obtained by code very similar to this example

The template

An openoffice writer document (.odt extension) can be used as template. No particular templating skills are required by the template designer, just ability to create an openoffice document and a list of variable’s names that must be used. Clearly this list must be provided by the programmer to the designer.

scenario

oootemplate will substitute variables values where needed.

Dear Mr. $user.name $user.last_name,

Today $date we  received an order for $n books:

+-----------------------------+----------------+----------+----------+
|Title                        |Author          |N. pieces |$currency |
+-----------------------------+----------------+----------+----------+
| ++$title                    |$author         |$qty      |$price    |
+-----------------------------+----------------+----------+----------+

This is an example of a template rendered as possible with ascii art.

There are 2 different substitutions that can be done:

  1. simple substitutions ($user, $date, $currency, above - yellow in the image)
  2. multiline substitutions (the book entries above, starting with ++ - green in the image)

the first refers to substitution of a single value that is already present in the document, the second refers to the insertion of several rows according to a list of fields that are probably in a table.

The variables defined in the table should be repeted in loop for each book provided in the context, that implies an increment of the number of rows of the table. The expected output resembles what follows:

Dear Mr. Alessandro Dentella,

today June, 2 2008, we received an order of 2 books:

+-----------------------------+----------------+----------+----------+
|Title                        |Author          |Copies    |Euro      |
+-----------------------------+----------------+----------+----------+
| Q                           |Luther Blisset  |1         |10        |
+-----------------------------+----------------+----------+----------+
| Il sistema periodico        |Primo Levi      |2         |8         |
+-----------------------------+----------------+----------+----------+

As for any template system a special syntax is needed to allow people to create loops. We are constrained to what can be done by a simple user of openoffice (no programming at all) so we choose to use a MULTI_LINE_MARKER in the default form of a ‘++’ (red circle in the image) .

To make things more complicated it’s clear that the person that created the template (the .odt document), may have used a table just for formatting reason so that substitution of type a. can be in an openoffice table or not.

implementation

Substitution of type a. above are done using search and replace functionality of openoffice API, while substitution of type b. are implemented as a loop on table’s rows and cell in 2 different ways: one that preserves the style of each word of the cells and one that doesn’t. The former uses getTrasferable() method on each cell and is slower.

You can switch from one to the other setting Template’s attrribute Template.preserve_styles

The pattern used to detect what is a table can be customized. While the default is ‘$’ as in the shell or in python template system (and perl and php...) since you may have the ‘$’ symbol in your document you may want to customize it. See Template’s method set_pattern.

context

The context is the object that contains the mapping variable/value to be used. It needs an argument -a dict- that holds the values.

oootemplate allows you to have more that one tables in your document. That means you can implement easily things as:

Dear Mr. $user.name $user.last_name,

you can order these books at 20% discount

+-----------------------------+----------------+----------+----------+
|Title                        |Author          |N. pieces |$currency |
+-----------------------------+----------------+----------+----------+
| ++$title                    |$author         |$qty      |$price    |
+-----------------------------+----------------+----------+----------+

or these books at 50% discount

+-----------------------------+-----------------+----------+----------+
|Title                        |Author           |N. pieces |$currency |
+-----------------------------+-----------------+----------+----------+
| ++$title                    |$author          |$qty      |$price    |
+-----------------------------+----------+------+----------+----------+
|Title                        |Author    | Extra|N. pieces |$currency |
+-----------------------------+----------+------+----------+----------+
| ++$title                    |$author   | $x   |$qty      |$price    |
+-----------------------------+----------+------+----------+----------+

In this example we have 3 lines that start with ++, that means that will be conseidered prototipes for new lines. For each of these 3 rows there need to be a list of objects (books in the example) in the context.

Since Openoffice-org tables have names, we wil use that name as a key in the context for the value. That’s enought for the first table (20% discount) not for the second where we have 2 lists in a table. To cope with this case, we can put as value a dict with entry an integer that indicates the position starting from 1 (see example below)

name mapping

Occasionally the name of the variable will be too long to fit in the space that you want to allocate. You can translate a shorter name to the real name in the dict context.translate (see example in the demo), blue circle in the image.

This way you can hide the complexity of some variable name. Note that you can translate both $rs.manager.address in $addr or $director.last_name in $d.last_name.

output

All output accepted by openoffice filters, you’re probably using .odt or .pdf

example

A tipical sample code is:

import ooootemplate as oo

tmpl = oo.Template('/tmp/mytemplate.odt', server='127.0.0.1', port=2002)
context = oo.Context({
    'user' : user,
    'date' : date(2008, 6, 2),
    'currency' : 'Euro',
    'Table1' : (book1, book2, ...)  # lazy assignement (simple tuple)
    'Table2' : (
         (book21, book22, ...),     # correct assignement (list of tuples)
         (book31, book32, ...),
         )
    })

tmpl.render(context)
tmpl.save_as('/tmp/new_document.pdf')

API

Context

class sqlkit.misc.oootemplate.Context(content, lazy=True)

A context used to render a template. It contains both the data and the way to substitute variable with the data.

__init__(content, lazy=True)
Parameters:
  • content – a dict with keys the variable names
  • lazy

    boolean. If True (default) invokes _implement_lazy_tables to allow the list of objects for a table rendered to be directly set as value of the table_name entry (rather than a list of lists). See example Table1 is lazy Table2 is not.

    The goal is to prevent common errors rather than promoting lazy writing. When you only have a single list of objects you may easily forget that you may have more than one.

    The assumption is that you don’t normally have lists as values of context (other that for tables). While probably true, should you need lists as contetxt values, you can just set lazy=False.

Template

class sqlkit.misc.oootemplate.Template(filename, server='127.0.0.1', port=8100, headless=False, oo_context=None, preserve_styles=False)

The class template that connects to a server (or starts a local one), read a document, parses the document to find tables

__init__(filename, server='127.0.0.1', port=8100, headless=False, oo_context=None, preserve_styles=False)

only the filename is needed if the server is local. If we already have a template on the same server we can reuse the oo_context

Params filename:
 

the template filename in the server’s filesystem

Parameters:
  • server – a server name
  • port – the port to connect to
  • headless – if False, disables the headless mode.
  • oo_context – the openoffice context (not to be confused with oootemplate.Context). The oo_context` plays the role of the connection to the server
  • preserve_styles – use TemplateWithStyles to enforce preservation of styles in each word of the cell when duplicating rows
render(context)

substitute all the variables with values from context

Parameter:context – the Contex instance to be used
save_as(filename, local=None)

save the template using save_as capability of openoffice.

Parameter:filename – filename in the server‘s filesystem. The extension is used to detect the file type as in regular openoffice use.
set_pattern(pattern, oo_pattern)

Set the pattern to detect what is a variable to be substituted

Parameters:
  • pattern – the pattern with syntax suitable for module re module. It must define at least 2 groups: var_name and match pointing respectively to the name of the variable and the whole match. Default is (?P<match>\$(?P<var_name>[^ ]+))
  • oo_pattern – the pattern with syntax suitable for openoffice regexp search. It can only use the openoffice syntax. Default is $[^ ]+
VARIABLE_PATTERN
the pattern for python variable detection. it’s a regular expression read set_pattern for details
VARIABLE_PATTERN_OO
the pattern for openoffice variable detection. read set_pattern for details
MULTI_LINE_MARKER
the pattern used to tel when a multiline line starts. Defaults to ++
document
the openoffice document from the server
oo_context
the connection with the server. This can be reused between templates
search
the openoffice SearchDescriptor
preserve_styles
Preserve style of each word in the cell when cloning rows. This will slow down the process so it’s disabled by default

Table

class sqlkit.misc.oootemplate.Table(oo_table, template)

table object detail on the API exposed by uno: http://api.openoffice.org/docs/common/ref/com/sun/star/table/module-ix.html

__init__(oo_table, template)
Parameters:
  • oo_table – the openoffice table object
  • template – the oootemplate.template object in which this table is
class sqlkit.misc.oootemplate.TableWithStyles(oo_table, template)

A Table that clones rows preserving style info even if several different styles are used within the same cell. This process is slower so it’s not active by default: set Template’s arg preserve_styles to True to enable it (see ex. N. 5).

__init__(oo_table, template)
Parameters:
  • oo_table – the openoffice table object
  • template – the oootemplate.template object in which this table is