Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Manier les formats des cellules Excel avec Perl 5

7 décembre 2011

Il y a quelque temps, j’ai travaillé sur un projet Perl 5 qui consistait à manipuler des fichiers Excel via les modules CPAN Spreadsheet::ParseExcel et Spreadsheet::WriteExcel.

Ce projet consistait à recopier certaines cellules d’un fichier A vers un fichier B en conservant le format de celles-ci.

Mon premier réflexe a été d’appliquer le format de la cellule que je recopie à la cellule dans laquelle j’écris. Ce qui donne :

#!/usr/bin/perl -w

use strict;
use Spreadsheet::ParseExcel;
use Spreadsheet::WriteExcel;

#Lecture
my $parser   = Spreadsheet::ParseExcel->new();
my $xls_r = $parser->parse('fichierA.xls');

#Ecriture
my $xls_w = Spreadsheet::WriteExcel->new('fichierB.xls');
my $worksheet_w = $xls_w->add_worksheet();

#Vérification
if ( !defined $xls_r ) {
    die $parser->error() . "\n";
}

#valeurs min/max
my ( $row_min, $row_max ) = (0, 54);
my ( $col_min, $col_max ) = (0, 23);

#traitement
my $worksheet_r = $xls_r->worksheet(0);

for my $col ( $col_min .. $col_max ) {
  for my $row ( $row_min .. $row_max ) {
    my $cell = $worksheet_r->get_cell( $row, 0);
    next unless $cell;

    #On récupère le format
    my $format = $cell->get_format();

    #On écrit
    $worksheet_w->write($row, 0, $cell->value(), %$format);
  }
}

Oui mais voilà, si le contenu des cellules est bien recopié, le format lui n’est absolument pas conservé… Et pour cause ! Entre les modules CPAN Spreadsheet::ParseExcel et Spreadsheet::WriteExcel le format n’est pas du tout exprimé de la même façon !

La solution est donc de convertir le format à la main !

Voici les morceaux de script qui permettent de faire ça, propriété par propriété.

Font

#Font
if(my $font = $format_r->{Font}) {
  $format_w->set_font($font->{Name});
  $format_w->set_bold($font->{Bold});
  $format_w->set_italic($font->{Italic});
  $format_w->set_size($font->{Height});
  $format_w->set_underline($font->{UnderlineStyle});
  $format_w->set_color($font->{Color});
  $format_w->set_font_strikeout($font->{Strikeout});
  $format_w->set_font_script($font->{Super});
}

Protection

#Protection
$format_w->set_locked($format_r->{Lock});
$format_w->set_hidden($format_r->{Hidden});

Alignment

#Alignment
my $alignH = $format_r->{AlignH};

if($alignH == 1) {
  $format_w->set_align('left');
}
elsif($alignH == 2) {
  $format_w->set_align('center');
}
elsif($alignH == 3) {
  $format_w->set_align('right');
}
elsif($alignH == 4) {
  $format_w->set_align('fill');
}
elsif($alignH == 5) {
  $format_w->set_align('justify');
}
elsif($alignH == 6) {
  $format_w->set_align('center_across');
}

#AlignmentV
my $alignV = $format_r->{AlignV};

if($alignV == 0) {
  $format_w->set_align('top');
}
elsif($alignV == 1) {
  $format_w->set_align('vcenter');
}
elsif($alignV == 2) {
  $format_w->set_align('bottom');
}
elsif($alignV == 3) {
  $format_w->set_align('vjustify');
}

Fill

#Fill
if(my $fill = $format_r->{Fill}) {
  $format_w->set_pattern(@$fill[0]);
  $format_w->set_fg_color(@$fill[1]);
  $format_w->set_bg_color(@$fill[2]);
}

Border style

#Border style
if(my $borderStyle = $format_r->{BdrStyle}) {
  $format_w->set_left(@$borderStyle[0]);
  $format_w->set_right(@$borderStyle[1]);
  $format_w->set_top(@$borderStyle[2]);
  $format_w->set_bottom(@$borderStyle[3]);
}

Border Color

#Border color
if(my $borderColor = $format_r->{BdrColor}) {
  $format_w->set_left_color(@$borderColor[0]);
  $format_w->set_right_color(@$borderColor[1]);
  $format_w->set_top_color(@$borderColor[2]);
  $format_w->set_bottom_color(@$borderColor[3]);
}

Diagonal Cell Borders

#Diagonal Cell Borders
if(my $borderDiag = $format_r->{BdrDiag}) {
  $format_w->set_format_properties(diag_type => @$borderDiag[0], diag_border => @$borderDiag[1], diag_color => @$borderDiag[2],);
}

Les autres propriétés

#Le reste
$format_w->set_indent($format_r->{Indent});
$format_w->set_text_wrap($format_r->{Wrap});
$format_w->set_shrink($format_r->{Shrink});
$format_w->set_rotation($format_r->{Rotate});
$format_w->set_text_justlast($format_r->{JustLast});

Vous êtes maintenant en mesure d’exploiter correctement le style de vos cellules Excel !

Commentaires