Transferring table styles using OpenOffice::OODoc

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:

  • settings.xml
  • styles.xml
  • content.xml

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>
 ...
  • style:name="Table6" describes the style for the current table,
  • style:name="Table6.A" describes the style for column A of this table,
  • style:name="Table6.A1" describes the style for the cell A1

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.

Answers


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;

Need Your Help

How do I verify that an Android apk is signed with a release certificate?

android apk android-keystore

How can I check that an Android apk is signed with a release and not debug cert?

Sealed keyword in association with override

c# overriding sealed

Is it always necessary to follow the sealed keyword with override in the signature of a method like the below code: