Skip Menu |

This queue is for tickets about the Spreadsheet-WriteExcel CPAN distribution.

Maintainer(s)' notes

If you are reporting a bug in Spreadsheet::WriteExcel here are some pointers

1) State the issues as clearly and as concisely as possible. A simple program or Excel test file (see below) will often explain the issue better than a lot of text.

2) Provide information on your system, version of perl and module versions. The following program will generate everything that is required. Put this information in your bug report.

    #!/usr/bin/perl -w

    print "\n    Perl version   : $]";
    print "\n    OS name        : $^O";
    print "\n    Module versions: (not all are required)\n";

    my @modules = qw(
                      Spreadsheet::WriteExcel
                      Parse::RecDescent
                      File::Temp
                      OLE::Storage_Lite
                      IO::Stringy
                      Spreadsheet::ParseExcel
                      Scalar::Util
                      Unicode::Map
                    );

    for my $module (@modules) {
        my $version;
        eval "require $module";

        if (not $@) {
            $version = $module->VERSION;
            $version = '(unknown)' if not defined $version;
        }
        else {
            $version = '(not installed)';
        }

        printf "%21s%-24s\t%s\n", "", $module, $version;
    }

    __END__

3) Upgrade to the latest version of Spreadsheet::WriteExcel (or at least test on a system with an upgraded version). The issue you are reporting may already have been fixed.

4) Create a small but complete example program that demonstrates your problem. The program should be as small as possible. At the same time it should be a complete program that generates an Excel file. If the Spreadsheet::WriteExcel section is part of a much larger program then simplify it down to the essentials. Simulate any DB reads with an array.

5) Say if you tested with Excel, OpenOffice, Gnumeric or something else. Say which version of that application you used.

6) If you are submitting a patch you should check with the author whether the issue has already been patched or if a fix is in the works. Patches should be accompanied by test cases.

Asking a question

If you would like to ask a more general question there is the Spreadsheet::WriteExcel Google Group.

Report information
The Basics
Id: 2925
Status: resolved
Priority: 0/
Queue: Spreadsheet-WriteExcel

People
Owner: jmcnamara [...] cpan.org
Requestors: jon.daniel [...] intercity-comms.com
Cc:
AdminCc:

Bug Information
Severity: Unimportant
Broken in: 0.37
Fixed in: (no value)



