fix bug#1572 and bug#2942 - Problems with files with over 200 row / or 30kb of filesize - patch originally by michal dot fapso at goldenboat dot net - tested and reviewed
git-svn-id: https://svn.php.net/repository/pear/packages/Spreadsheet_Excel_Writer/trunk@289242 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
parent
f70336321a
commit
366794efd7
|
|
@ -1297,9 +1297,9 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
8228 : Maximum Excel97 block size
|
8228 : Maximum Excel97 block size
|
||||||
-4 : Length of block header
|
-4 : Length of block header
|
||||||
-8 : Length of additional SST header information
|
-8 : Length of additional SST header information
|
||||||
= 8216
|
-8 : Arbitrary number to keep within _add_continue() limit = 8208
|
||||||
*/
|
*/
|
||||||
$continue_limit = 8216;
|
$continue_limit = 8208;
|
||||||
$block_length = 0;
|
$block_length = 0;
|
||||||
$written = 0;
|
$written = 0;
|
||||||
$this->_block_sizes = array();
|
$this->_block_sizes = array();
|
||||||
|
|
@ -1307,6 +1307,9 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
|
|
||||||
foreach (array_keys($this->_str_table) as $string) {
|
foreach (array_keys($this->_str_table) as $string) {
|
||||||
$string_length = strlen($string);
|
$string_length = strlen($string);
|
||||||
|
$headerinfo = unpack("vlength/Cencoding", $string);
|
||||||
|
$encoding = $headerinfo["encoding"];
|
||||||
|
$split_string = 0;
|
||||||
|
|
||||||
// Block length is the total length of the strings that will be
|
// Block length is the total length of the strings that will be
|
||||||
// written out in a single SST or CONTINUE block.
|
// written out in a single SST or CONTINUE block.
|
||||||
|
|
@ -1333,16 +1336,39 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
boundaries. Therefore, in some cases we need to reduce the
|
boundaries. Therefore, in some cases we need to reduce the
|
||||||
amount of available
|
amount of available
|
||||||
*/
|
*/
|
||||||
|
$align = 0;
|
||||||
|
|
||||||
|
// Only applies to Unicode strings
|
||||||
|
if ($encoding == 1) {
|
||||||
|
// Min string + header size -1
|
||||||
|
$header_length = 4;
|
||||||
|
|
||||||
|
if ($space_remaining > $header_length) {
|
||||||
|
// String contains 3 byte header => split on odd boundary
|
||||||
|
if (!$split_string && $space_remaining % 2 != 1) {
|
||||||
|
$space_remaining--;
|
||||||
|
$align = 1;
|
||||||
|
}
|
||||||
|
// Split section without header => split on even boundary
|
||||||
|
else if ($split_string && $space_remaining % 2 == 1) {
|
||||||
|
$space_remaining--;
|
||||||
|
$align = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$split_string = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($space_remaining > $header_length) {
|
if ($space_remaining > $header_length) {
|
||||||
// Write as much as possible of the string in the current block
|
// Write as much as possible of the string in the current block
|
||||||
$written += $space_remaining;
|
$written += $space_remaining;
|
||||||
|
|
||||||
// Reduce the current block length by the amount written
|
// Reduce the current block length by the amount written
|
||||||
$block_length -= $continue_limit - $continue;
|
$block_length -= $continue_limit - $continue - $align;
|
||||||
|
|
||||||
// Store the max size for this block
|
// Store the max size for this block
|
||||||
$this->_block_sizes[] = $continue_limit;
|
$this->_block_sizes[] = $continue_limit - $align;
|
||||||
|
|
||||||
// If the current string was split then the next CONTINUE block
|
// If the current string was split then the next CONTINUE block
|
||||||
// should have the string continue flag (grbit) set unless the
|
// should have the string continue flag (grbit) set unless the
|
||||||
|
|
@ -1384,13 +1410,19 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
This length is required to set the offsets in the BOUNDSHEET records since
|
This length is required to set the offsets in the BOUNDSHEET records since
|
||||||
they must be written before the SST records
|
they must be written before the SST records
|
||||||
*/
|
*/
|
||||||
$total_offset = array_sum($this->_block_sizes);
|
|
||||||
// SST information
|
$tmp_block_sizes = array();
|
||||||
$total_offset += 8;
|
$tmp_block_sizes = $this->_block_sizes;
|
||||||
if (!empty($this->_block_sizes)) {
|
|
||||||
$total_offset += (count($this->_block_sizes)) * 4; // add CONTINUE headers
|
$length = 12;
|
||||||
|
if (!empty($tmp_block_sizes)) {
|
||||||
|
$length += array_shift($tmp_block_sizes); // SST
|
||||||
}
|
}
|
||||||
return $total_offset;
|
while (!empty($tmp_block_sizes)) {
|
||||||
|
$length += 4 + array_shift($tmp_block_sizes); // CONTINUEs
|
||||||
|
}
|
||||||
|
|
||||||
|
return $length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1407,9 +1439,31 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
function _storeSharedStringsTable()
|
function _storeSharedStringsTable()
|
||||||
{
|
{
|
||||||
$record = 0x00fc; // Record identifier
|
$record = 0x00fc; // Record identifier
|
||||||
|
$length = 0x0008; // Number of bytes to follow
|
||||||
|
$total = 0x0000;
|
||||||
|
|
||||||
|
// Iterate through the strings to calculate the CONTINUE block sizes
|
||||||
|
$continue_limit = 8208;
|
||||||
|
$block_length = 0;
|
||||||
|
$written = 0;
|
||||||
|
$continue = 0;
|
||||||
|
|
||||||
// sizes are upside down
|
// sizes are upside down
|
||||||
$this->_block_sizes = array_reverse($this->_block_sizes);
|
$tmp_block_sizes = $this->_block_sizes;
|
||||||
$length = array_pop($this->_block_sizes) + 8; // First block size plus SST information
|
// $tmp_block_sizes = array_reverse($this->_block_sizes);
|
||||||
|
|
||||||
|
// The SST record is required even if it contains no strings. Thus we will
|
||||||
|
// always have a length
|
||||||
|
//
|
||||||
|
if (!empty($tmp_block_sizes)) {
|
||||||
|
$length = 8 + array_shift($tmp_block_sizes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No strings
|
||||||
|
$length = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Write the SST block header information
|
// Write the SST block header information
|
||||||
$header = pack("vv", $record, $length);
|
$header = pack("vv", $record, $length);
|
||||||
|
|
@ -1417,18 +1471,14 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
$this->_append($header . $data);
|
$this->_append($header . $data);
|
||||||
|
|
||||||
|
|
||||||
// Iterate through the strings to calculate the CONTINUE block sizes
|
|
||||||
$continue_limit = 8216;
|
|
||||||
$block_length = 0;
|
|
||||||
$written = 0;
|
|
||||||
$continue = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: not good for performance */
|
/* TODO: not good for performance */
|
||||||
foreach (array_keys($this->_str_table) as $string) {
|
foreach (array_keys($this->_str_table) as $string) {
|
||||||
|
|
||||||
$string_length = strlen($string);
|
$string_length = strlen($string);
|
||||||
$encoding = 0; // assume there are no Unicode strings
|
$headerinfo = unpack("vlength/Cencoding", $string);
|
||||||
|
$encoding = $headerinfo["encoding"];
|
||||||
$split_string = 0;
|
$split_string = 0;
|
||||||
|
|
||||||
// Block length is the total length of the strings that will be
|
// Block length is the total length of the strings that will be
|
||||||
|
|
@ -1459,6 +1509,30 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
|
|
||||||
// Unicode data should only be split on char (2 byte) boundaries.
|
// Unicode data should only be split on char (2 byte) boundaries.
|
||||||
// Therefore, in some cases we need to reduce the amount of available
|
// Therefore, in some cases we need to reduce the amount of available
|
||||||
|
// space by 1 byte to ensure the correct alignment.
|
||||||
|
$align = 0;
|
||||||
|
|
||||||
|
// Only applies to Unicode strings
|
||||||
|
if ($encoding == 1) {
|
||||||
|
// Min string + header size -1
|
||||||
|
$header_length = 4;
|
||||||
|
|
||||||
|
if ($space_remaining > $header_length) {
|
||||||
|
// String contains 3 byte header => split on odd boundary
|
||||||
|
if (!$split_string && $space_remaining % 2 != 1) {
|
||||||
|
$space_remaining--;
|
||||||
|
$align = 1;
|
||||||
|
}
|
||||||
|
// Split section without header => split on even boundary
|
||||||
|
else if ($split_string && $space_remaining % 2 == 1) {
|
||||||
|
$space_remaining--;
|
||||||
|
$align = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$split_string = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($space_remaining > $header_length) {
|
if ($space_remaining > $header_length) {
|
||||||
// Write as much as possible of the string in the current block
|
// Write as much as possible of the string in the current block
|
||||||
|
|
@ -1469,7 +1543,7 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
$string = substr($string, $space_remaining);
|
$string = substr($string, $space_remaining);
|
||||||
|
|
||||||
// Reduce the current block length by the amount written
|
// Reduce the current block length by the amount written
|
||||||
$block_length -= $continue_limit - $continue;
|
$block_length -= $continue_limit - $continue - $align;
|
||||||
|
|
||||||
// If the current string was split then the next CONTINUE block
|
// If the current string was split then the next CONTINUE block
|
||||||
// should have the string continue flag (grbit) set unless the
|
// should have the string continue flag (grbit) set unless the
|
||||||
|
|
@ -1489,7 +1563,8 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
// Write the CONTINUE block header
|
// Write the CONTINUE block header
|
||||||
if (!empty($this->_block_sizes)) {
|
if (!empty($this->_block_sizes)) {
|
||||||
$record = 0x003C;
|
$record = 0x003C;
|
||||||
$length = array_pop($this->_block_sizes);
|
$length = array_shift($tmp_block_sizes);
|
||||||
|
|
||||||
$header = pack('vv', $record, $length);
|
$header = pack('vv', $record, $length);
|
||||||
if ($continue) {
|
if ($continue) {
|
||||||
$header .= pack('C', $encoding);
|
$header .= pack('C', $encoding);
|
||||||
|
|
@ -1510,5 +1585,7 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue