Minor performance tweaks to the HTML Writer

git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@63950 2327b42d-5241-43d6-9e2a-de5ac946f064
This commit is contained in:
Mark Baker 2010-11-19 14:09:53 +00:00
parent dbcd7fb1af
commit 951c332cda
2 changed files with 117 additions and 104 deletions

View File

@ -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);
}
/**

View File

@ -309,18 +309,18 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
}
// Construct HTML
$html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . "\r\n";
$html .= '<!-- Generated by PHPExcel - http://www.phpexcel.net -->' . "\r\n";
$html .= '<html>' . "\r\n";
$html .= ' <head>' . "\r\n";
$html .= ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . "\r\n";
$html .= ' <title>' . htmlspecialchars($this->_phpExcel->getProperties()->getTitle()) . '</title>' . "\r\n";
$html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . PHP_EOL;
$html .= '<!-- Generated by PHPExcel - http://www.phpexcel.net -->' . PHP_EOL;
$html .= '<html>' . PHP_EOL;
$html .= ' <head>' . PHP_EOL;
$html .= ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . PHP_EOL;
$html .= ' <title>' . htmlspecialchars($this->_phpExcel->getProperties()->getTitle()) . '</title>' . PHP_EOL;
if ($pIncludeStyles) {
$html .= $this->generateStyles(true);
}
$html .= ' </head>' . "\r\n";
$html .= '' . "\r\n";
$html .= ' <body>' . "\r\n";
$html .= ' </head>' . PHP_EOL;
$html .= '' . PHP_EOL;
$html .= ' <body>' . PHP_EOL;
// Return
return $html;
@ -374,8 +374,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
// calculate start of <tbody>, <thead>
$tbodyStart = $rowMin;
$tbodyEnd = $rowMax;
$theadStart = 0; // default: no <thead>
$theadEnd = 0; // default: no </thead>
$theadStart = $theadEnd = 0; // default: no <thead> no </thead>
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) {
// <thead> ?
if ($row == $theadStart) {
$html .= ' <thead>' . "\r\n";
$html .= ' <thead>' . PHP_EOL;
}
// <tbody> ?
if ($row == $tbodyStart) {
$html .= ' <tbody>' . "\r\n";
$html .= ' <tbody>' . 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);
}
// </thead> ?
if ($row == $theadEnd) {
$html .= ' </thead>' . "\r\n";
$html .= ' </thead>' . PHP_EOL;
}
// </tbody> ?
if ($row == $tbodyEnd) {
$html .= ' </tbody>' . "\r\n";
$html .= ' </tbody>' . 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 .= '<tcpdf method="AddPage" />';
}
@ -477,14 +474,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
// Loop all sheets
$sheetId = 0;
$html .= '<ul class="navigation">' . "\r\n";
$html .= '<ul class="navigation">' . PHP_EOL;
foreach ($sheets as $sheet) {
$html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . "\r\n";
$html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL;
++$sheetId;
}
$html .= '</ul>' . "\r\n";
$html .= '</ul>' . 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 .= ' <img style="position: relative; left: ' . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . $filename . '" border="0" width="' . $drawing->getWidth() . '" height="' . $drawing->getHeight() . '" />' . "\r\n";
$html .= PHP_EOL;
$html .= ' <img style="position: relative; left: ' . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . $filename . '" border="0" width="' . $drawing->getWidth() . '" height="' . $drawing->getHeight() . '" />' . PHP_EOL;
}
}
}
@ -555,20 +552,20 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
// Start styles
if ($generateSurroundingHTML) {
$html .= ' <style type="text/css">' . "\r\n";
$html .= ' html { ' . $this->_assembleCSS($css['html']) . ' }' . "\r\n";
$html .= ' <style type="text/css">' . PHP_EOL;
$html .= ' html { ' . $this->_assembleCSS($css['html']) . ' }' . PHP_EOL;
}
// Write all other styles
foreach ($css as $styleName => $styleDefinition) {
if ($styleName != 'html') {
$html .= ' ' . $styleName . ' { ' . $this->_assembleCSS($styleDefinition) . ' }' . "\r\n";
$html .= ' ' . $styleName . ' { ' . $this->_assembleCSS($styleDefinition) . ' }' . PHP_EOL;
}
}
// End styles
if ($generateSurroundingHTML) {
$html .= ' </style>' . "\r\n";
$html .= ' </style>' . 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 .= ' </body>' . "\r\n";
$html .= '</html>' . "\r\n";
$html .= ' </body>' . PHP_EOL;
$html .= '</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 .= ' <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex . '" class="sheet' . $sheetIndex . $gridlines . '">' . "\r\n";
$html .= ' <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex . '" class="sheet' . $sheetIndex . $gridlines . '">' . PHP_EOL;
} else {
$style = isset($this->_cssStyles['table']) ?
$this->_assembleCSS($this->_cssStyles['table']) : '';
if ($this->_isPdf && $pSheet->getShowGridLines()) {
$html .= ' <table border="1" cellpadding="0" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . "\r\n";
$html .= ' <table border="1" cellpadding="0" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL;
} else {
$html .= ' <table border="0" cellpadding="0" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . "\r\n";
$html .= ' <table border="0" cellpadding="0" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL;
}
}
// Write <col> elements
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1;
for ($i = 0; $i <= $highestColumnIndex; ++$i) {
$i = -1;
while($i++ < $highestColumnIndex) {
if (!$this->_useInlineCss) {
$html .= ' <col class="col' . $i . '">' . "\r\n";
$html .= ' <col class="col' . $i . '">' . PHP_EOL;
} else {
$style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ?
$this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : '';
$html .= ' <col style="' . $style . '">' . "\r\n";
$html .= ' <col style="' . $style . '">' . PHP_EOL;
}
}
@ -920,7 +919,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
private function _generateTableFooter() {
// Construct HTML
$html = '';
$html .= ' </table>' . "\r\n";
$html .= ' </table>' . PHP_EOL;
// Return
return $html;
@ -962,12 +961,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
// Write row start
if (!$this->_useInlineCss) {
$html .= ' <tr class="row' . $pRow . '">' . "\r\n";
$html .= ' <tr class="row' . $pRow . '">' . PHP_EOL;
} else {
$style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow])
? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : '';
$html .= ' <tr style="' . $style . '">' . "\r\n";
$html .= ' <tr style="' . $style . '">' . PHP_EOL;
}
// Write cells
@ -1096,7 +1095,9 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
// We must explicitly write the width of the <td> element because TCPDF
// does not recognize e.g. <col style="width:42pt">
$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 .= '</td>' . "\r\n";
$html .= '</td>' . PHP_EOL;
}
// Next column
@ -1136,7 +1137,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter {
}
// Write row end
$html .= ' </tr>' . "\r\n";
$html .= ' </tr>' . 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;