Subject: Writing a long formula (>255 chars) to the same cell twice causes Excel crash
$ perl -v This is perl, version 5.005_03 built for aix $ uname -a AIX 59H 3 4 0009388AA100 $ oslevel 4.3.3.0 Hi, I currently use the Spreadsheet::WriteExcel module to convert some manually produced HTML reports into Excel format - I've come across a problem when trying to write long strings to a cell repeatedly. e.g. $test = $worksheet->write(1,1,long_string($str)); $test = $worksheet->write(1,1,long_string($str)); When trying to load the produced spreadsheet using Excel, I consistently get a memory error, and a prompt crash of Excel (with "The instruction at 0x301ee91e referenced memory at 0x00000000. The memory could not be read"). I've attached a test perl script which should show this in more detail. I'm attempting to create a workaround (i.e. Make sure I only write long strings once!), but this may be tricky considering my source information.
#!/usr/bin/perl -w # Converts a HTML file into Excel format. (badly) # Author: Jonathan Daniel - jon.daniel@intercity-comms.com # Version: 1.0 # Date: 30/08/02 # Description: # Takes a html file, and converts it into an excel file. # Designed for where I have good control over the html file being produced, # and if your data is not organised into tables (or the tables are nested) # then it'll produce rather unsatisfactory results. # # Version 1.1, 07/05/03 # "use strict". # Occasionally HTML::Parser would decide it was only going to spit out half # of the detail between <td> tags, so I've had to buffer to prevent data loss. # Now recognises the th tag, and handles hr better. # Space stripping on number columns improved. # use strict; use Spreadsheet::WriteExcel; # define variables: my $outputfile = ""; # Parse arguments if(@ARGV < 1) { print "test.pl outputfile"; exit(1); } $outputfile = $ARGV[0]; # Define variables # Setup spreadsheet my $workbook = Spreadsheet::WriteExcel->new($outputfile); my $prevtext = ""; my $worksheet = $workbook->addworksheet(); $worksheet->hide_gridlines(2); # Initialise very long string... $prevtext = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"; # Attempt to write my $test = 0; $test = $worksheet->write_string(1,1,$prevtext); if($test == -3) { # string was too long to be written use long string instead to write as a formula... $test = $worksheet->write(1,1,long_string($prevtext)); } # Ok, now try writing to the same cell again, with the same long string # Excel will now crash when trying to load this spreadsheet $test = $worksheet->write(1,1,long_string($prevtext)); # Note that my source sometimes splits large strings up, so I have to rewrite a # cell occasionally - rewriting works fine, but not for long strings - I think # most formulas are OK though, though I don't tend to use them except for # long_string() # Also fails, just attempting to write a long string twice - e.g. #$test = $worksheet->write(1,1,long_string($prevtext)); #$test = $worksheet->write(1,1,long_string($prevtext)); # Note the following double write does not crash Excel! #$test = $worksheet->write(2,2,"=A1"); #$test = $worksheet->write(2,2,"=A1"); #---------------------------------------- #sub tag #{ # my($tag, $num, $attr) = @_; # $inside{$tag} += $num; # if(@_ eq "table") # { # $intable++; # } # if(@_ eq "/table") # { # $intable++; # } # if($tag eq "td") # { # if($tdcheck == 0) # { # $col++; # if( $col > $maxcol) # { # $maxcol = $col; # } # $tdcheck++; # } # else # { # $tdcheck--; # } # } # if($tag eq "br") # { # $row++; # $col=0; # } # if($tag eq "tr") # { # if($col >= 1) # { # $row++; # $col = 0; # } # } # if($tag eq "th") # { # if($col >= 1) # { # $row++; # $col = 0; # } # } # # if($tag eq "hr") # { # $row++; # $col = 0; ## apply changes to column using format11 # $worksheet->set_row($row, undef, $format11); # $row++; # } # # # if($tag eq "b") # { # return; # } # # if($tag eq "td") # { # $prevtext = ""; # if($attr){ # $fieldtype = 0; # if(exists($attr->{style})) # { # if($attr->{style} eq "vnd.ms-excel.numberformat:@") # { # $fieldtype = 1; # } # if($attr->{style} eq "vnd.ms-excel.numberformat:0") # { # $fieldtype = 2; # } # if($attr->{style} eq "vnd.ms-excel.numberformat:0.00") # { # $fieldtype = 3; # } # if($attr->{style} eq "vnd.ms-excel.numberformat:dd/mm/yy") # { # $fieldtype = 4; # } # } # } # } #} # #sub text #{ # return if(substr($_[0],0,9) eq "<!DOCTYPE"); # return if $inside{script} || $inside{style} || $inside{title}; # return if ($_[0] !~ /\S/); # my $subs = ""; # my $test = 0; # my $test2 = 0; # # if ( $inside{table} ) # { # $prevtext = $prevtext . $_[0]; # if( $inside{b} ) # { # if($fieldtype == 0) # { # $worksheet->write($row,$col,$prevtext, $format1); # } # if($fieldtype == 1) # { # $worksheet->write($row,$col,$prevtext, $format1); # } # if($fieldtype == 2) # { # $prevtext =~ s/ //g; # $worksheet->write($row,$col,$prevtext, $format8); # } # if($fieldtype == 3) # { # $prevtext =~ s/ //g; # $worksheet->write($row,$col,$prevtext,$format9); # } # if($fieldtype == 4) # { # $worksheet->write($row,$col,$prevtext,$format10); # } # # if ($colarray[$col] < length($prevtext)) # { # $colarray[$col] = length($prevtext); # } # } # else # { # if($fieldtype == 1) # { # $test = $worksheet->write_string($row,$col,$prevtext); # if($test == -3) # { # print "string too long - "; # $test = $worksheet->write($row,$col,long_string($prevtext)); # print $test . " " . long_string($prevtext); # } # } # if($fieldtype == 0) # { # $worksheet->write($row,$col,$prevtext); # } # if($fieldtype == 2) # { # $prevtext =~ s/ //g; # $worksheet->write($row,$col,$prevtext,$format5); # } # if($fieldtype == 3) # { # $prevtext =~ s/ //g; # $worksheet->write($row,$col,$prevtext,$format6); # } # if($fieldtype == 4) # { # $prevtext =~ s/ //g; # $worksheet->write($row,$col,$prevtext,$format7); # } # if ($colarray[$col] < length($prevtext)) # { # $colarray[$col] = length($prevtext); # } # } # } # else # { # $subs = $_[0]; # $subs =~ s/\n//g; # if( $inside{h1} || $inside{h2} || $inside{h3} || $inside{h4} ) # { # if( $inside{h1} ) # { # $col = 0; # $worksheet->write($row,$col,$subs, $format2); # $row+=2; # } # if( $inside{h2} ) # { # $col=0; # $worksheet->write($row,$col,$subs, $format3); # $row+=2; # } # } # else # { # $col = 0; # $worksheet->write($row,$col,$subs); # $row++; # } # } #} ###################################################################### # # long_string($str) # # Converts long strings into an Excel string concatenation formula. # The concatenation is inserted between words to improve legibility. # # returns: An Excel formula if string is longer than 255 chars. # The unmodified string otherwise. # sub long_string { my $str = shift; my $limit = 255; # Return short strings return $str if length $str <= $limit; # Split the line at word boundaries where possible my @segments = $str =~ m[.{1,$limit}$|.{1,$limit}\b|.{1,$limit}]sog; # Join the string back together with quotes and Excel concatenation $str = join '"&"', @segments; # Add formatting to convert the string to a formula string return $str = qq(="$str"); }
I cannot say why Excel crashes when you write two formulas to the same cell. As a guess I would say that it is probably due to an incorrect interpretation of the data as an internal Excel optimisation called a "shared formula". They way to avoid this is to not write more than one formula to the same cell. I appreciate that this may be difficult in your case but if I modified Spreadsheet::WriteExcel to keep track of every cell that is written it would incur a potentially large memory overhead. However, since you are only using formulas to workaround the 255 character string limit you could avoid this problem altogether by moving to the Excel 97 beta version of the module. See: http://freshmeat.net/projects/writeexcel/#comment-24916 This will eventually become the official CPAN version. John. --