From 42663073c54b6317e2f65aa7a201ad583ef5b140 Mon Sep 17 00:00:00 2001 From: Arcturus Date: Thu, 19 Sep 2024 20:44:10 +0900 Subject: [PATCH] update lib/Excel --- AvocadoEdition_Light/lib/Excel/itemexcel.xls | Bin 0 -> 33792 bytes .../lib/Excel/oleread.inc.php | 541 ++-- .../class.writeexcel_biffwriter.inc.php | 4 +- .../class.writeexcel_format.inc.php | 4 +- .../class.writeexcel_formula.inc.php | 33 +- .../class.writeexcel_olewriter.inc.php | 4 +- .../class.writeexcel_workbook.inc.php | 4 +- .../class.writeexcel_workbookbig.inc.php | 4 +- .../class.writeexcel_worksheet.inc.php | 4 +- AvocadoEdition_Light/lib/Excel/reader.php | 2166 ++++++++--------- 10 files changed, 1373 insertions(+), 1391 deletions(-) create mode 100644 AvocadoEdition_Light/lib/Excel/itemexcel.xls diff --git a/AvocadoEdition_Light/lib/Excel/itemexcel.xls b/AvocadoEdition_Light/lib/Excel/itemexcel.xls new file mode 100644 index 0000000000000000000000000000000000000000..d99bf6b64b5d5f302794c8c7cc7919e936fd5dac GIT binary patch literal 33792 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 = 1; - return false; - } - - $this->data = @file_get_contents($sFileName); - if (!$this->data) { - $this->error = 1; - return false; - } - //echo IDENTIFIER_OLE; - //echo 'start'; - if (substr($this->data, 0, 8) != IDENTIFIER_OLE) { - $this->error = 1; - return false; - } - $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); - $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS); - $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS); - $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS); - $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS); - - /* - echo $this->numBigBlockDepotBlocks." "; - echo $this->sbdStartBlock." "; - echo $this->rootStartBlock." "; - echo $this->extensionBlock." "; - echo $this->numExtensionBlocks." "; - */ - //echo "sbdStartBlock = $this->sbdStartBlock\n"; - $bigBlockDepotBlocks = array(); - $pos = BIG_BLOCK_DEPOT_BLOCKS_POS; - // echo "pos = $pos"; - $bbdBlocks = $this->numBigBlockDepotBlocks; - - if ($this->numExtensionBlocks != 0) { - $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; - } - - for ($i = 0; $i < $bbdBlocks; $i++) { - $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); - $pos += 4; - } - - - for ($j = 0; $j < $this->numExtensionBlocks; $j++) { - $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE; - $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); - - for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) { - $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); - $pos += 4; - } - - $bbdBlocks += $blocksToRead; - if ($bbdBlocks < $this->numBigBlockDepotBlocks) { - $this->extensionBlock = GetInt4d($this->data, $pos); - } - } - - // var_dump($bigBlockDepotBlocks); - - // readBigBlockDepot - $pos = 0; - $index = 0; - $this->bigBlockChain = array(); - - for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) { - $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE; - //echo "pos = $pos"; - for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) { - $this->bigBlockChain[$index] = GetInt4d($this->data, $pos); - $pos += 4 ; - $index++; - } - } - - //var_dump($this->bigBlockChain); - //echo '=====2'; - // readSmallBlockDepot(); - $pos = 0; - $index = 0; - $sbdBlock = $this->sbdStartBlock; - $this->smallBlockChain = array(); - - while ($sbdBlock != -2) { - - $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE; - - for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) { - $this->smallBlockChain[$index] = GetInt4d($this->data, $pos); - $pos += 4; - $index++; - } - - $sbdBlock = $this->bigBlockChain[$sbdBlock]; - } - - - // readData(rootStartBlock) - $block = $this->rootStartBlock; - $pos = 0; - $this->entry = $this->__readData($block); - - /* - while ($block != -2) { - $pos = ($block + 1) * BIG_BLOCK_SIZE; - $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE); - $block = $this->bigBlockChain[$block]; - } - */ - //echo '==='.$this->entry."==="; - $this->__readPropertySets(); - - } - - function __readData($bl) { - $block = $bl; - $pos = 0; - $data = ''; - - while ($block != -2) { - $pos = ($block + 1) * BIG_BLOCK_SIZE; - $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE); - //echo "pos = $pos data=$data\n"; - $block = $this->bigBlockChain[$block]; - } - return $data; - } - - function __readPropertySets(){ - $offset = 0; - //var_dump($this->entry); - while ($offset < strlen($this->entry)) { - $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE); - - $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8); - - $type = ord($d[TYPE_POS]); - //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1; - - $startBlock = GetInt4d($d, START_BLOCK_POS); - $size = GetInt4d($d, SIZE_POS); - - $name = ''; - for ($i = 0; $i < $nameSize ; $i++) { - $name .= $d[$i]; - } - - $name = str_replace("\x00", "", $name); - - $this->props[] = array ( - 'name' => $name, - 'type' => $type, - 'startBlock' => $startBlock, - 'size' => $size); - - if (($name == "Workbook") || ($name == "Book")) { - $this->wrkbook = count($this->props) - 1; - } - - if ($name == "Root Entry") { - $this->rootentry = count($this->props) - 1; - } - - //echo "name ==$name=\n"; - - - $offset += PROPERTY_STORAGE_BLOCK_SIZE; - } - - } - - - function getWorkBook(){ - if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){ -// getSmallBlockStream(PropertyStorage ps) - - $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']); - - $streamData = ''; - $block = $this->props[$this->wrkbook]['startBlock']; - //$count = 0; - $pos = 0; - while ($block != -2) { - $pos = $block * SMALL_BLOCK_SIZE; - $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE); - - $block = $this->smallBlockChain[$block]; - } - - return $streamData; - - - }else{ - - $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE; - if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) { - $numBlocks++; - } - - if ($numBlocks == 0) return ''; - - //echo "numBlocks = $numBlocks\n"; - //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; - //print_r($this->wrkbook); - $streamData = ''; - $block = $this->props[$this->wrkbook]['startBlock']; - //$count = 0; - $pos = 0; - //echo "block = $block"; - while ($block != -2) { - $pos = ($block + 1) * BIG_BLOCK_SIZE; - $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE); - $block = $this->bigBlockChain[$block]; - } - //echo 'stream'.$streamData; - return $streamData; - } - } - -} -?> \ No newline at end of file +=4294967294) + { + $value=-2; + } + return $value; +} + + +class OLERead { + var $data = ''; + + + function OLERead(){ + + + } + + function read($sFileName){ + + // check if file exist and is readable (Darko Miljanovic) + if(!is_readable($sFileName)) { + $this->error = 1; + return false; + } + + $this->data = @file_get_contents($sFileName); + if (!$this->data) { + $this->error = 1; + return false; + } + //echo IDENTIFIER_OLE; + //echo 'start'; + if (substr($this->data, 0, 8) != IDENTIFIER_OLE) { + $this->error = 1; + return false; + } + $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); + $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS); + $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS); + $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS); + $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS); + + /* + echo $this->numBigBlockDepotBlocks." "; + echo $this->sbdStartBlock." "; + echo $this->rootStartBlock." "; + echo $this->extensionBlock." "; + echo $this->numExtensionBlocks." "; + */ + //echo "sbdStartBlock = $this->sbdStartBlock\n"; + $bigBlockDepotBlocks = array(); + $pos = BIG_BLOCK_DEPOT_BLOCKS_POS; + // echo "pos = $pos"; + $bbdBlocks = $this->numBigBlockDepotBlocks; + + if ($this->numExtensionBlocks != 0) { + $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; + } + + for ($i = 0; $i < $bbdBlocks; $i++) { + $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); + $pos += 4; + } + + + for ($j = 0; $j < $this->numExtensionBlocks; $j++) { + $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE; + $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); + + for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) { + $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); + $pos += 4; + } + + $bbdBlocks += $blocksToRead; + if ($bbdBlocks < $this->numBigBlockDepotBlocks) { + $this->extensionBlock = GetInt4d($this->data, $pos); + } + } + + // var_dump($bigBlockDepotBlocks); + + // readBigBlockDepot + $pos = 0; + $index = 0; + $this->bigBlockChain = array(); + + for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) { + $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE; + //echo "pos = $pos"; + for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) { + $this->bigBlockChain[$index] = GetInt4d($this->data, $pos); + $pos += 4 ; + $index++; + } + } + + //var_dump($this->bigBlockChain); + //echo '=====2'; + // readSmallBlockDepot(); + $pos = 0; + $index = 0; + $sbdBlock = $this->sbdStartBlock; + $this->smallBlockChain = array(); + + while ($sbdBlock != -2) { + + $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE; + + for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) { + $this->smallBlockChain[$index] = GetInt4d($this->data, $pos); + $pos += 4; + $index++; + } + + $sbdBlock = $this->bigBlockChain[$sbdBlock]; + } + + + // readData(rootStartBlock) + $block = $this->rootStartBlock; + $pos = 0; + $this->entry = $this->__readData($block); + + /* + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE); + $block = $this->bigBlockChain[$block]; + } + */ + //echo '==='.$this->entry."==="; + $this->__readPropertySets(); + + } + + function __readData($bl) { + $block = $bl; + $pos = 0; + $data = ''; + + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE); + //echo "pos = $pos data=$data\n"; + $block = $this->bigBlockChain[$block]; + } + return $data; + } + + function __readPropertySets(){ + $offset = 0; + //var_dump($this->entry); + while ($offset < strlen($this->entry)) { + $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE); + + $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8); + + $type = ord($d[TYPE_POS]); + //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1; + + $startBlock = GetInt4d($d, START_BLOCK_POS); + $size = GetInt4d($d, SIZE_POS); + + $name = ''; + for ($i = 0; $i < $nameSize ; $i++) { + $name .= $d[$i]; + } + + $name = str_replace("\x00", "", $name); + + $this->props[] = array ( + 'name' => $name, + 'type' => $type, + 'startBlock' => $startBlock, + 'size' => $size); + + if (($name == "Workbook") || ($name == "Book")) { + $this->wrkbook = count($this->props) - 1; + } + + if ($name == "Root Entry") { + $this->rootentry = count($this->props) - 1; + } + + //echo "name ==$name=\n"; + + + $offset += PROPERTY_STORAGE_BLOCK_SIZE; + } + + } + + + function getWorkBook(){ + if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){ +// getSmallBlockStream(PropertyStorage ps) + + $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']); + + $streamData = ''; + $block = $this->props[$this->wrkbook]['startBlock']; + //$count = 0; + $pos = 0; + while ($block != -2) { + $pos = $block * SMALL_BLOCK_SIZE; + $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE); + + $block = $this->smallBlockChain[$block]; + } + + return $streamData; + + + }else{ + + $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE; + if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) { + $numBlocks++; + } + + if ($numBlocks == 0) return ''; + + //echo "numBlocks = $numBlocks\n"; + //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; + //print_r($this->wrkbook); + $streamData = ''; + $block = $this->props[$this->wrkbook]['startBlock']; + //$count = 0; + $pos = 0; + //echo "block = $block"; + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE); + $block = $this->bigBlockChain[$block]; + } + //echo 'stream'.$streamData; + return $streamData; + } + } + +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_biffwriter.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_biffwriter.inc.php index 04f90fb..93bdefd 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_biffwriter.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_biffwriter.inc.php @@ -204,6 +204,4 @@ class writeexcel_biffwriter { return $tmp; } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_format.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_format.inc.php index 15435c0..b24f422 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_format.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_format.inc.php @@ -690,6 +690,4 @@ class writeexcel_format { $this->_right_color=$this->_get_color($color); } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_formula.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_formula.inc.php index 7a04fd6..5422e82 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_formula.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_formula.inc.php @@ -153,7 +153,7 @@ function parse_formula() { $this->_formula = $formula; $this->_current_char = 0; - $this->_lookahead = $this->_formula{1}; + $this->_lookahead = $this->_formula[1]; $this->_advance($formula); $parsetree = $this->_condition(); @@ -663,10 +663,10 @@ function _convertRange2d($range) // 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) = explode(':', $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 @@ -714,7 +714,7 @@ function _convertRange3d($token) $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) = explode('!', $token); // Convert the external reference part $ext_ref = $this->_packExtRef($ext_ref); @@ -723,7 +723,7 @@ function _convertRange3d($token) } // Split the range into 2 cell refs - list($cell1, $cell2) = split(':', $range); + list($cell1, $cell2) = explode(':', $range); // Convert the cell references if (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $cell1)) @@ -812,7 +812,7 @@ function _convertRef3d($cell) $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) = explode('!', $cell); // Convert the external reference part $ext_ref = $this->_packExtRef($ext_ref); @@ -853,7 +853,7 @@ function _packExtRef($ext_ref) { // 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) = explode(':', $ext_ref); $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -1005,7 +1005,7 @@ function _cellToRowcol($cell) $col = 0; for ($i=0; $i < strlen($col_ref); $i++) { - $col += (ord($col_ref{$i}) - ord('A') + 1) * pow(26, $expn); + $col += (ord($col_ref[$i]) - ord('A') + 1) * pow(26, $expn); $expn--; } @@ -1027,19 +1027,19 @@ function _advance() // eat up white spaces if ($i < strlen($this->_formula)) { - while ($this->_formula{$i} == " ") { + while ($this->_formula[$i] == " ") { $i++; } if ($i < strlen($this->_formula) - 1) { - $this->_lookahead = $this->_formula{$i+1}; + $this->_lookahead = $this->_formula[$i+1]; } $token = ""; } while ($i < strlen($this->_formula)) { - $token .= $this->_formula{$i}; + $token .= $this->_formula[$i]; if ($i < strlen($this->_formula) - 1) { - $this->_lookahead = $this->_formula{$i+1}; + $this->_lookahead = $this->_formula[$i+1]; } else { $this->_lookahead = ''; @@ -1054,7 +1054,7 @@ function _advance() return 1; } if ($i < strlen($this->_formula) - 2) { - $this->_lookahead = $this->_formula{$i+2}; + $this->_lookahead = $this->_formula[$i+2]; } else { // if we run out of characters _lookahead becomes empty @@ -1195,7 +1195,7 @@ function parse($formula) { $this->_current_char = 0; $this->_formula = $formula; - $this->_lookahead = $formula{1}; + $this->_lookahead = $formula[1]; $this->_advance(); $this->_parse_tree = $this->_condition(); if ($this->isError($this->_parse_tree)) { @@ -1604,7 +1604,4 @@ function toReversePolish($tree = array()) return $polish; } -} - - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_olewriter.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_olewriter.inc.php index 133a1b5..1841495 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_olewriter.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_olewriter.inc.php @@ -348,6 +348,4 @@ class writeexcel_olewriter { } } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbook.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbook.inc.php index 11c7c0e..be13fb2 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbook.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbook.inc.php @@ -1144,6 +1144,4 @@ function _store_codepage() { $this->_append($header.$data); } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbookbig.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbookbig.inc.php index 3fb2f61..d705cb2 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbookbig.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_workbookbig.inc.php @@ -50,6 +50,4 @@ class writeexcel_workbookbig extends writeexcel_workbook { $ole->save($this->_filename); } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_worksheet.inc.php b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_worksheet.inc.php index 9860cbf..5127cf2 100644 --- a/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_worksheet.inc.php +++ b/AvocadoEdition_Light/lib/Excel/php_writeexcel/class.writeexcel_worksheet.inc.php @@ -2963,6 +2963,4 @@ function insert_bitmap() { $this->_append($header . $data); } -} - -?> +} \ No newline at end of file diff --git a/AvocadoEdition_Light/lib/Excel/reader.php b/AvocadoEdition_Light/lib/Excel/reader.php index 7cba18b..02cdfc3 100644 --- a/AvocadoEdition_Light/lib/Excel/reader.php +++ b/AvocadoEdition_Light/lib/Excel/reader.php @@ -1,1084 +1,1082 @@ - -* @license http://www.php.net/license/3_0.txt PHP License 3.0 -* @version CVS: $Id: reader.php 19 2007-03-13 12:42:41Z shangxiao $ -* @link http://pear.php.net/package/Spreadsheet_Excel_Reader -* @see OLE, Spreadsheet_Excel_Writer -*/ - - -//require_once 'PEAR.php'; -require_once 'oleread.inc.php'; -//require_once 'OLE.php'; - -define('SPREADSHEET_EXCEL_READER_BIFF8', 0x600); -define('SPREADSHEET_EXCEL_READER_BIFF7', 0x500); -define('SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS', 0x5); -define('SPREADSHEET_EXCEL_READER_WORKSHEET', 0x10); - -define('SPREADSHEET_EXCEL_READER_TYPE_BOF', 0x809); -define('SPREADSHEET_EXCEL_READER_TYPE_EOF', 0x0a); -define('SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET', 0x85); -define('SPREADSHEET_EXCEL_READER_TYPE_DIMENSION', 0x200); -define('SPREADSHEET_EXCEL_READER_TYPE_ROW', 0x208); -define('SPREADSHEET_EXCEL_READER_TYPE_DBCELL', 0xd7); -define('SPREADSHEET_EXCEL_READER_TYPE_FILEPASS', 0x2f); -define('SPREADSHEET_EXCEL_READER_TYPE_NOTE', 0x1c); -define('SPREADSHEET_EXCEL_READER_TYPE_TXO', 0x1b6); -define('SPREADSHEET_EXCEL_READER_TYPE_RK', 0x7e); -define('SPREADSHEET_EXCEL_READER_TYPE_RK2', 0x27e); -define('SPREADSHEET_EXCEL_READER_TYPE_MULRK', 0xbd); -define('SPREADSHEET_EXCEL_READER_TYPE_MULBLANK', 0xbe); -define('SPREADSHEET_EXCEL_READER_TYPE_INDEX', 0x20b); -define('SPREADSHEET_EXCEL_READER_TYPE_SST', 0xfc); -define('SPREADSHEET_EXCEL_READER_TYPE_EXTSST', 0xff); -define('SPREADSHEET_EXCEL_READER_TYPE_CONTINUE', 0x3c); -define('SPREADSHEET_EXCEL_READER_TYPE_LABEL', 0x204); -define('SPREADSHEET_EXCEL_READER_TYPE_LABELSST', 0xfd); -define('SPREADSHEET_EXCEL_READER_TYPE_NUMBER', 0x203); -define('SPREADSHEET_EXCEL_READER_TYPE_NAME', 0x18); -define('SPREADSHEET_EXCEL_READER_TYPE_ARRAY', 0x221); -define('SPREADSHEET_EXCEL_READER_TYPE_STRING', 0x207); -define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA', 0x406); -define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA2', 0x6); -define('SPREADSHEET_EXCEL_READER_TYPE_FORMAT', 0x41e); -define('SPREADSHEET_EXCEL_READER_TYPE_XF', 0xe0); -define('SPREADSHEET_EXCEL_READER_TYPE_BOOLERR', 0x205); -define('SPREADSHEET_EXCEL_READER_TYPE_UNKNOWN', 0xffff); -define('SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR', 0x22); -define('SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS', 0xE5); - -define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS' , 25569); -define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904', 24107); -define('SPREADSHEET_EXCEL_READER_MSINADAY', 86400); -//define('SPREADSHEET_EXCEL_READER_MSINADAY', 24 * 60 * 60); - -//define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%.2f"); -define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%s"); - - -/* -* Place includes, constant defines and $_GLOBAL settings here. -* Make sure they have appropriate docblocks to avoid phpDocumentor -* construing they are documented by the page-level docblock. -*/ - -/** -* A class for reading Microsoft Excel Spreadsheets. -* -* Originally developed by Vadim Tkachenko under the name PHPExcelReader. -* (http://sourceforge.net/projects/phpexcelreader) -* Based on the Java version by Andy Khan (http://www.andykhan.com). Now -* maintained by David Sanders. Reads only Biff 7 and Biff 8 formats. -* -* @category Spreadsheet -* @package Spreadsheet_Excel_Reader -* @author Vadim Tkachenko -* @copyright 1997-2005 The PHP Group -* @license http://www.php.net/license/3_0.txt PHP License 3.0 -* @version Release: @package_version@ -* @link http://pear.php.net/package/PackageName -* @see OLE, Spreadsheet_Excel_Writer -*/ -class Spreadsheet_Excel_Reader -{ - /** - * Array of worksheets found - * - * @var array - * @access public - */ - var $boundsheets = array(); - - /** - * Array of format records found - * - * @var array - * @access public - */ - var $formatRecords = array(); - - /** - * todo - * - * @var array - * @access public - */ - var $sst = array(); - - /** - * Array of worksheets - * - * The data is stored in 'cells' and the meta-data is stored in an array - * called 'cellsInfo' - * - * Example: - * - * $sheets --> 'cells' --> row --> column --> Interpreted value - * --> 'cellsInfo' --> row --> column --> 'type' - Can be 'date', 'number', or 'unknown' - * --> 'raw' - The raw data that Excel stores for that data cell - * - * @var array - * @access public - */ - var $sheets = array(); - - /** - * The data returned by OLE - * - * @var string - * @access public - */ - var $data; - - /** - * OLE object for reading the file - * - * @var OLE object - * @access private - */ - var $_ole; - - /** - * Default encoding - * - * @var string - * @access private - */ - var $_defaultEncoding; - - /** - * Default number format - * - * @var integer - * @access private - */ - var $_defaultFormat = SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT; - - /** - * todo - * List of formats to use for each column - * - * @var array - * @access private - */ - var $_columnsFormat = array(); - - /** - * todo - * - * @var integer - * @access private - */ - var $_rowoffset = 1; - - /** - * todo - * - * @var integer - * @access private - */ - var $_coloffset = 1; - - /** - * List of default date formats used by Excel - * - * @var array - * @access public - */ - var $dateFormats = array ( - 0xe => "d/m/Y", - 0xf => "d-M-Y", - 0x10 => "d-M", - 0x11 => "M-Y", - 0x12 => "h:i a", - 0x13 => "h:i:s a", - 0x14 => "H:i", - 0x15 => "H:i:s", - 0x16 => "d/m/Y H:i", - 0x2d => "i:s", - 0x2e => "H:i:s", - 0x2f => "i:s.S"); - - /** - * Default number formats used by Excel - * - * @var array - * @access public - */ - var $numberFormats = array( - 0x1 => "%1.0f", // "0" - 0x2 => "%1.2f", // "0.00", - 0x3 => "%1.0f", //"#,##0", - 0x4 => "%1.2f", //"#,##0.00", - 0x5 => "%1.0f", /*"$#,##0;($#,##0)",*/ - 0x6 => '$%1.0f', /*"$#,##0;($#,##0)",*/ - 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)", - 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)", - 0x9 => '%1.0f%%', // "0%" - 0xa => '%1.2f%%', // "0.00%" - 0xb => '%1.2f', // 0.00E00", - 0x25 => '%1.0f', // "#,##0;(#,##0)", - 0x26 => '%1.0f', //"#,##0;(#,##0)", - 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)", - 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)", - 0x29 => '%1.0f', //"#,##0;(#,##0)", - 0x2a => '$%1.0f', //"$#,##0;($#,##0)", - 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)", - 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)", - 0x30 => '%1.0f'); //"##0.0E0"; - - // }}} - // {{{ Spreadsheet_Excel_Reader() - - /** - * Constructor - * - * Some basic initialisation - */ - function Spreadsheet_Excel_Reader() - { - $this->_ole = new OLERead(); - $this->setUTFEncoder('iconv'); - } - - // }}} - // {{{ setOutputEncoding() - - /** - * Set the encoding method - * - * @param string Encoding to use - * @access public - */ - function setOutputEncoding($encoding) - { - $this->_defaultEncoding = $encoding; - } - - // }}} - // {{{ setUTFEncoder() - - /** - * $encoder = 'iconv' or 'mb' - * set iconv if you would like use 'iconv' for encode UTF-16LE to your encoding - * set mb if you would like use 'mb_convert_encoding' for encode UTF-16LE to your encoding - * - * @access public - * @param string Encoding type to use. Either 'iconv' or 'mb' - */ - function setUTFEncoder($encoder = 'iconv') - { - $this->_encoderFunction = ''; - - if ($encoder == 'iconv') { - $this->_encoderFunction = function_exists('iconv') ? 'iconv' : ''; - } elseif ($encoder == 'mb') { - $this->_encoderFunction = function_exists('mb_convert_encoding') ? - 'mb_convert_encoding' : - ''; - } - } - - // }}} - // {{{ setRowColOffset() - - /** - * todo - * - * @access public - * @param offset - */ - function setRowColOffset($iOffset) - { - $this->_rowoffset = $iOffset; - $this->_coloffset = $iOffset; - } - - // }}} - // {{{ setDefaultFormat() - - /** - * Set the default number format - * - * @access public - * @param Default format - */ - function setDefaultFormat($sFormat) - { - $this->_defaultFormat = $sFormat; - } - - // }}} - // {{{ setColumnFormat() - - /** - * Force a column to use a certain format - * - * @access public - * @param integer Column number - * @param string Format - */ - function setColumnFormat($column, $sFormat) - { - $this->_columnsFormat[$column] = $sFormat; - } - - - // }}} - // {{{ read() - - /** - * Read the spreadsheet file using OLE, then parse - * - * @access public - * @param filename - * @todo return a valid value - */ - function read($sFileName) - { - /* - require_once 'OLE.php'; - $ole = new OLE(); - $ole->read($sFileName); - - foreach ($ole->_list as $i => $pps) { - if (($pps->Name == 'Workbook' || $pps->Name == 'Book') && - $pps->Size >= SMALL_BLOCK_THRESHOLD) { - - $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); - } elseif ($pps->Name == 'Root Entry') { - $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); - } - //var_dump(strlen($ole->getData($i, 0, $ole->getDataLength($i))), $pps->Name, md5($this->data), $ole->getDataLength($i)); - } -//exit; - $this->_parse(); - - return sizeof($this->sheets) > 0; - */ - - $res = $this->_ole->read($sFileName); - - // oops, something goes wrong (Darko Miljanovic) - if($res === false) { - // check error code - if($this->_ole->error == 1) { - // bad file - die('The filename ' . $sFileName . ' is not readable'); - } - // check other error codes here (eg bad fileformat, etc...) - } - - $this->data = $this->_ole->getWorkBook(); - - - /* - $res = $this->_ole->read($sFileName); - - if ($this->isError($res)) { -// var_dump($res); - return $this->raiseError($res); - } - - $total = $this->_ole->ppsTotal(); - for ($i = 0; $i < $total; $i++) { - if ($this->_ole->isFile($i)) { - $type = unpack("v", $this->_ole->getData($i, 0, 2)); - if ($type[''] == 0x0809) { // check if it's a BIFF stream - $this->_index = $i; - $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i)); - break; - } - } - } - - if ($this->_index === null) { - return $this->raiseError("$file doesn't seem to be an Excel file"); - } - - */ - - //echo "data =".$this->data; - //$this->readRecords(); - $this->_parse(); - } - - - // }}} - // {{{ _parse() - - /** - * Parse a workbook - * - * @access private - * @return bool - */ - function _parse() - { - $pos = 0; - - $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; - $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; - - $version = ord($this->data[$pos + 4]) | ord($this->data[$pos + 5])<<8; - $substreamType = ord($this->data[$pos + 6]) | ord($this->data[$pos + 7])<<8; - //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; - - if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && - ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { - return false; - } - - if ($substreamType != SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS){ - return false; - } - - //print_r($rec); - $pos += $length + 4; - - $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; - $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; - - while ($code != SPREADSHEET_EXCEL_READER_TYPE_EOF) { - switch ($code) { - case SPREADSHEET_EXCEL_READER_TYPE_SST: - //echo "Type_SST\n"; - $spos = $pos + 4; - $limitpos = $spos + $length; - $uniqueStrings = $this->_GetInt4d($this->data, $spos+4); - $spos += 8; - for ($i = 0; $i < $uniqueStrings; $i++) { - // Read in the number of characters - if ($spos == $limitpos) { - $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - if ($opcode != 0x3c) { - return -1; - } - $spos += 4; - $limitpos = $spos + $conlength; - } - $numChars = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); - //echo "i = $i pos = $pos numChars = $numChars "; - $spos += 2; - $optionFlags = ord($this->data[$spos]); - $spos++; - $asciiEncoding = (($optionFlags & 0x01) == 0) ; - $extendedString = ( ($optionFlags & 0x04) != 0); - - // See if string contains formatting information - $richString = ( ($optionFlags & 0x08) != 0); - - if ($richString) { - // Read in the crun - $formattingRuns = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); - $spos += 2; - } - - if ($extendedString) { - // Read in cchExtRst - $extendedRunLength = $this->_GetInt4d($this->data, $spos); - $spos += 4; - } - - $len = ($asciiEncoding)? $numChars : $numChars*2; - if ($spos + $len < $limitpos) { - $retstr = substr($this->data, $spos, $len); - $spos += $len; - }else{ - // found countinue - $retstr = substr($this->data, $spos, $limitpos - $spos); - $bytesRead = $limitpos - $spos; - $charsLeft = $numChars - (($asciiEncoding) ? $bytesRead : ($bytesRead / 2)); - $spos = $limitpos; - - while ($charsLeft > 0){ - $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - if ($opcode != 0x3c) { - return -1; - } - $spos += 4; - $limitpos = $spos + $conlength; - $option = ord($this->data[$spos]); - $spos += 1; - if ($asciiEncoding && ($option == 0)) { - $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); - $retstr .= substr($this->data, $spos, $len); - $charsLeft -= $len; - $asciiEncoding = true; - }elseif (!$asciiEncoding && ($option != 0)){ - $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); - $retstr .= substr($this->data, $spos, $len); - $charsLeft -= $len/2; - $asciiEncoding = false; - }elseif (!$asciiEncoding && ($option == 0)) { - // Bummer - the string starts off as Unicode, but after the - // continuation it is in straightforward ASCII encoding - $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); - for ($j = 0; $j < $len; $j++) { - $retstr .= $this->data[$spos + $j].chr(0); - } - $charsLeft -= $len; - $asciiEncoding = false; - }else{ - $newstr = ''; - for ($j = 0; $j < strlen($retstr); $j++) { - $newstr = $retstr[$j].chr(0); - } - $retstr = $newstr; - $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); - $retstr .= substr($this->data, $spos, $len); - $charsLeft -= $len/2; - $asciiEncoding = false; - //echo "Izavrat\n"; - } - $spos += $len; - - } - } - $retstr = ($asciiEncoding) ? $retstr : $this->_encodeUTF16($retstr); -// echo "Str $i = $retstr\n"; - if ($richString){ - $spos += 4 * $formattingRuns; - } - - // For extended strings, skip over the extended string data - if ($extendedString) { - $spos += $extendedRunLength; - } - //if ($retstr == 'Derby'){ - // echo "bb\n"; - //} - $this->sst[]=$retstr; - } - /*$continueRecords = array(); - while ($this->getNextCode() == Type_CONTINUE) { - $continueRecords[] = &$this->nextRecord(); - } - //echo " 1 Type_SST\n"; - $this->shareStrings = new SSTRecord($r, $continueRecords); - //print_r($this->shareStrings->strings); - */ - // echo 'SST read: '.($time_end-$time_start)."\n"; - break; - - case SPREADSHEET_EXCEL_READER_TYPE_FILEPASS: - return false; - break; - case SPREADSHEET_EXCEL_READER_TYPE_NAME: - //echo "Type_NAME\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_FORMAT: - $indexCode = ord($this->data[$pos+4]) | ord($this->data[$pos+5]) << 8; - - if ($version == SPREADSHEET_EXCEL_READER_BIFF8) { - $numchars = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; - if (ord($this->data[$pos+8]) == 0){ - $formatString = substr($this->data, $pos+9, $numchars); - } else { - $formatString = substr($this->data, $pos+9, $numchars*2); - } - } else { - $numchars = ord($this->data[$pos+6]); - $formatString = substr($this->data, $pos+7, $numchars*2); - } - - $this->formatRecords[$indexCode] = $formatString; - // echo "Type.FORMAT\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_XF: - //global $dateFormats, $numberFormats; - $indexCode = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; - //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode "; - if (array_key_exists($indexCode, $this->dateFormats)) { - //echo "isdate ".$dateFormats[$indexCode]; - $this->formatRecords['xfrecords'][] = array( - 'type' => 'date', - 'format' => $this->dateFormats[$indexCode] - ); - }elseif (array_key_exists($indexCode, $this->numberFormats)) { - //echo "isnumber ".$this->numberFormats[$indexCode]; - $this->formatRecords['xfrecords'][] = array( - 'type' => 'number', - 'format' => $this->numberFormats[$indexCode] - ); - }else{ - $isdate = FALSE; - if ($indexCode > 0){ - if (isset($this->formatRecords[$indexCode])) - $formatstr = $this->formatRecords[$indexCode]; - //echo '.other.'; - //echo "\ndate-time=$formatstr=\n"; - if ($formatstr) - if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 0) { // found day and time format - $isdate = TRUE; - $formatstr = str_replace('mm', 'i', $formatstr); - $formatstr = str_replace('h', 'H', $formatstr); - //echo "\ndate-time $formatstr \n"; - } - } - - if ($isdate){ - $this->formatRecords['xfrecords'][] = array( - 'type' => 'date', - 'format' => $formatstr, - ); - }else{ - $this->formatRecords['xfrecords'][] = array( - 'type' => 'other', - 'format' => '', - 'code' => $indexCode - ); - } - } - //echo "\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR: - //echo "Type.NINETEENFOUR\n"; - $this->nineteenFour = (ord($this->data[$pos+4]) == 1); - break; - case SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET: - //echo "Type.BOUNDSHEET\n"; - $rec_offset = $this->_GetInt4d($this->data, $pos+4); - $rec_typeFlag = ord($this->data[$pos+8]); - $rec_visibilityFlag = ord($this->data[$pos+9]); - $rec_length = ord($this->data[$pos+10]); - - if ($version == SPREADSHEET_EXCEL_READER_BIFF8){ - $chartype = ord($this->data[$pos+11]); - if ($chartype == 0){ - $rec_name = substr($this->data, $pos+12, $rec_length); - } else { - $rec_name = $this->_encodeUTF16(substr($this->data, $pos+12, $rec_length*2)); - } - }elseif ($version == SPREADSHEET_EXCEL_READER_BIFF7){ - $rec_name = substr($this->data, $pos+11, $rec_length); - } - $this->boundsheets[] = array('name'=>$rec_name, - 'offset'=>$rec_offset); - - break; - - } - - //echo "Code = ".base_convert($r['code'],10,16)."\n"; - $pos += $length + 4; - $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; - $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; - - //$r = &$this->nextRecord(); - //echo "1 Code = ".base_convert($r['code'],10,16)."\n"; - } - - foreach ($this->boundsheets as $key=>$val){ - $this->sn = $key; - $this->_parsesheet($val['offset']); - } - return true; - - } - - /** - * Parse a worksheet - * - * @access private - * @param todo - * @todo fix return codes - */ - function _parsesheet($spos) - { - $cont = true; - // read BOF - $code = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - - $version = ord($this->data[$spos + 4]) | ord($this->data[$spos + 5])<<8; - $substreamType = ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8; - - if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { - return -1; - } - - if ($substreamType != SPREADSHEET_EXCEL_READER_WORKSHEET){ - return -2; - } - //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; - $spos += $length + 4; - //var_dump($this->formatRecords); - //echo "code $code $length"; - while($cont) { - //echo "mem= ".memory_get_usage()."\n"; -// $r = &$this->file->nextRecord(); - $lowcode = ord($this->data[$spos]); - if ($lowcode == SPREADSHEET_EXCEL_READER_TYPE_EOF) break; - $code = $lowcode | ord($this->data[$spos+1])<<8; - $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $spos += 4; - $this->sheets[$this->sn]['maxrow'] = $this->_rowoffset - 1; - $this->sheets[$this->sn]['maxcol'] = $this->_coloffset - 1; - //echo "Code=".base_convert($code,10,16)." $code\n"; - unset($this->rectype); - $this->multiplier = 1; // need for format with % - switch ($code) { - case SPREADSHEET_EXCEL_READER_TYPE_DIMENSION: - //echo 'Type_DIMENSION '; - if (!isset($this->numRows)) { - if (($length == 10) || ($version == SPREADSHEET_EXCEL_READER_BIFF7)){ - $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+2]) | ord($this->data[$spos+3]) << 8; - $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+6]) | ord($this->data[$spos+7]) << 8; - } else { - $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; - $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+10]) | ord($this->data[$spos+11]) << 8; - } - } - //echo 'numRows '.$this->numRows.' '.$this->numCols."\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS: - $cellRanges = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - for ($i = 0; $i < $cellRanges; $i++) { - $fr = ord($this->data[$spos + 8*$i + 2]) | ord($this->data[$spos + 8*$i + 3])<<8; - $lr = ord($this->data[$spos + 8*$i + 4]) | ord($this->data[$spos + 8*$i + 5])<<8; - $fc = ord($this->data[$spos + 8*$i + 6]) | ord($this->data[$spos + 8*$i + 7])<<8; - $lc = ord($this->data[$spos + 8*$i + 8]) | ord($this->data[$spos + 8*$i + 9])<<8; - //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1); - if ($lr - $fr > 0) { - $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['rowspan'] = $lr - $fr + 1; - } - if ($lc - $fc > 0) { - $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['colspan'] = $lc - $fc + 1; - } - } - //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_RK: - case SPREADSHEET_EXCEL_READER_TYPE_RK2: - //echo 'SPREADSHEET_EXCEL_READER_TYPE_RK'."\n"; - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $rknum = $this->_GetInt4d($this->data, $spos + 6); - $numValue = $this->_GetIEEE754($rknum); - //echo $numValue." "; - if ($this->isDate($spos)) { - list($string, $raw) = $this->createDate($numValue); - }else{ - $raw = $numValue; - if (isset($this->_columnsFormat[$column + 1])){ - $this->curformat = $this->_columnsFormat[$column + 1]; - } - $string = sprintf($this->curformat, $numValue * $this->multiplier); - //$this->addcell(RKRecord($r)); - } - $this->addcell($row, $column, $string, $raw); - //echo "Type_RK $row $column $string $raw {$this->curformat}\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_LABELSST: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5])<<8; - $index = $this->_GetInt4d($this->data, $spos + 6); - //var_dump($this->sst); - $this->addcell($row, $column, $this->sst[$index]); - //echo "LabelSST $row $column $string\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_MULRK: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $colFirst = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $colLast = ord($this->data[$spos + $length - 2]) | ord($this->data[$spos + $length - 1])<<8; - $columns = $colLast - $colFirst + 1; - $tmppos = $spos+4; - for ($i = 0; $i < $columns; $i++) { - $numValue = $this->_GetIEEE754($this->_GetInt4d($this->data, $tmppos + 2)); - if ($this->isDate($tmppos-4)) { - list($string, $raw) = $this->createDate($numValue); - }else{ - $raw = $numValue; - if (isset($this->_columnsFormat[$colFirst + $i + 1])){ - $this->curformat = $this->_columnsFormat[$colFirst + $i + 1]; - } - $string = sprintf($this->curformat, $numValue * $this->multiplier); - } - //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8; - $tmppos += 6; - $this->addcell($row, $colFirst + $i, $string, $raw); - //echo "MULRK $row ".($colFirst + $i)." $string\n"; - } - //MulRKRecord($r); - // Get the individual cell records from the multiple record - //$num = ; - - break; - case SPREADSHEET_EXCEL_READER_TYPE_NUMBER: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent - if ($this->isDate($spos)) { - list($string, $raw) = $this->createDate($tmp['double']); - // $this->addcell(DateRecord($r, 1)); - }else{ - //$raw = $tmp['']; - if (isset($this->_columnsFormat[$column + 1])){ - $this->curformat = $this->_columnsFormat[$column + 1]; - } - $raw = $this->createNumber($spos); - $string = sprintf($this->curformat, $raw * $this->multiplier); - - // $this->addcell(NumberRecord($r)); - } - $this->addcell($row, $column, $string, $raw); - //echo "Number $row $column $string\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_FORMULA: - case SPREADSHEET_EXCEL_READER_TYPE_FORMULA2: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - if ((ord($this->data[$spos+6])==0) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { - //String formula. Result follows in a STRING record - //echo "FORMULA $row $column Formula with a string
\n"; - } elseif ((ord($this->data[$spos+6])==1) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { - //Boolean formula. Result is in +2; 0=false,1=true - } elseif ((ord($this->data[$spos+6])==2) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { - //Error formula. Error code is in +2; - } elseif ((ord($this->data[$spos+6])==3) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { - //Formula result is a null string. - } else { - // result is a number, so first 14 bytes are just like a _NUMBER record - $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent - if ($this->isDate($spos)) { - list($string, $raw) = $this->createDate($tmp['double']); - // $this->addcell(DateRecord($r, 1)); - }else{ - //$raw = $tmp['']; - if (isset($this->_columnsFormat[$column + 1])){ - $this->curformat = $this->_columnsFormat[$column + 1]; - } - $raw = $this->createNumber($spos); - $string = sprintf($this->curformat, $raw * $this->multiplier); - - // $this->addcell(NumberRecord($r)); - } - $this->addcell($row, $column, $string, $raw); - //echo "Number $row $column $string\n"; - } - break; - case SPREADSHEET_EXCEL_READER_TYPE_BOOLERR: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $string = ord($this->data[$spos+6]); - $this->addcell($row, $column, $string); - //echo 'Type_BOOLERR '."\n"; - break; - case SPREADSHEET_EXCEL_READER_TYPE_ROW: - case SPREADSHEET_EXCEL_READER_TYPE_DBCELL: - case SPREADSHEET_EXCEL_READER_TYPE_MULBLANK: - break; - case SPREADSHEET_EXCEL_READER_TYPE_LABEL: - $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; - $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; - $this->addcell($row, $column, substr($this->data, $spos + 8, ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8)); - - // $this->addcell(LabelRecord($r)); - break; - - case SPREADSHEET_EXCEL_READER_TYPE_EOF: - $cont = false; - break; - default: - //echo ' unknown :'.base_convert($r['code'],10,16)."\n"; - break; - - } - $spos += $length; - } - - if (!isset($this->sheets[$this->sn]['numRows'])) - $this->sheets[$this->sn]['numRows'] = $this->sheets[$this->sn]['maxrow']; - if (!isset($this->sheets[$this->sn]['numCols'])) - $this->sheets[$this->sn]['numCols'] = $this->sheets[$this->sn]['maxcol']; - - } - - /** - * Check whether the current record read is a date - * - * @param todo - * @return boolean True if date, false otherwise - */ - function isDate($spos) - { - //$xfindex = GetInt2d(, 4); - $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; - //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n"; - //var_dump($this->formatRecords['xfrecords'][$xfindex]); - if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'date') { - $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; - $this->rectype = 'date'; - return true; - } else { - if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'number') { - $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; - $this->rectype = 'number'; - if (($xfindex == 0x9) || ($xfindex == 0xa)){ - $this->multiplier = 100; - } - }else{ - $this->curformat = $this->_defaultFormat; - $this->rectype = 'unknown'; - } - return false; - } - } - - //}}} - //{{{ createDate() - - /** - * Convert the raw Excel date into a human readable format - * - * Dates in Excel are stored as number of seconds from an epoch. On - * Windows, the epoch is 30/12/1899 and on Mac it's 01/01/1904 - * - * @access private - * @param integer The raw Excel value to convert - * @return array First element is the converted date, the second element is number a unix timestamp - */ - function createDate($numValue) - { - if ($numValue > 1) { - $utcDays = $numValue - ($this->nineteenFour ? SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904 : SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS); - $utcValue = round(($utcDays+1) * SPREADSHEET_EXCEL_READER_MSINADAY); - $string = date ($this->curformat, $utcValue); - $raw = $utcValue; - } else { - $raw = $numValue; - $hours = floor($numValue * 24); - $mins = floor($numValue * 24 * 60) - $hours * 60; - $secs = floor($numValue * SPREADSHEET_EXCEL_READER_MSINADAY) - $hours * 60 * 60 - $mins * 60; - $string = date ($this->curformat, mktime($hours, $mins, $secs)); - } - - return array($string, $raw); - } - - function createNumber($spos) - { - $rknumhigh = $this->_GetInt4d($this->data, $spos + 10); - $rknumlow = $this->_GetInt4d($this->data, $spos + 6); - //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "
"; - $sign = ($rknumhigh & 0x80000000) >> 31; - $exp = ($rknumhigh & 0x7ff00000) >> 20; - $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); - $mantissalow1 = ($rknumlow & 0x80000000) >> 31; - $mantissalow2 = ($rknumlow & 0x7fffffff); - $value = $mantissa / pow( 2 , (20- ($exp - 1023))); - if ($mantissalow1 != 0) $value += 1 / pow (2 , (21 - ($exp - 1023))); - $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023))); - //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2
\n"; - if ($sign) {$value = -1 * $value;} - return $value; - } - - function addcell($row, $col, $string, $raw = '') - { - //echo "ADD cel $row-$col $string\n"; - $this->sheets[$this->sn]['maxrow'] = max($this->sheets[$this->sn]['maxrow'], $row + $this->_rowoffset); - $this->sheets[$this->sn]['maxcol'] = max($this->sheets[$this->sn]['maxcol'], $col + $this->_coloffset); - $this->sheets[$this->sn]['cells'][$row + $this->_rowoffset][$col + $this->_coloffset] = $string; - if ($raw) - $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['raw'] = $raw; - if (isset($this->rectype)) - $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['type'] = $this->rectype; - - } - - - function _GetIEEE754($rknum) - { - if (($rknum & 0x02) != 0) { - $value = $rknum >> 2; - } else { -//mmp -// first comment out the previously existing 7 lines of code here -// $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc))); -// //$value = $tmp['']; -// if (array_key_exists(1, $tmp)) { -// $value = $tmp[1]; -// } else { -// $value = $tmp['']; -// } -// I got my info on IEEE754 encoding from -// http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html -// The RK format calls for using only the most significant 30 bits of the -// 64 bit floating point value. The other 34 bits are assumed to be 0 -// So, we use the upper 30 bits of $rknum as follows... - $sign = ($rknum & 0x80000000) >> 31; - $exp = ($rknum & 0x7ff00000) >> 20; - $mantissa = (0x100000 | ($rknum & 0x000ffffc)); - $value = $mantissa / pow( 2 , (20- ($exp - 1023))); - if ($sign) {$value = -1 * $value;} -//end of changes by mmp - - } - - if (($rknum & 0x01) != 0) { - $value /= 100; - } - return $value; - } - - function _encodeUTF16($string) - { - $result = $string; - if ($this->_defaultEncoding){ - switch ($this->_encoderFunction){ - case 'iconv' : $result = iconv('UTF-16LE', $this->_defaultEncoding, $string); - break; - case 'mb_convert_encoding' : $result = mb_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE' ); - break; - } - } - return $result; - } - - function _GetInt4d($data, $pos) - { - $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24); - if ($value>=4294967294) - { - $value=-2; - } - return $value; - } - -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * c-hanging-comment-ender-p: nil - * End: - */ - -?> + +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version CVS: $Id: reader.php 19 2007-03-13 12:42:41Z shangxiao $ +* @link http://pear.php.net/package/Spreadsheet_Excel_Reader +* @see OLE, Spreadsheet_Excel_Writer +*/ + + +//require_once 'PEAR.php'; +require_once 'oleread.inc.php'; +//require_once 'OLE.php'; + +define('SPREADSHEET_EXCEL_READER_BIFF8', 0x600); +define('SPREADSHEET_EXCEL_READER_BIFF7', 0x500); +define('SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS', 0x5); +define('SPREADSHEET_EXCEL_READER_WORKSHEET', 0x10); + +define('SPREADSHEET_EXCEL_READER_TYPE_BOF', 0x809); +define('SPREADSHEET_EXCEL_READER_TYPE_EOF', 0x0a); +define('SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET', 0x85); +define('SPREADSHEET_EXCEL_READER_TYPE_DIMENSION', 0x200); +define('SPREADSHEET_EXCEL_READER_TYPE_ROW', 0x208); +define('SPREADSHEET_EXCEL_READER_TYPE_DBCELL', 0xd7); +define('SPREADSHEET_EXCEL_READER_TYPE_FILEPASS', 0x2f); +define('SPREADSHEET_EXCEL_READER_TYPE_NOTE', 0x1c); +define('SPREADSHEET_EXCEL_READER_TYPE_TXO', 0x1b6); +define('SPREADSHEET_EXCEL_READER_TYPE_RK', 0x7e); +define('SPREADSHEET_EXCEL_READER_TYPE_RK2', 0x27e); +define('SPREADSHEET_EXCEL_READER_TYPE_MULRK', 0xbd); +define('SPREADSHEET_EXCEL_READER_TYPE_MULBLANK', 0xbe); +define('SPREADSHEET_EXCEL_READER_TYPE_INDEX', 0x20b); +define('SPREADSHEET_EXCEL_READER_TYPE_SST', 0xfc); +define('SPREADSHEET_EXCEL_READER_TYPE_EXTSST', 0xff); +define('SPREADSHEET_EXCEL_READER_TYPE_CONTINUE', 0x3c); +define('SPREADSHEET_EXCEL_READER_TYPE_LABEL', 0x204); +define('SPREADSHEET_EXCEL_READER_TYPE_LABELSST', 0xfd); +define('SPREADSHEET_EXCEL_READER_TYPE_NUMBER', 0x203); +define('SPREADSHEET_EXCEL_READER_TYPE_NAME', 0x18); +define('SPREADSHEET_EXCEL_READER_TYPE_ARRAY', 0x221); +define('SPREADSHEET_EXCEL_READER_TYPE_STRING', 0x207); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA', 0x406); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA2', 0x6); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMAT', 0x41e); +define('SPREADSHEET_EXCEL_READER_TYPE_XF', 0xe0); +define('SPREADSHEET_EXCEL_READER_TYPE_BOOLERR', 0x205); +define('SPREADSHEET_EXCEL_READER_TYPE_UNKNOWN', 0xffff); +define('SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR', 0x22); +define('SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS', 0xE5); + +define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS' , 25569); +define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904', 24107); +define('SPREADSHEET_EXCEL_READER_MSINADAY', 86400); +//define('SPREADSHEET_EXCEL_READER_MSINADAY', 24 * 60 * 60); + +//define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%.2f"); +define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%s"); + + +/* +* Place includes, constant defines and $_GLOBAL settings here. +* Make sure they have appropriate docblocks to avoid phpDocumentor +* construing they are documented by the page-level docblock. +*/ + +/** +* A class for reading Microsoft Excel Spreadsheets. +* +* Originally developed by Vadim Tkachenko under the name PHPExcelReader. +* (http://sourceforge.net/projects/phpexcelreader) +* Based on the Java version by Andy Khan (http://www.andykhan.com). Now +* maintained by David Sanders. Reads only Biff 7 and Biff 8 formats. +* +* @category Spreadsheet +* @package Spreadsheet_Excel_Reader +* @author Vadim Tkachenko +* @copyright 1997-2005 The PHP Group +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version Release: @package_version@ +* @link http://pear.php.net/package/PackageName +* @see OLE, Spreadsheet_Excel_Writer +*/ +class Spreadsheet_Excel_Reader +{ + /** + * Array of worksheets found + * + * @var array + * @access public + */ + var $boundsheets = array(); + + /** + * Array of format records found + * + * @var array + * @access public + */ + var $formatRecords = array(); + + /** + * todo + * + * @var array + * @access public + */ + var $sst = array(); + + /** + * Array of worksheets + * + * The data is stored in 'cells' and the meta-data is stored in an array + * called 'cellsInfo' + * + * Example: + * + * $sheets --> 'cells' --> row --> column --> Interpreted value + * --> 'cellsInfo' --> row --> column --> 'type' - Can be 'date', 'number', or 'unknown' + * --> 'raw' - The raw data that Excel stores for that data cell + * + * @var array + * @access public + */ + var $sheets = array(); + + /** + * The data returned by OLE + * + * @var string + * @access public + */ + var $data; + + /** + * OLE object for reading the file + * + * @var OLE object + * @access private + */ + var $_ole; + + /** + * Default encoding + * + * @var string + * @access private + */ + var $_defaultEncoding; + + /** + * Default number format + * + * @var integer + * @access private + */ + var $_defaultFormat = SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT; + + /** + * todo + * List of formats to use for each column + * + * @var array + * @access private + */ + var $_columnsFormat = array(); + + /** + * todo + * + * @var integer + * @access private + */ + var $_rowoffset = 1; + + /** + * todo + * + * @var integer + * @access private + */ + var $_coloffset = 1; + + /** + * List of default date formats used by Excel + * + * @var array + * @access public + */ + var $dateFormats = array ( + 0xe => "d/m/Y", + 0xf => "d-M-Y", + 0x10 => "d-M", + 0x11 => "M-Y", + 0x12 => "h:i a", + 0x13 => "h:i:s a", + 0x14 => "H:i", + 0x15 => "H:i:s", + 0x16 => "d/m/Y H:i", + 0x2d => "i:s", + 0x2e => "H:i:s", + 0x2f => "i:s.S"); + + /** + * Default number formats used by Excel + * + * @var array + * @access public + */ + var $numberFormats = array( + 0x1 => "%1.0f", // "0" + 0x2 => "%1.2f", // "0.00", + 0x3 => "%1.0f", //"#,##0", + 0x4 => "%1.2f", //"#,##0.00", + 0x5 => "%1.0f", /*"$#,##0;($#,##0)",*/ + 0x6 => '$%1.0f', /*"$#,##0;($#,##0)",*/ + 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x9 => '%1.0f%%', // "0%" + 0xa => '%1.2f%%', // "0.00%" + 0xb => '%1.2f', // 0.00E00", + 0x25 => '%1.0f', // "#,##0;(#,##0)", + 0x26 => '%1.0f', //"#,##0;(#,##0)", + 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x29 => '%1.0f', //"#,##0;(#,##0)", + 0x2a => '$%1.0f', //"$#,##0;($#,##0)", + 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x30 => '%1.0f'); //"##0.0E0"; + + // }}} + // {{{ Spreadsheet_Excel_Reader() + + /** + * Constructor + * + * Some basic initialisation + */ + function Spreadsheet_Excel_Reader() + { + $this->_ole = new OLERead(); + $this->setUTFEncoder('iconv'); + } + + // }}} + // {{{ setOutputEncoding() + + /** + * Set the encoding method + * + * @param string Encoding to use + * @access public + */ + function setOutputEncoding($encoding) + { + $this->_defaultEncoding = $encoding; + } + + // }}} + // {{{ setUTFEncoder() + + /** + * $encoder = 'iconv' or 'mb' + * set iconv if you would like use 'iconv' for encode UTF-16LE to your encoding + * set mb if you would like use 'mb_convert_encoding' for encode UTF-16LE to your encoding + * + * @access public + * @param string Encoding type to use. Either 'iconv' or 'mb' + */ + function setUTFEncoder($encoder = 'iconv') + { + $this->_encoderFunction = ''; + + if ($encoder == 'iconv') { + $this->_encoderFunction = function_exists('iconv') ? 'iconv' : ''; + } elseif ($encoder == 'mb') { + $this->_encoderFunction = function_exists('mb_convert_encoding') ? + 'mb_convert_encoding' : + ''; + } + } + + // }}} + // {{{ setRowColOffset() + + /** + * todo + * + * @access public + * @param offset + */ + function setRowColOffset($iOffset) + { + $this->_rowoffset = $iOffset; + $this->_coloffset = $iOffset; + } + + // }}} + // {{{ setDefaultFormat() + + /** + * Set the default number format + * + * @access public + * @param Default format + */ + function setDefaultFormat($sFormat) + { + $this->_defaultFormat = $sFormat; + } + + // }}} + // {{{ setColumnFormat() + + /** + * Force a column to use a certain format + * + * @access public + * @param integer Column number + * @param string Format + */ + function setColumnFormat($column, $sFormat) + { + $this->_columnsFormat[$column] = $sFormat; + } + + + // }}} + // {{{ read() + + /** + * Read the spreadsheet file using OLE, then parse + * + * @access public + * @param filename + * @todo return a valid value + */ + function read($sFileName) + { + /* + require_once 'OLE.php'; + $ole = new OLE(); + $ole->read($sFileName); + + foreach ($ole->_list as $i => $pps) { + if (($pps->Name == 'Workbook' || $pps->Name == 'Book') && + $pps->Size >= SMALL_BLOCK_THRESHOLD) { + + $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); + } elseif ($pps->Name == 'Root Entry') { + $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); + } + //var_dump(strlen($ole->getData($i, 0, $ole->getDataLength($i))), $pps->Name, md5($this->data), $ole->getDataLength($i)); + } +//exit; + $this->_parse(); + + return sizeof($this->sheets) > 0; + */ + + $res = $this->_ole->read($sFileName); + + // oops, something goes wrong (Darko Miljanovic) + if($res === false) { + // check error code + if($this->_ole->error == 1) { + // bad file + die('The filename ' . $sFileName . ' is not readable'); + } + // check other error codes here (eg bad fileformat, etc...) + } + + $this->data = $this->_ole->getWorkBook(); + + + /* + $res = $this->_ole->read($sFileName); + + if ($this->isError($res)) { +// var_dump($res); + return $this->raiseError($res); + } + + $total = $this->_ole->ppsTotal(); + for ($i = 0; $i < $total; $i++) { + if ($this->_ole->isFile($i)) { + $type = unpack("v", $this->_ole->getData($i, 0, 2)); + if ($type[''] == 0x0809) { // check if it's a BIFF stream + $this->_index = $i; + $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i)); + break; + } + } + } + + if ($this->_index === null) { + return $this->raiseError("$file doesn't seem to be an Excel file"); + } + + */ + + //echo "data =".$this->data; + //$this->readRecords(); + $this->_parse(); + } + + + // }}} + // {{{ _parse() + + /** + * Parse a workbook + * + * @access private + * @return bool + */ + function _parse() + { + $pos = 0; + + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + $version = ord($this->data[$pos + 4]) | ord($this->data[$pos + 5])<<8; + $substreamType = ord($this->data[$pos + 6]) | ord($this->data[$pos + 7])<<8; + //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; + + if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && + ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { + return false; + } + + if ($substreamType != SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS){ + return false; + } + + //print_r($rec); + $pos += $length + 4; + + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + while ($code != SPREADSHEET_EXCEL_READER_TYPE_EOF) { + switch ($code) { + case SPREADSHEET_EXCEL_READER_TYPE_SST: + //echo "Type_SST\n"; + $spos = $pos + 4; + $limitpos = $spos + $length; + $uniqueStrings = $this->_GetInt4d($this->data, $spos+4); + $spos += 8; + for ($i = 0; $i < $uniqueStrings; $i++) { + // Read in the number of characters + if ($spos == $limitpos) { + $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ($opcode != 0x3c) { + return -1; + } + $spos += 4; + $limitpos = $spos + $conlength; + } + $numChars = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); + //echo "i = $i pos = $pos numChars = $numChars "; + $spos += 2; + $optionFlags = ord($this->data[$spos]); + $spos++; + $asciiEncoding = (($optionFlags & 0x01) == 0) ; + $extendedString = ( ($optionFlags & 0x04) != 0); + + // See if string contains formatting information + $richString = ( ($optionFlags & 0x08) != 0); + + if ($richString) { + // Read in the crun + $formattingRuns = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); + $spos += 2; + } + + if ($extendedString) { + // Read in cchExtRst + $extendedRunLength = $this->_GetInt4d($this->data, $spos); + $spos += 4; + } + + $len = ($asciiEncoding)? $numChars : $numChars*2; + if ($spos + $len < $limitpos) { + $retstr = substr($this->data, $spos, $len); + $spos += $len; + }else{ + // found countinue + $retstr = substr($this->data, $spos, $limitpos - $spos); + $bytesRead = $limitpos - $spos; + $charsLeft = $numChars - (($asciiEncoding) ? $bytesRead : ($bytesRead / 2)); + $spos = $limitpos; + + while ($charsLeft > 0){ + $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ($opcode != 0x3c) { + return -1; + } + $spos += 4; + $limitpos = $spos + $conlength; + $option = ord($this->data[$spos]); + $spos += 1; + if ($asciiEncoding && ($option == 0)) { + $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len; + $asciiEncoding = true; + }elseif (!$asciiEncoding && ($option != 0)){ + $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len/2; + $asciiEncoding = false; + }elseif (!$asciiEncoding && ($option == 0)) { + // Bummer - the string starts off as Unicode, but after the + // continuation it is in straightforward ASCII encoding + $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); + for ($j = 0; $j < $len; $j++) { + $retstr .= $this->data[$spos + $j].chr(0); + } + $charsLeft -= $len; + $asciiEncoding = false; + }else{ + $newstr = ''; + for ($j = 0; $j < strlen($retstr); $j++) { + $newstr = $retstr[$j].chr(0); + } + $retstr = $newstr; + $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len/2; + $asciiEncoding = false; + //echo "Izavrat\n"; + } + $spos += $len; + + } + } + $retstr = ($asciiEncoding) ? $retstr : $this->_encodeUTF16($retstr); +// echo "Str $i = $retstr\n"; + if ($richString){ + $spos += 4 * $formattingRuns; + } + + // For extended strings, skip over the extended string data + if ($extendedString) { + $spos += $extendedRunLength; + } + //if ($retstr == 'Derby'){ + // echo "bb\n"; + //} + $this->sst[]=$retstr; + } + /*$continueRecords = array(); + while ($this->getNextCode() == Type_CONTINUE) { + $continueRecords[] = &$this->nextRecord(); + } + //echo " 1 Type_SST\n"; + $this->shareStrings = new SSTRecord($r, $continueRecords); + //print_r($this->shareStrings->strings); + */ + // echo 'SST read: '.($time_end-$time_start)."\n"; + break; + + case SPREADSHEET_EXCEL_READER_TYPE_FILEPASS: + return false; + break; + case SPREADSHEET_EXCEL_READER_TYPE_NAME: + //echo "Type_NAME\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_FORMAT: + $indexCode = ord($this->data[$pos+4]) | ord($this->data[$pos+5]) << 8; + + if ($version == SPREADSHEET_EXCEL_READER_BIFF8) { + $numchars = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; + if (ord($this->data[$pos+8]) == 0){ + $formatString = substr($this->data, $pos+9, $numchars); + } else { + $formatString = substr($this->data, $pos+9, $numchars*2); + } + } else { + $numchars = ord($this->data[$pos+6]); + $formatString = substr($this->data, $pos+7, $numchars*2); + } + + $this->formatRecords[$indexCode] = $formatString; + // echo "Type.FORMAT\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_XF: + //global $dateFormats, $numberFormats; + $indexCode = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; + //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode "; + if (array_key_exists($indexCode, $this->dateFormats)) { + //echo "isdate ".$dateFormats[$indexCode]; + $this->formatRecords['xfrecords'][] = array( + 'type' => 'date', + 'format' => $this->dateFormats[$indexCode] + ); + }elseif (array_key_exists($indexCode, $this->numberFormats)) { + //echo "isnumber ".$this->numberFormats[$indexCode]; + $this->formatRecords['xfrecords'][] = array( + 'type' => 'number', + 'format' => $this->numberFormats[$indexCode] + ); + }else{ + $isdate = FALSE; + if ($indexCode > 0){ + if (isset($this->formatRecords[$indexCode])) + $formatstr = $this->formatRecords[$indexCode]; + //echo '.other.'; + //echo "\ndate-time=$formatstr=\n"; + if ($formatstr) + if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 0) { // found day and time format + $isdate = TRUE; + $formatstr = str_replace('mm', 'i', $formatstr); + $formatstr = str_replace('h', 'H', $formatstr); + //echo "\ndate-time $formatstr \n"; + } + } + + if ($isdate){ + $this->formatRecords['xfrecords'][] = array( + 'type' => 'date', + 'format' => $formatstr, + ); + }else{ + $this->formatRecords['xfrecords'][] = array( + 'type' => 'other', + 'format' => '', + 'code' => $indexCode + ); + } + } + //echo "\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR: + //echo "Type.NINETEENFOUR\n"; + $this->nineteenFour = (ord($this->data[$pos+4]) == 1); + break; + case SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET: + //echo "Type.BOUNDSHEET\n"; + $rec_offset = $this->_GetInt4d($this->data, $pos+4); + $rec_typeFlag = ord($this->data[$pos+8]); + $rec_visibilityFlag = ord($this->data[$pos+9]); + $rec_length = ord($this->data[$pos+10]); + + if ($version == SPREADSHEET_EXCEL_READER_BIFF8){ + $chartype = ord($this->data[$pos+11]); + if ($chartype == 0){ + $rec_name = substr($this->data, $pos+12, $rec_length); + } else { + $rec_name = $this->_encodeUTF16(substr($this->data, $pos+12, $rec_length*2)); + } + }elseif ($version == SPREADSHEET_EXCEL_READER_BIFF7){ + $rec_name = substr($this->data, $pos+11, $rec_length); + } + $this->boundsheets[] = array('name'=>$rec_name, + 'offset'=>$rec_offset); + + break; + + } + + //echo "Code = ".base_convert($r['code'],10,16)."\n"; + $pos += $length + 4; + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + //$r = &$this->nextRecord(); + //echo "1 Code = ".base_convert($r['code'],10,16)."\n"; + } + + foreach ($this->boundsheets as $key=>$val){ + $this->sn = $key; + $this->_parsesheet($val['offset']); + } + return true; + + } + + /** + * Parse a worksheet + * + * @access private + * @param todo + * @todo fix return codes + */ + function _parsesheet($spos) + { + $cont = true; + // read BOF + $code = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + + $version = ord($this->data[$spos + 4]) | ord($this->data[$spos + 5])<<8; + $substreamType = ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8; + + if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { + return -1; + } + + if ($substreamType != SPREADSHEET_EXCEL_READER_WORKSHEET){ + return -2; + } + //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; + $spos += $length + 4; + //var_dump($this->formatRecords); + //echo "code $code $length"; + while($cont) { + //echo "mem= ".memory_get_usage()."\n"; +// $r = &$this->file->nextRecord(); + $lowcode = ord($this->data[$spos]); + if ($lowcode == SPREADSHEET_EXCEL_READER_TYPE_EOF) break; + $code = $lowcode | ord($this->data[$spos+1])<<8; + $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $spos += 4; + $this->sheets[$this->sn]['maxrow'] = $this->_rowoffset - 1; + $this->sheets[$this->sn]['maxcol'] = $this->_coloffset - 1; + //echo "Code=".base_convert($code,10,16)." $code\n"; + unset($this->rectype); + $this->multiplier = 1; // need for format with % + switch ($code) { + case SPREADSHEET_EXCEL_READER_TYPE_DIMENSION: + //echo 'Type_DIMENSION '; + if (!isset($this->numRows)) { + if (($length == 10) || ($version == SPREADSHEET_EXCEL_READER_BIFF7)){ + $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+2]) | ord($this->data[$spos+3]) << 8; + $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+6]) | ord($this->data[$spos+7]) << 8; + } else { + $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; + $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+10]) | ord($this->data[$spos+11]) << 8; + } + } + //echo 'numRows '.$this->numRows.' '.$this->numCols."\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS: + $cellRanges = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + for ($i = 0; $i < $cellRanges; $i++) { + $fr = ord($this->data[$spos + 8*$i + 2]) | ord($this->data[$spos + 8*$i + 3])<<8; + $lr = ord($this->data[$spos + 8*$i + 4]) | ord($this->data[$spos + 8*$i + 5])<<8; + $fc = ord($this->data[$spos + 8*$i + 6]) | ord($this->data[$spos + 8*$i + 7])<<8; + $lc = ord($this->data[$spos + 8*$i + 8]) | ord($this->data[$spos + 8*$i + 9])<<8; + //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1); + if ($lr - $fr > 0) { + $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['rowspan'] = $lr - $fr + 1; + } + if ($lc - $fc > 0) { + $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['colspan'] = $lc - $fc + 1; + } + } + //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_RK: + case SPREADSHEET_EXCEL_READER_TYPE_RK2: + //echo 'SPREADSHEET_EXCEL_READER_TYPE_RK'."\n"; + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $rknum = $this->_GetInt4d($this->data, $spos + 6); + $numValue = $this->_GetIEEE754($rknum); + //echo $numValue." "; + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($numValue); + }else{ + $raw = $numValue; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $string = sprintf($this->curformat, $numValue * $this->multiplier); + //$this->addcell(RKRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Type_RK $row $column $string $raw {$this->curformat}\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_LABELSST: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5])<<8; + $index = $this->_GetInt4d($this->data, $spos + 6); + //var_dump($this->sst); + $this->addcell($row, $column, $this->sst[$index]); + //echo "LabelSST $row $column $string\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_MULRK: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $colFirst = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $colLast = ord($this->data[$spos + $length - 2]) | ord($this->data[$spos + $length - 1])<<8; + $columns = $colLast - $colFirst + 1; + $tmppos = $spos+4; + for ($i = 0; $i < $columns; $i++) { + $numValue = $this->_GetIEEE754($this->_GetInt4d($this->data, $tmppos + 2)); + if ($this->isDate($tmppos-4)) { + list($string, $raw) = $this->createDate($numValue); + }else{ + $raw = $numValue; + if (isset($this->_columnsFormat[$colFirst + $i + 1])){ + $this->curformat = $this->_columnsFormat[$colFirst + $i + 1]; + } + $string = sprintf($this->curformat, $numValue * $this->multiplier); + } + //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8; + $tmppos += 6; + $this->addcell($row, $colFirst + $i, $string, $raw); + //echo "MULRK $row ".($colFirst + $i)." $string\n"; + } + //MulRKRecord($r); + // Get the individual cell records from the multiple record + //$num = ; + + break; + case SPREADSHEET_EXCEL_READER_TYPE_NUMBER: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($tmp['double']); + // $this->addcell(DateRecord($r, 1)); + }else{ + //$raw = $tmp['']; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $raw = $this->createNumber($spos); + $string = sprintf($this->curformat, $raw * $this->multiplier); + + // $this->addcell(NumberRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Number $row $column $string\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_FORMULA: + case SPREADSHEET_EXCEL_READER_TYPE_FORMULA2: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ((ord($this->data[$spos+6])==0) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //String formula. Result follows in a STRING record + //echo "FORMULA $row $column Formula with a string
\n"; + } elseif ((ord($this->data[$spos+6])==1) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Boolean formula. Result is in +2; 0=false,1=true + } elseif ((ord($this->data[$spos+6])==2) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Error formula. Error code is in +2; + } elseif ((ord($this->data[$spos+6])==3) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Formula result is a null string. + } else { + // result is a number, so first 14 bytes are just like a _NUMBER record + $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($tmp['double']); + // $this->addcell(DateRecord($r, 1)); + }else{ + //$raw = $tmp['']; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $raw = $this->createNumber($spos); + $string = sprintf($this->curformat, $raw * $this->multiplier); + + // $this->addcell(NumberRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Number $row $column $string\n"; + } + break; + case SPREADSHEET_EXCEL_READER_TYPE_BOOLERR: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $string = ord($this->data[$spos+6]); + $this->addcell($row, $column, $string); + //echo 'Type_BOOLERR '."\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_ROW: + case SPREADSHEET_EXCEL_READER_TYPE_DBCELL: + case SPREADSHEET_EXCEL_READER_TYPE_MULBLANK: + break; + case SPREADSHEET_EXCEL_READER_TYPE_LABEL: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $this->addcell($row, $column, substr($this->data, $spos + 8, ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8)); + + // $this->addcell(LabelRecord($r)); + break; + + case SPREADSHEET_EXCEL_READER_TYPE_EOF: + $cont = false; + break; + default: + //echo ' unknown :'.base_convert($r['code'],10,16)."\n"; + break; + + } + $spos += $length; + } + + if (!isset($this->sheets[$this->sn]['numRows'])) + $this->sheets[$this->sn]['numRows'] = $this->sheets[$this->sn]['maxrow']; + if (!isset($this->sheets[$this->sn]['numCols'])) + $this->sheets[$this->sn]['numCols'] = $this->sheets[$this->sn]['maxcol']; + + } + + /** + * Check whether the current record read is a date + * + * @param todo + * @return boolean True if date, false otherwise + */ + function isDate($spos) + { + //$xfindex = GetInt2d(, 4); + $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; + //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n"; + //var_dump($this->formatRecords['xfrecords'][$xfindex]); + if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'date') { + $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; + $this->rectype = 'date'; + return true; + } else { + if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'number') { + $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; + $this->rectype = 'number'; + if (($xfindex == 0x9) || ($xfindex == 0xa)){ + $this->multiplier = 100; + } + }else{ + $this->curformat = $this->_defaultFormat; + $this->rectype = 'unknown'; + } + return false; + } + } + + //}}} + //{{{ createDate() + + /** + * Convert the raw Excel date into a human readable format + * + * Dates in Excel are stored as number of seconds from an epoch. On + * Windows, the epoch is 30/12/1899 and on Mac it's 01/01/1904 + * + * @access private + * @param integer The raw Excel value to convert + * @return array First element is the converted date, the second element is number a unix timestamp + */ + function createDate($numValue) + { + if ($numValue > 1) { + $utcDays = $numValue - ($this->nineteenFour ? SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904 : SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS); + $utcValue = round(($utcDays+1) * SPREADSHEET_EXCEL_READER_MSINADAY); + $string = date ($this->curformat, $utcValue); + $raw = $utcValue; + } else { + $raw = $numValue; + $hours = floor($numValue * 24); + $mins = floor($numValue * 24 * 60) - $hours * 60; + $secs = floor($numValue * SPREADSHEET_EXCEL_READER_MSINADAY) - $hours * 60 * 60 - $mins * 60; + $string = date ($this->curformat, mktime($hours, $mins, $secs)); + } + + return array($string, $raw); + } + + function createNumber($spos) + { + $rknumhigh = $this->_GetInt4d($this->data, $spos + 10); + $rknumlow = $this->_GetInt4d($this->data, $spos + 6); + //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "
"; + $sign = ($rknumhigh & 0x80000000) >> 31; + $exp = ($rknumhigh & 0x7ff00000) >> 20; + $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); + $mantissalow1 = ($rknumlow & 0x80000000) >> 31; + $mantissalow2 = ($rknumlow & 0x7fffffff); + $value = $mantissa / pow( 2 , (20- ($exp - 1023))); + if ($mantissalow1 != 0) $value += 1 / pow (2 , (21 - ($exp - 1023))); + $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023))); + //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2
\n"; + if ($sign) {$value = -1 * $value;} + return $value; + } + + function addcell($row, $col, $string, $raw = '') + { + //echo "ADD cel $row-$col $string\n"; + $this->sheets[$this->sn]['maxrow'] = max($this->sheets[$this->sn]['maxrow'], $row + $this->_rowoffset); + $this->sheets[$this->sn]['maxcol'] = max($this->sheets[$this->sn]['maxcol'], $col + $this->_coloffset); + $this->sheets[$this->sn]['cells'][$row + $this->_rowoffset][$col + $this->_coloffset] = $string; + if ($raw) + $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['raw'] = $raw; + if (isset($this->rectype)) + $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['type'] = $this->rectype; + + } + + + function _GetIEEE754($rknum) + { + if (($rknum & 0x02) != 0) { + $value = $rknum >> 2; + } else { +//mmp +// first comment out the previously existing 7 lines of code here +// $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc))); +// //$value = $tmp['']; +// if (array_key_exists(1, $tmp)) { +// $value = $tmp[1]; +// } else { +// $value = $tmp['']; +// } +// I got my info on IEEE754 encoding from +// http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html +// The RK format calls for using only the most significant 30 bits of the +// 64 bit floating point value. The other 34 bits are assumed to be 0 +// So, we use the upper 30 bits of $rknum as follows... + $sign = ($rknum & 0x80000000) >> 31; + $exp = ($rknum & 0x7ff00000) >> 20; + $mantissa = (0x100000 | ($rknum & 0x000ffffc)); + $value = $mantissa / pow( 2 , (20- ($exp - 1023))); + if ($sign) {$value = -1 * $value;} +//end of changes by mmp + + } + + if (($rknum & 0x01) != 0) { + $value /= 100; + } + return $value; + } + + function _encodeUTF16($string) + { + $result = $string; + if ($this->_defaultEncoding){ + switch ($this->_encoderFunction){ + case 'iconv' : $result = iconv('UTF-16LE', $this->_defaultEncoding, $string); + break; + case 'mb_convert_encoding' : $result = mb_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE' ); + break; + } + } + return $result; + } + + function _GetInt4d($data, $pos) + { + $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24); + if ($value>=4294967294) + { + $value=-2; + } + return $value; + } + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */; \ No newline at end of file