141 $this->_phpExcel = $phpExcel;
151 public function save($pFilename = null) {
153 $this->_phpExcel->garbageCollect();
161 $this->
buildCSS(!$this->_useInlineCss);
164 $fileHandle = fopen($pFilename,
'wb+');
165 if ($fileHandle ===
false) {
166 throw new Exception(
"Could not open file $pFilename for writing.");
173 if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) {
199 default:
return 'baseline';
216 default:
return false;
224 switch ($borderStyle) {
239 default:
return '1px solid';
259 $this->_sheetIndex = $pValue;
279 $this->_generateSheetNavigationBlock = (bool) $pValue;
287 $this->_sheetIndex = null;
300 if (is_null($this->_phpExcel)) {
301 throw new Exception(
'Internal PHPExcel object not set to an instance of an object.');
305 $html =
'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . PHP_EOL;
306 $html .=
'<!-- Generated by PHPExcel - http://www.phpexcel.net -->' . PHP_EOL;
307 $html .=
'<html>' . PHP_EOL;
308 $html .=
' <head>' . PHP_EOL;
309 $html .=
' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . PHP_EOL;
310 $html .=
' <title>' . htmlspecialchars($this->_phpExcel->getProperties()->getTitle()) .
'</title>' . PHP_EOL;
311 if ($pIncludeStyles) {
314 $html .=
' </head>' . PHP_EOL;
315 $html .=
'' . PHP_EOL;
316 $html .=
' <body>' . PHP_EOL;
330 if (is_null($this->_phpExcel)) {
331 throw new Exception(
'Internal PHPExcel object not set to an instance of an object.');
335 if (!$this->_spansAreCalculated) {
341 if (is_null($this->_sheetIndex)) {
342 $sheets = $this->_phpExcel->getAllSheets();
344 $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
352 foreach ($sheets as $sheet) {
357 $dimension = explode(
':', $sheet->calculateWorksheetDimension());
364 $rowMin = $dimension[0][1];
365 $rowMax = $dimension[1][1];
368 $tbodyStart = $rowMin;
370 $theadStart = $theadEnd = 0;
371 if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
372 $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop();
375 if ($rowsToRepeatAtTop[0] == 1) {
376 $theadStart = $rowsToRepeatAtTop[0];
377 $theadEnd = $rowsToRepeatAtTop[1];
378 $tbodyStart = $rowsToRepeatAtTop[1] + 1;
384 while(
$row++ < $rowMax) {
386 if (
$row == $theadStart) {
387 $html .=
' <thead>' . PHP_EOL;
391 if (
$row == $tbodyStart) {
392 $html .=
' <tbody>' . PHP_EOL;
396 if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][
$row]) ) {
400 $column = $dimension[0][0] - 1;
401 while($column++ < $dimension[1][0]) {
403 if ($sheet->cellExistsByColumnAndRow($column,
$row)) {
404 $rowData[$column] = $sheet->getCellByColumnAndRow($column,
$row);
406 $rowData[$column] =
'';
413 if (
$row == $theadEnd) {
414 $html .=
' </thead>' . PHP_EOL;
418 if (
$row == $tbodyEnd) {
419 $html .=
' </tbody>' . PHP_EOL;
428 if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) {
429 $html .=
'<div style="page-break-before:always" />';
450 if (is_null($this->_phpExcel)) {
451 throw new Exception(
'Internal PHPExcel object not set to an instance of an object.');
456 if (is_null($this->_sheetIndex)) {
457 $sheets = $this->_phpExcel->getAllSheets();
459 $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
466 if (count($sheets) > 1) {
470 $html .=
'<ul class="navigation">' . PHP_EOL;
472 foreach ($sheets as $sheet) {
473 $html .=
' <li class="sheet' . $sheetId .
'"><a href="#sheet' . $sheetId .
'">' . $sheet->getTitle() .
'</a></li>' . PHP_EOL;
477 $html .=
'</ul>' . PHP_EOL;
498 if ($drawing->getCoordinates() == $coordinates) {
518 $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;
536 if (is_null($this->_phpExcel)) {
537 throw new Exception(
'Internal PHPExcel object not set to an instance of an object.');
541 $css = $this->
buildCSS($generateSurroundingHTML);
547 if ($generateSurroundingHTML) {
548 $html .=
' <style type="text/css">' . PHP_EOL;
549 $html .=
' html { ' . $this->
_assembleCSS($css[
'html']) .
' }' . PHP_EOL;
553 foreach ($css as $styleName => $styleDefinition) {
554 if ($styleName !=
'html') {
555 $html .=
' ' . $styleName .
' { ' . $this->
_assembleCSS($styleDefinition) .
' }' . PHP_EOL;
560 if ($generateSurroundingHTML) {
561 $html .=
' </style>' . PHP_EOL;
575 public function buildCSS($generateSurroundingHTML =
true) {
577 if (is_null($this->_phpExcel)) {
578 throw new Exception(
'Internal PHPExcel object not set to an instance of an object.');
582 if (!is_null($this->_cssStyles)) {
587 if (!$this->_spansAreCalculated) {
595 if ($generateSurroundingHTML) {
597 $css[
'html'][
'font-family'] =
'Calibri, Arial, Helvetica, sans-serif';
598 $css[
'html'][
'font-size'] =
'11pt';
599 $css[
'html'][
'background-color'] =
'white';
604 $css[
'table'][
'border-collapse'] =
'collapse';
605 $css[
'table'][
'page-break-after'] =
'always';
608 $css[
'.gridlines td'][
'border'] =
'1px dotted black';
611 $css[
'.b'][
'text-align'] =
'center';
614 $css[
'.e'][
'text-align'] =
'center';
617 $css[
'.f'][
'text-align'] =
'right';
620 $css[
'.inlineStr'][
'text-align'] =
'left';
623 $css[
'.n'][
'text-align'] =
'right';
626 $css[
'.s'][
'text-align'] =
'left';
629 foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) {
635 if (is_null($this->_sheetIndex)) {
636 $sheets = $this->_phpExcel->getAllSheets();
638 $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
642 foreach ($sheets as $sheet) {
644 $sheetIndex = $sheet->getParent()->getIndex($sheet);
648 $sheet->calculateColumnWidths();
653 while($column++ < $highestColumnIndex) {
654 $this->_columnWidths[$sheetIndex][$column] = 42;
655 $css[
'table.sheet' . $sheetIndex .
' col.col' . $column][
'width'] =
'42pt';
659 foreach ($sheet->getColumnDimensions() as $columnDimension) {
663 $this->_columnWidths[$sheetIndex][$column] = $width;
664 $css[
'table.sheet' . $sheetIndex .
' col.col' . $column][
'width'] = $width .
'pt';
666 if ($columnDimension->getVisible() ===
false) {
667 $css[
'table.sheet' . $sheetIndex .
' col.col' . $column][
'visibility'] =
'collapse';
668 $css[
'table.sheet' . $sheetIndex .
' col.col' . $column][
'*display'] =
'none';
674 $rowDimension = $sheet->getDefaultRowDimension();
677 $css[
'table.sheet' . $sheetIndex .
' tr'] = array();
679 if ($rowDimension->getRowHeight() == -1) {
682 $pt_height = $rowDimension->getRowHeight();
684 $css[
'table.sheet' . $sheetIndex .
' tr'][
'height'] = $pt_height .
'pt';
685 if ($rowDimension->getVisible() ===
false) {
686 $css[
'table.sheet' . $sheetIndex .
' tr'][
'display'] =
'none';
687 $css[
'table.sheet' . $sheetIndex .
' tr'][
'visibility'] =
'hidden';
691 foreach ($sheet->getRowDimensions() as $rowDimension) {
692 $row = $rowDimension->getRowIndex() - 1;
695 $css[
'table.sheet' . $sheetIndex .
' tr.row' .
$row] = array();
697 if ($rowDimension->getRowHeight() == -1) {
700 $pt_height = $rowDimension->getRowHeight();
702 $css[
'table.sheet' . $sheetIndex .
' tr.row' .
$row][
'height'] = $pt_height .
'pt';
703 if ($rowDimension->getVisible() ===
false) {
704 $css[
'table.sheet' . $sheetIndex .
' tr.row' .
$row][
'display'] =
'none';
705 $css[
'table.sheet' . $sheetIndex .
' tr.row' .
$row][
'visibility'] =
'hidden';
711 if (is_null($this->_cssStyles)) {
712 $this->_cssStyles = $css;
754 $css[
'text-align'] = $textAlign;
773 $css[
'font-weight'] =
'bold';
776 $css[
'text-decoration'] =
'underline line-through';
778 $css[
'text-decoration'] =
'underline';
780 $css[
'text-decoration'] =
'line-through';
783 $css[
'font-style'] =
'italic';
786 $css[
'color'] =
'#' . $pStyle->
getColor()->getRGB();
787 $css[
'font-family'] =
'\'' . $pStyle->
getName() .
'\'';
788 $css[
'font-size'] = $pStyle->
getSize() .
'pt';
844 $css[
'background-color'] = $value;
856 $html .=
' </body>' . PHP_EOL;
857 $html .=
'</html>' . PHP_EOL;
871 $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
876 if (!$this->_useInlineCss) {
877 $gridlines = $pSheet->getShowGridLines() ?
' gridlines' :
'';
878 $html .=
' <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex .
'" class="sheet' . $sheetIndex . $gridlines .
'">' . PHP_EOL;
880 $style = isset($this->_cssStyles[
'table']) ?
883 if ($this->_isPdf && $pSheet->getShowGridLines()) {
884 $html .=
' <table border="1" cellpadding="1" id="sheet' . $sheetIndex .
'" cellspacing="4" style="' . $style .
'">' . PHP_EOL;
886 $html .=
' <table border="0" cellpadding="1" id="sheet' . $sheetIndex .
'" cellspacing="4" style="' . $style .
'">' . PHP_EOL;
893 while($i++ < $highestColumnIndex) {
894 if (!$this->_useInlineCss) {
895 $html .=
' <col class="col' . $i .
'">' . PHP_EOL;
897 $style = isset($this->_cssStyles[
'table.sheet' . $sheetIndex .
' col.col' . $i]) ?
898 $this->
_assembleCSS($this->_cssStyles[
'table.sheet' . $sheetIndex .
' col.col' . $i]) :
'';
899 $html .=
' <col style="' . $style .
'">' . PHP_EOL;
915 $html .=
' </table>' . PHP_EOL;
931 if (is_array($pValues)) {
936 $sheetIndex = $pSheet->
getParent()->getIndex($pSheet);
939 if ($this->_isPdf && count($pSheet->
getBreaks()) > 0) {
943 if (isset($breaks[
'A' . $pRow])) {
948 $html .=
'<div style="page-break-before:always" />';
956 if (!$this->_useInlineCss) {
957 $html .=
' <tr class="row' . $pRow .
'">' . PHP_EOL;
959 $style = isset($this->_cssStyles[
'table.sheet' . $sheetIndex .
' tr.row' . $pRow])
960 ? $this->
_assembleCSS($this->_cssStyles[
'table.sheet' . $sheetIndex .
' tr.row' . $pRow]) :
'';
962 $html .=
' <tr style="' . $style .
'">' . PHP_EOL;
967 foreach ($pValues as $cell) {
970 if (!$this->_useInlineCss) {
972 $cssClass =
'column' . $colNum;
975 if (isset($this->_cssStyles[
'table.sheet' . $sheetIndex .
' td.column' . $colNum])) {
976 $this->_cssStyles[
'table.sheet' . $sheetIndex .
' td.column' . $colNum];
987 if (is_null($cell->getParent())) {
988 $cell->attach($pSheet);
993 $elements = $cell->getValue()->getRichTextElements();
994 foreach ($elements as $element) {
999 if ($element->getFont()->getSuperScript()) {
1000 $cellData .=
'<sup>';
1001 }
else if ($element->getFont()->getSubScript()) {
1002 $cellData .=
'<sub>';
1007 $cellText = $element->getText();
1008 $cellData .= htmlspecialchars($cellText);
1010 if ($element instanceof PHPExcel_RichText_Run) {
1011 if ($element->getFont()->getSuperScript()) {
1012 $cellData .=
'</sup>';
1013 }
else if ($element->getFont()->getSubScript()) {
1014 $cellData .=
'</sub>';
1017 $cellData .=
'</span>';
1021 if ($this->_preCalculateFormulas) {
1023 $cell->getCalculatedValue(),
1024 $pSheet->
getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1025 array($this,
'formatColor')
1028 $cellData = PHPExcel_Style_NumberFormat::ToFormattedString(
1030 $pSheet->
getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1031 array($this,
'formatColor')
1034 if ($pSheet->
getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) {
1035 $cellData =
'<sup>'.$cellData.
'</sup>';
1036 } elseif ($pSheet->
getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) {
1037 $cellData =
'<sub>'.$cellData.
'</sub>';
1043 $cellData = preg_replace(
"/(?m)(?:^|\\G) /",
' ', $cellData);
1046 $cellData = nl2br($cellData);
1049 if (!$this->_useInlineCss) {
1050 $cssClass .=
' style' . $cell->getXfIndex();
1051 $cssClass .=
' ' . $cell->getDataType();
1053 if (isset($this->_cssStyles[
'td.style' . $cell->getXfIndex()])) {
1054 $cssClass = array_merge($cssClass, $this->_cssStyles[
'td.style' . $cell->getXfIndex()]);
1058 $sharedStyle = $pSheet->
getParent()->getCellXfByIndex( $cell->getXfIndex() );
1060 && isset($this->_cssStyles[
'.' . $cell->getDataType()][
'text-align']))
1062 $cssClass[
'text-align'] = $this->_cssStyles[
'.' . $cell->getDataType()][
'text-align'];
1069 $cellData =
'<a href="' . htmlspecialchars($pSheet->
getHyperlink($coordinate)->getUrl()) .
'" title="' . htmlspecialchars($pSheet->
getHyperlink($coordinate)->getTooltip()) .
'">' . $cellData .
'</a>';
1073 $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->
getParent()->getIndex($pSheet)][$pRow + 1][$colNum])
1074 && $this->_isSpannedCell[$pSheet->
getParent()->getIndex($pSheet)][$pRow + 1][$colNum] );
1079 if (isset($this->_isBaseCell[$pSheet->
getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) {
1080 $spans = $this->_isBaseCell[$pSheet->
getParent()->getIndex($pSheet)][$pRow + 1][$colNum];
1081 $rowSpan = $spans[
'rowspan'];
1082 $colSpan = $spans[
'colspan'];
1089 if (!$this->_useInlineCss) {
1090 $html .=
' class="' . $cssClass .
'"';
1097 $e = $colNum + $colSpan - 1;
1099 if (isset($this->_columnWidths[$sheetIndex][$i])) {
1100 $width += $this->_columnWidths[$sheetIndex][$i];
1103 $cssClass[
'width'] = $width .
'pt';
1107 if (isset($this->_cssStyles[
'table.sheet' . $sheetIndex .
' tr.row' . $pRow][
'height'])) {
1108 $height = $this->_cssStyles[
'table.sheet' . $sheetIndex .
' tr.row' . $pRow][
'height'];
1109 $cssClass[
'height'] = $height;
1113 $html .=
' style="' . $this->
_assembleCSS($cssClass) .
'"';
1116 $html .=
' colspan="' . $colSpan .
'"';
1119 $html .=
' rowspan="' . $rowSpan .
'"';
1130 $html .=
'</td>' . PHP_EOL;
1138 $html .=
' </tr>' . PHP_EOL;
1143 throw new Exception(
"Invalid parameters passed.");
1156 foreach ($pValue as $property => $value) {
1157 $pairs[] = $property .
':' . $value;
1159 $string = implode(
'; ', $pairs);
1180 $this->_preCalculateFormulas = $pValue;
1200 $this->_imagesRoot = $pValue;
1220 $this->_useInlineCss = $pValue;
1237 $color_regex =
'/^\\[[a-zA-Z]+\\]/';
1238 if (preg_match($color_regex, $pFormat, $matches)) {
1239 $color = str_replace(
'[',
'', $matches[0]);
1240 $color = str_replace(
']',
'', $color);
1241 $color = strtolower($color);
1245 $value = htmlspecialchars($pValue);
1248 if ($color !== null) {
1249 $value =
'<span style="color:' . $color .
'">' . $value .
'</span>';
1263 $sheetIndexes = $this->_sheetIndex !== null ?
1264 array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1);
1266 foreach ($sheetIndexes as $sheetIndex) {
1267 $sheet = $this->_phpExcel->getSheet($sheetIndex);
1269 $candidateSpannedRow = array();
1272 foreach ($sheet->getMergeCells() as $cells) {
1287 $candidateSpannedRow[$r] = $r;
1291 if ( !($c == $fc && $r == $fr) ) {
1293 $this->_isSpannedCell[$sheetIndex][$r][$c] = array(
1294 'baseCell' => array($fr, $fc),
1298 $this->_isBaseCell[$sheetIndex][$r][$c] = array(
1299 'xlrowspan' => $lr - $fr + 1,
1300 'rowspan' => $lr - $fr + 1,
1301 'xlcolspan' => $lc - $fc + 1,
1302 'colspan' => $lc - $fc + 1,
1312 foreach ($candidateSpannedRow as $rowIndex) {
1313 if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) {
1314 if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) {
1315 $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex;
1321 if ( isset($this->_isSpannedRow[$sheetIndex]) ) {
1322 foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) {
1323 $adjustedBaseCells = array();
1325 $e = $countColumns - 1;
1327 $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c][
'baseCell'];
1329 if ( !in_array($baseCell, $adjustedBaseCells) ) {
1331 --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ][
'rowspan'];
1332 $adjustedBaseCells[] = $baseCell;
1342 $this->_spansAreCalculated =
true;