Creating an OpenOffice Spreadsheet in pure Tcl

SRIV Sept 18,2010 This is a quick port of the php example at http://www.ibm.com/developerworks/web/library/wa-odf/ . It's not a generic file writing library, but instead just a script that creates a spreadsheet, that you can modify and enhance to your liking. Feel free to add enhancements and break out the functionality, perhaps using TclOO.

#!/usr/bin/env tclsh

###########################################
# application name: odswriter.tcl
# author: Steve Redler IV, SR Technology
# date: Sept 18, 2010
# function: Create an OpenOffice Spreadsheet in pure tcl
#


set XML_START {<?xml version="1.0" encoding="UTF-8"?>
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" office:version="1.2" grddl:transformation="http://docs.oasis-open.org/office/1.2/xslt/odf2rdf.xsl">
<office:scripts/>
}

set XML_AUTOMATIC_STYLES {<office:automatic-styles>
        <style:style style:name='bbb' style:display-name='bbb' 
            style:family='table-cell'>
            <style:text-properties fo:font-weight='bold' 
            fo:color='#0000ff' fo:font-size='15'/>
        </style:style>
        <style:style style:name='bld'  style:display-name='bld' 
            style:family='table-cell'>
            <style:text-properties fo:font-weight='bold'/>
            <style:table-cell-properties fo:background-color='#AEAEAE'/>
        </style:style>
    </office:automatic-styles>
}

set XML_BODY_START {<office:body>
<office:spreadsheet>
<table:table table:name="Sheet1" table:style-name="ta1" table:print="false">        
}

set MIMETYPE "application/vnd.oasis.opendocument.spreadsheet"

set XML_MANIFEST {<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:version="1.2" manifest:full-path="/"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
</manifest:manifest>}

set XML_ROW_START "<table:table-row>"
set XML_CELL_START "<table:table-cell><text:p>"
set XML_CELL_END "</text:p></table:table-cell>"
set XML_ROW_END "</table:table-row>"
set XML_END "</table:table></office:spreadsheet></office:body></office:document-content>"

set XML_BBB_CELL_START "<table:table-cell table:style-name='bbb'><text:p>"
set XML_BLD_CELL_START "<table:table-cell table:style-name='bld'><text:p>"

# Create the content.xml file
set contents $XML_START
append contents $XML_AUTOMATIC_STYLES
append contents $XML_BODY_START
# Add a big, bold, blue, title, and an empty line:

append contents $XML_ROW_START
append contents $XML_BBB_CELL_START
append contents "Cities whose name starts with 'Darwin'"
append contents $XML_CELL_END
append contents $XML_ROW_END

append contents $XML_ROW_START
append contents $XML_ROW_END

# Add some titles, in bold:

append contents $XML_ROW_START
foreach title {"Country" "" "Region" "" "City" "Pop" "Lat" "Long"} {
    append contents $XML_BLD_CELL_START
    append contents $title
    append contents $XML_CELL_END
}
append contents $XML_ROW_END

# ...get the data...
set data {{AR Argentina 16 {Rio Negro} darwin {} -39.200000008 -65.7666702} \
          {AU Australia 03 {Nothern Territory} darwin 93081 -12.4666672 130.8333282} \
         {IQ Iraq 05 {As Sulaymaniya} darwina {} 36.126667 45.2377777}}

foreach row $data {
    append contents $XML_ROW_START
    foreach value $row {
        append contents $XML_CELL_START
        append contents $value
        append contents $XML_CELL_END
    }
    append contents $XML_ROW_END
}
append contents $XML_END

# let tempzip be the name of a temporary file

file mkdir tempzip
file mkdir tempzip/META-INF
set fh [open tempzip/META-INF/manifest.xml "CREAT WRONLY TRUNC"]
puts -nonewline $fh $XML_MANIFEST
close $fh

set fh [open tempzip/content.xml "CREAT WRONLY TRUNC"]
puts -nonewline $fh  $contents
close $fh

set fh [open tempzip/mimetype "CREAT WRONLY TRUNC"]
puts -nonewline $fh $MIMETYPE
close $fh

cd tempzip
# zip creation was only tested in Linux and WinXP
#get zip.exe from http://stahlworks.com/dev/zip.exe
exec {*}{zip -mr ../tempzip.ods mimetype META-INF/manifest.xml content.xml}
cd ..

file delete -force tempzip

Running the file result againsts https://odf-validator.rhcloud.com/ fails with few errors. Few fixes are needed.