09.03.2017

Excel-Datei mit perl erzeugen

Hach, ich liebe perl! Hab ich das schon mal erwähnt? Bestimmt nicht.

Eine ganze Zeit lang habe ich ein etwas älteres perl-Modul für Excel-Spreadsheets verwendet. Beim Lesen der Anleitung fand ich kürzlich den Hinweis, dass es einen Nachfolger gibt, mit dem das neuere XML-Dokumentenformat erzeugt werden kann. Dieses Modul kann nahezu den kompletten Umfang von Excel-Spreadsheets ausreizen, inklusive Formatierung, Charts und Formeln.

Hier ist ein kurzes Beispiel für die Verwendung. Es liest die /etc/passwd eines Unix-Systems und erzeugt daraus eine kleine Exceltabelle. Als Schmankerl setzt es die Spaltenbreite und Autofilter für alle Spalten, so dass man z.B. alle Benutzer mit "nologin" filtern kann.

Vor der ersten Benutzung muss man das perl-Modul noch mit dem Befehl

# cpan install Excel::Writer::XLSX

(als root) installieren. In blau habe ich ein paar zusätzliche Kommentare an interessanten Stellen eingefügt.

#!/usr/bin/perl -w

use strict 'refs';
use strict 'vars';

use Excel::Writer::XLSX;

my %userlist;

# Spaltentitel
my @t_passwd =qw( USER PASSWD UID GID GECOS HOME SHELL );
# Spaltenbreiten, <0 heißt Spalte verbergen
my @f_passwd =qw(   20     -3  10  10    30   20    20 );

sub setfilter {
    my ($worksheet,$row,@colwidth)=@_;
    my $numcol=scalar(@colwidth);


# Autofilter für alle Spalten
    $worksheet->autofilter(0,0,$row,$numcol-1);
    for (my $i=0; $i<$numcol; ++$i) {
        my $w=$colwidth[$i];

        if ($w>0) {
            $worksheet->set_column( $i,$i, $w );
        }
        else {

# Breite setzen, kein Format, aber verstecken
            $worksheet->set_column( $i,$i, -$w, undef, 1);
        }
    }
}

sub collect_linux_passwd {
    my ($file)=@_;

    if (open(F,"<",$file)) {
        while (my $u=<F>) {
            chomp($u);
            my @user=split(/:/,$u);
            my $uname=$user[0];

# split löscht leere Felder am Ende

            $user[6]||="";
            $userlist{$uname}=[ @user ];
        }
        close(F);
    }
}

sub exceloutpasswd {
    my ($worksheet,$title,$list)=@_;
    my $row=0;


# eine ganze Zeile schreiben ($title ist ein Arrayref)
    $worksheet->write(0,0, $title);
    foreach my $i (sort(keys(%{$list}))) {
        ++$row;

# $list->{$i} ist ein Arrayref
        $worksheet->write($row, 0, $list->{$i});
    }
    setfilter($worksheet,$row,@f_passwd);
}

collect_linux_passwd("/etc/passwd");
my $workbook = Excel::Writer::XLSX->new('passwd.xlsx');
exceloutpasswd( $workbook->add_worksheet('unix users'), \@t_passwd, \%userlist );

$workbook->close();