Initial Commit
This commit is contained in:
317
database/perl/vendor/lib/Spreadsheet/WriteExcel/BIFFwriter.pm
vendored
Normal file
317
database/perl/vendor/lib/Spreadsheet/WriteExcel/BIFFwriter.pm
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
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.40';
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# 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__
|
||||
|
||||
=encoding latin1
|
||||
|
||||
=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
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user