I'm attempting to copy the formatting of a table from one OpenOffice Writer file to another... I can tell that I'm writing the name of the style to the second document, but not the style data.
I suspect that this has something to do with the 'styles'
part of the odfContainer
, but I'm not clear on how to write this to the second document, especially because when I inspect the $style
object in the debugger, it appears to be identical to the $doc
object, which has supposedly loaded the 'content'
part.
Here's what I've got so far...
#! /usr/bin/perl use warnings; use strict; use OpenOffice::OODoc; my $file='mytest.odt'; my $outfile='doc2.odt'; # load input file my $container = odfContainer("$file"); $container->raw_export("styles.xml"); my $doc = odfDocument ( container => $container, part => 'content' ); my $style = odfDocument ( container => $container, part => 'styles' ); # load output file my $container2 = odfContainer( $outfile, create => 'text' ); $container2->raw_import("styles.xml"); my $doc2 = odfDocument ( container => $container2, part => 'content' ); # Load table from 'mytest.odt' my $table=$doc->getTable(0); # Get style from first cell in $table my $headerstyle=$doc->getStyle( $doc->getCell($table, 0, 0) ); # Create table in $doc2 my $newtable=$doc2->appendTable('newtable', 1, 1, 'table-style' => $doc->getStyle($table) ); # Set style of first cell in $newtable to 'Table1.A1' $doc2->cellStyle( $newtable, 0, 0, 'Table1.A1' ); # Write 'doc2.odt' to disk $container2->save;
The reason that I'm loading 'Table1.A1'
as the cell style is that I found the following deep inside $table
, when inspecting inside the debugger:
'next_sibling' => OpenOffice::OODoc::Element=HASH(0x102029250) 'att' => HASH(0x102029180) 'style:family' => 'table-cell' 'style:name' => 'Table1.A1' 'empty' => 0 'first_child' => OpenOffice::OODoc::Element=HASH(0x1020294a0) 'att' => HASH(0x102029200) 'fo:background-color' => '#cccccc' 'fo:border' => '0.0069in solid #000000' 'fo:padding-bottom' => '0in' 'fo:padding-left' => '0.075in' 'fo:padding-right' => '0.075in' 'fo:padding-top' => '0in' 'style:vertical-align' => 'top' 'style:writing-mode' => 'lr-tb'
I know that the attributes match what I'm trying to copy, and I also know from experimentation that the 'getStyle'
method returns the style::name
attribute... I just don't know how to get from setting the style::name
attribute using the cellStyle
method to actually having the underlying data written in to the new document.
Edit:
Unzipping the OpenOffice file, I get several xml files:
etc.
The 'styles'
and 'content'
parts of the OdfContainer
correspond to styles.xml and content.xml. Styles.xml is a little like a css file, containing the style information for various header levels of an ODF file. Content.xml also contains style information, much like the css header in an html document.
Here's the style part of content.xml extracted from the odt file (actually one much like it... I didn't save the original).
<?xml version="1.0" encoding="utf-8"?> <office:document-content> ... <office:automatic-styles> <style:style style:name="Table6" style:family="table" style:master-page-name="First_20_Page"> <style:table-properties style:width="6.9208in" style:page-number="auto" table:align="left" style:writing-mode="lr-tb" /> </style:style> <style:style style:name="Table6.A" style:family="table-column"> <style:table-column-properties style:column-width="1.2729in" /> </style:style> <style:style style:name="Table6.B" style:family="table-column"> <style:table-column-properties style:column-width="3.2604in" /> </style:style> <style:style style:name="Table6.C" style:family="table-column"> <style:table-column-properties style:column-width="2.3875in" /> </style:style> <style:style style:name="Table6.1" style:family="table-row"> <style:table-row-properties style:min-row-height="0.1597in" style:keep-together="true" fo:keep-together="auto" /> </style:style> <style:style style:name="Table6.A1" style:family="table-cell"> <style:table-cell-properties style:vertical-align="bottom" fo:background-color="#cccccc" fo:padding-left="0.075in" fo:padding-right="0.075in" fo:padding-top="0in" fo:padding-bottom="0in" fo:border-left="0.0069in solid #000000" fo:border-right="none" fo:border-top="0.0069in solid #000000" fo:border-bottom="0.0069in solid #000000" style:writing-mode="lr-tb"> <style:background-image /> </style:table-cell-properties> </style:style> ...
Doing a raw export of 'content.xml' section of the input file, then a raw import in the output file does transfer data from one file to the other.
#! /usr/local/bin/perl use warnings; use strict; use OpenOffice::OODoc; my $infile=$ARGV[0]; my $outfile='outfile.odt'; my $incontainer = odfContainer( $infile ); $incontainer->raw_export("content.xml"); my $outcontainer = odfContainer( $outfile, create => 'text' ); $outcontainer->raw_import("content.xml"); $outcontainer->save;
Running oodoc.pl infile.odt
, Then unzipping outfile.odt and inspecting content.xml does show that the style has been successfully transferred:
<style:style style:name="Table1" style:family="table"> <style:table-properties style:width="6.925in" table:align="margins" /> </style:style> <style:style style:name="Table1.A" style:family="table-column"> <style:table-column-properties style:column-width="2.3083in" style:rel-column-width="21845*" /> </style:style> <style:style style:name="Table1.A1" style:family="table-cell"> <style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="none" fo:border-top="0.0007in solid #000000" fo:border-bottom="0.0007in solid #000000"> <style:background-image /> </style:table-cell-properties> </style:style>
Now that this has been done, I'll need to actually load and use the cell styles in $outcontainer
.
You did a raw import. The docs for that say "Remember too that the import is not actually carried out by OODoc::File until a save and the imported data is therefore not immediately available." I suggest you try $container2->save;
and then re-load it right after importing styles and then see if Table.A1 shows up in doc2.odt's content.xml after the next save:
# load output file my $container2 = odfContainer( $outfile, create => 'text' ); $container2->raw_import("styles.xml"); # Carry out the import and reload it with the new styles. $container2->save; $container2 = odfContainer( $outfile ); my $doc2 = odfDocument ( container => $container2, part => 'content' ); # Load table from 'mytest.odt' my $table=$doc->getTable(0); # Get style from first cell in $table my $headerstyle=$doc->getStyle( $doc->getCell($table, 0, 0) ); # Create table in $doc2 my $newtable=$doc2->appendTable('newtable', 1, 1, 'table-style' => $doc->getStyle($table) ); # Set style of first cell in $newtable to 'Table1.A1' $doc2->cellStyle( $newtable, 0, 0, 'Table1.A1' ); # Write 'doc2.odt' to disk $container2->save;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With