Programmatically create OpenDocument files
The OpenDocument file formats are great, interoperable file formats for exchanging data with Office Applications. Unfortunately the 728-pages ISO/IEC 26300:2006 “Information technology — Open Document Format for Office Applications (OpenDocument) v1.0” is not exactly an entertaining reading, and someone wishing to programmatically create OpenDocument files may have a hard time. I present here a tiny utility to generate programmatically OpenDocument files, in particular for the spreadsheet format ODS; all this goodness in just 2687 lines of ANSI C code, with no dependencies on external libraries!
How is this possible ?
Although OpenDocument files can consist of just a single XML document, more often they are ZIP-compressed archives containing a number of files and directories. The minimum number of files in a ZIP-compressed ODS is four:
Quite interestingly, the ZIP format supports non-deflated archives, in which case the files are just added as-they-are to the archive, without compression (it behaves then like a pure file archiver such as tar). The utility I propose creates am ODS file by archiving in a non-deflated ZIP file the files content.xml, meta.xml, mimetype, META-INF\manifest.xml it finds in the current folder.
The utility is based on a stripped-down version of minizip version 1.01h, plus the five files crc32.h, crc32.c, zutil.c, zutil.h and zlib.h from zlib version 1.2.5.
Compile and run genods; the resulting test.ods file should be compatible with the typical OpenDocument-compatible applications (tested with OpenOffice 3.2). The file run through the ODF Validator reports errors in content.xml and missing styles.xml, settings.xml – nothing that you can not fix.
Now you might be asking yourself: how do I use this ? I suggest you create a reference OpenDocument file with your preferred office application, then open it with a ZIP archiver and inspect the files present in the archive. Do some reverse engineering, test it, and set up your program to generate just the core file, the content.xml. Then link in this utility and snap ! (you might need to add more writefile statements to add other files).
For the curious, these were the changes to minizip:
- create genods.c starting from minizip.c
- patch zip.c to remove reference to the functions deflateInit2_, deflate and deflateEnd.