35 votes

Transfert des styles de tableaux à l'aide d'OpenOffice::OODoc

Je tente de copier le formatage d'un tableau d'un fichier OpenOffice Writer à un autre... Je peux dire que j'écris le nom du style dans le second document, mais pas les données du style.

Je soupçonne que cela a quelque chose à voir avec le 'styles' partie de la odfContainer mais je ne sais pas comment l'écrire dans le deuxième document, notamment parce que lorsque j'inspecte le fichier $style dans le débogueur, il semble être identique à l'objet $doc qui a soi-disant chargé l'objet 'content' partie.

Voici ce que j'ai pour l'instant...

#! /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;

La raison pour laquelle je charge 'Table1.A1' comme le style de cellule est que j'ai trouvé ce qui suit profondément à l'intérieur $table lors de l'inspection dans le débogueur :

'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' 

Je sais que les attributs correspondent à ce que j'essaie de copier, et je sais aussi par expérience que le 'getStyle' renvoie la méthode style::name l'attribut... Je ne sais simplement pas comment passer de la définition de l'attribut style::name en utilisant l'attribut cellStyle pour que les données sous-jacentes soient réellement écrites dans le nouveau document.

Edit :

En décompressant le fichier OpenOffice, j'obtiens plusieurs fichiers xml :

  • paramètres.xml
  • styles.xml
  • contenu.xml

etc.

Le site 'styles' et 'content' les parties de la OdfContainer correspondent à styles.xml et content.xml. Styles.xml est un peu comme un fichier css, contenant les informations de style pour les différents niveaux d'en-tête d'un fichier ODF. Content.xml contient également des informations de style, un peu comme l'en-tête css dans un document html.

Voici la partie style du content.xml extraite du fichier odt (en fait un fichier similaire... je n'ai pas sauvegardé l'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" décrit le style de la table actuelle,
  • style:name="Tableau6.A" décrit le style de la colonne A de ce tableau,
  • style:name="Table6.A1" décrit le style de la cellule A1

Exportation brute de la section 'content.xml' du fichier d'entrée, puis importation brute dans le fichier de sortie. fait transférer des données d'un fichier à l'autre.

#! /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 Ensuite, en décompressant outfile.odt et en inspectant content.xml, on constate que le style a été transféré avec succès :

<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>

Maintenant que cela a été fait, je vais devoir charger et utiliser les styles de cellules dans le fichier $outcontainer .

1voto

Dave Scotese Points 150

Vous avez fait une importation brute. Les docs pour cela disent "Rappelez-vous aussi que l'importation n'est pas réellement effectuée par OODoc::File avant une sauvegarde et les données importées ne sont donc pas immédiatement disponibles". Je vous suggère d'essayer $container2->save; puis rechargez-le juste après l'importation des styles et voyez si Table.A1 apparaît dans le content.xml de doc2.odt après la prochaine sauvegarde :

# 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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X