Performance improvements for the Excel5 Reader and Writer

git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@64968 2327b42d-5241-43d6-9e2a-de5ac946f064
This commit is contained in:
Mark Baker 2010-12-07 17:34:47 +00:00
parent 1238c6086d
commit c5ea92442d
7 changed files with 99 additions and 104 deletions

View File

@ -2630,10 +2630,10 @@ class PHPExcel_Calculation {
// echo 'Element is a Percentage operator<br />'; // echo 'Element is a Percentage operator<br />';
$stack->push('Unary Operator','%'); // Put a percentage on the stack $stack->push('Unary Operator','%'); // Put a percentage on the stack
++$index; ++$index;
} elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (rather than plus) can be discarded? } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded?
// echo 'Element is a Positive number, not Plus operator<br />'; // echo 'Element is a Positive number, not Plus operator<br />';
++$index; // Drop the redundant plus symbol ++$index; // Drop the redundant plus symbol
} elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal
return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression
} elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
@ -3278,7 +3278,7 @@ class PHPExcel_Calculation {
// echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />'; // echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />';
$stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]);
$this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.$this->_showTypeDetails(self::$_ExcelConstants[$excelConstant])); $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.$this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
} elseif ((is_numeric($token)) || (is_bool($token)) || (is_null($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { } elseif ((is_numeric($token)) || (is_null($token)) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) {
// echo 'Token is a number, boolean, string, null or an Excel error<br />'; // echo 'Token is a number, boolean, string, null or an Excel error<br />';
$stack->push('Value',$token); $stack->push('Value',$token);
// if the token is a named range, push the named range name onto the stack // if the token is a named range, push the named range name onto the stack

View File

@ -570,7 +570,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
if (!$this->_readDataOnly) { if (!$this->_readDataOnly) {
foreach ($this->_objFonts as $objFont) { foreach ($this->_objFonts as $objFont) {
if (isset($objFont->colorIndex)) { if (isset($objFont->colorIndex)) {
$color = self::_readColor($objFont->colorIndex,$this->_palette); $color = self::_readColor($objFont->colorIndex,$this->_palette,$this->_version);
$objFont->getColor()->setRGB($color['rgb']); $objFont->getColor()->setRGB($color['rgb']);
} }
} }
@ -580,12 +580,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
$fill = $objStyle->getFill(); $fill = $objStyle->getFill();
if (isset($fill->startcolorIndex)) { if (isset($fill->startcolorIndex)) {
$startColor = self::_readColor($fill->startcolorIndex,$this->_palette); $startColor = self::_readColor($fill->startcolorIndex,$this->_palette,$this->_version);
$fill->getStartColor()->setRGB($startColor['rgb']); $fill->getStartColor()->setRGB($startColor['rgb']);
} }
if (isset($fill->endcolorIndex)) { if (isset($fill->endcolorIndex)) {
$endColor = self::_readColor($fill->endcolorIndex,$this->_palette); $endColor = self::_readColor($fill->endcolorIndex,$this->_palette,$this->_version);
$fill->getEndColor()->setRGB($endColor['rgb']); $fill->getEndColor()->setRGB($endColor['rgb']);
} }
@ -597,27 +597,27 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
$diagonal = $objStyle->getBorders()->getDiagonal(); $diagonal = $objStyle->getBorders()->getDiagonal();
if (isset($top->colorIndex)) { if (isset($top->colorIndex)) {
$borderTopColor = self::_readColor($top->colorIndex,$this->_palette); $borderTopColor = self::_readColor($top->colorIndex,$this->_palette,$this->_version);
$top->getColor()->setRGB($borderTopColor['rgb']); $top->getColor()->setRGB($borderTopColor['rgb']);
} }
if (isset($right->colorIndex)) { if (isset($right->colorIndex)) {
$borderRightColor = self::_readColor($right->colorIndex,$this->_palette); $borderRightColor = self::_readColor($right->colorIndex,$this->_palette,$this->_version);
$right->getColor()->setRGB($borderRightColor['rgb']); $right->getColor()->setRGB($borderRightColor['rgb']);
} }
if (isset($bottom->colorIndex)) { if (isset($bottom->colorIndex)) {
$borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette); $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette,$this->_version);
$bottom->getColor()->setRGB($borderBottomColor['rgb']); $bottom->getColor()->setRGB($borderBottomColor['rgb']);
} }
if (isset($left->colorIndex)) { if (isset($left->colorIndex)) {
$borderLeftColor = self::_readColor($left->colorIndex,$this->_palette); $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette,$this->_version);
$left->getColor()->setRGB($borderLeftColor['rgb']); $left->getColor()->setRGB($borderLeftColor['rgb']);
} }
if (isset($diagonal->colorIndex)) { if (isset($diagonal->colorIndex)) {
$borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette); $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette,$this->_version);
$diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']);
} }
} }
@ -4229,7 +4229,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
case 0x14: case 0x14:
// offset: 16; size: 2; color index for sheet tab // offset: 16; size: 2; color index for sheet tab
$colorIndex = self::_GetInt2d($recordData, 16); $colorIndex = self::_GetInt2d($recordData, 16);
$color = self::_readColor($colorIndex,$this->_palette); $color = self::_readColor($colorIndex,$this->_palette,$this->_version);
$this->_phpSheet->getTabColor()->setRGB($color['rgb']); $this->_phpSheet->getTabColor()->setRGB($color['rgb']);
break; break;
@ -4665,7 +4665,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
case 'tAdd': // addition case 'tAdd': // addition
case 'tConcat': // addition case 'tConcat': // addition
case 'tDiv': // division case 'tDiv': // division
case 'tEQ': // equaltiy case 'tEQ': // equality
case 'tGE': // greater than or equal case 'tGE': // greater than or equal
case 'tGT': // greater than case 'tGT': // greater than
case 'tIsect': // intersection case 'tIsect': // intersection
@ -6124,11 +6124,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
*/ */
private static function _GetInt4d($data, $pos) private static function _GetInt4d($data, $pos)
{ {
//return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) |
// (ord($data[$pos + 2]) << 16) | (ord($data[$pos + 3]) << 24);
// FIX: represent numbers correctly on 64-bit system // FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos + 3]); $_or_24 = ord($data[$pos + 3]);
if ($_or_24 >= 128) { if ($_or_24 >= 128) {
// negative number // negative number
@ -6146,7 +6144,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
* @param array $palette Color palette * @param array $palette Color palette
* @return array RGB color value, example: array('rgb' => 'FF0000') * @return array RGB color value, example: array('rgb' => 'FF0000')
*/ */
private static function _readColor($color,$palette) private static function _readColor($color,$palette,$version)
{ {
if ($color <= 0x07 || $color >= 0x40) { if ($color <= 0x07 || $color >= 0x40) {
// special built-in color // special built-in color
@ -6156,7 +6154,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader
return $palette[$color - 8]; return $palette[$color - 8];
} else { } else {
// default color table // default color table
if ($this->_version == self::XLS_BIFF8) { if ($version == self::XLS_BIFF8) {
return self::_mapColor($color); return self::_mapColor($color);
} else { } else {
// BIFF5 // BIFF5

View File

@ -111,36 +111,36 @@ class PHPExcel_Shared_OLE
throw new Exception("Only Little-Endian encoding is supported."); throw new Exception("Only Little-Endian encoding is supported.");
} }
// Size of blocks and short blocks in bytes // Size of blocks and short blocks in bytes
$this->bigBlockSize = pow(2, $this->_readInt2($fh)); $this->bigBlockSize = pow(2, self::_readInt2($fh));
$this->smallBlockSize = pow(2, $this->_readInt2($fh)); $this->smallBlockSize = pow(2, self::_readInt2($fh));
// Skip UID, revision number and version number // Skip UID, revision number and version number
fseek($fh, 44); fseek($fh, 44);
// Number of blocks in Big Block Allocation Table // Number of blocks in Big Block Allocation Table
$bbatBlockCount = $this->_readInt4($fh); $bbatBlockCount = self::_readInt4($fh);
// Root chain 1st block // Root chain 1st block
$directoryFirstBlockId = $this->_readInt4($fh); $directoryFirstBlockId = self::_readInt4($fh);
// Skip unused bytes // Skip unused bytes
fseek($fh, 56); fseek($fh, 56);
// Streams shorter than this are stored using small blocks // Streams shorter than this are stored using small blocks
$this->bigBlockThreshold = $this->_readInt4($fh); $this->bigBlockThreshold = self::_readInt4($fh);
// Block id of first sector in Short Block Allocation Table // Block id of first sector in Short Block Allocation Table
$sbatFirstBlockId = $this->_readInt4($fh); $sbatFirstBlockId = self::_readInt4($fh);
// Number of blocks in Short Block Allocation Table // Number of blocks in Short Block Allocation Table
$sbbatBlockCount = $this->_readInt4($fh); $sbbatBlockCount = self::_readInt4($fh);
// Block id of first sector in Master Block Allocation Table // Block id of first sector in Master Block Allocation Table
$mbatFirstBlockId = $this->_readInt4($fh); $mbatFirstBlockId = self::_readInt4($fh);
// Number of blocks in Master Block Allocation Table // Number of blocks in Master Block Allocation Table
$mbbatBlockCount = $this->_readInt4($fh); $mbbatBlockCount = self::_readInt4($fh);
$this->bbat = array(); $this->bbat = array();
// Remaining 4 * 109 bytes of current block is beginning of Master // Remaining 4 * 109 bytes of current block is beginning of Master
// Block Allocation Table // Block Allocation Table
$mbatBlocks = array(); $mbatBlocks = array();
for ($i = 0; $i < 109; ++$i) { for ($i = 0; $i < 109; ++$i) {
$mbatBlocks[] = $this->_readInt4($fh); $mbatBlocks[] = self::_readInt4($fh);
} }
// Read rest of Master Block Allocation Table (if any is left) // Read rest of Master Block Allocation Table (if any is left)
@ -148,10 +148,10 @@ class PHPExcel_Shared_OLE
for ($i = 0; $i < $mbbatBlockCount; ++$i) { for ($i = 0; $i < $mbbatBlockCount; ++$i) {
fseek($fh, $pos); fseek($fh, $pos);
for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) { for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) {
$mbatBlocks[] = $this->_readInt4($fh); $mbatBlocks[] = self::_readInt4($fh);
} }
// Last block id in each block points to next block // Last block id in each block points to next block
$pos = $this->_getBlockOffset($this->_readInt4($fh)); $pos = $this->_getBlockOffset(self::_readInt4($fh));
} }
// Read Big Block Allocation Table according to chain specified by // Read Big Block Allocation Table according to chain specified by
@ -160,7 +160,7 @@ class PHPExcel_Shared_OLE
$pos = $this->_getBlockOffset($mbatBlocks[$i]); $pos = $this->_getBlockOffset($mbatBlocks[$i]);
fseek($fh, $pos); fseek($fh, $pos);
for ($j = 0 ; $j < $this->bigBlockSize / 4; ++$j) { for ($j = 0 ; $j < $this->bigBlockSize / 4; ++$j) {
$this->bbat[] = $this->_readInt4($fh); $this->bbat[] = self::_readInt4($fh);
} }
} }
@ -169,7 +169,7 @@ class PHPExcel_Shared_OLE
$shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4; $shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4;
$sbatFh = $this->getStream($sbatFirstBlockId); $sbatFh = $this->getStream($sbatFirstBlockId);
for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) { for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) {
$this->sbat[$blockId] = $this->_readInt4($sbatFh); $this->sbat[$blockId] = self::_readInt4($sbatFh);
} }
fclose($sbatFh); fclose($sbatFh);
@ -225,7 +225,7 @@ class PHPExcel_Shared_OLE
* @return int * @return int
* @access public * @access public
*/ */
public function _readInt1($fh) private static function _readInt1($fh)
{ {
list(, $tmp) = unpack("c", fread($fh, 1)); list(, $tmp) = unpack("c", fread($fh, 1));
return $tmp; return $tmp;
@ -237,7 +237,7 @@ class PHPExcel_Shared_OLE
* @return int * @return int
* @access public * @access public
*/ */
public function _readInt2($fh) private static function _readInt2($fh)
{ {
list(, $tmp) = unpack("v", fread($fh, 2)); list(, $tmp) = unpack("v", fread($fh, 2));
return $tmp; return $tmp;
@ -249,7 +249,7 @@ class PHPExcel_Shared_OLE
* @return int * @return int
* @access public * @access public
*/ */
public function _readInt4($fh) private static function _readInt4($fh)
{ {
list(, $tmp) = unpack("V", fread($fh, 4)); list(, $tmp) = unpack("V", fread($fh, 4));
return $tmp; return $tmp;
@ -269,11 +269,11 @@ class PHPExcel_Shared_OLE
for ($pos = 0; ; $pos += 128) { for ($pos = 0; ; $pos += 128) {
fseek($fh, $pos, SEEK_SET); fseek($fh, $pos, SEEK_SET);
$nameUtf16 = fread($fh, 64); $nameUtf16 = fread($fh, 64);
$nameLength = $this->_readInt2($fh); $nameLength = self::_readInt2($fh);
$nameUtf16 = substr($nameUtf16, 0, $nameLength - 2); $nameUtf16 = substr($nameUtf16, 0, $nameLength - 2);
// Simple conversion from UTF-16LE to ISO-8859-1 // Simple conversion from UTF-16LE to ISO-8859-1
$name = str_replace("\x00", "", $nameUtf16); $name = str_replace("\x00", "", $nameUtf16);
$type = $this->_readInt1($fh); $type = self::_readInt1($fh);
switch ($type) { switch ($type) {
case self::OLE_PPS_TYPE_ROOT: case self::OLE_PPS_TYPE_ROOT:
$pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array()); $pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array());
@ -292,14 +292,14 @@ class PHPExcel_Shared_OLE
fseek($fh, 1, SEEK_CUR); fseek($fh, 1, SEEK_CUR);
$pps->Type = $type; $pps->Type = $type;
$pps->Name = $name; $pps->Name = $name;
$pps->PrevPps = $this->_readInt4($fh); $pps->PrevPps = self::_readInt4($fh);
$pps->NextPps = $this->_readInt4($fh); $pps->NextPps = self::_readInt4($fh);
$pps->DirPps = $this->_readInt4($fh); $pps->DirPps = self::_readInt4($fh);
fseek($fh, 20, SEEK_CUR); fseek($fh, 20, SEEK_CUR);
$pps->Time1st = self::OLE2LocalDate(fread($fh, 8)); $pps->Time1st = self::OLE2LocalDate(fread($fh, 8));
$pps->Time2nd = self::OLE2LocalDate(fread($fh, 8)); $pps->Time2nd = self::OLE2LocalDate(fread($fh, 8));
$pps->_StartBlock = $this->_readInt4($fh); $pps->_StartBlock = self::_readInt4($fh);
$pps->Size = $this->_readInt4($fh); $pps->Size = self::_readInt4($fh);
$pps->No = count($this->_list); $pps->No = count($this->_list);
$this->_list[] = $pps; $this->_list[] = $pps;

View File

@ -169,10 +169,8 @@ class PHPExcel_Shared_OLE_PPS
*/ */
public function _getPpsWk() public function _getPpsWk()
{ {
$ret = $this->Name; $ret = str_pad($this->Name,64,"\x00");
for ($i = 0; $i < (64 - strlen($this->Name)); ++$i) {
$ret .= "\x00";
}
$ret .= pack("v", strlen($this->Name) + 2) // 66 $ret .= pack("v", strlen($this->Name) + 2) // 66
. pack("c", $this->Type) // 67 . pack("c", $this->Type) // 67
. pack("c", 0x00) //UK // 68 . pack("c", 0x00) //UK // 68

View File

@ -63,9 +63,9 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
{ {
// Initial Setting for saving // Initial Setting for saving
$this->_BIG_BLOCK_SIZE = pow(2, $this->_BIG_BLOCK_SIZE = pow(2,
((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE) : 9)); ((isset($this->_BIG_BLOCK_SIZE))? self::_adjust2($this->_BIG_BLOCK_SIZE) : 9));
$this->_SMALL_BLOCK_SIZE= pow(2, $this->_SMALL_BLOCK_SIZE= pow(2,
((isset($this->_SMALL_BLOCK_SIZE))? $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6)); ((isset($this->_SMALL_BLOCK_SIZE))? self::_adjust2($this->_SMALL_BLOCK_SIZE): 6));
if (is_resource($filename)) { if (is_resource($filename)) {
$this->_FILEH_ = $filename; $this->_FILEH_ = $filename;
@ -119,7 +119,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0); list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0);
$iSmallLen = 0; $iSmallLen = 0;
$iSBcnt = 0; $iSBcnt = 0;
for ($i = 0; $i < count($raList); ++$i) { $iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) {
$raList[$i]->Size = $raList[$i]->_DataLen(); $raList[$i]->Size = $raList[$i]->_DataLen();
if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) {
@ -151,7 +152,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
* @see save() * @see save()
* @return integer * @return integer
*/ */
public function _adjust2($i2) private static function _adjust2($i2)
{ {
$iWk = log($i2)/log(2); $iWk = log($i2)/log(2);
return ($iWk > floor($iWk))? floor($iWk)+1:$iWk; return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
@ -229,7 +230,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
fwrite($FILE, pack("V", $iAll+$i)); fwrite($FILE, pack("V", $iAll+$i));
} }
if ($i < $i1stBdL) { if ($i < $i1stBdL) {
for ($j = 0; $j < ($i1stBdL-$i); ++$j) { $jB = $i1stBdL - $i;
for ($j = 0; $j < $jB; ++$j) {
fwrite($FILE, (pack("V", -1))); fwrite($FILE, (pack("V", -1)));
} }
} }
@ -247,7 +249,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
$FILE = $this->_FILEH_; $FILE = $this->_FILEH_;
// cycle through PPS's // cycle through PPS's
for ($i = 0; $i < count($raList); ++$i) { $iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) { if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) {
$raList[$i]->Size = $raList[$i]->_DataLen(); $raList[$i]->Size = $raList[$i]->_DataLen();
if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) ||
@ -266,9 +269,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
//} //}
if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) { if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) {
for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); ++$j) { fwrite($FILE, str_repeat("\x00", $this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)));
fwrite($FILE, "\x00");
}
} }
// Set For PPS // Set For PPS
$raList[$i]->_StartBlock = $iStBlk; $raList[$i]->_StartBlock = $iStBlk;
@ -298,7 +299,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
$FILE = $this->_FILEH_; $FILE = $this->_FILEH_;
$iSmBlk = 0; $iSmBlk = 0;
for ($i = 0; $i < count($raList); ++$i) { $iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
// Make SBD, small data string // Make SBD, small data string
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) {
if ($raList[$i]->Size <= 0) { if ($raList[$i]->Size <= 0) {
@ -308,7 +310,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
$iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
// Add to SBD // Add to SBD
for ($j = 0; $j < ($iSmbCnt-1); ++$j) { $jB = $iSmbCnt - 1;
for ($j = 0; $j < $jB; ++$j) {
fwrite($FILE, pack("V", $j+$iSmBlk+1)); fwrite($FILE, pack("V", $j+$iSmBlk+1));
} }
fwrite($FILE, pack("V", -2)); fwrite($FILE, pack("V", -2));
@ -323,9 +326,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
$sRes .= $raList[$i]->_data; $sRes .= $raList[$i]->_data;
//} //}
if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) { if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) {
for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); ++$j) { $sRes .= str_repeat("\x00",$this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE));
$sRes .= "\x00";
}
} }
// Set for PPS // Set for PPS
$raList[$i]->_StartBlock = $iSmBlk; $raList[$i]->_StartBlock = $iSmBlk;
@ -335,7 +336,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
} }
$iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); $iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE);
if ($iSmBlk % $iSbCnt) { if ($iSmBlk % $iSbCnt) {
for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); ++$i) { $iB = $iSbCnt - ($iSmBlk % $iSbCnt);
for ($i = 0; $i < $iB; ++$i) {
fwrite($FILE, pack("V", -1)); fwrite($FILE, pack("V", -1));
} }
} }
@ -351,16 +353,15 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
public function _savePps(&$raList) public function _savePps(&$raList)
{ {
// Save each PPS WK // Save each PPS WK
for ($i = 0; $i < count($raList); ++$i) { $iC = count($raList);
for ($i = 0; $i < $iC; ++$i) {
fwrite($this->_FILEH_, $raList[$i]->_getPpsWk()); fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
} }
// Adjust for Block // Adjust for Block
$iCnt = count($raList); $iCnt = count($raList);
$iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; $iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE;
if ($iCnt % $iBCnt) { if ($iCnt % $iBCnt) {
for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE); ++$i) { fwrite($this->_FILEH_, str_repeat("\x00",($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE));
fwrite($this->_FILEH_, "\x00");
}
} }
} }
@ -426,7 +427,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
} }
// Adjust for Block // Adjust for Block
if (($iAllW + $iBdCnt) % $iBbCnt) { if (($iAllW + $iBdCnt) % $iBbCnt) {
for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); ++$i) { $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
for ($i = 0; $i < $iBlock; ++$i) {
fwrite($FILE, pack("V", -1)); fwrite($FILE, pack("V", -1));
} }
} }
@ -443,7 +445,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
} }
if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) { if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) {
for ($i = 0; $i < (($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1))); ++$i) { $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
for ($i = 0; $i < $iB; ++$i) {
fwrite($FILE, pack("V", -1)); fwrite($FILE, pack("V", -1));
} }
} }

