6

I have a WSGI application that generates invoices and stores them as PDF.

So far I have solved similar problems with FPDF (or equivalents), generating the PDF from scratch like a GUI. Sadly this means the entire formatting logic (positioning headers, footers and content, styling) is in the application, where it really shouldn't be.

As the templates already exist in Office formats (ODT, DOC, DOCX), I would prefer to simply use those as a basis and fill in the actual content. I've found the Appy framework, which does pretty much that with annotated ODT files.

That still leaves the bigger problem open, tho: converting ODT (or DOC, or DOCX) to PDF. On a server. Running Linux. Without GUI libraries. And thus, without OO.o or MS Office.

Is this at all possible or am I better off keeping the styling in my code?

The actual content that would be filled in is actually quite restricted: a few paragraphs, some of which may be optional, a headline or two, always at the same place, and a few rows of a table. In HTML this would be trivial.

EDIT: Basically, I want a library that can generate ODT files from ODF files acting as templates and a library that can convert the result into PDF (which is probably the crux).

Alan Plum
  • 10,814
  • 4
  • 40
  • 57

2 Answers2

2

I don't know how to go about automatic ODT -> PDF conversion, but a simpler route might be to generate your invoices as HTML and convert them to PDF using http://www.xhtml2pdf.com/. I haven't tried the library myself, but it definitely seems promising.

Pär Wieslander
  • 28,374
  • 7
  • 55
  • 54
  • I figured the problem with this approach would be that footers/headers would still need to be handled directly -- I have to keep the footer in the same place on every page. I know that CSS has a lot of print options, but I'm not sure whether it can do that (prove me wrong). – Alan Plum Nov 30 '09 at 13:56
  • 1
    It seems XHTML2PDF/Pisa supports headers and footer through some CSS extensions. Have a look at http://www.xhtml2pdf.com/doc/pisa-en.html - section 7.4 contains an example on how to create a footer on every page in a document. – Pär Wieslander Nov 30 '09 at 14:02
  • That seems to do the trick. Great! I'll have to fiddle with it a bit, but I think it's a perfect solution for keeping the styling out of the code. It still leaves the redundancy of recreating an ODF/DOC(X) template as XHTML/CSS+, but that's only a minor concern. – Alan Plum Nov 30 '09 at 14:34
1

You can use QTextDocument, QTextCursor and QTextDocumentWriter in PyQt4. A simple example to show how to write to an odt file:

>>>from pyqt4 import QtGui
# Create a document object
>>>doc = QtGui.QTextDocument()
# Create a cursor pointing to the beginning of the document
>>>cursor = QtGui.QTextCursor(doc)
# Insert some text
>>>cursor.insertText('Hello world')
# Create a writer to save the document
>>>writer = QtGui.QTextDocumentWriter()
>>>writer.supportedDocumentFormats()
[PyQt4.QtCore.QByteArray(b'HTML'), PyQt4.QtCore.QByteArray(b'ODF'), PyQt4.QtCore.QByteArray(b'plaintext')]
>>>odf_format = writer.supportedDocumentFormats()[1]
>>>writer.setFormat(odf_format)
>>>writer.setFileName('hello_world.odt')
>>>writer.write(doc) # Return True if successful
True

If not sure the difference between odt and odf in this case. I checked the file type and it said 'application/vnd.oasis.opendocument.text'. So I assume it is odt. You can print to a pdf file by using QPrinter.

More information at: http://qt-project.org/doc/qt-4.8/

Hieu
  • 7,138
  • 2
  • 42
  • 34