// Split the range into 2 cell refs
if (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\:([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) {
- list($cell1, $cell2) = split(':', $range);
+ list($cell1, $cell2) = preg_split('/:/', $range);
} elseif (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\.\.([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) {
- list($cell1, $cell2) = split('\.\.', $range);
+ list($cell1, $cell2) = preg_split('/\.\./', $range);
} else {
// TODO: use real error codes
$class = 2; // as far as I know, this is magick.
// Split the ref at the ! symbol
- list($ext_ref, $range) = split('!', $token);
+ list($ext_ref, $range) = preg_split('/!/', $token);
// Convert the external reference part (different for BIFF8)
if ($this->_BIFF_version == 0x0500) {
}
// Split the range into 2 cell refs
- list($cell1, $cell2) = split(':', $range);
+ list($cell1, $cell2) = preg_split('/:/', $range);
// Convert the cell references
if (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/", $cell1)) {
$class = 2; // as far as I know, this is magick.
// Split the ref at the ! symbol
- list($ext_ref, $cell) = split('!', $cell);
+ list($ext_ref, $cell) = preg_split('/!/', $cell);
// Convert the external reference part (different for BIFF8)
if ($this->_BIFF_version == 0x0500) {
// Check if there is a sheet range eg., Sheet1:Sheet2.
if (preg_match("/:/", $ext_ref)) {
- list($sheet_name1, $sheet_name2) = split(':', $ext_ref);
+ list($sheet_name1, $sheet_name2) = preg_split('/:/', $ext_ref);
$sheet1 = $this->_getSheetIndex($sheet_name1);
if ($sheet1 == -1) {
// Check if there is a sheet range eg., Sheet1:Sheet2.
if (preg_match("/:/", $ext_ref)) {
- list($sheet_name1, $sheet_name2) = split(':', $ext_ref);
+ list($sheet_name1, $sheet_name2) = preg_split('/:/', $ext_ref);
$sheet1 = $this->_getSheetIndex($sheet_name1);
if ($sheet1 == -1) {
default:
// if it's a reference
if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and
- !ereg("[0-9]",$this->_lookahead) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.') and
($this->_lookahead != '!'))
{
}
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and
- !ereg("[0-9]",$this->_lookahead) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.'))
{
return $token;
}
// If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1)
elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and
- !ereg("[0-9]",$this->_lookahead) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.'))
{
return $token;
}
// if it's a range (A1:A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
- !ereg("[0-9]",$this->_lookahead))
+ !preg_match("/[0-9]/",$this->_lookahead))
{
return $token;
}
// if it's a range (A1..A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
- !ereg("[0-9]",$this->_lookahead))
+ !preg_match("/[0-9]/",$this->_lookahead))
{
return $token;
}
// If it's an external range like Sheet1!A1 or Sheet1:Sheet2!A1:B2
elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and
- !ereg("[0-9]",$this->_lookahead))
+ !preg_match("/[0-9]/",$this->_lookahead))
{
return $token;
}
// If it's an external range like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2
elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and
- !ereg("[0-9]",$this->_lookahead))
+ !preg_match("/[0-9]/",$this->_lookahead))
{
return $token;
}
return $token;
}
// If it's a string (of maximum 255 characters)
- elseif (ereg("^\"[^\"]{0,255}\"$",$token))
+ elseif (preg_match("/^\"[^\"]{0,255}\"$/",$token))
{
return $token;
}
// if it's a function call
- elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$token) and ($this->_lookahead == "("))
+ elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "("))
{
return $token;
}
return $result;
}
// if it's a function call
- elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$this->_current_token))
+ elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token))
{
$result = $this->_func();
return $result;
$row = $match[2];
// Convert base26 column string to number
- $chars = split('', $col);
+ $chars = preg_split('//', $col);
$expn = 0;
$col = 0;
*/
function setInputEncoding($encoding)
{
- global $encoding_string;
+ global $encoding_string;
if ($encoding != 'UTF-16LE' && !function_exists('iconv')) {
die("Using an input encoding other than UTF-16LE requires PHP support for iconv");
}
// parameters accordingly.
// Split the dir name and sheet name (if it exists)
/*if (preg_match("/\#/", $url)) {
- list($dir_long, $sheet) = split("\#", $url);
+ list($dir_long, $sheet) = preg_split("/\#/", $url);
} else {
$dir_long = $url;
}
if (isset($sheet)) {
$link_type |= 0x08;
$sheet_len = pack("V", strlen($sheet) + 0x01);
- $sheet = join("\0", split('', $sheet));
+ $sheet = join("\0", preg_split('//', $sheet));
$sheet .= "\0\0\0";
} else {
$sheet_len = '';
$dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0";
// Store the long dir name as a wchar string (non-null terminated)
- //$dir_long = join("\0", split('', $dir_long));
+ //$dir_long = join("\0", preg_split('//', $dir_long));
$dir_long = $dir_long . "\0";
// Pack the lengths of the dir strings
$this->Spreadsheet_Excel_Writer_BIFFwriter();
$this->_filename = $filename;
- $this->_parser =& new Spreadsheet_Excel_Writer_Parser($this->_byte_order, $this->_BIFF_version);
+ $this->_parser = new Spreadsheet_Excel_Writer_Parser($this->_byte_order, $this->_BIFF_version);
$this->_1904 = 0;
$this->_activesheet = 0;
$this->_firstsheet = 0;
$this->_fileclosed = 0;
$this->_biffsize = 0;
$this->_sheetname = 'Sheet';
- $this->_tmp_format =& new Spreadsheet_Excel_Writer_Format($this->_BIFF_version);
+ $this->_tmp_format = new Spreadsheet_Excel_Writer_Format($this->_BIFF_version);
$this->_worksheets = array();
$this->_sheetnames = array();
$this->_formats = array();
8228 : Maximum Excel97 block size
-4 : Length of block header
-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;
$written = 0;
$this->_block_sizes = array();
foreach (array_keys($this->_str_table) as $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
// written out in a single SST or CONTINUE block.
boundaries. Therefore, in some cases we need to reduce the
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) {
// Write as much as possible of the string in the current block
$written += $space_remaining;
// 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
- $this->_block_sizes[] = $continue_limit;
+ $this->_block_sizes[] = $continue_limit - $align;
// If the current string was split then the next CONTINUE block
// should have the string continue flag (grbit) set unless the
This length is required to set the offsets in the BOUNDSHEET records since
they must be written before the SST records
*/
- $total_offset = array_sum($this->_block_sizes);
- // SST information
- $total_offset += 8;
- if (!empty($this->_block_sizes)) {
- $total_offset += (count($this->_block_sizes)) * 4; // add CONTINUE headers
+
+ $tmp_block_sizes = array();
+ $tmp_block_sizes = $this->_block_sizes;
+
+ $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;
}
/**
function _storeSharedStringsTable()
{
$record = 0x00fc; // Record identifier
- // sizes are upside down
- $this->_block_sizes = array_reverse($this->_block_sizes);
- $length = array_pop($this->_block_sizes) + 8; // First block size plus SST information
-
- // Write the SST block header information
- $header = pack("vv", $record, $length);
- $data = pack("VV", $this->_str_total, $this->_str_unique);
- $this->_append($header . $data);
-
+ $length = 0x0008; // Number of bytes to follow
+ $total = 0x0000;
// Iterate through the strings to calculate the CONTINUE block sizes
- $continue_limit = 8216;
+ $continue_limit = 8208;
$block_length = 0;
$written = 0;
$continue = 0;
+ // sizes are upside down
+ $tmp_block_sizes = $this->_block_sizes;
+ // $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
+ $header = pack("vv", $record, $length);
+ $data = pack("VV", $this->_str_total, $this->_str_unique);
+ $this->_append($header . $data);
/* TODO: not good for performance */
foreach (array_keys($this->_str_table) as $string) {
$string_length = strlen($string);
- $encoding = 0; // assume there are no Unicode strings
+ $headerinfo = unpack("vlength/Cencoding", $string);
+ $encoding = $headerinfo["encoding"];
$split_string = 0;
// Block length is the total length of the strings that will be
// Unicode data should only be split on char (2 byte) boundaries.
// 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) {
// Write as much as possible of the string in the current block
$string = substr($string, $space_remaining);
// 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
// should have the string continue flag (grbit) set unless the
// Write the CONTINUE block header
if (!empty($this->_block_sizes)) {
$record = 0x003C;
- $length = array_pop($this->_block_sizes);
+ $length = array_shift($tmp_block_sizes);
+
$header = pack('vv', $record, $length);
if ($continue) {
$header .= pack('C', $encoding);