From 951c332cda24498067216959b232c36fa28293bf Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 19 Nov 2010 14:09:53 +0000 Subject: [PATCH] Minor performance tweaks to the HTML Writer git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@63950 2327b42d-5241-43d6-9e2a-de5ac946f064 --- Classes/PHPExcel/Worksheet.php | 97 +++++++++++++----------- Classes/PHPExcel/Writer/HTML.php | 124 ++++++++++++++++--------------- 2 files changed, 117 insertions(+), 104 deletions(-) diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index 0493b6b6..f932022b 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -304,6 +304,20 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ private $_tabColor; + /** + * Dirty flag + * + * @var boolean + */ + private $_dirty = true; + + /** + * Hash + * + * @var string + */ + private $_hash = null; + /** * Create a new worksheet * @@ -644,7 +658,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable { // Is this a 'rename' or not? if ($this->getTitle() == $pValue) { - return; + return $this; } // Syntax check @@ -675,13 +689,12 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } $altTitle = $pValue . ' ' . $i; - $this->setTitle($altTitle); - - return; + return $this->setTitle($altTitle); } // Set title $this->_title = $pValue; + $this->_dirty = true; // New title $newTitle = $this->getTitle(); @@ -817,6 +830,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function setProtection(PHPExcel_Worksheet_Protection $pValue) { $this->_protection = $pValue; + $this->_dirty = true; + return $this; } @@ -1629,6 +1644,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if (strpos($pRange,':') !== false) { $this->_autoFilter = $pRange; + $this->_dirty = true; } else { throw new Exception('Autofilter must be set on a range of cells.'); } @@ -2176,25 +2192,29 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function garbageCollect() { // Build a reference table from images - $imageCoordinates = array(); - $iterator = $this->getDrawingCollection()->getIterator(); - while ($iterator->valid()) { - $imageCoordinates[$iterator->current()->getCoordinates()] = true; - - $iterator->next(); - } - +// $imageCoordinates = array(); +// $iterator = $this->getDrawingCollection()->getIterator(); +// while ($iterator->valid()) { +// $imageCoordinates[$iterator->current()->getCoordinates()] = true; +// +// $iterator->next(); +// } +// // Lookup highest column and highest row if cells are cleaned $highestColumn = -1; $highestRow = 1; // Find cells that can be cleaned + $col = $row = array(); foreach ($this->_cellCollection->getCellList() as $coord) { - list($col,$row) = sscanf($coord,'%[A-Z]%d'); - // Determine highest column and row - $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($col)); - $highestRow = max($highestRow,$row); + list($c,$r) = sscanf($coord,'%[A-Z]%d'); + $row[$r] = $r; + $col[$c] = strlen($c).$c; } + // Determine highest column and row + $highestRow = max($row); + $highestColumn = PHPExcel_Cell::columnIndexFromString(substr(max($col),1)); + // Loop through column dimensions foreach ($this->_columnDimensions as $dimension) { @@ -2224,20 +2244,22 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @return string Hash code */ public function getHashCode() { - return md5( - $this->_title - . $this->_autoFilter - . ($this->_protection->isProtectionEnabled() ? 't' : 'f') - //. $this->calculateWorksheetDimension() - . __CLASS__ - ); + if ($this->_dirty) { + $this->_hash = md5( $this->_title . + $this->_autoFilter . + ($this->_protection->isProtectionEnabled() ? 't' : 'f') . + __CLASS__ + ); + $this->_dirty = false; + } + return $this->_hash; } /** * Extract worksheet title from range. * - * Example: extractSheetTitle('test!A1') ==> 'A1' - * Example: extractSheetTitle('test!A1', true) ==> array('test', 'A1'); + * Example: extractSheetTitle("testSheet!A1") ==> 'A1' + * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); * * @param string $pRange Range to extract title from * @param bool $returnRange Return range? (see example) @@ -2245,30 +2267,17 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public static function extractSheetTitle($pRange, $returnRange = false) { // Sheet title included? - if (strpos($pRange, '!') === false) { + if (($sep = strpos($pRange, '!')) === false) { return ''; } - // Position of separator exclamation mark - $sep = strrpos($pRange, '!'); - - // Extract sheet title - $reference[0] = substr($pRange, 0, $sep); - $reference[1] = substr($pRange, $sep + 1); - - // Strip possible enclosing single quotes - if (strpos($reference[0], '\'') === 0) { - $reference[0] = substr($reference[0], 1); - } - if (strrpos($reference[0], '\'') === strlen($reference[0]) - 1) { - $reference[0] = substr($reference[0], 0, strlen($reference[0]) - 1); - } - if ($returnRange) { - return $reference; - } else { - return $reference[1]; + return array( trim(substr($pRange, 0, $sep),"'"), + substr($pRange, $sep + 1) + ); } + + return substr($pRange, $sep + 1); } /** diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index cad3205d..57f393ca 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -309,18 +309,18 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { } // Construct HTML - $html = '' . "\r\n"; - $html .= '' . "\r\n"; - $html .= '' . "\r\n"; - $html .= ' ' . "\r\n"; - $html .= ' ' . "\r\n"; - $html .= ' ' . htmlspecialchars($this->_phpExcel->getProperties()->getTitle()) . '' . "\r\n"; + $html = '' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' ' . PHP_EOL; + $html .= ' ' . PHP_EOL; + $html .= ' ' . htmlspecialchars($this->_phpExcel->getProperties()->getTitle()) . '' . PHP_EOL; if ($pIncludeStyles) { $html .= $this->generateStyles(true); } - $html .= ' ' . "\r\n"; - $html .= '' . "\r\n"; - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' ' . PHP_EOL; // Return return $html; @@ -374,8 +374,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // calculate start of , $tbodyStart = $rowMin; $tbodyEnd = $rowMax; - $theadStart = 0; // default: no - $theadEnd = 0; // default: no + $theadStart = $theadEnd = 0; // default: no no if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); @@ -388,44 +387,43 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { } // Loop through cells - $rowData = null; - for ($row = $rowMin; $row <= $rowMax; ++$row) { - // Start a new row - $rowData = array(); - - // Loop through columns - for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { - // Cell exists? - if ($sheet->cellExistsByColumnAndRow($column, $row)) { - $rowData[$column] = $cell = $sheet->getCellByColumnAndRow($column, $row); - } else { - $rowData[$column] = ''; - } - } - + $row = $rowMin-1; + while($row++ < $rowMax) { // ? if ($row == $theadStart) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } // ? if ($row == $tbodyStart) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } // Write row if there are HTML table cells in it if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { + // Start a new rowData + $rowData = array(); + // Loop through columns + $column = $dimension[0][0] - 1; + while($column++ < $dimension[1][0]) { + // Cell exists? + if ($sheet->cellExistsByColumnAndRow($column, $row)) { + $rowData[$column] = $sheet->getCellByColumnAndRow($column, $row); + } else { + $rowData[$column] = ''; + } + } $html .= $this->_generateRow($sheet, $rowData, $row - 1); } // ? if ($row == $theadEnd) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } // ? if ($row == $tbodyEnd) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } } @@ -433,8 +431,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $html .= $this->_generateTableFooter(); // Writing PDF? - if ($this->_isPdf) - { + if ($this->_isPdf) { if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) { $html .= ''; } @@ -477,14 +474,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Loop all sheets $sheetId = 0; - $html .= '' . PHP_EOL; } return $html; @@ -524,8 +521,8 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Convert UTF8 data to PCDATA $filename = htmlspecialchars($filename); - $html .= "\r\n"; - $html .= ' ' . "\r\n"; + $html .= PHP_EOL; + $html .= ' ' . PHP_EOL; } } } @@ -555,20 +552,20 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Start styles if ($generateSurroundingHTML) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } // Return @@ -659,7 +656,8 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // col elements, initialize $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1; - for ($column = 0; $column <= $highestColumnIndex; ++$column) { + $column = -1; + while($column++ < $highestColumnIndex) { $this->_columnWidths[$sheetIndex][$column] = 42; // approximation $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt'; } @@ -862,8 +860,8 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { public function generateHTMLFooter() { // Construct HTML $html = ''; - $html .= ' ' . "\r\n"; - $html .= '' . "\r\n"; + $html .= ' ' . PHP_EOL; + $html .= '' . PHP_EOL; // Return return $html; @@ -884,27 +882,28 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if (!$this->_useInlineCss) { $gridlines = $pSheet->getShowGridLines() ? ' gridlines' : ''; - $html .= ' ' . "\r\n"; + $html .= '
' . PHP_EOL; } else { $style = isset($this->_cssStyles['table']) ? $this->_assembleCSS($this->_cssStyles['table']) : ''; if ($this->_isPdf && $pSheet->getShowGridLines()) { - $html .= '
' . "\r\n"; + $html .= '
' . PHP_EOL; } else { - $html .= '
' . "\r\n"; + $html .= '
' . PHP_EOL; } } // Write elements $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1; - for ($i = 0; $i <= $highestColumnIndex; ++$i) { + $i = -1; + while($i++ < $highestColumnIndex) { if (!$this->_useInlineCss) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } else { $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : ''; - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } } @@ -920,7 +919,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { private function _generateTableFooter() { // Construct HTML $html = ''; - $html .= '
' . "\r\n"; + $html .= ' ' . PHP_EOL; // Return return $html; @@ -962,12 +961,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Write row start if (!$this->_useInlineCss) { - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } else { $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : ''; - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; } // Write cells @@ -1096,7 +1095,9 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // We must explicitly write the width of the element because TCPDF // does not recognize e.g. $width = 0; - for ($i = $colNum; $i < $colNum + $colSpan; ++$i) { + $i = $colNum - 1; + $e = $colNum + $colSpan - 1; + while($i++ < $e) { if (isset($this->_columnWidths[$sheetIndex][$i])) { $width += $this->_columnWidths[$sheetIndex][$i]; } @@ -1128,7 +1129,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $html .= $cellData; // Column end - $html .= '' . "\r\n"; + $html .= '' . PHP_EOL; } // Next column @@ -1136,7 +1137,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { } // Write row end - $html .= ' ' . "\r\n"; + $html .= ' ' . PHP_EOL; // Return return $html; @@ -1282,11 +1283,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; // loop through the individual cells in the individual merge - for ($r = $fr; $r <= $lr; ++$r) { + $r = $fr - 1; + while($r++ < $lr) { // also, flag this row as a HTML row that is candidate to be omitted $candidateSpannedRow[$r] = $r; - for ($c = $fc; $c <= $lc; ++$c) { + $c = $fc - 1; + while($c++ < $lc) { if ( !($c == $fc && $r == $fr) ) { // not the upper-left cell (should not be written in HTML) $this->_isSpannedCell[$sheetIndex][$r][$c] = array( @@ -1320,11 +1323,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if ( isset($this->_isSpannedRow[$sheetIndex]) ) { foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { $adjustedBaseCells = array(); - for ($c = 0; $c < $countColumns; ++$c) { + $c = -1; + $e = $countColumns - 1; + while($c++ < $e) { $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; if ( !in_array($baseCell, $adjustedBaseCells) ) { - // subtract rowspan by 1 --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; $adjustedBaseCells[] = $baseCell;