AppyPrinciplesGetting started
appy.pod

POD (Python Open Document) is the part of Appy allowing to easily generate documents whose content is dynamic. The principle is simple: you create an ODF (Open Document Format) text or spreadsheet document with LibreOffice, you insert some Python code at some places inside it, and from any program written in Python, you can call POD with, as input, the OpenDocument document template and a bunch of Python objects. POD generates another ODF document containing the desired result. If you prefer to get the result in another format, POD can call LibreOffice in server mode to convert the result in various formats, among which PDF, DOC, DOCX, XLS, XLSX and CSV.

A simple example based on an ODT template

Create, with LibreOffice Writer, a POD template, like the one below.

A POD template is an ODT document where:

  • Python expressions are inserted into fields;
  • comments are (mis)used for writing special Python-based statements that allow to conditionally include or repeat a portion of the document.

In this template, I wrote the Python expression commercial in a conditional field. With LibreOffice, click on [Ctrl]-F2 to create a field. Choose field type conditional text, write true as condition, write commercial in the then expression and write nothing in the else expression. Another expression ("i") in the next line has been defined similarly. 2 comments were also added. With LibreOffice, in the Insert menu, choose "Comment".

Here is the code for calling POD for generating a result in ODT format.

from appy.pod.renderer import Renderer
commercial = 'creative'
beingPaidForIt = True
renderer = Renderer('SimpleTest.odt', globals(), 'result.odt')
renderer.run()

First we need to import class Renderer. Then, we define some Python variables. We must create an instance of the Renderer, with, as parameters, the name of the POD template (we assume here that the POD template shown above is called SimpleTest.odt and lies in the current folder), a dictionary of named Python objects (here we simply take the global interpreter environment) and the name of the result file. The script will generate it, with, as content, what is shown in the image below.

The second line of the template is repeated 3 times. It is the effect of the for loop in the first comment. Content of every field was replaced by the result of evaluating it as a Python expression, thanks to the context given to the Renderer as second parameter of its constructor. Note that within a loop, a new name (the iterator variable, i in this case) is added in the context and can be used within the document part that is impacted by the for loop. The last line of the template was not rendered because the condition of the second comment evaluated to False.

Generate the result in PDF or DOC(X)

The previous example generates a result in ODT format. If you prefer to get the result in PDF, DOC or DOCX, you must first launch LibreOffice in server mode, listening to some port. Under Linux, the following command launches a LibreOffice server running on port 2002:

soffice --invisible --headless "--accept=socket,host=localhost,port=2002;urp;"&

Under Windows, this is... hum... In fact I don't know, I do not use Microsoft software for many years.

Once LibreOffice server is started, change the creation of the Renderer instance that way:

renderer = Renderer('SimpleTest.odt', globals(), 'result.pdf')

Instead of specifying a result being "result.odt", specify it being "result.pdf". Launch your Python script and you should get a nice PDF file.

For generating a result as a .doc or .docx file, simply update the result extension accordingly.

A simple example based on an ODS template

Suppose you write, with LibreOffice Calc, the following template, named SimpleTestOds.ods.

Here is the way we will call POD for producing an ODS spreadsheet, based on some Python dict containing a bunch of people.

from appy.pod.renderer import Renderer
staff = [{'firstName': 'Delannay', 'name': 'Gaetan', 'age': 112},
         {'firstName': 'Gauthier', 'name': 'Bastien', 'age': 5},
         {'firstName': 'Jean-Michel', 'name': 'Abe', 'age': 79}]
renderer = Renderer('SimpleTestOds.ods', globals(), 'result.ods')
renderer.run()

Some remarks now. POD considers that any cell containing something of the form ="..." (= a formula whose result is a string and that is directly expressed as a string literal, surrounded by double quotes) will contain a Python expression, that will be executed according to the current context. POD statements (like the comment containing do row for person in staff), allowing to conditionaly or repeatedly include parts of the spreadsheet, are expressed in the same way as in ODT templates (see above).

Within ODT templates, any Python expression is converted to string, because an ODT is only made of text. Within ODS templates, a Python expression that produces a Python int, long or float will be rendered as a float value within the resulting spreadsheet. In the previous example, cells containing ages are float values.

Within an ODS spreadsheet, every sheet is internally represented as a table. With statements like do table for... you can repeat a template sheet and produce several sheets in the resulting spreadsheet.

Generate the result in XLS(X)

The previous example generates a result in ODS format. If you prefer to get the result in Excel (XLS or XLSX), you must first launch LibreOffice in server mode, listening to some port. Under Linux, the following command launches a LibreOffice server running on port 2002:

soffice --invisible --headless "--accept=socket,host=localhost,port=2002;urp;"&

Under Windows, this is... hum... In fact I don't know, I do not use Microsoft software for many years.

Once LibreOffice server is started, change the creation of the Renderer instance that way:

renderer = Renderer('SimpleTestOds.ods', globals(), 'result.xlsx')

Instead of specifying a result being "result.odt", specify it being "result.xls[x]". Launch your Python script and you should get an Excel file.

//9
Title
1 Writing ODT templates
2 Writing ODS templates
3 The default POD context
4 Alternate expressions
5 Generating a CSV file
6 The LibreOffice server
7 Using RestrictedPython
8 The Renderer reference
9 Command-line programs