Tuesday, January 19, 2010

Quick perl script to convert .cvs to Excel .xml

I've got a number of programs that write out data in .cvs format, for those customers who want to import it into a spreadsheet. It would be much more convenient if I could actually write it out as an Excel spreadsheet, for a number of reasons. There are a couple of Perl/Python programs out there, but they're usually way too complicated - they're designed to take something you have no control over and fix it. This is a quick and dirty perl script designed to take a well-formed .cvs file, and convert it.


#!/usr/bin/perl;

use strict;
use warnings;
use Text::CSV_XS;
use Spreadsheet::WriteExcel;
my $row = 0;


my $infile = $ARGV[0];

open (my $fh, $infile) or die "$infile: $!";

my $outfile = "$infile";
if ($infile =~ /\.csv/) {
    $outfile =~ s/\.csv/.xls/;
}
else {
   $outfile = $infile . ".xls";
}

my $workbook = Spreadsheet::WriteExcel->;new($outfile);
my $worksheet = $workbook->;add_worksheet("sheet1");

my $csv = Text::CSV_XS->new ({ binary => 1, allow_whitespace => 1 });

while (my $rowdata = $csv->getline ($fh)) {
    my @rowdata = @$rowdata;
    foreach my $col (0 .. $#rowdata) {
        my $field = $rowdata[$col] || "";
        $worksheet->write($row, $col, $field);
    }
    $row++;
}

close $fh or die "$fh:  $!";

Note the'allow_whitespace' parameter on the output file open.  This is one that's driven a lot of folks nuts.  Strict CSV grammar says that there is no whitespace in between delimiters, i.e.

"testing",1,2,3,"four","five",6

However, if you're writing out numbers with a trailing sign (did I mention I'm a COBOL programmer?), you're going to get a space there with positive numbers:

"testing",1 ,2 , etc.

Excel will see these as 'Number stored as text' and give you an error, and refuse to format them nicely.  The 'allow_whitespace' parameter eliminates this.

No comments:

Post a Comment