So I had this huge bunch of Spreadsheet::WriteExcel code where I was generating Excel sheets from some statistics I was gathering and I noticed that everytime I opened the Excel file I got a message with something along the lines “File error: data may have been lost”, but on a casual look the spreadsheet looked fine… but of course the devil is in the details. It turns out that if you happen to Spreadsheet::WriteExcel::write
in the same cell twice (or more I guess đ ) that error message is what my Excel produces…. So how to find where the problem is… in this huge bunch of writes…
Enter Adam Kennedy’s excellent Aspect library for Perl, a truly brilliant module!! Thanks Adam!
How did I use it in this case? Here goes…
.... lots of other code....
use Aspect;
my $pointcut = call qr/Spreadsheet::WriteExcel::Worksheet::write$/;
# Observe the $ at the end, otherwise write_string will also match, and we don't want that
...... code passes ...
sub in_my_big_excel_write_block {
my %spcoords = ();
my $before_write = before {
my @args = @{$_->params};
if ( $spcoords{$args[1]}{$args[2]} ) {
croak "Will do double write at coord: ["
. $args[1] . "," . $args[2] . "] = >" . $args[3] . "<\n"
. "Previous write at coord: ["
. $args[1] . "," . $args[2] . "] = >" .
$spcoords{$args[1]}{$args[2]} . "<\n";
}
$spcoords{$args[1]}{$args[2]} = $args[3];
} $pointcut;
.... lots of $worksheet->write(...) code....
}
Now my poor perl script will die with a message telling me where and what I tried to write double and what I wrote there previously, now it’s easy to find!
đ
A more general debugging tip would be this simple “before” advice:
before {
if( ($cnt % 1000) == 0 ) {
my @args = @{$_->params};
print "Calling " . $_->sub_name . " with args : " . Dumper(@args) . "\n";
sleep 1;
}
$cnt++;
} $pointcut;
Neat huh!? And trust me, this is only some small simple example of the power of the Aspect library.