| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- # DISCLAIMER OF WARRANTY
- # Because this software is licensed free of charge, there is no warranty for the software,
- # to the extent permitted by applicable law. Except when otherwise stated in writing
- # the copyright holders and/or other parties provide the software "as is" without
- # warranty of any kind, either expressed or implied, including, but not limited to,
- # the implied warranties of merchantability and fitness for a particular purpose.
- # The entire risk as to the quality and performance of the software is with you.
- # Should the software prove defective, you assume the cost of all necessary
- # servicing, repair, or correction.
- # In no event unless required by applicable law or agreed to in writing will any
- # copyright holder, or any other party who may modify and/or redistribute the software
- # as permitted by the above licence, be liable to you for damages, including any general,
- # special, incidental, or consequential damages arising out of the use or inability
- # to use the software (including but not limited to loss of data or data being rendered
- # inaccurate or losses sustained by you or third parties or a failure of the software
- # to operate with any other software), even if such holder or other party
- # has been advised of the possibility of such damages.
- # AUTHOR
- # John McNamara jmcnamara@cpan.org
- # COPYRIGHT
- # Copyright MM-MMX, John McNamara.
- # All Rights Reserved. This module is free software. It may be used,
- # redistributed and/or modified under the terms of
- # the Artistic License(full text of the Artistic License http://dev.perl.org/licenses/artistic.html).
- package Spreadsheet::WriteExcel::BIFFwriter;
- ###############################################################################
- #
- # BIFFwriter - An abstract base class for Excel workbooks and worksheets.
- #
- #
- # Used in conjunction with Spreadsheet::WriteExcel
- #
- # Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
- #
- # Documentation after __END__
- #
- use Exporter;
- use strict;
- use vars qw($VERSION @ISA);
- @ISA = qw(Exporter);
- $VERSION = '2.37';
- ###############################################################################
- #
- # Class data.
- #
- my $byte_order = '';
- my $BIFF_version = 0x0600;
- ###############################################################################
- #
- # new()
- #
- # Constructor
- #
- sub new {
- my $class = $_[0];
- my $self = {
- _byte_order => '',
- _data => '',
- _datasize => 0,
- _limit => 8224,
- _ignore_continue => 0,
- };
- bless $self, $class;
- $self->_set_byte_order();
- return $self;
- }
- ###############################################################################
- #
- # _set_byte_order()
- #
- # Determine the byte order and store it as class data to avoid
- # recalculating it for each call to new().
- #
- sub _set_byte_order {
- my $self = shift;
- if ($byte_order eq ''){
- # Check if "pack" gives the required IEEE 64bit float
- my $teststr = pack "d", 1.2345;
- my @hexdata =(0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
- my $number = pack "C8", @hexdata;
- if ($number eq $teststr) {
- $byte_order = 0; # Little Endian
- }
- elsif ($number eq reverse($teststr)){
- $byte_order = 1; # Big Endian
- }
- else {
- # Give up. I'll fix this in a later version.
- croak ( "Required floating point format not supported " .
- "on this platform. See the portability section " .
- "of the documentation."
- );
- }
- }
- $self->{_byte_order} = $byte_order;
- }
- ###############################################################################
- #
- # _prepend($data)
- #
- # General storage function
- #
- sub _prepend {
- my $self = shift;
- my $data = join('', @_);
- $data = $self->_add_continue($data) if length($data) > $self->{_limit};
- $self->{_data} = $data . $self->{_data};
- $self->{_datasize} += length($data);
- return $data;
- }
- ###############################################################################
- #
- # _append($data)
- #
- # General storage function
- #
- sub _append {
- my $self = shift;
- my $data = join('', @_);
- $data = $self->_add_continue($data) if length($data) > $self->{_limit};
- $self->{_data} = $self->{_data} . $data;
- $self->{_datasize} += length($data);
- return $data;
- }
- ###############################################################################
- #
- # _store_bof($type)
- #
- # $type = 0x0005, Workbook
- # $type = 0x0010, Worksheet
- # $type = 0x0020, Chart
- #
- # Writes Excel BOF record to indicate the beginning of a stream or
- # sub-stream in the BIFF file.
- #
- sub _store_bof {
- my $self = shift;
- my $record = 0x0809; # Record identifier
- my $length = 0x0010; # Number of bytes to follow
- my $version = $BIFF_version;
- my $type = $_[0];
- # According to the SDK $build and $year should be set to zero.
- # However, this throws a warning in Excel 5. So, use these
- # magic numbers.
- my $build = 0x0DBB;
- my $year = 0x07CC;
- my $bfh = 0x00000041;
- my $sfo = 0x00000006;
- my $header = pack("vv", $record, $length);
- my $data = pack("vvvvVV", $version, $type, $build, $year, $bfh, $sfo);
- $self->_prepend($header, $data);
- }
- ###############################################################################
- #
- # _store_eof()
- #
- # Writes Excel EOF record to indicate the end of a BIFF stream.
- #
- sub _store_eof {
- my $self = shift;
- my $record = 0x000A; # Record identifier
- my $length = 0x0000; # Number of bytes to follow
- my $header = pack("vv", $record, $length);
- $self->_append($header);
- }
- ###############################################################################
- #
- # _add_continue()
- #
- # Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
- # Excel 97 the limit is 8228 bytes. Records that are longer than these limits
- # must be split up into CONTINUE blocks.
- #
- # This function take a long BIFF record and inserts CONTINUE records as
- # necessary.
- #
- # Some records have their own specialised Continue blocks so there is also an
- # option to bypass this function.
- #
- sub _add_continue {
- my $self = shift;
- my $data = $_[0];
- my $limit = $self->{_limit};
- my $record = 0x003C; # Record identifier
- my $header;
- my $tmp;
- # Skip this if another method handles the continue blocks.
- return $data if $self->{_ignore_continue};
- # The first 2080/8224 bytes remain intact. However, we have to change
- # the length field of the record.
- #
- $tmp = substr($data, 0, $limit, "");
- substr($tmp, 2, 2, pack("v", $limit-4));
- # Strip out chunks of 2080/8224 bytes +4 for the header.
- while (length($data) > $limit) {
- $header = pack("vv", $record, $limit);
- $tmp .= $header;
- $tmp .= substr($data, 0, $limit, "");
- }
- # Mop up the last of the data
- $header = pack("vv", $record, length($data));
- $tmp .= $header;
- $tmp .= $data;
- return $tmp ;
- }
- ###############################################################################
- #
- # _add_mso_generic()
- #
- # Create a mso structure that is part of an Escher drawing object. These are
- # are used for images, comments and filters. This generic method is used by
- # other methods to create specific mso records.
- #
- # Returns the packed record.
- #
- sub _add_mso_generic {
- my $self = shift;
- my $type = $_[0];
- my $version = $_[1];
- my $instance = $_[2];
- my $data = $_[3];
- my $length = defined $_[4] ? $_[4] : length($data);
- # The header contains version and instance info packed into 2 bytes.
- my $header = $version | ($instance << 4);
- my $record = pack "vvV", $header, $type, $length;
- $record .= $data;
- return $record;
- }
- ###############################################################################
- #
- # For debugging
- #
- sub _hexout {
- my $self = shift;
- print +(caller(1))[3], "\n";
- my $data = join '', @_;
- my @bytes = unpack("H*", $data) =~ /../g;
- while (@bytes > 16) {
- print join " ", splice @bytes, 0, 16;
- print "\n";
- }
- print join " ", @bytes, "\n\n";
- }
- 1;
- __END__
- =head1 NAME
- BIFFwriter - An abstract base class for Excel workbooks and worksheets.
- =head1 SYNOPSIS
- See the documentation for Spreadsheet::WriteExcel
- =head1 DESCRIPTION
- This module is used in conjunction with Spreadsheet::WriteExcel.
- =head1 AUTHOR
- John McNamara jmcnamara@cpan.org
- =head1 COPYRIGHT
- © MM-MMX, John McNamara.
- All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
|