View File

@ -81,19 +81,19 @@ class PHPExcel_Shared_OLERead {
} }
// Total number of sectors used for the SAT // Total number of sectors used for the SAT
$this->numBigBlockDepotBlocks = $this->_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); $this->numBigBlockDepotBlocks = self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
// SecID of the first sector of the directory stream // SecID of the first sector of the directory stream
$this->rootStartBlock = $this->_GetInt4d($this->data, self::ROOT_START_BLOCK_POS); $this->rootStartBlock = self::_GetInt4d($this->data, self::ROOT_START_BLOCK_POS);
// SecID of the first sector of the SSAT (or -2 if not extant) // SecID of the first sector of the SSAT (or -2 if not extant)
$this->sbdStartBlock = $this->_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); $this->sbdStartBlock = self::_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used) // SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
$this->extensionBlock = $this->_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); $this->extensionBlock = self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS);
// Total number of sectors used by MSAT // Total number of sectors used by MSAT
$this->numExtensionBlocks = $this->_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); $this->numExtensionBlocks = self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
$bigBlockDepotBlocks = array(); $bigBlockDepotBlocks = array();
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
@ -105,7 +105,7 @@ class PHPExcel_Shared_OLERead {
} }
for ($i = 0; $i < $bbdBlocks; ++$i) { for ($i = 0; $i < $bbdBlocks; ++$i) {
$bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos); $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos);
$pos += 4; $pos += 4;
} }
@ -114,13 +114,13 @@ class PHPExcel_Shared_OLERead {
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
$bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos); $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos);
$pos += 4; $pos += 4;
} }
$bbdBlocks += $blocksToRead; $bbdBlocks += $blocksToRead;
if ($bbdBlocks < $this->numBigBlockDepotBlocks) { if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
$this->extensionBlock = $this->_GetInt4d($this->data, $pos); $this->extensionBlock = self::_GetInt4d($this->data, $pos);
} }
} }
@ -128,11 +128,12 @@ class PHPExcel_Shared_OLERead {
$index = 0; $index = 0;
$this->bigBlockChain = array(); $this->bigBlockChain = array();
$bbs = self::BIG_BLOCK_SIZE / 4;
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
for ($j = 0 ; $j < self::BIG_BLOCK_SIZE / 4; ++$j) { for ($j = 0 ; $j < $bbs; ++$j) {
$this->bigBlockChain[$index] = $this->_GetInt4d($this->data, $pos); $this->bigBlockChain[$index] = self::_GetInt4d($this->data, $pos);
$pos += 4 ; $pos += 4 ;
++$index; ++$index;
} }
@ -146,8 +147,8 @@ class PHPExcel_Shared_OLERead {
while ($sbdBlock != -2) { while ($sbdBlock != -2) {
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
for ($j = 0; $j < self::BIG_BLOCK_SIZE / 4; ++$j) { for ($j = 0; $j < $bbs; ++$j) {
$this->smallBlockChain[$index] = $this->_GetInt4d($this->data, $pos); $this->smallBlockChain[$index] = self::_GetInt4d($this->data, $pos);
$pos += 4; $pos += 4;
++$index; ++$index;
} }
@ -187,7 +188,6 @@ class PHPExcel_Shared_OLERead {
return $streamData; return $streamData;
} else { } else {
$numBlocks = $this->props[$this->wrkbook]['size'] / self::BIG_BLOCK_SIZE; $numBlocks = $this->props[$this->wrkbook]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$this->wrkbook]['size'] % self::BIG_BLOCK_SIZE != 0) { if ($this->props[$this->wrkbook]['size'] % self::BIG_BLOCK_SIZE != 0) {
@ -196,7 +196,6 @@ class PHPExcel_Shared_OLERead {
if ($numBlocks == 0) return ''; if ($numBlocks == 0) return '';
$streamData = ''; $streamData = '';
$block = $this->props[$this->wrkbook]['startBlock']; $block = $this->props[$this->wrkbook]['startBlock'];
@ -239,7 +238,6 @@ class PHPExcel_Shared_OLERead {
return $streamData; return $streamData;
} else { } else {
$numBlocks = $this->props[$this->summaryInformation]['size'] / self::BIG_BLOCK_SIZE; $numBlocks = $this->props[$this->summaryInformation]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$this->summaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) { if ($this->props[$this->summaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) {
@ -248,7 +246,6 @@ class PHPExcel_Shared_OLERead {
if ($numBlocks == 0) return ''; if ($numBlocks == 0) return '';
$streamData = ''; $streamData = '';
$block = $this->props[$this->summaryInformation]['startBlock']; $block = $this->props[$this->summaryInformation]['startBlock'];
@ -291,7 +288,6 @@ class PHPExcel_Shared_OLERead {
return $streamData; return $streamData;
} else { } else {
$numBlocks = $this->props[$this->documentSummaryInformation]['size'] / self::BIG_BLOCK_SIZE; $numBlocks = $this->props[$this->documentSummaryInformation]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$this->documentSummaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) { if ($this->props[$this->documentSummaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) {
@ -300,7 +296,6 @@ class PHPExcel_Shared_OLERead {
if ($numBlocks == 0) return ''; if ($numBlocks == 0) return '';
$streamData = ''; $streamData = '';
$block = $this->props[$this->documentSummaryInformation]['startBlock']; $block = $this->props[$this->documentSummaryInformation]['startBlock'];
@ -330,7 +325,7 @@ class PHPExcel_Shared_OLERead {
while ($block != -2) { while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE; $pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$data = $data . substr($this->data, $pos, self::BIG_BLOCK_SIZE); $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = $this->bigBlockChain[$block]; $block = $this->bigBlockChain[$block];
} }
return $data; return $data;
@ -356,16 +351,11 @@ class PHPExcel_Shared_OLERead {
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) // sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
// sectorID of first sector of the short-stream container stream, if this entry is root entry // sectorID of first sector of the short-stream container stream, if this entry is root entry
$startBlock = $this->_GetInt4d($d, self::START_BLOCK_POS); $startBlock = self::_GetInt4d($d, self::START_BLOCK_POS);
$size = $this->_GetInt4d($d, self::SIZE_POS); $size = self::_GetInt4d($d, self::SIZE_POS);
$name = ''; $name = str_replace("\x00", "", substr($d,0,$nameSize));
for ($i = 0; $i < $nameSize ; ++$i) {
$name .= $d[$i];
}
$name = str_replace("\x00", "", $name);
$this->props[] = array ( $this->props[] = array (
'name' => $name, 'name' => $name,
@ -407,13 +397,18 @@ class PHPExcel_Shared_OLERead {
* @param int $pos * @param int $pos
* @return int * @return int
*/ */
private function _GetInt4d($data, $pos) private static function _GetInt4d($data, $pos)
{ {
// FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos + 3]); $_or_24 = ord($data[$pos + 3]);
if ($_or_24>=128) $_ord_24 = -abs((256-$_or_24) << 24); if ($_or_24 >= 128) {
else $_ord_24 = ($_or_24&127) << 24; // negative number
$_ord_24 = -abs((256 - $_or_24) << 24);
} else {
$_ord_24 = ($_or_24 & 127) << 24;
}
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24;
} }

View File

@ -58,6 +58,7 @@ Fixed in SVN:
- Bugfix: (MBaker) Work item 14679 - Formula evaluation fails with Japanese sheet refs - Bugfix: (MBaker) Work item 14679 - Formula evaluation fails with Japanese sheet refs
- Bugfix: (MBaker) Work item 13559 - PHPExcel_Writer_PDF does not handle cell borders correctly - Bugfix: (MBaker) Work item 13559 - PHPExcel_Writer_PDF does not handle cell borders correctly
- Bugfix: (MBaker) Work item 14831 - Style : applyFromArray() for 'allborders' not working - Bugfix: (MBaker) Work item 14831 - Style : applyFromArray() for 'allborders' not working
- Bugfix: (MBaker) Work item 14837 - Using $this when not in object context in Excel5 Reader
- General: (MBaker) Applied patch 6609 - Removes a unnecessary loop through each cell when applying conditional formatting to a range. - General: (MBaker) Applied patch 6609 - Removes a unnecessary loop through each cell when applying conditional formatting to a range.
- General: (MBaker) Applied patch 7169 - Removed spurious PHP end tags (?>) - General: (MBaker) Applied patch 7169 - Removed spurious PHP end tags (?>)
- General: (MBaker) Improved performance (speed) and reduced memory overheads, particularly for the Writers, but across the whole library. - General: (MBaker) Improved performance (speed) and reduced memory overheads, particularly for the Writers, but across the whole library.