From c70e289dacc794ac37e11c4f5ee035b126aea8df Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Mon, 11 May 2015 22:38:52 +0100 Subject: [PATCH] More efforts to get codebase to conform with PSR-2 coding standards --- Classes/PHPExcel/Chart.php | 962 +- Classes/PHPExcel/Comment.php | 20 +- Classes/PHPExcel/DocumentProperties.php | 280 +- Classes/PHPExcel/DocumentSecurity.php | 202 +- Classes/PHPExcel/HashTable.php | 322 +- Classes/PHPExcel/IComparable.php | 26 +- Classes/PHPExcel/IOFactory.php | 469 +- Classes/PHPExcel/NamedRange.php | 196 +- Classes/PHPExcel/Reader/Abstract.php | 378 +- Classes/PHPExcel/Reader/CSV.php | 602 +- Classes/PHPExcel/Reader/DefaultReadFilter.php | 34 +- Classes/PHPExcel/Reader/Excel2003XML.php | 1420 +- Classes/PHPExcel/Reader/Excel2007.php | 3414 ++-- Classes/PHPExcel/Reader/Excel5.php | 13904 ++++++++-------- Classes/PHPExcel/Reader/Exception.php | 38 +- Classes/PHPExcel/Reader/Gnumeric.php | 1512 +- Classes/PHPExcel/Reader/HTML.php | 124 +- Classes/PHPExcel/Reader/IReadFilter.php | 32 +- Classes/PHPExcel/Reader/IReader.php | 30 +- Classes/PHPExcel/Reader/OOCalc.php | 1202 +- Classes/PHPExcel/Reader/SYLK.php | 742 +- Classes/PHPExcel/ReferenceHelper.php | 1598 +- Classes/PHPExcel/Worksheet.php | 294 +- Classes/PHPExcel/Writer/Abstract.php | 207 +- Classes/PHPExcel/Writer/CSV.php | 495 +- Classes/PHPExcel/Writer/Excel2007.php | 714 +- Classes/PHPExcel/Writer/Excel2007/Chart.php | 30 +- .../PHPExcel/Writer/Excel2007/Comments.php | 378 +- .../Writer/Excel2007/ContentTypes.php | 444 +- .../PHPExcel/Writer/Excel2007/DocProps.php | 366 +- Classes/PHPExcel/Writer/Excel2007/Drawing.php | 894 +- Classes/PHPExcel/Writer/Excel2007/Rels.php | 706 +- .../PHPExcel/Writer/Excel2007/RelsRibbon.php | 70 +- Classes/PHPExcel/Writer/Excel2007/RelsVBA.php | 60 +- .../PHPExcel/Writer/Excel2007/StringTable.php | 488 +- Classes/PHPExcel/Writer/Excel2007/Style.php | 1162 +- Classes/PHPExcel/Writer/Excel2007/Theme.php | 1352 +- .../PHPExcel/Writer/Excel2007/Workbook.php | 710 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 2372 +-- .../PHPExcel/Writer/Excel2007/WriterPart.php | 78 +- Classes/PHPExcel/Writer/Excel5.php | 1762 +- Classes/PHPExcel/Writer/Excel5/BIFFwriter.php | 320 +- Classes/PHPExcel/Writer/Excel5/Escher.php | 824 +- Classes/PHPExcel/Writer/Excel5/Font.php | 232 +- Classes/PHPExcel/Writer/Excel5/Parser.php | 2826 ++-- Classes/PHPExcel/Writer/Excel5/Workbook.php | 2756 +-- Classes/PHPExcel/Writer/Excel5/Worksheet.php | 7218 ++++---- Classes/PHPExcel/Writer/Excel5/Xf.php | 844 +- Classes/PHPExcel/Writer/Exception.php | 50 +- Classes/PHPExcel/Writer/HTML.php | 2737 ++- Classes/PHPExcel/Writer/IWriter.php | 14 +- Classes/PHPExcel/Writer/OpenDocument.php | 50 +- Classes/PHPExcel/Writer/OpenDocument/Meta.php | 79 +- .../PHPExcel/Writer/OpenDocument/MetaInf.php | 15 +- .../PHPExcel/Writer/OpenDocument/Mimetype.php | 15 +- .../PHPExcel/Writer/OpenDocument/Settings.php | 15 +- .../PHPExcel/Writer/OpenDocument/Styles.php | 15 +- .../Writer/OpenDocument/Thumbnails.php | 15 +- .../Writer/OpenDocument/WriterPart.php | 14 +- 59 files changed, 29020 insertions(+), 29108 deletions(-) diff --git a/Classes/PHPExcel/Chart.php b/Classes/PHPExcel/Chart.php index 04af7b96..c8d96529 100644 --- a/Classes/PHPExcel/Chart.php +++ b/Classes/PHPExcel/Chart.php @@ -1,6 +1,7 @@ _name = $name; - $this->_title = $title; - $this->_legend = $legend; - $this->_xAxisLabel = $xAxisLabel; - $this->_yAxisLabel = $yAxisLabel; - $this->_plotArea = $plotArea; - $this->_plotVisibleOnly = $plotVisibleOnly; - $this->_displayBlanksAs = $displayBlanksAs; - $this->_xAxis = $xAxis; - $this->_yAxis = $yAxis; - $this->_majorGridlines = $majorGridlines; - $this->_minorGridlines = $minorGridlines; - } + /** + * Create a new PHPExcel_Chart + */ + public function __construct($name, PHPExcel_Chart_Title $title = null, PHPExcel_Chart_Legend $legend = null, PHPExcel_Chart_PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = '0', PHPExcel_Chart_Title $xAxisLabel = null, PHPExcel_Chart_Title $yAxisLabel = null, PHPExcel_Chart_Axis $xAxis = null, PHPExcel_Chart_Axis $yAxis = null, PHPExcel_Chart_GridLines $majorGridlines = null, PHPExcel_Chart_GridLines $minorGridlines = null) + { + $this->_name = $name; + $this->_title = $title; + $this->_legend = $legend; + $this->_xAxisLabel = $xAxisLabel; + $this->_yAxisLabel = $yAxisLabel; + $this->_plotArea = $plotArea; + $this->_plotVisibleOnly = $plotVisibleOnly; + $this->_displayBlanksAs = $displayBlanksAs; + $this->_xAxis = $xAxis; + $this->_yAxis = $yAxis; + $this->_majorGridlines = $majorGridlines; + $this->_minorGridlines = $minorGridlines; + } - /** - * Get Name - * - * @return string - */ - public function getName() { - return $this->_name; - } + /** + * Get Name + * + * @return string + */ + public function getName() + { + return $this->_name; + } - /** - * Get Worksheet - * - * @return PHPExcel_Worksheet - */ - public function getWorksheet() { - return $this->_worksheet; - } + /** + * Get Worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() + { + return $this->_worksheet; + } - /** - * Set Worksheet - * - * @param PHPExcel_Worksheet $pValue - * @throws PHPExcel_Chart_Exception - * @return PHPExcel_Chart - */ - public function setWorksheet(PHPExcel_Worksheet $pValue = null) { - $this->_worksheet = $pValue; + /** + * Set Worksheet + * + * @param PHPExcel_Worksheet $pValue + * @throws PHPExcel_Chart_Exception + * @return PHPExcel_Chart + */ + public function setWorksheet(PHPExcel_Worksheet $pValue = null) + { + $this->_worksheet = $pValue; - return $this; - } + return $this; + } - /** - * Get Title - * - * @return PHPExcel_Chart_Title - */ - public function getTitle() { - return $this->_title; - } + /** + * Get Title + * + * @return PHPExcel_Chart_Title + */ + public function getTitle() + { + return $this->_title; + } - /** - * Set Title - * - * @param PHPExcel_Chart_Title $title - * @return PHPExcel_Chart - */ - public function setTitle(PHPExcel_Chart_Title $title) { - $this->_title = $title; + /** + * Set Title + * + * @param PHPExcel_Chart_Title $title + * @return PHPExcel_Chart + */ + public function setTitle(PHPExcel_Chart_Title $title) + { + $this->_title = $title; - return $this; - } + return $this; + } - /** - * Get Legend - * - * @return PHPExcel_Chart_Legend - */ - public function getLegend() { - return $this->_legend; - } + /** + * Get Legend + * + * @return PHPExcel_Chart_Legend + */ + public function getLegend() + { + return $this->_legend; + } - /** - * Set Legend - * - * @param PHPExcel_Chart_Legend $legend - * @return PHPExcel_Chart - */ - public function setLegend(PHPExcel_Chart_Legend $legend) { - $this->_legend = $legend; + /** + * Set Legend + * + * @param PHPExcel_Chart_Legend $legend + * @return PHPExcel_Chart + */ + public function setLegend(PHPExcel_Chart_Legend $legend) + { + $this->_legend = $legend; - return $this; - } + return $this; + } - /** - * Get X-Axis Label - * - * @return PHPExcel_Chart_Title - */ - public function getXAxisLabel() { - return $this->_xAxisLabel; - } + /** + * Get X-Axis Label + * + * @return PHPExcel_Chart_Title + */ + public function getXAxisLabel() + { + return $this->_xAxisLabel; + } - /** - * Set X-Axis Label - * - * @param PHPExcel_Chart_Title $label - * @return PHPExcel_Chart - */ - public function setXAxisLabel(PHPExcel_Chart_Title $label) { - $this->_xAxisLabel = $label; + /** + * Set X-Axis Label + * + * @param PHPExcel_Chart_Title $label + * @return PHPExcel_Chart + */ + public function setXAxisLabel(PHPExcel_Chart_Title $label) + { + $this->_xAxisLabel = $label; - return $this; - } + return $this; + } - /** - * Get Y-Axis Label - * - * @return PHPExcel_Chart_Title - */ - public function getYAxisLabel() { - return $this->_yAxisLabel; - } + /** + * Get Y-Axis Label + * + * @return PHPExcel_Chart_Title + */ + public function getYAxisLabel() + { + return $this->_yAxisLabel; + } - /** - * Set Y-Axis Label - * - * @param PHPExcel_Chart_Title $label - * @return PHPExcel_Chart - */ - public function setYAxisLabel(PHPExcel_Chart_Title $label) { - $this->_yAxisLabel = $label; + /** + * Set Y-Axis Label + * + * @param PHPExcel_Chart_Title $label + * @return PHPExcel_Chart + */ + public function setYAxisLabel(PHPExcel_Chart_Title $label) { + $this->_yAxisLabel = $label; - return $this; - } + return $this; + } - /** - * Get Plot Area - * - * @return PHPExcel_Chart_PlotArea - */ - public function getPlotArea() { - return $this->_plotArea; - } + /** + * Get Plot Area + * + * @return PHPExcel_Chart_PlotArea + */ + public function getPlotArea() + { + return $this->_plotArea; + } - /** - * Get Plot Visible Only - * - * @return boolean - */ - public function getPlotVisibleOnly() { - return $this->_plotVisibleOnly; - } + /** + * Get Plot Visible Only + * + * @return boolean + */ + public function getPlotVisibleOnly() + { + return $this->_plotVisibleOnly; + } - /** - * Set Plot Visible Only - * - * @param boolean $plotVisibleOnly - * @return PHPExcel_Chart - */ - public function setPlotVisibleOnly($plotVisibleOnly = true) { - $this->_plotVisibleOnly = $plotVisibleOnly; + /** + * Set Plot Visible Only + * + * @param boolean $plotVisibleOnly + * @return PHPExcel_Chart + */ + public function setPlotVisibleOnly($plotVisibleOnly = true) + { + $this->_plotVisibleOnly = $plotVisibleOnly; - return $this; - } + return $this; + } - /** - * Get Display Blanks as - * - * @return string - */ - public function getDisplayBlanksAs() { - return $this->_displayBlanksAs; - } + /** + * Get Display Blanks as + * + * @return string + */ + public function getDisplayBlanksAs() + { + return $this->_displayBlanksAs; + } - /** - * Set Display Blanks as - * - * @param string $displayBlanksAs - * @return PHPExcel_Chart - */ - public function setDisplayBlanksAs($displayBlanksAs = '0') { - $this->_displayBlanksAs = $displayBlanksAs; - } + /** + * Set Display Blanks as + * + * @param string $displayBlanksAs + * @return PHPExcel_Chart + */ + public function setDisplayBlanksAs($displayBlanksAs = '0') + { + $this->_displayBlanksAs = $displayBlanksAs; + } /** @@ -363,8 +370,9 @@ class PHPExcel_Chart * * @return PHPExcel_Chart_Axis */ - public function getChartAxisY() { - if($this->_yAxis !== NULL){ + public function getChartAxisY() + { + if ($this->_yAxis !== null) { return $this->_yAxis; } @@ -376,8 +384,9 @@ class PHPExcel_Chart * * @return PHPExcel_Chart_Axis */ - public function getChartAxisX() { - if($this->_xAxis !== NULL){ + public function getChartAxisX() + { + if ($this->_xAxis !== null) { return $this->_xAxis; } @@ -389,8 +398,9 @@ class PHPExcel_Chart * * @return PHPExcel_Chart_GridLines */ - public function getMajorGridlines() { - if($this->_majorGridlines !== NULL){ + public function getMajorGridlines() + { + if ($this->_majorGridlines !== null) { return $this->_majorGridlines; } @@ -402,8 +412,9 @@ class PHPExcel_Chart * * @return PHPExcel_Chart_GridLines */ - public function getMinorGridlines() { - if($this->_minorGridlines !== NULL){ + public function getMinorGridlines() + { + if ($this->_minorGridlines !== null) { return $this->_minorGridlines; } @@ -411,225 +422,258 @@ class PHPExcel_Chart } - /** - * Set the Top Left position for the chart - * - * @param string $cell - * @param integer $xOffset - * @param integer $yOffset - * @return PHPExcel_Chart - */ - public function setTopLeftPosition($cell, $xOffset=null, $yOffset=null) { - $this->_topLeftCellRef = $cell; - if (!is_null($xOffset)) - $this->setTopLeftXOffset($xOffset); - if (!is_null($yOffset)) - $this->setTopLeftYOffset($yOffset); + /** + * Set the Top Left position for the chart + * + * @param string $cell + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setTopLeftPosition($cell, $xOffset=null, $yOffset=null) + { + $this->_topLeftCellRef = $cell; + if (!is_null($xOffset)) { + $this->setTopLeftXOffset($xOffset); + } + if (!is_null($yOffset)) { + $this->setTopLeftYOffset($yOffset); + } - return $this; - } + return $this; + } - /** - * Get the top left position of the chart - * - * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell - */ - public function getTopLeftPosition() { - return array( 'cell' => $this->_topLeftCellRef, - 'xOffset' => $this->_topLeftXOffset, - 'yOffset' => $this->_topLeftYOffset - ); - } + /** + * Get the top left position of the chart + * + * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell + */ + public function getTopLeftPosition() + { + return array( + 'cell' => $this->_topLeftCellRef, + 'xOffset' => $this->_topLeftXOffset, + 'yOffset' => $this->_topLeftYOffset + ); + } - /** - * Get the cell address where the top left of the chart is fixed - * - * @return string - */ - public function getTopLeftCell() { - return $this->_topLeftCellRef; - } + /** + * Get the cell address where the top left of the chart is fixed + * + * @return string + */ + public function getTopLeftCell() + { + return $this->_topLeftCellRef; + } - /** - * Set the Top Left cell position for the chart - * - * @param string $cell - * @return PHPExcel_Chart - */ - public function setTopLeftCell($cell) { - $this->_topLeftCellRef = $cell; + /** + * Set the Top Left cell position for the chart + * + * @param string $cell + * @return PHPExcel_Chart + */ + public function setTopLeftCell($cell) + { + $this->_topLeftCellRef = $cell; - return $this; - } + return $this; + } - /** - * Set the offset position within the Top Left cell for the chart - * - * @param integer $xOffset - * @param integer $yOffset - * @return PHPExcel_Chart - */ - public function setTopLeftOffset($xOffset=null,$yOffset=null) { - if (!is_null($xOffset)) - $this->setTopLeftXOffset($xOffset); - if (!is_null($yOffset)) - $this->setTopLeftYOffset($yOffset); + /** + * Set the offset position within the Top Left cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setTopLeftOffset($xOffset = null, $yOffset = null) + { + if (!is_null($xOffset)) { + $this->setTopLeftXOffset($xOffset); + } + if (!is_null($yOffset)) { + $this->setTopLeftYOffset($yOffset); + } - return $this; - } + return $this; + } - /** - * Get the offset position within the Top Left cell for the chart - * - * @return integer[] - */ - public function getTopLeftOffset() { - return array( 'X' => $this->_topLeftXOffset, - 'Y' => $this->_topLeftYOffset - ); - } + /** + * Get the offset position within the Top Left cell for the chart + * + * @return integer[] + */ + public function getTopLeftOffset() + { + return array( + 'X' => $this->_topLeftXOffset, + 'Y' => $this->_topLeftYOffset + ); + } - public function setTopLeftXOffset($xOffset) { - $this->_topLeftXOffset = $xOffset; + public function setTopLeftXOffset($xOffset) + { + $this->_topLeftXOffset = $xOffset; - return $this; - } + return $this; + } - public function getTopLeftXOffset() { - return $this->_topLeftXOffset; - } + public function getTopLeftXOffset() + { + return $this->_topLeftXOffset; + } - public function setTopLeftYOffset($yOffset) { - $this->_topLeftYOffset = $yOffset; + public function setTopLeftYOffset($yOffset) + { + $this->_topLeftYOffset = $yOffset; - return $this; - } + return $this; + } - public function getTopLeftYOffset() { - return $this->_topLeftYOffset; - } + public function getTopLeftYOffset() + { + return $this->_topLeftYOffset; + } - /** - * Set the Bottom Right position of the chart - * - * @param string $cell - * @param integer $xOffset - * @param integer $yOffset - * @return PHPExcel_Chart - */ - public function setBottomRightPosition($cell, $xOffset=null, $yOffset=null) { - $this->_bottomRightCellRef = $cell; - if (!is_null($xOffset)) - $this->setBottomRightXOffset($xOffset); - if (!is_null($yOffset)) - $this->setBottomRightYOffset($yOffset); + /** + * Set the Bottom Right position of the chart + * + * @param string $cell + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setBottomRightPosition($cell, $xOffset = null, $yOffset = null) + { + $this->_bottomRightCellRef = $cell; + if (!is_null($xOffset)) { + $this->setBottomRightXOffset($xOffset); + } + if (!is_null($yOffset)) { + $this->setBottomRightYOffset($yOffset); + } - return $this; - } + return $this; + } - /** - * Get the bottom right position of the chart - * - * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell - */ - public function getBottomRightPosition() { - return array( 'cell' => $this->_bottomRightCellRef, - 'xOffset' => $this->_bottomRightXOffset, - 'yOffset' => $this->_bottomRightYOffset - ); - } + /** + * Get the bottom right position of the chart + * + * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell + */ + public function getBottomRightPosition() + { + return array( + 'cell' => $this->_bottomRightCellRef, + 'xOffset' => $this->_bottomRightXOffset, + 'yOffset' => $this->_bottomRightYOffset + ); + } - public function setBottomRightCell($cell) { - $this->_bottomRightCellRef = $cell; + public function setBottomRightCell($cell) + { + $this->_bottomRightCellRef = $cell; - return $this; - } + return $this; + } - /** - * Get the cell address where the bottom right of the chart is fixed - * - * @return string - */ - public function getBottomRightCell() { - return $this->_bottomRightCellRef; - } + /** + * Get the cell address where the bottom right of the chart is fixed + * + * @return string + */ + public function getBottomRightCell() + { + return $this->_bottomRightCellRef; + } - /** - * Set the offset position within the Bottom Right cell for the chart - * - * @param integer $xOffset - * @param integer $yOffset - * @return PHPExcel_Chart - */ - public function setBottomRightOffset($xOffset=null,$yOffset=null) { - if (!is_null($xOffset)) - $this->setBottomRightXOffset($xOffset); - if (!is_null($yOffset)) - $this->setBottomRightYOffset($yOffset); + /** + * Set the offset position within the Bottom Right cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setBottomRightOffset($xOffset = null, $yOffset = null) + { + if (!is_null($xOffset)) { + $this->setBottomRightXOffset($xOffset); + } + if (!is_null($yOffset)) { + $this->setBottomRightYOffset($yOffset); + } - return $this; - } + return $this; + } - /** - * Get the offset position within the Bottom Right cell for the chart - * - * @return integer[] - */ - public function getBottomRightOffset() { - return array( 'X' => $this->_bottomRightXOffset, - 'Y' => $this->_bottomRightYOffset - ); - } + /** + * Get the offset position within the Bottom Right cell for the chart + * + * @return integer[] + */ + public function getBottomRightOffset() + { + return array( + 'X' => $this->_bottomRightXOffset, + 'Y' => $this->_bottomRightYOffset + ); + } - public function setBottomRightXOffset($xOffset) { - $this->_bottomRightXOffset = $xOffset; + public function setBottomRightXOffset($xOffset) + { + $this->_bottomRightXOffset = $xOffset; - return $this; - } + return $this; + } - public function getBottomRightXOffset() { - return $this->_bottomRightXOffset; - } + public function getBottomRightXOffset() + { + return $this->_bottomRightXOffset; + } - public function setBottomRightYOffset($yOffset) { - $this->_bottomRightYOffset = $yOffset; + public function setBottomRightYOffset($yOffset) + { + $this->_bottomRightYOffset = $yOffset; - return $this; - } + return $this; + } - public function getBottomRightYOffset() { - return $this->_bottomRightYOffset; - } + public function getBottomRightYOffset() + { + return $this->_bottomRightYOffset; + } - public function refresh() { - if ($this->_worksheet !== NULL) { - $this->_plotArea->refresh($this->_worksheet); - } - } + public function refresh() + { + if ($this->_worksheet !== null) { + $this->_plotArea->refresh($this->_worksheet); + } + } - public function render($outputDestination = null) { - $libraryName = PHPExcel_Settings::getChartRendererName(); - if (is_null($libraryName)) { - return false; - } - // Ensure that data series values are up-to-date before we render - $this->refresh(); + public function render($outputDestination = null) + { + $libraryName = PHPExcel_Settings::getChartRendererName(); + if (is_null($libraryName)) { + return false; + } + // Ensure that data series values are up-to-date before we render + $this->refresh(); - $libraryPath = PHPExcel_Settings::getChartRendererPath(); - $includePath = str_replace('\\','/',get_include_path()); - $rendererPath = str_replace('\\','/',$libraryPath); - if (strpos($rendererPath,$includePath) === false) { - set_include_path(get_include_path() . PATH_SEPARATOR . $libraryPath); - } + $libraryPath = PHPExcel_Settings::getChartRendererPath(); + $includePath = str_replace('\\','/',get_include_path()); + $rendererPath = str_replace('\\','/',$libraryPath); + if (strpos($rendererPath,$includePath) === false) { + set_include_path(get_include_path() . PATH_SEPARATOR . $libraryPath); + } - $rendererName = 'PHPExcel_Chart_Renderer_'.$libraryName; - $renderer = new $rendererName($this); - - if ($outputDestination == 'php://output') { - $outputDestination = null; - } - return $renderer->render($outputDestination); - } + $rendererName = 'PHPExcel_Chart_Renderer_'.$libraryName; + $renderer = new $rendererName($this); + if ($outputDestination == 'php://output') { + $outputDestination = null; + } + return $renderer->render($outputDestination); + } } diff --git a/Classes/PHPExcel/Comment.php b/Classes/PHPExcel/Comment.php index 4d5ef18f..bdadfbf5 100644 --- a/Classes/PHPExcel/Comment.php +++ b/Classes/PHPExcel/Comment.php @@ -1,6 +1,7 @@ _author = 'Author'; - $this->_text = new PHPExcel_RichText(); - $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); - $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + $this->_author = 'Author'; + $this->_text = new PHPExcel_RichText(); + $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); + $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; } /** diff --git a/Classes/PHPExcel/DocumentProperties.php b/Classes/PHPExcel/DocumentProperties.php index feaa1546..d872142c 100644 --- a/Classes/PHPExcel/DocumentProperties.php +++ b/Classes/PHPExcel/DocumentProperties.php @@ -1,6 +1,7 @@ _creator; } @@ -154,7 +147,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setCreator($pValue = '') { + public function setCreator($pValue = '') + { $this->_creator = $pValue; return $this; } @@ -164,7 +158,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getLastModifiedBy() { + public function getLastModifiedBy() + { return $this->_lastModifiedBy; } @@ -174,7 +169,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setLastModifiedBy($pValue = '') { + public function setLastModifiedBy($pValue = '') + { $this->_lastModifiedBy = $pValue; return $this; } @@ -184,7 +180,8 @@ class PHPExcel_DocumentProperties * * @return datetime */ - public function getCreated() { + public function getCreated() + { return $this->_created; } @@ -194,8 +191,9 @@ class PHPExcel_DocumentProperties * @param datetime $pValue * @return PHPExcel_DocumentProperties */ - public function setCreated($pValue = null) { - if ($pValue === NULL) { + public function setCreated($pValue = null) + { + if ($pValue === null) { $pValue = time(); } elseif (is_string($pValue)) { if (is_numeric($pValue)) { @@ -214,7 +212,8 @@ class PHPExcel_DocumentProperties * * @return datetime */ - public function getModified() { + public function getModified() + { return $this->_modified; } @@ -224,8 +223,9 @@ class PHPExcel_DocumentProperties * @param datetime $pValue * @return PHPExcel_DocumentProperties */ - public function setModified($pValue = null) { - if ($pValue === NULL) { + public function setModified($pValue = null) + { + if ($pValue === null) { $pValue = time(); } elseif (is_string($pValue)) { if (is_numeric($pValue)) { @@ -244,7 +244,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getTitle() { + public function getTitle() + { return $this->_title; } @@ -254,7 +255,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setTitle($pValue = '') { + public function setTitle($pValue = '') + { $this->_title = $pValue; return $this; } @@ -264,7 +266,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getDescription() { + public function getDescription() + { return $this->_description; } @@ -274,7 +277,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setDescription($pValue = '') { + public function setDescription($pValue = '') + { $this->_description = $pValue; return $this; } @@ -284,7 +288,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getSubject() { + public function getSubject() + { return $this->_subject; } @@ -294,7 +299,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setSubject($pValue = '') { + public function setSubject($pValue = '') + { $this->_subject = $pValue; return $this; } @@ -304,7 +310,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getKeywords() { + public function getKeywords() + { return $this->_keywords; } @@ -314,7 +321,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setKeywords($pValue = '') { + public function setKeywords($pValue = '') + { $this->_keywords = $pValue; return $this; } @@ -324,7 +332,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getCategory() { + public function getCategory() + { return $this->_category; } @@ -334,7 +343,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setCategory($pValue = '') { + public function setCategory($pValue = '') + { $this->_category = $pValue; return $this; } @@ -344,7 +354,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getCompany() { + public function getCompany() + { return $this->_company; } @@ -354,7 +365,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setCompany($pValue = '') { + public function setCompany($pValue = '') + { $this->_company = $pValue; return $this; } @@ -364,7 +376,8 @@ class PHPExcel_DocumentProperties * * @return string */ - public function getManager() { + public function getManager() + { return $this->_manager; } @@ -374,7 +387,8 @@ class PHPExcel_DocumentProperties * @param string $pValue * @return PHPExcel_DocumentProperties */ - public function setManager($pValue = '') { + public function setManager($pValue = '') + { $this->_manager = $pValue; return $this; } @@ -384,7 +398,8 @@ class PHPExcel_DocumentProperties * * @return array of string */ - public function getCustomProperties() { + public function getCustomProperties() + { return array_keys($this->_customProperties); } @@ -394,7 +409,8 @@ class PHPExcel_DocumentProperties * @param string $propertyName * @return boolean */ - public function isCustomPropertySet($propertyName) { + public function isCustomPropertySet($propertyName) + { return isset($this->_customProperties[$propertyName]); } @@ -404,7 +420,8 @@ class PHPExcel_DocumentProperties * @param string $propertyName * @return string */ - public function getCustomPropertyValue($propertyName) { + public function getCustomPropertyValue($propertyName) + { if (isset($this->_customProperties[$propertyName])) { return $this->_customProperties[$propertyName]['value']; } @@ -417,7 +434,8 @@ class PHPExcel_DocumentProperties * @param string $propertyName * @return string */ - public function getCustomPropertyType($propertyName) { + public function getCustomPropertyType($propertyName) + { if (isset($this->_customProperties[$propertyName])) { return $this->_customProperties[$propertyName]['type']; } @@ -430,20 +448,21 @@ class PHPExcel_DocumentProperties * @param string $propertyName * @param mixed $propertyValue * @param string $propertyType - * 'i' : Integer + * 'i' : Integer * 'f' : Floating Point * 's' : String * 'd' : Date/Time * 'b' : Boolean * @return PHPExcel_DocumentProperties */ - public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) { - if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER, - self::PROPERTY_TYPE_FLOAT, - self::PROPERTY_TYPE_STRING, - self::PROPERTY_TYPE_DATE, - self::PROPERTY_TYPE_BOOLEAN)))) { - if ($propertyValue === NULL) { + public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) + { + if (($propertyType === null) || (!in_array($propertyType, array(self::PROPERTY_TYPE_INTEGER, + self::PROPERTY_TYPE_FLOAT, + self::PROPERTY_TYPE_STRING, + self::PROPERTY_TYPE_DATE, + self::PROPERTY_TYPE_BOOLEAN)))) { + if ($propertyValue === null) { $propertyType = self::PROPERTY_TYPE_STRING; } elseif (is_float($propertyValue)) { $propertyType = self::PROPERTY_TYPE_FLOAT; @@ -456,14 +475,18 @@ class PHPExcel_DocumentProperties } } - $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType); + $this->_customProperties[$propertyName] = array( + 'value' => $propertyValue, + 'type' => $propertyType + ); return $this; } /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ - public function __clone() { + public function __clone() + { $vars = get_object_vars($this); foreach ($vars as $key => $value) { if (is_object($value)) { @@ -474,58 +497,59 @@ class PHPExcel_DocumentProperties } } - public static function convertProperty($propertyValue,$propertyType) { + public static function convertProperty($propertyValue,$propertyType) + { switch ($propertyType) { - case 'empty' : // Empty + case 'empty': // Empty return ''; break; - case 'null' : // Null - return NULL; + case 'null': // Null + return null; break; - case 'i1' : // 1-Byte Signed Integer - case 'i2' : // 2-Byte Signed Integer - case 'i4' : // 4-Byte Signed Integer - case 'i8' : // 8-Byte Signed Integer - case 'int' : // Integer + case 'i1': // 1-Byte Signed Integer + case 'i2': // 2-Byte Signed Integer + case 'i4': // 4-Byte Signed Integer + case 'i8': // 8-Byte Signed Integer + case 'int': // Integer return (int) $propertyValue; break; - case 'ui1' : // 1-Byte Unsigned Integer - case 'ui2' : // 2-Byte Unsigned Integer - case 'ui4' : // 4-Byte Unsigned Integer - case 'ui8' : // 8-Byte Unsigned Integer - case 'uint' : // Unsigned Integer + case 'ui1': // 1-Byte Unsigned Integer + case 'ui2': // 2-Byte Unsigned Integer + case 'ui4': // 4-Byte Unsigned Integer + case 'ui8': // 8-Byte Unsigned Integer + case 'uint': // Unsigned Integer return abs((int) $propertyValue); break; - case 'r4' : // 4-Byte Real Number - case 'r8' : // 8-Byte Real Number - case 'decimal' : // Decimal + case 'r4': // 4-Byte Real Number + case 'r8': // 8-Byte Real Number + case 'decimal': // Decimal return (float) $propertyValue; break; - case 'lpstr' : // LPSTR - case 'lpwstr' : // LPWSTR - case 'bstr' : // Basic String + case 'lpstr': // LPSTR + case 'lpwstr': // LPWSTR + case 'bstr': // Basic String return $propertyValue; break; - case 'date' : // Date and Time - case 'filetime' : // File Time + case 'date': // Date and Time + case 'filetime': // File Time return strtotime($propertyValue); break; - case 'bool' : // Boolean + case 'bool': // Boolean return ($propertyValue == 'true') ? True : False; break; - case 'cy' : // Currency - case 'error' : // Error Status Code - case 'vector' : // Vector - case 'array' : // Array - case 'blob' : // Binary Blob - case 'oblob' : // Binary Blob Object - case 'stream' : // Binary Stream - case 'ostream' : // Binary Stream Object - case 'storage' : // Binary Storage - case 'ostorage' : // Binary Storage Object - case 'vstream' : // Binary Versioned Stream - case 'clsid' : // Class ID - case 'cf' : // Clipboard Data + case 'cy': // Currency + case 'error': // Error Status Code + case 'vector': // Vector + case 'array': // Array + case 'blob': // Binary Blob + case 'oblob': // Binary Blob Object + case 'stream': // Binary Stream + case 'ostream': // Binary Stream Object + case 'storage': // Binary Storage + case 'ostorage': // Binary Storage Object + case 'vstream': // Binary Versioned Stream + case 'clsid': // Class ID + case 'cf': // Clipboard Data return $propertyValue; break; } @@ -534,50 +558,50 @@ class PHPExcel_DocumentProperties public static function convertPropertyType($propertyType) { switch ($propertyType) { - case 'i1' : // 1-Byte Signed Integer - case 'i2' : // 2-Byte Signed Integer - case 'i4' : // 4-Byte Signed Integer - case 'i8' : // 8-Byte Signed Integer - case 'int' : // Integer - case 'ui1' : // 1-Byte Unsigned Integer - case 'ui2' : // 2-Byte Unsigned Integer - case 'ui4' : // 4-Byte Unsigned Integer - case 'ui8' : // 8-Byte Unsigned Integer - case 'uint' : // Unsigned Integer + case 'i1': // 1-Byte Signed Integer + case 'i2': // 2-Byte Signed Integer + case 'i4': // 4-Byte Signed Integer + case 'i8': // 8-Byte Signed Integer + case 'int': // Integer + case 'ui1': // 1-Byte Unsigned Integer + case 'ui2': // 2-Byte Unsigned Integer + case 'ui4': // 4-Byte Unsigned Integer + case 'ui8': // 8-Byte Unsigned Integer + case 'uint': // Unsigned Integer return self::PROPERTY_TYPE_INTEGER; break; - case 'r4' : // 4-Byte Real Number - case 'r8' : // 8-Byte Real Number - case 'decimal' : // Decimal + case 'r4': // 4-Byte Real Number + case 'r8': // 8-Byte Real Number + case 'decimal': // Decimal return self::PROPERTY_TYPE_FLOAT; break; - case 'empty' : // Empty - case 'null' : // Null - case 'lpstr' : // LPSTR - case 'lpwstr' : // LPWSTR - case 'bstr' : // Basic String + case 'empty': // Empty + case 'null': // Null + case 'lpstr': // LPSTR + case 'lpwstr': // LPWSTR + case 'bstr': // Basic String return self::PROPERTY_TYPE_STRING; break; - case 'date' : // Date and Time - case 'filetime' : // File Time + case 'date': // Date and Time + case 'filetime': // File Time return self::PROPERTY_TYPE_DATE; break; - case 'bool' : // Boolean + case 'bool': // Boolean return self::PROPERTY_TYPE_BOOLEAN; break; - case 'cy' : // Currency - case 'error' : // Error Status Code - case 'vector' : // Vector - case 'array' : // Array - case 'blob' : // Binary Blob - case 'oblob' : // Binary Blob Object - case 'stream' : // Binary Stream - case 'ostream' : // Binary Stream Object - case 'storage' : // Binary Storage - case 'ostorage' : // Binary Storage Object - case 'vstream' : // Binary Versioned Stream - case 'clsid' : // Class ID - case 'cf' : // Clipboard Data + case 'cy': // Currency + case 'error': // Error Status Code + case 'vector': // Vector + case 'array': // Array + case 'blob': // Binary Blob + case 'oblob': // Binary Blob Object + case 'stream': // Binary Stream + case 'ostream': // Binary Stream Object + case 'storage': // Binary Storage + case 'ostorage': // Binary Storage Object + case 'vstream': // Binary Versioned Stream + case 'clsid': // Class ID + case 'cf': // Clipboard Data return self::PROPERTY_TYPE_UNKNOWN; break; } diff --git a/Classes/PHPExcel/DocumentSecurity.php b/Classes/PHPExcel/DocumentSecurity.php index b194ecd8..09550193 100644 --- a/Classes/PHPExcel/DocumentSecurity.php +++ b/Classes/PHPExcel/DocumentSecurity.php @@ -1,6 +1,7 @@ _lockRevision = false; - $this->_lockStructure = false; - $this->_lockWindows = false; - $this->_revisionsPassword = ''; - $this->_workbookPassword = ''; + // Initialise values + $this->_lockRevision = false; + $this->_lockStructure = false; + $this->_lockWindows = false; + $this->_revisionsPassword = ''; + $this->_workbookPassword = ''; } /** @@ -88,10 +80,11 @@ class PHPExcel_DocumentSecurity * * @return boolean */ - function isSecurityEnabled() { - return $this->_lockRevision || - $this->_lockStructure || - $this->_lockWindows; + function isSecurityEnabled() + { + return $this->_lockRevision || + $this->_lockStructure || + $this->_lockWindows; } /** @@ -99,8 +92,9 @@ class PHPExcel_DocumentSecurity * * @return boolean */ - function getLockRevision() { - return $this->_lockRevision; + function getLockRevision() + { + return $this->_lockRevision; } /** @@ -109,9 +103,10 @@ class PHPExcel_DocumentSecurity * @param boolean $pValue * @return PHPExcel_DocumentSecurity */ - function setLockRevision($pValue = false) { - $this->_lockRevision = $pValue; - return $this; + function setLockRevision($pValue = false) + { + $this->_lockRevision = $pValue; + return $this; } /** @@ -119,8 +114,9 @@ class PHPExcel_DocumentSecurity * * @return boolean */ - function getLockStructure() { - return $this->_lockStructure; + function getLockStructure() + { + return $this->_lockStructure; } /** @@ -129,9 +125,10 @@ class PHPExcel_DocumentSecurity * @param boolean $pValue * @return PHPExcel_DocumentSecurity */ - function setLockStructure($pValue = false) { - $this->_lockStructure = $pValue; - return $this; + function setLockStructure($pValue = false) + { + $this->_lockStructure = $pValue; + return $this; } /** @@ -139,8 +136,9 @@ class PHPExcel_DocumentSecurity * * @return boolean */ - function getLockWindows() { - return $this->_lockWindows; + function getLockWindows() + { + return $this->_lockWindows; } /** @@ -149,9 +147,10 @@ class PHPExcel_DocumentSecurity * @param boolean $pValue * @return PHPExcel_DocumentSecurity */ - function setLockWindows($pValue = false) { - $this->_lockWindows = $pValue; - return $this; + function setLockWindows($pValue = false) + { + $this->_lockWindows = $pValue; + return $this; } /** @@ -159,23 +158,25 @@ class PHPExcel_DocumentSecurity * * @return string */ - function getRevisionsPassword() { - return $this->_revisionsPassword; + function getRevisionsPassword() + { + return $this->_revisionsPassword; } /** * Set RevisionsPassword * - * @param string $pValue - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true * @return PHPExcel_DocumentSecurity */ - function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) { - if (!$pAlreadyHashed) { - $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); - } - $this->_revisionsPassword = $pValue; - return $this; + function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) + { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_revisionsPassword = $pValue; + return $this; } /** @@ -183,36 +184,39 @@ class PHPExcel_DocumentSecurity * * @return string */ - function getWorkbookPassword() { - return $this->_workbookPassword; + function getWorkbookPassword() + { + return $this->_workbookPassword; } /** * Set WorkbookPassword * - * @param string $pValue - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true * @return PHPExcel_DocumentSecurity */ - function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) { - if (!$pAlreadyHashed) { - $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); - } - $this->_workbookPassword = $pValue; - return $this; + function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) + { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_workbookPassword = $pValue; + return $this; } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/Classes/PHPExcel/HashTable.php b/Classes/PHPExcel/HashTable.php index 4fb41adb..8ec020ba 100644 --- a/Classes/PHPExcel/HashTable.php +++ b/Classes/PHPExcel/HashTable.php @@ -1,6 +1,7 @@ addFromSource($pSource); - } - } + /** + * Create a new PHPExcel_HashTable + * + * @param PHPExcel_IComparable[] $pSource Optional source array to create HashTable from + * @throws PHPExcel_Exception + */ + public function __construct($pSource = null) + { + if ($pSource !== null) { + // Create HashTable + $this->addFromSource($pSource); + } + } - /** - * Add HashTable items from source - * - * @param PHPExcel_IComparable[] $pSource Source array to create HashTable from - * @throws PHPExcel_Exception - */ - public function addFromSource($pSource = null) { - // Check if an array was passed - if ($pSource == null) { - return; - } else if (!is_array($pSource)) { - throw new PHPExcel_Exception('Invalid array parameter passed.'); - } + /** + * Add HashTable items from source + * + * @param PHPExcel_IComparable[] $pSource Source array to create HashTable from + * @throws PHPExcel_Exception + */ + public function addFromSource($pSource = null) + { + // Check if an array was passed + if ($pSource == null) { + return; + } else if (!is_array($pSource)) { + throw new PHPExcel_Exception('Invalid array parameter passed.'); + } - foreach ($pSource as $item) { - $this->add($item); - } - } + foreach ($pSource as $item) { + $this->add($item); + } + } - /** - * Add HashTable item - * - * @param PHPExcel_IComparable $pSource Item to add - * @throws PHPExcel_Exception - */ - public function add(PHPExcel_IComparable $pSource = null) { - $hash = $pSource->getHashCode(); - if (!isset($this->_items[$hash])) { - $this->_items[$hash] = $pSource; - $this->_keyMap[count($this->_items) - 1] = $hash; - } - } + /** + * Add HashTable item + * + * @param PHPExcel_IComparable $pSource Item to add + * @throws PHPExcel_Exception + */ + public function add(PHPExcel_IComparable $pSource = null) + { + $hash = $pSource->getHashCode(); + if (!isset($this->_items[$hash])) { + $this->_items[$hash] = $pSource; + $this->_keyMap[count($this->_items) - 1] = $hash; + } + } - /** - * Remove HashTable item - * - * @param PHPExcel_IComparable $pSource Item to remove - * @throws PHPExcel_Exception - */ - public function remove(PHPExcel_IComparable $pSource = null) { - $hash = $pSource->getHashCode(); - if (isset($this->_items[$hash])) { - unset($this->_items[$hash]); + /** + * Remove HashTable item + * + * @param PHPExcel_IComparable $pSource Item to remove + * @throws PHPExcel_Exception + */ + public function remove(PHPExcel_IComparable $pSource = null) + { + $hash = $pSource->getHashCode(); + if (isset($this->_items[$hash])) { + unset($this->_items[$hash]); - $deleteKey = -1; - foreach ($this->_keyMap as $key => $value) { - if ($deleteKey >= 0) { - $this->_keyMap[$key - 1] = $value; - } + $deleteKey = -1; + foreach ($this->_keyMap as $key => $value) { + if ($deleteKey >= 0) { + $this->_keyMap[$key - 1] = $value; + } - if ($value == $hash) { - $deleteKey = $key; - } - } - unset($this->_keyMap[count($this->_keyMap) - 1]); - } - } + if ($value == $hash) { + $deleteKey = $key; + } + } + unset($this->_keyMap[count($this->_keyMap) - 1]); + } + } - /** - * Clear HashTable - * - */ - public function clear() { - $this->_items = array(); - $this->_keyMap = array(); - } + /** + * Clear HashTable + * + */ + public function clear() + { + $this->_items = array(); + $this->_keyMap = array(); + } - /** - * Count - * - * @return int - */ - public function count() { - return count($this->_items); - } + /** + * Count + * + * @return int + */ + public function count() + { + return count($this->_items); + } - /** - * Get index for hash code - * - * @param string $pHashCode - * @return int Index - */ - public function getIndexForHashCode($pHashCode = '') { - return array_search($pHashCode, $this->_keyMap); - } + /** + * Get index for hash code + * + * @param string $pHashCode + * @return int Index + */ + public function getIndexForHashCode($pHashCode = '') + { + return array_search($pHashCode, $this->_keyMap); + } - /** - * Get by index - * - * @param int $pIndex - * @return PHPExcel_IComparable - * - */ - public function getByIndex($pIndex = 0) { - if (isset($this->_keyMap[$pIndex])) { - return $this->getByHashCode( $this->_keyMap[$pIndex] ); - } + /** + * Get by index + * + * @param int $pIndex + * @return PHPExcel_IComparable + * + */ + public function getByIndex($pIndex = 0) + { + if (isset($this->_keyMap[$pIndex])) { + return $this->getByHashCode( $this->_keyMap[$pIndex] ); + } - return null; - } + return null; + } - /** - * Get by hashcode - * - * @param string $pHashCode - * @return PHPExcel_IComparable - * - */ - public function getByHashCode($pHashCode = '') { - if (isset($this->_items[$pHashCode])) { - return $this->_items[$pHashCode]; - } + /** + * Get by hashcode + * + * @param string $pHashCode + * @return PHPExcel_IComparable + * + */ + public function getByHashCode($pHashCode = '') + { + if (isset($this->_items[$pHashCode])) { + return $this->_items[$pHashCode]; + } - return null; - } + return null; + } - /** - * HashTable to array - * - * @return PHPExcel_IComparable[] - */ - public function toArray() { - return $this->_items; - } + /** + * HashTable to array + * + * @return PHPExcel_IComparable[] + */ + public function toArray() + { + return $this->_items; + } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } - } - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } + } + } } diff --git a/Classes/PHPExcel/IComparable.php b/Classes/PHPExcel/IComparable.php index 3afbf4bc..62a06aea 100644 --- a/Classes/PHPExcel/IComparable.php +++ b/Classes/PHPExcel/IComparable.php @@ -1,6 +1,7 @@ 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), - array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) - ); - - /** - * Autoresolve classes - * - * @var array - * @access private - * @static - */ - private static $_autoResolveClasses = array( - 'Excel2007', - 'Excel5', - 'Excel2003XML', - 'OOCalc', - 'SYLK', - 'Gnumeric', - 'HTML', - 'CSV', - ); + /** + * Search locations + * + * @var array + * @access private + * @static + */ + private static $_searchLocations = array( + array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), + array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) + ); /** - * Private constructor for PHPExcel_IOFactory + * Autoresolve classes + * + * @var array + * @access private + * @static + */ + private static $_autoResolveClasses = array( + 'Excel2007', + 'Excel5', + 'Excel2003XML', + 'OOCalc', + 'SYLK', + 'Gnumeric', + 'HTML', + 'CSV', + ); + + /** + * Private constructor for PHPExcel_IOFactory */ private function __construct() { } /** * Get search locations * - * @static - * @access public - * @return array + * @static + * @access public + * @return array */ - public static function getSearchLocations() { - return self::$_searchLocations; - } // function getSearchLocations() + public static function getSearchLocations() + { + return self::$_searchLocations; + } - /** - * Set search locations - * - * @static - * @access public - * @param array $value - * @throws PHPExcel_Reader_Exception - */ - public static function setSearchLocations($value) { - if (is_array($value)) { - self::$_searchLocations = $value; - } else { - throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); - } - } // function setSearchLocations() + /** + * Set search locations + * + * @static + * @access public + * @param array $value + * @throws PHPExcel_Reader_Exception + */ + public static function setSearchLocations($value) + { + if (is_array($value)) { + self::$_searchLocations = $value; + } else { + throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); + } + } - /** - * Add search location - * - * @static - * @access public - * @param string $type Example: IWriter - * @param string $location Example: PHPExcel/Writer/{0}.php - * @param string $classname Example: PHPExcel_Writer_{0} - */ - public static function addSearchLocation($type = '', $location = '', $classname = '') { - self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); - } // function addSearchLocation() + /** + * Add search location + * + * @static + * @access public + * @param string $type Example: IWriter + * @param string $location Example: PHPExcel/Writer/{0}.php + * @param string $classname Example: PHPExcel_Writer_{0} + */ + public static function addSearchLocation($type = '', $location = '', $classname = '') + { + self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); + } - /** - * Create PHPExcel_Writer_IWriter - * - * @static - * @access public - * @param PHPExcel $phpExcel - * @param string $writerType Example: Excel2007 - * @return PHPExcel_Writer_IWriter - * @throws PHPExcel_Reader_Exception - */ - public static function createWriter(PHPExcel $phpExcel, $writerType = '') { - // Search type - $searchType = 'IWriter'; + /** + * Create PHPExcel_Writer_IWriter + * + * @static + * @access public + * @param PHPExcel $phpExcel + * @param string $writerType Example: Excel2007 + * @return PHPExcel_Writer_IWriter + * @throws PHPExcel_Reader_Exception + */ + public static function createWriter(PHPExcel $phpExcel, $writerType = '') + { + // Search type + $searchType = 'IWriter'; - // Include class - foreach (self::$_searchLocations as $searchLocation) { - if ($searchLocation['type'] == $searchType) { - $className = str_replace('{0}', $writerType, $searchLocation['class']); + // Include class + foreach (self::$_searchLocations as $searchLocation) { + if ($searchLocation['type'] == $searchType) { + $className = str_replace('{0}', $writerType, $searchLocation['class']); - $instance = new $className($phpExcel); - if ($instance !== NULL) { - return $instance; - } - } - } + $instance = new $className($phpExcel); + if ($instance !== NULL) { + return $instance; + } + } + } - // Nothing found... - throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); - } // function createWriter() + // Nothing found... + throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); + } - /** - * Create PHPExcel_Reader_IReader - * - * @static - * @access public - * @param string $readerType Example: Excel2007 - * @return PHPExcel_Reader_IReader - * @throws PHPExcel_Reader_Exception - */ - public static function createReader($readerType = '') { - // Search type - $searchType = 'IReader'; + /** + * Create PHPExcel_Reader_IReader + * + * @static + * @access public + * @param string $readerType Example: Excel2007 + * @return PHPExcel_Reader_IReader + * @throws PHPExcel_Reader_Exception + */ + public static function createReader($readerType = '') + { + // Search type + $searchType = 'IReader'; - // Include class - foreach (self::$_searchLocations as $searchLocation) { - if ($searchLocation['type'] == $searchType) { - $className = str_replace('{0}', $readerType, $searchLocation['class']); + // Include class + foreach (self::$_searchLocations as $searchLocation) { + if ($searchLocation['type'] == $searchType) { + $className = str_replace('{0}', $readerType, $searchLocation['class']); - $instance = new $className(); - if ($instance !== NULL) { - return $instance; - } - } - } + $instance = new $className(); + if ($instance !== NULL) { + return $instance; + } + } + } - // Nothing found... - throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); - } // function createReader() + // Nothing found... + throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); + } - /** - * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution - * - * @static - * @access public - * @param string $pFilename The name of the spreadsheet file - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public static function load($pFilename) { - $reader = self::createReaderForFile($pFilename); - return $reader->load($pFilename); - } // function load() + /** + * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public static function load($pFilename) + { + $reader = self::createReaderForFile($pFilename); + return $reader->load($pFilename); + } - /** - * Identify file type using automatic PHPExcel_Reader_IReader resolution - * - * @static - * @access public - * @param string $pFilename The name of the spreadsheet file to identify - * @return string - * @throws PHPExcel_Reader_Exception - */ - public static function identify($pFilename) { - $reader = self::createReaderForFile($pFilename); - $className = get_class($reader); - $classType = explode('_',$className); - unset($reader); - return array_pop($classType); - } // function identify() + /** + * Identify file type using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file to identify + * @return string + * @throws PHPExcel_Reader_Exception + */ + public static function identify($pFilename) + { + $reader = self::createReaderForFile($pFilename); + $className = get_class($reader); + $classType = explode('_',$className); + unset($reader); + return array_pop($classType); + } - /** - * Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution - * - * @static - * @access public - * @param string $pFilename The name of the spreadsheet file - * @return PHPExcel_Reader_IReader - * @throws PHPExcel_Reader_Exception - */ - public static function createReaderForFile($pFilename) { + /** + * Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file + * @return PHPExcel_Reader_IReader + * @throws PHPExcel_Reader_Exception + */ + public static function createReaderForFile($pFilename) + { + // First, lucky guess by inspecting file extension + $pathinfo = pathinfo($pFilename); - // First, lucky guess by inspecting file extension - $pathinfo = pathinfo($pFilename); + $extensionType = NULL; + if (isset($pathinfo['extension'])) { + switch (strtolower($pathinfo['extension'])) { + case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet + case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) + case 'xltx': // Excel (OfficeOpenXML) Template + case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) + $extensionType = 'Excel2007'; + break; + case 'xls': // Excel (BIFF) Spreadsheet + case 'xlt': // Excel (BIFF) Template + $extensionType = 'Excel5'; + break; + case 'ods': // Open/Libre Offic Calc + case 'ots': // Open/Libre Offic Calc Template + $extensionType = 'OOCalc'; + break; + case 'slk': + $extensionType = 'SYLK'; + break; + case 'xml': // Excel 2003 SpreadSheetML + $extensionType = 'Excel2003XML'; + break; + case 'gnumeric': + $extensionType = 'Gnumeric'; + break; + case 'htm': + case 'html': + $extensionType = 'HTML'; + break; + case 'csv': + // Do nothing + // We must not try to use CSV reader since it loads + // all files including Excel files etc. + break; + default: + break; + } - $extensionType = NULL; - if (isset($pathinfo['extension'])) { - switch (strtolower($pathinfo['extension'])) { - case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet - case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) - case 'xltx': // Excel (OfficeOpenXML) Template - case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) - $extensionType = 'Excel2007'; - break; - case 'xls': // Excel (BIFF) Spreadsheet - case 'xlt': // Excel (BIFF) Template - $extensionType = 'Excel5'; - break; - case 'ods': // Open/Libre Offic Calc - case 'ots': // Open/Libre Offic Calc Template - $extensionType = 'OOCalc'; - break; - case 'slk': - $extensionType = 'SYLK'; - break; - case 'xml': // Excel 2003 SpreadSheetML - $extensionType = 'Excel2003XML'; - break; - case 'gnumeric': - $extensionType = 'Gnumeric'; - break; - case 'htm': - case 'html': - $extensionType = 'HTML'; - break; - case 'csv': - // Do nothing - // We must not try to use CSV reader since it loads - // all files including Excel files etc. - break; - default: - break; - } + if ($extensionType !== null) { + $reader = self::createReader($extensionType); + // Let's see if we are lucky + if (isset($reader) && $reader->canRead($pFilename)) { + return $reader; + } + } + } - if ($extensionType !== NULL) { - $reader = self::createReader($extensionType); - // Let's see if we are lucky - if (isset($reader) && $reader->canRead($pFilename)) { - return $reader; - } - } - } + // If we reach here then "lucky guess" didn't give any result + // Try walking through all the options in self::$_autoResolveClasses + foreach (self::$_autoResolveClasses as $autoResolveClass) { + // Ignore our original guess, we know that won't work + if ($autoResolveClass !== $extensionType) { + $reader = self::createReader($autoResolveClass); + if ($reader->canRead($pFilename)) { + return $reader; + } + } + } - // If we reach here then "lucky guess" didn't give any result - // Try walking through all the options in self::$_autoResolveClasses - foreach (self::$_autoResolveClasses as $autoResolveClass) { - // Ignore our original guess, we know that won't work - if ($autoResolveClass !== $extensionType) { - $reader = self::createReader($autoResolveClass); - if ($reader->canRead($pFilename)) { - return $reader; - } - } - } - - throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); - } // function createReaderForFile() + throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); + } } diff --git a/Classes/PHPExcel/NamedRange.php b/Classes/PHPExcel/NamedRange.php index cab3c7ec..164246fe 100644 --- a/Classes/PHPExcel/NamedRange.php +++ b/Classes/PHPExcel/NamedRange.php @@ -1,6 +1,7 @@ _worksheet) - * - * @var bool - */ - private $_localOnly; + /** + * Is the named range local? (i.e. can only be used on $this->_worksheet) + * + * @var bool + */ + private $_localOnly; - /** - * Scope - * - * @var PHPExcel_Worksheet - */ - private $_scope; + /** + * Scope + * + * @var PHPExcel_Worksheet + */ + private $_scope; /** * Create a new NamedRange @@ -77,23 +69,23 @@ class PHPExcel_NamedRange * @param PHPExcel_Worksheet $pWorksheet * @param string $pRange * @param bool $pLocalOnly - * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. + * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. * @throws PHPExcel_Exception */ public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) { - // Validate data - if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) { - throw new PHPExcel_Exception('Parameters can not be null.'); - } + // Validate data + if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) { + throw new PHPExcel_Exception('Parameters can not be null.'); + } - // Set local members - $this->_name = $pName; - $this->_worksheet = $pWorksheet; - $this->_range = $pRange; - $this->_localOnly = $pLocalOnly; - $this->_scope = ($pLocalOnly == true) ? - (($pScope == null) ? $pWorksheet : $pScope) : null; + // Set local members + $this->_name = $pName; + $this->_worksheet = $pWorksheet; + $this->_range = $pRange; + $this->_localOnly = $pLocalOnly; + $this->_scope = ($pLocalOnly == true) ? + (($pScope == null) ? $pWorksheet : $pScope) : null; } /** @@ -102,7 +94,7 @@ class PHPExcel_NamedRange * @return string */ public function getName() { - return $this->_name; + return $this->_name; } /** @@ -112,25 +104,25 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public function setName($value = null) { - if ($value !== NULL) { - // Old title - $oldTitle = $this->_name; + if ($value !== NULL) { + // Old title + $oldTitle = $this->_name; - // Re-attach - if ($this->_worksheet !== NULL) { - $this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet); - } - $this->_name = $value; + // Re-attach + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet); + } + $this->_name = $value; - if ($this->_worksheet !== NULL) { - $this->_worksheet->getParent()->addNamedRange($this); - } + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->addNamedRange($this); + } - // New title - $newTitle = $this->_name; - PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle); - } - return $this; + // New title + $newTitle = $this->_name; + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle); + } + return $this; } /** @@ -139,7 +131,7 @@ class PHPExcel_NamedRange * @return PHPExcel_Worksheet */ public function getWorksheet() { - return $this->_worksheet; + return $this->_worksheet; } /** @@ -149,10 +141,10 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public function setWorksheet(PHPExcel_Worksheet $value = null) { - if ($value !== NULL) { - $this->_worksheet = $value; - } - return $this; + if ($value !== NULL) { + $this->_worksheet = $value; + } + return $this; } /** @@ -161,7 +153,7 @@ class PHPExcel_NamedRange * @return string */ public function getRange() { - return $this->_range; + return $this->_range; } /** @@ -171,10 +163,10 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public function setRange($value = null) { - if ($value !== NULL) { - $this->_range = $value; - } - return $this; + if ($value !== NULL) { + $this->_range = $value; + } + return $this; } /** @@ -183,7 +175,7 @@ class PHPExcel_NamedRange * @return bool */ public function getLocalOnly() { - return $this->_localOnly; + return $this->_localOnly; } /** @@ -193,9 +185,9 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public function setLocalOnly($value = false) { - $this->_localOnly = $value; - $this->_scope = $value ? $this->_worksheet : null; - return $this; + $this->_localOnly = $value; + $this->_scope = $value ? $this->_worksheet : null; + return $this; } /** @@ -204,7 +196,7 @@ class PHPExcel_NamedRange * @return PHPExcel_Worksheet|null */ public function getScope() { - return $this->_scope; + return $this->_scope; } /** @@ -214,9 +206,9 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public function setScope(PHPExcel_Worksheet $value = null) { - $this->_scope = $value; - $this->_localOnly = ($value == null) ? false : true; - return $this; + $this->_scope = $value; + $this->_localOnly = ($value == null) ? false : true; + return $this; } /** @@ -227,20 +219,20 @@ class PHPExcel_NamedRange * @return PHPExcel_NamedRange */ public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) { - return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet); + return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/Classes/PHPExcel/Reader/Abstract.php b/Classes/PHPExcel/Reader/Abstract.php index 8fa961b0..a0201366 100644 --- a/Classes/PHPExcel/Reader/Abstract.php +++ b/Classes/PHPExcel/Reader/Abstract.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -29,212 +29,212 @@ /** * PHPExcel_Reader_Abstract * - * @category PHPExcel - * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ abstract class PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Read data only? - * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; - * or whether it should read both data and formatting - * - * @var boolean - */ - protected $_readDataOnly = FALSE; + /** + * Read data only? + * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; + * or whether it should read both data and formatting + * + * @var boolean + */ + protected $_readDataOnly = FALSE; - /** - * Read charts that are defined in the workbook? - * Identifies whether the Reader should read the definitions for any charts that exist in the workbook; - * - * @var boolean - */ - protected $_includeCharts = FALSE; + /** + * Read charts that are defined in the workbook? + * Identifies whether the Reader should read the definitions for any charts that exist in the workbook; + * + * @var boolean + */ + protected $_includeCharts = FALSE; - /** - * Restrict which sheets should be loaded? - * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. - * - * @var array of string - */ - protected $_loadSheetsOnly = NULL; + /** + * Restrict which sheets should be loaded? + * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. + * + * @var array of string + */ + protected $_loadSheetsOnly = NULL; - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - protected $_readFilter = NULL; + /** + * PHPExcel_Reader_IReadFilter instance + * + * @var PHPExcel_Reader_IReadFilter + */ + protected $_readFilter = NULL; - protected $_fileHandle = NULL; + protected $_fileHandle = NULL; - /** - * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. - * If false (the default) it will read data and formatting. - * - * @return boolean - */ - public function getReadDataOnly() { - return $this->_readDataOnly; - } + /** + * Read data only? + * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. + * If false (the default) it will read data and formatting. + * + * @return boolean + */ + public function getReadDataOnly() { + return $this->_readDataOnly; + } - /** - * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. - * Set to false (the default) to advise the Reader to read both data and formatting for cells. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_IReader - */ - public function setReadDataOnly($pValue = FALSE) { - $this->_readDataOnly = $pValue; - return $this; - } + /** + * Set read data only + * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. + * Set to false (the default) to advise the Reader to read both data and formatting for cells. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setReadDataOnly($pValue = FALSE) { + $this->_readDataOnly = $pValue; + return $this; + } - /** - * Read charts in workbook? - * If this is true, then the Reader will include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * If false (the default) it will ignore any charts defined in the workbook file. - * - * @return boolean - */ - public function getIncludeCharts() { - return $this->_includeCharts; - } + /** + * Read charts in workbook? + * If this is true, then the Reader will include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * If false (the default) it will ignore any charts defined in the workbook file. + * + * @return boolean + */ + public function getIncludeCharts() { + return $this->_includeCharts; + } - /** - * Set read charts in workbook - * Set to true, to advise the Reader to include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * Set to false (the default) to discard charts. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_IReader - */ - public function setIncludeCharts($pValue = FALSE) { - $this->_includeCharts = (boolean) $pValue; - return $this; - } + /** + * Set read charts in workbook + * Set to true, to advise the Reader to include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * Set to false (the default) to discard charts. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setIncludeCharts($pValue = FALSE) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } - /** - * Get which sheets to load - * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null - * indicating that all worksheets in the workbook should be loaded. - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } + /** + * Get which sheets to load + * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null + * indicating that all worksheets in the workbook should be loaded. + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } - /** - * Set which sheets to load - * - * @param mixed $value - * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. - * If NULL, then it tells the Reader to read all worksheets in the workbook - * - * @return PHPExcel_Reader_IReader - */ - public function setLoadSheetsOnly($value = NULL) - { + /** + * Set which sheets to load + * + * @param mixed $value + * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. + * If NULL, then it tells the Reader to read all worksheets in the workbook + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadSheetsOnly($value = NULL) + { if ($value === NULL) return $this->setLoadAllSheets(); $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } + $value : array($value); + return $this; + } - /** - * Set all sheets to load - * Tells the Reader to load all worksheets from the workbook. - * - * @return PHPExcel_Reader_IReader - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = NULL; - return $this; - } + /** + * Set all sheets to load + * Tells the Reader to load all worksheets from the workbook. + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = NULL; + return $this; + } - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_IReader - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_IReader + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } - /** - * Open file for reading - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - * @return resource - */ - protected function _openFile($pFilename) - { - // Check if file exists - if (!file_exists($pFilename) || !is_readable($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Open file for reading + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + * @return resource + */ + protected function _openFile($pFilename) + { + // Check if file exists + if (!file_exists($pFilename) || !is_readable($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - // Open file - $this->_fileHandle = fopen($pFilename, 'r'); - if ($this->_fileHandle === FALSE) { - throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading."); - } - } + // Open file + $this->_fileHandle = fopen($pFilename, 'r'); + if ($this->_fileHandle === FALSE) { + throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading."); + } + } - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - // Check if file exists - try { - $this->_openFile($pFilename); - } catch (Exception $e) { - return FALSE; - } + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + try { + $this->_openFile($pFilename); + } catch (Exception $e) { + return FALSE; + } - $readable = $this->_isValidFormat(); - fclose ($this->_fileHandle); - return $readable; - } + $readable = $this->_isValidFormat(); + fclose ($this->_fileHandle); + return $readable; + } - /** - * Scan theXML for use of securityScan(file_get_contents($filestream)); } } diff --git a/Classes/PHPExcel/Reader/CSV.php b/Classes/PHPExcel/Reader/CSV.php index 2942e804..e92c93eb 100644 --- a/Classes/PHPExcel/Reader/CSV.php +++ b/Classes/PHPExcel/Reader/CSV.php @@ -21,18 +21,18 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** @@ -44,344 +44,344 @@ if (!defined('PHPEXCEL_ROOT')) { */ class PHPExcel_Reader_CSV extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Input encoding - * - * @access private - * @var string - */ - private $_inputEncoding = 'UTF-8'; + /** + * Input encoding + * + * @access private + * @var string + */ + private $_inputEncoding = 'UTF-8'; - /** - * Delimiter - * - * @access private - * @var string - */ - private $_delimiter = ','; + /** + * Delimiter + * + * @access private + * @var string + */ + private $_delimiter = ','; - /** - * Enclosure - * - * @access private - * @var string - */ - private $_enclosure = '"'; + /** + * Enclosure + * + * @access private + * @var string + */ + private $_enclosure = '"'; - /** - * Sheet index to read - * - * @access private - * @var int - */ - private $_sheetIndex = 0; + /** + * Sheet index to read + * + * @access private + * @var int + */ + private $_sheetIndex = 0; - /** - * Load rows contiguously - * - * @access private - * @var int - */ - private $_contiguous = false; + /** + * Load rows contiguously + * + * @access private + * @var int + */ + private $_contiguous = false; - /** - * Row counter for loading rows contiguously - * - * @var int - */ - private $_contiguousRow = -1; + /** + * Row counter for loading rows contiguously + * + * @var int + */ + private $_contiguousRow = -1; - /** - * Create a new PHPExcel_Reader_CSV - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } + /** + * Create a new PHPExcel_Reader_CSV + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } - /** - * Validate that the current file is a CSV file - * - * @return boolean - */ - protected function _isValidFormat() - { - return TRUE; - } + /** + * Validate that the current file is a CSV file + * + * @return boolean + */ + protected function _isValidFormat() + { + return TRUE; + } - /** - * Set input encoding - * - * @param string $pValue Input encoding - */ - public function setInputEncoding($pValue = 'UTF-8') - { - $this->_inputEncoding = $pValue; - return $this; - } + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'UTF-8') + { + $this->_inputEncoding = $pValue; + return $this; + } - /** - * Get input encoding - * - * @return string - */ - public function getInputEncoding() - { - return $this->_inputEncoding; - } + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } - /** - * Move filepointer past any BOM marker - * - */ - protected function _skipBOM() - { - rewind($this->_fileHandle); + /** + * Move filepointer past any BOM marker + * + */ + protected function _skipBOM() + { + rewind($this->_fileHandle); - switch ($this->_inputEncoding) { - case 'UTF-8': - fgets($this->_fileHandle, 4) == "\xEF\xBB\xBF" ? - fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0); - break; - case 'UTF-16LE': - fgets($this->_fileHandle, 3) == "\xFF\xFE" ? - fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); - break; - case 'UTF-16BE': - fgets($this->_fileHandle, 3) == "\xFE\xFF" ? - fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); - break; - case 'UTF-32LE': - fgets($this->_fileHandle, 5) == "\xFF\xFE\x00\x00" ? - fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); - break; - case 'UTF-32BE': - fgets($this->_fileHandle, 5) == "\x00\x00\xFE\xFF" ? - fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); - break; - default: - break; - } - } + switch ($this->_inputEncoding) { + case 'UTF-8': + fgets($this->_fileHandle, 4) == "\xEF\xBB\xBF" ? + fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0); + break; + case 'UTF-16LE': + fgets($this->_fileHandle, 3) == "\xFF\xFE" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); + break; + case 'UTF-16BE': + fgets($this->_fileHandle, 3) == "\xFE\xFF" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); + break; + case 'UTF-32LE': + fgets($this->_fileHandle, 5) == "\xFF\xFE\x00\x00" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); + break; + case 'UTF-32BE': + fgets($this->_fileHandle, 5) == "\x00\x00\xFE\xFF" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); + break; + default: + break; + } + } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Open file - $this->_openFile($pFilename); - if (!$this->_isValidFormat()) { - fclose ($this->_fileHandle); - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } - $fileHandle = $this->_fileHandle; + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; - // Skip BOM, if any - $this->_skipBOM(); + // Skip BOM, if any + $this->_skipBOM(); - $escapeEnclosures = array( "\\" . $this->_enclosure, $this->_enclosure . $this->_enclosure ); + $escapeEnclosures = array( "\\" . $this->_enclosure, $this->_enclosure . $this->_enclosure ); - $worksheetInfo = array(); - $worksheetInfo[0]['worksheetName'] = 'Worksheet'; - $worksheetInfo[0]['lastColumnLetter'] = 'A'; - $worksheetInfo[0]['lastColumnIndex'] = 0; - $worksheetInfo[0]['totalRows'] = 0; - $worksheetInfo[0]['totalColumns'] = 0; + $worksheetInfo = array(); + $worksheetInfo[0]['worksheetName'] = 'Worksheet'; + $worksheetInfo[0]['lastColumnLetter'] = 'A'; + $worksheetInfo[0]['lastColumnIndex'] = 0; + $worksheetInfo[0]['totalRows'] = 0; + $worksheetInfo[0]['totalColumns'] = 0; - // Loop through each line of the file in turn - while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { - $worksheetInfo[0]['totalRows']++; - $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1); - } + // Loop through each line of the file in turn + while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { + $worksheetInfo[0]['totalRows']++; + $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1); + } - $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); - $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; + $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); + $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; - // Close file - fclose($fileHandle); + // Close file + fclose($fileHandle); - return $worksheetInfo; - } + return $worksheetInfo; + } - /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Create new PHPExcel - $objPHPExcel = new PHPExcel(); + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); - // Load into this instance - return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } - /** - * Loads PHPExcel from file into PHPExcel instance - * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) - { - $lineEnding = ini_get('auto_detect_line_endings'); - ini_set('auto_detect_line_endings', true); + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $lineEnding = ini_get('auto_detect_line_endings'); + ini_set('auto_detect_line_endings', true); - // Open file - $this->_openFile($pFilename); - if (!$this->_isValidFormat()) { - fclose ($this->_fileHandle); - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } - $fileHandle = $this->_fileHandle; + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; - // Skip BOM, if any - $this->_skipBOM(); + // Skip BOM, if any + $this->_skipBOM(); - // Create new PHPExcel object - while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { - $objPHPExcel->createSheet(); - } - $sheet = $objPHPExcel->setActiveSheetIndex($this->_sheetIndex); + // Create new PHPExcel object + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $sheet = $objPHPExcel->setActiveSheetIndex($this->_sheetIndex); - $escapeEnclosures = array( "\\" . $this->_enclosure, - $this->_enclosure . $this->_enclosure - ); + $escapeEnclosures = array( "\\" . $this->_enclosure, + $this->_enclosure . $this->_enclosure + ); - // Set our starting row based on whether we're in contiguous mode or not - $currentRow = 1; - if ($this->_contiguous) { - $currentRow = ($this->_contiguousRow == -1) ? $sheet->getHighestRow(): $this->_contiguousRow; - } + // Set our starting row based on whether we're in contiguous mode or not + $currentRow = 1; + if ($this->_contiguous) { + $currentRow = ($this->_contiguousRow == -1) ? $sheet->getHighestRow(): $this->_contiguousRow; + } - // Loop through each line of the file in turn - while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { - $columnLetter = 'A'; - foreach($rowData as $rowDatum) { - if ($rowDatum != '' && $this->_readFilter->readCell($columnLetter, $currentRow)) { - // Unescape enclosures - $rowDatum = str_replace($escapeEnclosures, $this->_enclosure, $rowDatum); + // Loop through each line of the file in turn + while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { + $columnLetter = 'A'; + foreach($rowData as $rowDatum) { + if ($rowDatum != '' && $this->_readFilter->readCell($columnLetter, $currentRow)) { + // Unescape enclosures + $rowDatum = str_replace($escapeEnclosures, $this->_enclosure, $rowDatum); - // Convert encoding if necessary - if ($this->_inputEncoding !== 'UTF-8') { - $rowDatum = PHPExcel_Shared_String::ConvertEncoding($rowDatum, 'UTF-8', $this->_inputEncoding); - } + // Convert encoding if necessary + if ($this->_inputEncoding !== 'UTF-8') { + $rowDatum = PHPExcel_Shared_String::ConvertEncoding($rowDatum, 'UTF-8', $this->_inputEncoding); + } - // Set cell value - $sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); - } - ++$columnLetter; - } - ++$currentRow; - } + // Set cell value + $sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); + } + ++$columnLetter; + } + ++$currentRow; + } - // Close file - fclose($fileHandle); + // Close file + fclose($fileHandle); - if ($this->_contiguous) { - $this->_contiguousRow = $currentRow; - } + if ($this->_contiguous) { + $this->_contiguousRow = $currentRow; + } - ini_set('auto_detect_line_endings', $lineEnding); + ini_set('auto_detect_line_endings', $lineEnding); - // Return - return $objPHPExcel; - } + // Return + return $objPHPExcel; + } - /** - * Get delimiter - * - * @return string - */ - public function getDelimiter() { - return $this->_delimiter; - } + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } - /** - * Set delimiter - * - * @param string $pValue Delimiter, defaults to , - * @return PHPExcel_Reader_CSV - */ - public function setDelimiter($pValue = ',') { - $this->_delimiter = $pValue; - return $this; - } + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Reader_CSV + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } - /** - * Get enclosure - * - * @return string - */ - public function getEnclosure() { - return $this->_enclosure; - } + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } - /** - * Set enclosure - * - * @param string $pValue Enclosure, defaults to " - * @return PHPExcel_Reader_CSV - */ - public function setEnclosure($pValue = '"') { - if ($pValue == '') { - $pValue = '"'; - } - $this->_enclosure = $pValue; - return $this; - } + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Reader_CSV + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = '"'; + } + $this->_enclosure = $pValue; + return $this; + } - /** - * Get sheet index - * - * @return integer - */ - public function getSheetIndex() { - return $this->_sheetIndex; - } + /** + * Get sheet index + * + * @return integer + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } - /** - * Set sheet index - * - * @param integer $pValue Sheet index - * @return PHPExcel_Reader_CSV - */ - public function setSheetIndex($pValue = 0) { - $this->_sheetIndex = $pValue; - return $this; - } + /** + * Set sheet index + * + * @param integer $pValue Sheet index + * @return PHPExcel_Reader_CSV + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } - /** - * Set Contiguous - * - * @param boolean $contiguous - */ - public function setContiguous($contiguous = FALSE) - { - $this->_contiguous = (bool) $contiguous; - if (!$contiguous) { - $this->_contiguousRow = -1; - } + /** + * Set Contiguous + * + * @param boolean $contiguous + */ + public function setContiguous($contiguous = FALSE) + { + $this->_contiguous = (bool) $contiguous; + if (!$contiguous) { + $this->_contiguousRow = -1; + } - return $this; - } + return $this; + } - /** - * Get Contiguous - * - * @return boolean - */ - public function getContiguous() { - return $this->_contiguous; - } + /** + * Get Contiguous + * + * @return boolean + */ + public function getContiguous() { + return $this->_contiguous; + } } diff --git a/Classes/PHPExcel/Reader/DefaultReadFilter.php b/Classes/PHPExcel/Reader/DefaultReadFilter.php index 6fb5eb33..7caf2605 100644 --- a/Classes/PHPExcel/Reader/DefaultReadFilter.php +++ b/Classes/PHPExcel/Reader/DefaultReadFilter.php @@ -21,18 +21,18 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** @@ -44,15 +44,15 @@ if (!defined('PHPEXCEL_ROOT')) { */ class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter { - /** - * Should this cell be read? - * - * @param $column String column index - * @param $row Row index - * @param $worksheetName Optional worksheet name - * @return boolean - */ - public function readCell($column, $row, $worksheetName = '') { - return true; - } + /** + * Should this cell be read? + * + * @param $column String column index + * @param $row Row index + * @param $worksheetName Optional worksheet name + * @return boolean + */ + public function readCell($column, $row, $worksheetName = '') { + return true; + } } diff --git a/Classes/PHPExcel/Reader/Excel2003XML.php b/Classes/PHPExcel/Reader/Excel2003XML.php index 38bb349a..3b62b751 100644 --- a/Classes/PHPExcel/Reader/Excel2003XML.php +++ b/Classes/PHPExcel/Reader/Excel2003XML.php @@ -21,18 +21,18 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** @@ -44,766 +44,766 @@ if (!defined('PHPEXCEL_ROOT')) { */ class PHPExcel_Reader_Excel2003XML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Formats - * - * @var array - */ - protected $_styles = array(); + /** + * Formats + * + * @var array + */ + protected $_styles = array(); - /** - * Character set used in the file - * - * @var string - */ - protected $_charSet = 'UTF-8'; - - - /** - * Create a new PHPExcel_Reader_Excel2003XML - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } - - - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - - // Office xmlns:o="urn:schemas-microsoft-com:office:office" - // Excel xmlns:x="urn:schemas-microsoft-com:office:excel" - // XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" - // Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" - // XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" - // XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" - // MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" - // Rowset xmlns:z="#RowsetSchema" - // - - $signature = array( - '' - ); - - // Open file - $this->_openFile($pFilename); - $fileHandle = $this->_fileHandle; - - // Read sample data (first 2 KB will do) - $data = fread($fileHandle, 2048); - fclose($fileHandle); - - $valid = true; - foreach($signature as $match) { - // every part of the signature must be present - if (strpos($data, $match) === false) { - $valid = false; - break; - } - } - - // Retrieve charset encoding - if(preg_match('//um',$data,$matches)) { - $this->_charSet = strtoupper($matches[1]); - } -// echo 'Character Set is ',$this->_charSet,'
'; - - return $valid; - } - - - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - if (!$this->canRead($pFilename)) { - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } - - $worksheetNames = array(); - - $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespaces = $xml->getNamespaces(true); - - $xml_ss = $xml->children($namespaces['ss']); - foreach($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); - $worksheetNames[] = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); - } - - return $worksheetNames; - } - - - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $worksheetInfo = array(); - - $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespaces = $xml->getNamespaces(true); - - $worksheetID = 1; - $xml_ss = $xml->children($namespaces['ss']); - foreach($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); - - $tmpInfo = array(); - $tmpInfo['worksheetName'] = ''; - $tmpInfo['lastColumnLetter'] = 'A'; - $tmpInfo['lastColumnIndex'] = 0; - $tmpInfo['totalRows'] = 0; - $tmpInfo['totalColumns'] = 0; - - if (isset($worksheet_ss['Name'])) { - $tmpInfo['worksheetName'] = (string) $worksheet_ss['Name']; - } else { - $tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}"; - } - - if (isset($worksheet->Table->Row)) { - $rowIndex = 0; - - foreach($worksheet->Table->Row as $rowData) { - $columnIndex = 0; - $rowHasData = false; - - foreach($rowData->Cell as $cell) { - if (isset($cell->Data)) { - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); - $rowHasData = true; - } - - ++$columnIndex; - } - - ++$rowIndex; - - if ($rowHasData) { - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); - } - } - } - - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; - - $worksheetInfo[] = $tmpInfo; - ++$worksheetID; - } - - return $worksheetInfo; - } + /** + * Character set used in the file + * + * @var string + */ + protected $_charSet = 'UTF-8'; /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Create new PHPExcel - $objPHPExcel = new PHPExcel(); + * Create a new PHPExcel_Reader_Excel2003XML + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + + // Office xmlns:o="urn:schemas-microsoft-com:office:office" + // Excel xmlns:x="urn:schemas-microsoft-com:office:excel" + // XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" + // Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" + // XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" + // XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" + // MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" + // Rowset xmlns:z="#RowsetSchema" + // + + $signature = array( + '' + ); + + // Open file + $this->_openFile($pFilename); + $fileHandle = $this->_fileHandle; + + // Read sample data (first 2 KB will do) + $data = fread($fileHandle, 2048); + fclose($fileHandle); + + $valid = true; + foreach($signature as $match) { + // every part of the signature must be present + if (strpos($data, $match) === false) { + $valid = false; + break; + } + } + + // Retrieve charset encoding + if(preg_match('//um',$data,$matches)) { + $this->_charSet = strtoupper($matches[1]); + } +// echo 'Character Set is ',$this->_charSet,'
'; + + return $valid; + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + if (!$this->canRead($pFilename)) { + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + + $worksheetNames = array(); + + $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespaces = $xml->getNamespaces(true); + + $xml_ss = $xml->children($namespaces['ss']); + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + $worksheetNames[] = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespaces = $xml->getNamespaces(true); + + $worksheetID = 1; + $xml_ss = $xml->children($namespaces['ss']); + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + + $tmpInfo = array(); + $tmpInfo['worksheetName'] = ''; + $tmpInfo['lastColumnLetter'] = 'A'; + $tmpInfo['lastColumnIndex'] = 0; + $tmpInfo['totalRows'] = 0; + $tmpInfo['totalColumns'] = 0; + + if (isset($worksheet_ss['Name'])) { + $tmpInfo['worksheetName'] = (string) $worksheet_ss['Name']; + } else { + $tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}"; + } + + if (isset($worksheet->Table->Row)) { + $rowIndex = 0; + + foreach($worksheet->Table->Row as $rowData) { + $columnIndex = 0; + $rowHasData = false; + + foreach($rowData->Cell as $cell) { + if (isset($cell->Data)) { + $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); + $rowHasData = true; + } + + ++$columnIndex; + } + + ++$rowIndex; + + if ($rowHasData) { + $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); + } + } + } + + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; + + $worksheetInfo[] = $tmpInfo; + ++$worksheetID; + } + + return $worksheetInfo; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); $objPHPExcel->removeSheetByIndex(0); - // Load into this instance - return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } - protected static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { - $styleAttributeValue = strtolower($styleAttributeValue); - foreach($styleList as $style) { - if ($styleAttributeValue == strtolower($style)) { - $styleAttributeValue = $style; - return true; - } - } - return false; - } + protected static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } - /** - * pixel units to excel width units(units of 1/256th of a character width) - * @param pxs - * @return - */ - protected static function _pixel2WidthUnits($pxs) { - $UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); + /** + * pixel units to excel width units(units of 1/256th of a character width) + * @param pxs + * @return + */ + protected static function _pixel2WidthUnits($pxs) { + $UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); - $widthUnits = 256 * ($pxs / 7); - $widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; - return $widthUnits; - } + $widthUnits = 256 * ($pxs / 7); + $widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; + return $widthUnits; + } - /** - * excel width units(units of 1/256th of a character width) to pixel units - * @param widthUnits - * @return - */ - protected static function _widthUnits2Pixel($widthUnits) { - $pixels = ($widthUnits / 256) * 7; - $offsetWidthUnits = $widthUnits % 256; - $pixels += round($offsetWidthUnits / (256 / 7)); - return $pixels; - } + /** + * excel width units(units of 1/256th of a character width) to pixel units + * @param widthUnits + * @return + */ + protected static function _widthUnits2Pixel($widthUnits) { + $pixels = ($widthUnits / 256) * 7; + $offsetWidthUnits = $widthUnits % 256; + $pixels += round($offsetWidthUnits / (256 / 7)); + return $pixels; + } - protected static function _hex2str($hex) { - return chr(hexdec($hex[1])); - } + protected static function _hex2str($hex) { + return chr(hexdec($hex[1])); + } - /** - * Loads PHPExcel from file into PHPExcel instance - * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) - { - $fromFormats = array('\-', '\ '); - $toFormats = array('-', ' '); + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); - $underlineStyles = array ( - PHPExcel_Style_Font::UNDERLINE_NONE, - PHPExcel_Style_Font::UNDERLINE_DOUBLE, - PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, - PHPExcel_Style_Font::UNDERLINE_SINGLE, - PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING - ); - $verticalAlignmentStyles = array ( - PHPExcel_Style_Alignment::VERTICAL_BOTTOM, - PHPExcel_Style_Alignment::VERTICAL_TOP, - PHPExcel_Style_Alignment::VERTICAL_CENTER, - PHPExcel_Style_Alignment::VERTICAL_JUSTIFY - ); - $horizontalAlignmentStyles = array ( - PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, - PHPExcel_Style_Alignment::HORIZONTAL_LEFT, - PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, - PHPExcel_Style_Alignment::HORIZONTAL_CENTER, - PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, - PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY - ); + $underlineStyles = array ( + PHPExcel_Style_Font::UNDERLINE_NONE, + PHPExcel_Style_Font::UNDERLINE_DOUBLE, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, + PHPExcel_Style_Font::UNDERLINE_SINGLE, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING + ); + $verticalAlignmentStyles = array ( + PHPExcel_Style_Alignment::VERTICAL_BOTTOM, + PHPExcel_Style_Alignment::VERTICAL_TOP, + PHPExcel_Style_Alignment::VERTICAL_CENTER, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY + ); + $horizontalAlignmentStyles = array ( + PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY + ); - $timezoneObj = new DateTimeZone('Europe/London'); - $GMT = new DateTimeZone('UTC'); + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - if (!$this->canRead($pFilename)) { - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } + if (!$this->canRead($pFilename)) { + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } - $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespaces = $xml->getNamespaces(true); + $xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespaces = $xml->getNamespaces(true); - $docProps = $objPHPExcel->getProperties(); - if (isset($xml->DocumentProperties[0])) { - foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) { - switch ($propertyName) { - case 'Title' : - $docProps->setTitle(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Subject' : - $docProps->setSubject(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Author' : - $docProps->setCreator(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Created' : - $creationDate = strtotime($propertyValue); - $docProps->setCreated($creationDate); - break; - case 'LastAuthor' : - $docProps->setLastModifiedBy(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'LastSaved' : - $lastSaveDate = strtotime($propertyValue); - $docProps->setModified($lastSaveDate); - break; - case 'Company' : - $docProps->setCompany(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Category' : - $docProps->setCategory(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Manager' : - $docProps->setManager(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Keywords' : - $docProps->setKeywords(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - case 'Description' : - $docProps->setDescription(self::_convertStringEncoding($propertyValue,$this->_charSet)); - break; - } - } - } - if (isset($xml->CustomDocumentProperties)) { - foreach($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { - $propertyAttributes = $propertyValue->attributes($namespaces['dt']); - $propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/','PHPExcel_Reader_Excel2003XML::_hex2str',$propertyName); - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN; - switch((string) $propertyAttributes) { - case 'string' : - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; - $propertyValue = trim($propertyValue); - break; - case 'boolean' : - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; - $propertyValue = (bool) $propertyValue; - break; - case 'integer' : - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER; - $propertyValue = intval($propertyValue); - break; - case 'float' : - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; - $propertyValue = floatval($propertyValue); - break; - case 'dateTime.tz' : - $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; - $propertyValue = strtotime(trim($propertyValue)); - break; - } - $docProps->setCustomProperty($propertyName,$propertyValue,$propertyType); - } - } + $docProps = $objPHPExcel->getProperties(); + if (isset($xml->DocumentProperties[0])) { + foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) { + switch ($propertyName) { + case 'Title' : + $docProps->setTitle(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Subject' : + $docProps->setSubject(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Author' : + $docProps->setCreator(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Created' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'LastAuthor' : + $docProps->setLastModifiedBy(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'LastSaved' : + $lastSaveDate = strtotime($propertyValue); + $docProps->setModified($lastSaveDate); + break; + case 'Company' : + $docProps->setCompany(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Category' : + $docProps->setCategory(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Manager' : + $docProps->setManager(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Keywords' : + $docProps->setKeywords(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Description' : + $docProps->setDescription(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + } + } + } + if (isset($xml->CustomDocumentProperties)) { + foreach($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { + $propertyAttributes = $propertyValue->attributes($namespaces['dt']); + $propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/','PHPExcel_Reader_Excel2003XML::_hex2str',$propertyName); + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN; + switch((string) $propertyAttributes) { + case 'string' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + $propertyValue = trim($propertyValue); + break; + case 'boolean' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; + $propertyValue = (bool) $propertyValue; + break; + case 'integer' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER; + $propertyValue = intval($propertyValue); + break; + case 'float' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; + $propertyValue = floatval($propertyValue); + break; + case 'dateTime.tz' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; + $propertyValue = strtotime(trim($propertyValue)); + break; + } + $docProps->setCustomProperty($propertyName,$propertyValue,$propertyType); + } + } - foreach($xml->Styles[0] as $style) { - $style_ss = $style->attributes($namespaces['ss']); - $styleID = (string) $style_ss['ID']; -// echo 'Style ID = '.$styleID.'
'; - if ($styleID == 'Default') { - $this->_styles['Default'] = array(); - } else { - $this->_styles[$styleID] = $this->_styles['Default']; - } - foreach ($style as $styleType => $styleData) { - $styleAttributes = $styleData->attributes($namespaces['ss']); -// echo $styleType.'
'; - switch ($styleType) { - case 'Alignment' : - foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { -// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; - $styleAttributeValue = (string) $styleAttributeValue; - switch ($styleAttributeKey) { - case 'Vertical' : - if (self::identifyFixedStyleValue($verticalAlignmentStyles,$styleAttributeValue)) { - $this->_styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; - } - break; - case 'Horizontal' : - if (self::identifyFixedStyleValue($horizontalAlignmentStyles,$styleAttributeValue)) { - $this->_styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; - } - break; - case 'WrapText' : - $this->_styles[$styleID]['alignment']['wrap'] = true; - break; - } - } - break; - case 'Borders' : - foreach($styleData->Border as $borderStyle) { - $borderAttributes = $borderStyle->attributes($namespaces['ss']); - $thisBorder = array(); - foreach($borderAttributes as $borderStyleKey => $borderStyleValue) { -// echo $borderStyleKey.' = '.$borderStyleValue.'
'; - switch ($borderStyleKey) { - case 'LineStyle' : - $thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; -// $thisBorder['style'] = $borderStyleValue; - break; - case 'Weight' : -// $thisBorder['style'] = $borderStyleValue; - break; - case 'Position' : - $borderPosition = strtolower($borderStyleValue); - break; - case 'Color' : - $borderColour = substr($borderStyleValue,1); - $thisBorder['color']['rgb'] = $borderColour; - break; - } - } - if (!empty($thisBorder)) { - if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { - $this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder; - } - } - } - break; - case 'Font' : - foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { -// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; - $styleAttributeValue = (string) $styleAttributeValue; - switch ($styleAttributeKey) { - case 'FontName' : - $this->_styles[$styleID]['font']['name'] = $styleAttributeValue; - break; - case 'Size' : - $this->_styles[$styleID]['font']['size'] = $styleAttributeValue; - break; - case 'Color' : - $this->_styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue,1); - break; - case 'Bold' : - $this->_styles[$styleID]['font']['bold'] = true; - break; - case 'Italic' : - $this->_styles[$styleID]['font']['italic'] = true; - break; - case 'Underline' : - if (self::identifyFixedStyleValue($underlineStyles,$styleAttributeValue)) { - $this->_styles[$styleID]['font']['underline'] = $styleAttributeValue; - } - break; - } - } - break; - case 'Interior' : - foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { -// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; - switch ($styleAttributeKey) { - case 'Color' : - $this->_styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue,1); - break; - } - } - break; - case 'NumberFormat' : - foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { -// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; - $styleAttributeValue = str_replace($fromFormats,$toFormats,$styleAttributeValue); - switch ($styleAttributeValue) { - case 'Short Date' : - $styleAttributeValue = 'dd/mm/yyyy'; - break; - } - if ($styleAttributeValue > '') { - $this->_styles[$styleID]['numberformat']['code'] = $styleAttributeValue; - } - } - break; - case 'Protection' : - foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { -// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; - } - break; - } - } -// print_r($this->_styles[$styleID]); -// echo '
'; - } -// echo '
'; + foreach($xml->Styles[0] as $style) { + $style_ss = $style->attributes($namespaces['ss']); + $styleID = (string) $style_ss['ID']; +// echo 'Style ID = '.$styleID.'
'; + if ($styleID == 'Default') { + $this->_styles['Default'] = array(); + } else { + $this->_styles[$styleID] = $this->_styles['Default']; + } + foreach ($style as $styleType => $styleData) { + $styleAttributes = $styleData->attributes($namespaces['ss']); +// echo $styleType.'
'; + switch ($styleType) { + case 'Alignment' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'Vertical' : + if (self::identifyFixedStyleValue($verticalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; + } + break; + case 'Horizontal' : + if (self::identifyFixedStyleValue($horizontalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; + } + break; + case 'WrapText' : + $this->_styles[$styleID]['alignment']['wrap'] = true; + break; + } + } + break; + case 'Borders' : + foreach($styleData->Border as $borderStyle) { + $borderAttributes = $borderStyle->attributes($namespaces['ss']); + $thisBorder = array(); + foreach($borderAttributes as $borderStyleKey => $borderStyleValue) { +// echo $borderStyleKey.' = '.$borderStyleValue.'
'; + switch ($borderStyleKey) { + case 'LineStyle' : + $thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Weight' : +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Position' : + $borderPosition = strtolower($borderStyleValue); + break; + case 'Color' : + $borderColour = substr($borderStyleValue,1); + $thisBorder['color']['rgb'] = $borderColour; + break; + } + } + if (!empty($thisBorder)) { + if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { + $this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder; + } + } + } + break; + case 'Font' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'FontName' : + $this->_styles[$styleID]['font']['name'] = $styleAttributeValue; + break; + case 'Size' : + $this->_styles[$styleID]['font']['size'] = $styleAttributeValue; + break; + case 'Color' : + $this->_styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue,1); + break; + case 'Bold' : + $this->_styles[$styleID]['font']['bold'] = true; + break; + case 'Italic' : + $this->_styles[$styleID]['font']['italic'] = true; + break; + case 'Underline' : + if (self::identifyFixedStyleValue($underlineStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['font']['underline'] = $styleAttributeValue; + } + break; + } + } + break; + case 'Interior' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + switch ($styleAttributeKey) { + case 'Color' : + $this->_styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue,1); + break; + } + } + break; + case 'NumberFormat' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = str_replace($fromFormats,$toFormats,$styleAttributeValue); + switch ($styleAttributeValue) { + case 'Short Date' : + $styleAttributeValue = 'dd/mm/yyyy'; + break; + } + if ($styleAttributeValue > '') { + $this->_styles[$styleID]['numberformat']['code'] = $styleAttributeValue; + } + } + break; + case 'Protection' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + } + break; + } + } +// print_r($this->_styles[$styleID]); +// echo '
'; + } +// echo '
'; - $worksheetID = 0; - $xml_ss = $xml->children($namespaces['ss']); + $worksheetID = 0; + $xml_ss = $xml->children($namespaces['ss']); - foreach($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); - if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && - (!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) { - continue; - } + if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && + (!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) { + continue; + } -// echo '

Worksheet: ',$worksheet_ss['Name'],'

'; +// echo '

Worksheet: ',$worksheet_ss['Name'],'

'; // - // Create new Worksheet - $objPHPExcel->createSheet(); - $objPHPExcel->setActiveSheetIndex($worksheetID); - if (isset($worksheet_ss['Name'])) { - $worksheetName = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in - // formula cells... during the load, all formulae should be correct, and we're simply bringing - // the worksheet name in line with the formula, not the reverse - $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); - } + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheet_ss['Name'])) { + $worksheetName = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in + // formula cells... during the load, all formulae should be correct, and we're simply bringing + // the worksheet name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + } - $columnID = 'A'; - if (isset($worksheet->Table->Column)) { - foreach($worksheet->Table->Column as $columnData) { - $columnData_ss = $columnData->attributes($namespaces['ss']); - if (isset($columnData_ss['Index'])) { - $columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); - } - if (isset($columnData_ss['Width'])) { - $columnWidth = $columnData_ss['Width']; -// echo 'Setting column width for '.$columnID.' to '.$columnWidth.'
'; - $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); - } - ++$columnID; - } - } + $columnID = 'A'; + if (isset($worksheet->Table->Column)) { + foreach($worksheet->Table->Column as $columnData) { + $columnData_ss = $columnData->attributes($namespaces['ss']); + if (isset($columnData_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); + } + if (isset($columnData_ss['Width'])) { + $columnWidth = $columnData_ss['Width']; +// echo 'Setting column width for '.$columnID.' to '.$columnWidth.'
'; + $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); + } + ++$columnID; + } + } - $rowID = 1; - if (isset($worksheet->Table->Row)) { + $rowID = 1; + if (isset($worksheet->Table->Row)) { $additionalMergedCells = 0; - foreach($worksheet->Table->Row as $rowData) { - $rowHasData = false; - $row_ss = $rowData->attributes($namespaces['ss']); - if (isset($row_ss['Index'])) { - $rowID = (integer) $row_ss['Index']; - } -// echo 'Row '.$rowID.'
'; + foreach($worksheet->Table->Row as $rowData) { + $rowHasData = false; + $row_ss = $rowData->attributes($namespaces['ss']); + if (isset($row_ss['Index'])) { + $rowID = (integer) $row_ss['Index']; + } +// echo 'Row '.$rowID.'
'; - $columnID = 'A'; - foreach($rowData->Cell as $cell) { + $columnID = 'A'; + foreach($rowData->Cell as $cell) { - $cell_ss = $cell->attributes($namespaces['ss']); - if (isset($cell_ss['Index'])) { - $columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); - } - $cellRange = $columnID.$rowID; + $cell_ss = $cell->attributes($namespaces['ss']); + if (isset($cell_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); + } + $cellRange = $columnID.$rowID; - if ($this->getReadFilter() !== NULL) { - if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { - continue; - } - } + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { + continue; + } + } - if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { - $columnTo = $columnID; - if (isset($cell_ss['MergeAcross'])) { + if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { + $columnTo = $columnID; + if (isset($cell_ss['MergeAcross'])) { $additionalMergedCells += (int)$cell_ss['MergeAcross']; - $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); - } - $rowTo = $rowID; - if (isset($cell_ss['MergeDown'])) { - $rowTo = $rowTo + $cell_ss['MergeDown']; - } - $cellRange .= ':'.$columnTo.$rowTo; - $objPHPExcel->getActiveSheet()->mergeCells($cellRange); - } + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); + } + $rowTo = $rowID; + if (isset($cell_ss['MergeDown'])) { + $rowTo = $rowTo + $cell_ss['MergeDown']; + } + $cellRange .= ':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } - $cellIsSet = $hasCalculatedValue = false; - $cellDataFormula = ''; - if (isset($cell_ss['Formula'])) { - $cellDataFormula = $cell_ss['Formula']; - // added this as a check for array formulas - if (isset($cell_ss['ArrayRange'])) { - $cellDataCSEFormula = $cell_ss['ArrayRange']; -// echo "found an array formula at ".$columnID.$rowID."
"; - } - $hasCalculatedValue = true; - } - if (isset($cell->Data)) { - $cellValue = $cellData = $cell->Data; - $type = PHPExcel_Cell_DataType::TYPE_NULL; - $cellData_ss = $cellData->attributes($namespaces['ss']); - if (isset($cellData_ss['Type'])) { - $cellDataType = $cellData_ss['Type']; - switch ($cellDataType) { - /* - const TYPE_STRING = 's'; - const TYPE_FORMULA = 'f'; - const TYPE_NUMERIC = 'n'; - const TYPE_BOOL = 'b'; - const TYPE_NULL = 'null'; - const TYPE_INLINE = 'inlineStr'; - const TYPE_ERROR = 'e'; - */ - case 'String' : - $cellValue = self::_convertStringEncoding($cellValue,$this->_charSet); - $type = PHPExcel_Cell_DataType::TYPE_STRING; - break; - case 'Number' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $cellValue = (float) $cellValue; - if (floor($cellValue) == $cellValue) { - $cellValue = (integer) $cellValue; - } - break; - case 'Boolean' : - $type = PHPExcel_Cell_DataType::TYPE_BOOL; - $cellValue = ($cellValue != 0); - break; - case 'DateTime' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); - break; - case 'Error' : - $type = PHPExcel_Cell_DataType::TYPE_ERROR; - break; - } - } + $cellIsSet = $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cell_ss['Formula'])) { + $cellDataFormula = $cell_ss['Formula']; + // added this as a check for array formulas + if (isset($cell_ss['ArrayRange'])) { + $cellDataCSEFormula = $cell_ss['ArrayRange']; +// echo "found an array formula at ".$columnID.$rowID."
"; + } + $hasCalculatedValue = true; + } + if (isset($cell->Data)) { + $cellValue = $cellData = $cell->Data; + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $cellData_ss = $cellData->attributes($namespaces['ss']); + if (isset($cellData_ss['Type'])) { + $cellDataType = $cellData_ss['Type']; + switch ($cellDataType) { + /* + const TYPE_STRING = 's'; + const TYPE_FORMULA = 'f'; + const TYPE_NUMERIC = 'n'; + const TYPE_BOOL = 'b'; + const TYPE_NULL = 'null'; + const TYPE_INLINE = 'inlineStr'; + const TYPE_ERROR = 'e'; + */ + case 'String' : + $cellValue = self::_convertStringEncoding($cellValue,$this->_charSet); + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case 'Number' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = (float) $cellValue; + if (floor($cellValue) == $cellValue) { + $cellValue = (integer) $cellValue; + } + break; + case 'Boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cellValue = ($cellValue != 0); + break; + case 'DateTime' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); + break; + case 'Error' : + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + } + } - if ($hasCalculatedValue) { -// echo 'FORMULA
'; - $type = PHPExcel_Cell_DataType::TYPE_FORMULA; - $columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); - if (substr($cellDataFormula,0,3) == 'of:') { - $cellDataFormula = substr($cellDataFormula,3); -// echo 'Before: ',$cellDataFormula,'
'; - $temp = explode('"',$cellDataFormula); - $key = false; - foreach($temp as &$value) { - // Only replace in alternate array entries (i.e. non-quoted blocks) - if ($key = !$key) { - $value = str_replace(array('[.','.',']'),'',$value); - } - } - } else { - // Convert R1C1 style references to A1 style references (but only when not quoted) -// echo 'Before: ',$cellDataFormula,'
'; - $temp = explode('"',$cellDataFormula); - $key = false; - foreach($temp as &$value) { - // Only replace in alternate array entries (i.e. non-quoted blocks) - if ($key = !$key) { - preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); - // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way - // through the formula from left to right. Reversing means that we work right to left.through - // the formula - $cellReferences = array_reverse($cellReferences); - // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, - // then modify the formula to use that new reference - foreach($cellReferences as $cellReference) { - $rowReference = $cellReference[2][0]; - // Empty R reference is the current row - if ($rowReference == '') $rowReference = $rowID; - // Bracketed R references are relative to the current row - if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]'); - $columnReference = $cellReference[4][0]; - // Empty C reference is the current column - if ($columnReference == '') $columnReference = $columnNumber; - // Bracketed C references are relative to the current column - if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]'); - $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; - $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); - } - } - } - } - unset($value); - // Then rebuild the formula string - $cellDataFormula = implode('"',$temp); -// echo 'After: ',$cellDataFormula,'
'; - } + if ($hasCalculatedValue) { +// echo 'FORMULA
'; + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + $columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); + if (substr($cellDataFormula,0,3) == 'of:') { + $cellDataFormula = substr($cellDataFormula,3); +// echo 'Before: ',$cellDataFormula,'
'; + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($key = !$key) { + $value = str_replace(array('[.','.',']'),'',$value); + } + } + } else { + // Convert R1C1 style references to A1 style references (but only when not quoted) +// echo 'Before: ',$cellDataFormula,'
'; + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($key = !$key) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $rowID; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $columnNumber; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'After: ',$cellDataFormula,'
'; + } -// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'
'; +// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'
'; // - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type); - if ($hasCalculatedValue) { -// echo 'Formula result is '.$cellValue.'
'; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); - } - $cellIsSet = $rowHasData = true; - } + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type); + if ($hasCalculatedValue) { +// echo 'Formula result is '.$cellValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); + } + $cellIsSet = $rowHasData = true; + } - if (isset($cell->Comment)) { -// echo 'comment found
'; - $commentAttributes = $cell->Comment->attributes($namespaces['ss']); - $author = 'unknown'; - if (isset($commentAttributes->Author)) { - $author = (string)$commentAttributes->Author; -// echo 'Author: ',$author,'
'; - } - $node = $cell->Comment->Data->asXML(); -// $annotation = str_replace('html:','',substr($node,49,-10)); -// echo $annotation,'
'; - $annotation = strip_tags($node); -// echo 'Annotation: ',$annotation,'
'; - $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) - ->setAuthor(self::_convertStringEncoding($author ,$this->_charSet)) - ->setText($this->_parseRichText($annotation) ); - } + if (isset($cell->Comment)) { +// echo 'comment found
'; + $commentAttributes = $cell->Comment->attributes($namespaces['ss']); + $author = 'unknown'; + if (isset($commentAttributes->Author)) { + $author = (string)$commentAttributes->Author; +// echo 'Author: ',$author,'
'; + } + $node = $cell->Comment->Data->asXML(); +// $annotation = str_replace('html:','',substr($node,49,-10)); +// echo $annotation,'
'; + $annotation = strip_tags($node); +// echo 'Annotation: ',$annotation,'
'; + $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) + ->setAuthor(self::_convertStringEncoding($author ,$this->_charSet)) + ->setText($this->_parseRichText($annotation) ); + } - if (($cellIsSet) && (isset($cell_ss['StyleID']))) { - $style = (string) $cell_ss['StyleID']; -// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'
'; - if ((isset($this->_styles[$style])) && (!empty($this->_styles[$style]))) { -// echo 'Cell '.$columnID.$rowID.'
'; -// print_r($this->_styles[$style]); -// echo '
'; - if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(NULL); - } - $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); - } - } - ++$columnID; + if (($cellIsSet) && (isset($cell_ss['StyleID']))) { + $style = (string) $cell_ss['StyleID']; +// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'
'; + if ((isset($this->_styles[$style])) && (!empty($this->_styles[$style]))) { +// echo 'Cell '.$columnID.$rowID.'
'; +// print_r($this->_styles[$style]); +// echo '
'; + if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(NULL); + } + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); + } + } + ++$columnID; while ($additionalMergedCells > 0) { ++$columnID; $additionalMergedCells--; } - } + } - if ($rowHasData) { - if (isset($row_ss['StyleID'])) { - $rowStyle = $row_ss['StyleID']; - } - if (isset($row_ss['Height'])) { - $rowHeight = $row_ss['Height']; -// echo 'Setting row height to '.$rowHeight.'
'; - $objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); - } - } + if ($rowHasData) { + if (isset($row_ss['StyleID'])) { + $rowStyle = $row_ss['StyleID']; + } + if (isset($row_ss['Height'])) { + $rowHeight = $row_ss['Height']; +// echo 'Setting row height to '.$rowHeight.'
'; + $objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); + } + } - ++$rowID; - } - } - ++$worksheetID; - } + ++$rowID; + } + } + ++$worksheetID; + } - // Return - return $objPHPExcel; - } + // Return + return $objPHPExcel; + } - protected static function _convertStringEncoding($string,$charset) { - if ($charset != 'UTF-8') { - return PHPExcel_Shared_String::ConvertEncoding($string,'UTF-8',$charset); - } - return $string; - } + protected static function _convertStringEncoding($string,$charset) { + if ($charset != 'UTF-8') { + return PHPExcel_Shared_String::ConvertEncoding($string,'UTF-8',$charset); + } + return $string; + } - protected function _parseRichText($is = '') { - $value = new PHPExcel_RichText(); + protected function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); - $value->createText(self::_convertStringEncoding($is,$this->_charSet)); + $value->createText(self::_convertStringEncoding($is,$this->_charSet)); - return $value; - } + return $value; + } } diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index bff2147d..101424ea 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -21,991 +21,991 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** * PHPExcel_Reader_Excel2007 * - * @category PHPExcel - * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * PHPExcel_ReferenceHelper instance - * - * @var PHPExcel_ReferenceHelper - */ - private $_referenceHelper = NULL; + /** + * PHPExcel_ReferenceHelper instance + * + * @var PHPExcel_ReferenceHelper + */ + private $_referenceHelper = NULL; - /** - * PHPExcel_Reader_Excel2007_Theme instance - * - * @var PHPExcel_Reader_Excel2007_Theme - */ - private static $_theme = NULL; + /** + * PHPExcel_Reader_Excel2007_Theme instance + * + * @var PHPExcel_Reader_Excel2007_Theme + */ + private static $_theme = NULL; - /** - * Create a new PHPExcel_Reader_Excel2007 instance - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); - } + /** + * Create a new PHPExcel_Reader_Excel2007 instance + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); + } - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } $zipClass = PHPExcel_Settings::getZipClass(); - // Check if zip class exists -// if (!class_exists($zipClass, FALSE)) { -// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); -// } + // Check if zip class exists +// if (!class_exists($zipClass, FALSE)) { +// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); +// } - $xl = false; - // Load file - $zip = new $zipClass; - if ($zip->open($pFilename) === true) { - // check if it is an OOXML archive - $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if ($rels !== false) { - foreach ($rels->Relationship as $rel) { - switch ($rel["Type"]) { - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": - if (basename($rel["Target"]) == 'workbook.xml') { - $xl = true; - } - break; + $xl = false; + // Load file + $zip = new $zipClass; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if ($rels !== false) { + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + if (basename($rel["Target"]) == 'workbook.xml') { + $xl = true; + } + break; - } - } - } - $zip->close(); - } + } + } + } + $zip->close(); + } - return $xl; - } + return $xl; + } - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $worksheetNames = array(); + $worksheetNames = array(); $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - $zip->open($pFilename); + $zip = new $zipClass; + $zip->open($pFilename); - // The files we're looking at here are small enough that simpleXML is more efficient than XMLReader - $rels = simplexml_load_string( - $this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) - ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($rels->Relationship as $rel) { - switch ($rel["Type"]) { - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": - $xmlWorkbook = simplexml_load_string( - $this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) - ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + // The files we're looking at here are small enough that simpleXML is more efficient than XMLReader + $rels = simplexml_load_string( + $this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) + ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $xmlWorkbook = simplexml_load_string( + $this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) + ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if ($xmlWorkbook->sheets) { - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - // Check if sheet should be skipped - $worksheetNames[] = (string) $eleSheet["name"]; - } - } - } - } + if ($xmlWorkbook->sheets) { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + // Check if sheet should be skipped + $worksheetNames[] = (string) $eleSheet["name"]; + } + } + } + } - $zip->close(); + $zip->close(); - return $worksheetNames; - } + return $worksheetNames; + } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $worksheetInfo = array(); + $worksheetInfo = array(); $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - $zip->open($pFilename); + $zip = new $zipClass; + $zip->open($pFilename); - $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($rels->Relationship as $rel) { - if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") { - $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); + $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") { + $dir = dirname($rel["Target"]); + $relsWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); - $worksheets = array(); - foreach ($relsWorkbook->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { - $worksheets[(string) $ele["Id"]] = $ele["Target"]; - } - } + $worksheets = array(); + foreach ($relsWorkbook->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { + $worksheets[(string) $ele["Id"]] = $ele["Target"]; + } + } - $xmlWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if ($xmlWorkbook->sheets) { - $dir = dirname($rel["Target"]); - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - $tmpInfo = array( - 'worksheetName' => (string) $eleSheet["name"], - 'lastColumnLetter' => 'A', - 'lastColumnIndex' => 0, - 'totalRows' => 0, - 'totalColumns' => 0, - ); + $xmlWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + if ($xmlWorkbook->sheets) { + $dir = dirname($rel["Target"]); + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + $tmpInfo = array( + 'worksheetName' => (string) $eleSheet["name"], + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); - $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xml = new XMLReader(); - $res = $xml->xml($this->securityScanFile('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet"), null, PHPExcel_Settings::getLibXmlLoaderOptions()); - $xml->setParserProperty(2,true); + $xml = new XMLReader(); + $res = $xml->xml($this->securityScanFile('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet"), null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); - $currCells = 0; - while ($xml->read()) { - if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) { - $row = $xml->getAttribute('r'); - $tmpInfo['totalRows'] = $row; - $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); - $currCells = 0; - } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) { - $currCells++; - } - } - $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); - $xml->close(); + $currCells = 0; + while ($xml->read()) { + if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) { + $row = $xml->getAttribute('r'); + $tmpInfo['totalRows'] = $row; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) { + $currCells++; + } + } + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $xml->close(); - $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $worksheetInfo[] = $tmpInfo; - } - } - } - } + $worksheetInfo[] = $tmpInfo; + } + } + } + } - $zip->close(); + $zip->close(); - return $worksheetInfo; - } + return $worksheetInfo; + } - private static function _castToBool($c) { -// echo 'Initial Cast to Boolean', PHP_EOL; - $value = isset($c->v) ? (string) $c->v : NULL; - if ($value == '0') { - return FALSE; - } elseif ($value == '1') { - return TRUE; - } else { - return (bool)$c->v; - } - return $value; - } // function _castToBool() + private static function _castToBool($c) { +// echo 'Initial Cast to Boolean', PHP_EOL; + $value = isset($c->v) ? (string) $c->v : NULL; + if ($value == '0') { + return FALSE; + } elseif ($value == '1') { + return TRUE; + } else { + return (bool)$c->v; + } + return $value; + } // function _castToBool() - private static function _castToError($c) { -// echo 'Initial Cast to Error', PHP_EOL; - return isset($c->v) ? (string) $c->v : NULL; - } // function _castToError() + private static function _castToError($c) { +// echo 'Initial Cast to Error', PHP_EOL; + return isset($c->v) ? (string) $c->v : NULL; + } // function _castToError() - private static function _castToString($c) { -// echo 'Initial Cast to String, PHP_EOL; - return isset($c->v) ? (string) $c->v : NULL; - } // function _castToString() + private static function _castToString($c) { +// echo 'Initial Cast to String, PHP_EOL; + return isset($c->v) ? (string) $c->v : NULL; + } // function _castToString() - private function _castToFormula($c,$r,&$cellDataType,&$value,&$calculatedValue,&$sharedFormulas,$castBaseType) { -// echo 'Formula', PHP_EOL; -// echo '$c->f is ', $c->f, PHP_EOL; - $cellDataType = 'f'; - $value = "={$c->f}"; - $calculatedValue = self::$castBaseType($c); + private function _castToFormula($c,$r,&$cellDataType,&$value,&$calculatedValue,&$sharedFormulas,$castBaseType) { +// echo 'Formula', PHP_EOL; +// echo '$c->f is ', $c->f, PHP_EOL; + $cellDataType = 'f'; + $value = "={$c->f}"; + $calculatedValue = self::$castBaseType($c); - // Shared formula? - if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') { -// echo 'SHARED FORMULA', PHP_EOL; - $instance = (string)$c->f['si']; + // Shared formula? + if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') { +// echo 'SHARED FORMULA', PHP_EOL; + $instance = (string)$c->f['si']; -// echo 'Instance ID = ', $instance, PHP_EOL; +// echo 'Instance ID = ', $instance, PHP_EOL; // -// echo 'Shared Formula Array:', PHP_EOL; -// print_r($sharedFormulas); - if (!isset($sharedFormulas[(string)$c->f['si']])) { -// echo 'SETTING NEW SHARED FORMULA', PHP_EOL; -// echo 'Master is ', $r, PHP_EOL; -// echo 'Formula is ', $value, PHP_EOL; - $sharedFormulas[$instance] = array( 'master' => $r, - 'formula' => $value - ); -// echo 'New Shared Formula Array:', PHP_EOL; -// print_r($sharedFormulas); - } else { -// echo 'GETTING SHARED FORMULA', PHP_EOL; -// echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL; -// echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL; - $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']); - $current = PHPExcel_Cell::coordinateFromString($r); +// echo 'Shared Formula Array:', PHP_EOL; +// print_r($sharedFormulas); + if (!isset($sharedFormulas[(string)$c->f['si']])) { +// echo 'SETTING NEW SHARED FORMULA', PHP_EOL; +// echo 'Master is ', $r, PHP_EOL; +// echo 'Formula is ', $value, PHP_EOL; + $sharedFormulas[$instance] = array( 'master' => $r, + 'formula' => $value + ); +// echo 'New Shared Formula Array:', PHP_EOL; +// print_r($sharedFormulas); + } else { +// echo 'GETTING SHARED FORMULA', PHP_EOL; +// echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL; +// echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL; + $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']); + $current = PHPExcel_Cell::coordinateFromString($r); - $difference = array(0, 0); - $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]); - $difference[1] = $current[1] - $master[1]; + $difference = array(0, 0); + $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]); + $difference[1] = $current[1] - $master[1]; - $value = $this->_referenceHelper->updateFormulaReferences( $sharedFormulas[$instance]['formula'], - 'A1', - $difference[0], - $difference[1] - ); -// echo 'Adjusted Formula is ', $value, PHP_EOL; - } - } - } + $value = $this->_referenceHelper->updateFormulaReferences( $sharedFormulas[$instance]['formula'], + 'A1', + $difference[0], + $difference[1] + ); +// echo 'Adjusted Formula is ', $value, PHP_EOL; + } + } + } - public function _getFromZipArchive($archive, $fileName = '') - { - // Root-relative paths - if (strpos($fileName, '//') !== false) - { - $fileName = substr($fileName, strpos($fileName, '//') + 1); - } - $fileName = PHPExcel_Shared_File::realpath($fileName); + public function _getFromZipArchive($archive, $fileName = '') + { + // Root-relative paths + if (strpos($fileName, '//') !== false) + { + $fileName = substr($fileName, strpos($fileName, '//') + 1); + } + $fileName = PHPExcel_Shared_File::realpath($fileName); - // Apache POI fixes - $contents = $archive->getFromName($fileName); - if ($contents === false) - { - $contents = $archive->getFromName(substr($fileName, 1)); - } + // Apache POI fixes + $contents = $archive->getFromName($fileName); + if ($contents === false) + { + $contents = $archive->getFromName(substr($fileName, 1)); + } - return $contents; - } + return $contents; + } - /** - * Loads PHPExcel from file - * - * @param string $pFilename + /** + * Loads PHPExcel from file + * + * @param string $pFilename * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - // Initialisations - $excel = new PHPExcel; - $excel->removeSheetByIndex(0); - if (!$this->_readDataOnly) { - $excel->removeCellStyleXfByIndex(0); // remove the default style - $excel->removeCellXfByIndex(0); // remove the default style - } + // Initialisations + $excel = new PHPExcel; + $excel->removeSheetByIndex(0); + if (!$this->_readDataOnly) { + $excel->removeCellStyleXfByIndex(0); // remove the default style + $excel->removeCellXfByIndex(0); // remove the default style + } $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - $zip->open($pFilename); + $zip = new $zipClass; + $zip->open($pFilename); - // Read the theme first, because we need the colour scheme when reading the styles - $wbRels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($wbRels->Relationship as $rel) { - switch ($rel["Type"]) { - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": - $themeOrderArray = array('lt1','dk1','lt2','dk2'); - $themeOrderAdditional = count($themeOrderArray); + // Read the theme first, because we need the colour scheme when reading the styles + $wbRels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($wbRels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": + $themeOrderArray = array('lt1','dk1','lt2','dk2'); + $themeOrderAdditional = count($themeOrderArray); - $xmlTheme = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "xl/{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if (is_object($xmlTheme)) { - $xmlThemeName = $xmlTheme->attributes(); - $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); - $themeName = (string)$xmlThemeName['name']; + $xmlTheme = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "xl/{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if (is_object($xmlTheme)) { + $xmlThemeName = $xmlTheme->attributes(); + $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + $themeName = (string)$xmlThemeName['name']; - $colourScheme = $xmlTheme->themeElements->clrScheme->attributes(); - $colourSchemeName = (string)$colourScheme['name']; - $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + $colourScheme = $xmlTheme->themeElements->clrScheme->attributes(); + $colourSchemeName = (string)$colourScheme['name']; + $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); - $themeColours = array(); - foreach ($colourScheme as $k => $xmlColour) { - $themePos = array_search($k,$themeOrderArray); - if ($themePos === false) { - $themePos = $themeOrderAdditional++; - } - if (isset($xmlColour->sysClr)) { - $xmlColourData = $xmlColour->sysClr->attributes(); - $themeColours[$themePos] = $xmlColourData['lastClr']; - } elseif (isset($xmlColour->srgbClr)) { - $xmlColourData = $xmlColour->srgbClr->attributes(); - $themeColours[$themePos] = $xmlColourData['val']; - } - } - self::$_theme = new PHPExcel_Reader_Excel2007_Theme($themeName,$colourSchemeName,$themeColours); - } - break; - } - } + $themeColours = array(); + foreach ($colourScheme as $k => $xmlColour) { + $themePos = array_search($k,$themeOrderArray); + if ($themePos === false) { + $themePos = $themeOrderAdditional++; + } + if (isset($xmlColour->sysClr)) { + $xmlColourData = $xmlColour->sysClr->attributes(); + $themeColours[$themePos] = $xmlColourData['lastClr']; + } elseif (isset($xmlColour->srgbClr)) { + $xmlColourData = $xmlColour->srgbClr->attributes(); + $themeColours[$themePos] = $xmlColourData['val']; + } + } + self::$_theme = new PHPExcel_Reader_Excel2007_Theme($themeName,$colourSchemeName,$themeColours); + } + break; + } + } - $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($rels->Relationship as $rel) { - switch ($rel["Type"]) { - case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": - $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if (is_object($xmlCore)) { - $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); - $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); - $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); - $docProps = $excel->getProperties(); - $docProps->setCreator((string) self::array_item($xmlCore->xpath("dc:creator"))); - $docProps->setLastModifiedBy((string) self::array_item($xmlCore->xpath("cp:lastModifiedBy"))); - $docProps->setCreated(strtotime(self::array_item($xmlCore->xpath("dcterms:created")))); //! respect xsi:type - $docProps->setModified(strtotime(self::array_item($xmlCore->xpath("dcterms:modified")))); //! respect xsi:type - $docProps->setTitle((string) self::array_item($xmlCore->xpath("dc:title"))); - $docProps->setDescription((string) self::array_item($xmlCore->xpath("dc:description"))); - $docProps->setSubject((string) self::array_item($xmlCore->xpath("dc:subject"))); - $docProps->setKeywords((string) self::array_item($xmlCore->xpath("cp:keywords"))); - $docProps->setCategory((string) self::array_item($xmlCore->xpath("cp:category"))); - } - break; + $rels = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": + $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if (is_object($xmlCore)) { + $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); + $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); + $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + $docProps = $excel->getProperties(); + $docProps->setCreator((string) self::array_item($xmlCore->xpath("dc:creator"))); + $docProps->setLastModifiedBy((string) self::array_item($xmlCore->xpath("cp:lastModifiedBy"))); + $docProps->setCreated(strtotime(self::array_item($xmlCore->xpath("dcterms:created")))); //! respect xsi:type + $docProps->setModified(strtotime(self::array_item($xmlCore->xpath("dcterms:modified")))); //! respect xsi:type + $docProps->setTitle((string) self::array_item($xmlCore->xpath("dc:title"))); + $docProps->setDescription((string) self::array_item($xmlCore->xpath("dc:description"))); + $docProps->setSubject((string) self::array_item($xmlCore->xpath("dc:subject"))); + $docProps->setKeywords((string) self::array_item($xmlCore->xpath("cp:keywords"))); + $docProps->setCategory((string) self::array_item($xmlCore->xpath("cp:category"))); + } + break; - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": - $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if (is_object($xmlCore)) { - $docProps = $excel->getProperties(); - if (isset($xmlCore->Company)) - $docProps->setCompany((string) $xmlCore->Company); - if (isset($xmlCore->Manager)) - $docProps->setManager((string) $xmlCore->Manager); - } - break; + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": + $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if (is_object($xmlCore)) { + $docProps = $excel->getProperties(); + if (isset($xmlCore->Company)) + $docProps->setCompany((string) $xmlCore->Company); + if (isset($xmlCore->Manager)) + $docProps->setManager((string) $xmlCore->Manager); + } + break; - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": - $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if (is_object($xmlCore)) { - $docProps = $excel->getProperties(); - foreach ($xmlCore as $xmlProperty) { - $cellDataOfficeAttributes = $xmlProperty->attributes(); - if (isset($cellDataOfficeAttributes['name'])) { - $propertyName = (string) $cellDataOfficeAttributes['name']; - $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); - $attributeType = $cellDataOfficeChildren->getName(); - $attributeValue = (string) $cellDataOfficeChildren->{$attributeType}; - $attributeValue = PHPExcel_DocumentProperties::convertProperty($attributeValue,$attributeType); - $attributeType = PHPExcel_DocumentProperties::convertPropertyType($attributeType); - $docProps->setCustomProperty($propertyName,$attributeValue,$attributeType); - } - } - } - break; - //Ribbon - case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility": - $customUI = $rel['Target']; - if(!is_null($customUI)){ - $this->_readRibbon($excel, $customUI, $zip); - } - break; - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": - $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": + $xmlCore = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if (is_object($xmlCore)) { + $docProps = $excel->getProperties(); + foreach ($xmlCore as $xmlProperty) { + $cellDataOfficeAttributes = $xmlProperty->attributes(); + if (isset($cellDataOfficeAttributes['name'])) { + $propertyName = (string) $cellDataOfficeAttributes['name']; + $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + $attributeType = $cellDataOfficeChildren->getName(); + $attributeValue = (string) $cellDataOfficeChildren->{$attributeType}; + $attributeValue = PHPExcel_DocumentProperties::convertProperty($attributeValue,$attributeType); + $attributeType = PHPExcel_DocumentProperties::convertPropertyType($attributeType); + $docProps->setCustomProperty($propertyName,$attributeValue,$attributeType); + } + } + } + break; + //Ribbon + case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility": + $customUI = $rel['Target']; + if(!is_null($customUI)){ + $this->_readRibbon($excel, $customUI, $zip); + } + break; + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $dir = dirname($rel["Target"]); + $relsWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); - $sharedStrings = array(); - $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); - $xmlStrings = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if (isset($xmlStrings) && isset($xmlStrings->si)) { - foreach ($xmlStrings->si as $val) { - if (isset($val->t)) { - $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $val->t ); - } elseif (isset($val->r)) { - $sharedStrings[] = $this->_parseRichText($val); - } - } - } + $sharedStrings = array(); + $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); + $xmlStrings = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + if (isset($xmlStrings) && isset($xmlStrings->si)) { + foreach ($xmlStrings->si as $val) { + if (isset($val->t)) { + $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $val->t ); + } elseif (isset($val->r)) { + $sharedStrings[] = $this->_parseRichText($val); + } + } + } - $worksheets = array(); + $worksheets = array(); $macros = $customUI = NULL; - foreach ($relsWorkbook->Relationship as $ele) { - switch($ele['Type']){ - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet": - $worksheets[(string) $ele["Id"]] = $ele["Target"]; - break; - // a vbaProject ? (: some macros) - case "http://schemas.microsoft.com/office/2006/relationships/vbaProject": - $macros = $ele["Target"]; - break; - } - } + foreach ($relsWorkbook->Relationship as $ele) { + switch($ele['Type']){ + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet": + $worksheets[(string) $ele["Id"]] = $ele["Target"]; + break; + // a vbaProject ? (: some macros) + case "http://schemas.microsoft.com/office/2006/relationships/vbaProject": + $macros = $ele["Target"]; + break; + } + } - if(!is_null($macros)){ - $macrosCode = $this->_getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin - if($macrosCode !== false){ - $excel->setMacrosCode($macrosCode); - $excel->setHasMacros(true); - //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir - $Certificate = $this->_getFromZipArchive($zip, 'xl/vbaProjectSignature.bin'); - if($Certificate !== false) - $excel->setMacrosCertificate($Certificate); - } - } - $styles = array(); - $cellStyles = array(); - $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); - $xmlStyles = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - $numFmts = null; - if ($xmlStyles && $xmlStyles->numFmts[0]) { - $numFmts = $xmlStyles->numFmts[0]; - } - if (isset($numFmts) && ($numFmts !== NULL)) { - $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - } - if (!$this->_readDataOnly && $xmlStyles) { - foreach ($xmlStyles->cellXfs->xf as $xf) { - $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + if(!is_null($macros)){ + $macrosCode = $this->_getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin + if($macrosCode !== false){ + $excel->setMacrosCode($macrosCode); + $excel->setHasMacros(true); + //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir + $Certificate = $this->_getFromZipArchive($zip, 'xl/vbaProjectSignature.bin'); + if($Certificate !== false) + $excel->setMacrosCertificate($Certificate); + } + } + $styles = array(); + $cellStyles = array(); + $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); + $xmlStyles = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $numFmts = null; + if ($xmlStyles && $xmlStyles->numFmts[0]) { + $numFmts = $xmlStyles->numFmts[0]; + } + if (isset($numFmts) && ($numFmts !== NULL)) { + $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + } + if (!$this->_readDataOnly && $xmlStyles) { + foreach ($xmlStyles->cellXfs->xf as $xf) { + $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; - if ($xf["numFmtId"]) { - if (isset($numFmts)) { - $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); + if ($xf["numFmtId"]) { + if (isset($numFmts)) { + $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); - if (isset($tmpNumFmt["formatCode"])) { - $numFmt = (string) $tmpNumFmt["formatCode"]; - } - } + if (isset($tmpNumFmt["formatCode"])) { + $numFmt = (string) $tmpNumFmt["formatCode"]; + } + } - if ((int)$xf["numFmtId"] < 164) { - $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); - } - } + if ((int)$xf["numFmtId"] < 164) { + $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); + } + } $quotePrefix = false; - if (isset($xf["quotePrefix"])) { + if (isset($xf["quotePrefix"])) { $quotePrefix = (boolean) $xf["quotePrefix"]; } - //$numFmt = str_replace('mm', 'i', $numFmt); - //$numFmt = str_replace('h', 'H', $numFmt); + //$numFmt = str_replace('mm', 'i', $numFmt); + //$numFmt = str_replace('h', 'H', $numFmt); - $style = (object) array( - "numFmt" => $numFmt, - "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], - "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], - "border" => $xmlStyles->borders->border[intval($xf["borderId"])], - "alignment" => $xf->alignment, - "protection" => $xf->protection, - "quotePrefix" => $quotePrefix, - ); - $styles[] = $style; + $style = (object) array( + "numFmt" => $numFmt, + "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], + "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], + "border" => $xmlStyles->borders->border[intval($xf["borderId"])], + "alignment" => $xf->alignment, + "protection" => $xf->protection, + "quotePrefix" => $quotePrefix, + ); + $styles[] = $style; - // add style to cellXf collection - $objStyle = new PHPExcel_Style; - self::_readStyle($objStyle, $style); - $excel->addCellXf($objStyle); - } + // add style to cellXf collection + $objStyle = new PHPExcel_Style; + self::_readStyle($objStyle, $style); + $excel->addCellXf($objStyle); + } - foreach ($xmlStyles->cellStyleXfs->xf as $xf) { - $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; - if ($numFmts && $xf["numFmtId"]) { - $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); - if (isset($tmpNumFmt["formatCode"])) { - $numFmt = (string) $tmpNumFmt["formatCode"]; - } else if ((int)$xf["numFmtId"] < 165) { - $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); - } - } + foreach ($xmlStyles->cellStyleXfs->xf as $xf) { + $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + if ($numFmts && $xf["numFmtId"]) { + $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); + if (isset($tmpNumFmt["formatCode"])) { + $numFmt = (string) $tmpNumFmt["formatCode"]; + } else if ((int)$xf["numFmtId"] < 165) { + $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); + } + } - $cellStyle = (object) array( - "numFmt" => $numFmt, - "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], - "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], - "border" => $xmlStyles->borders->border[intval($xf["borderId"])], - "alignment" => $xf->alignment, - "protection" => $xf->protection, - "quotePrefix" => $quotePrefix, - ); - $cellStyles[] = $cellStyle; + $cellStyle = (object) array( + "numFmt" => $numFmt, + "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], + "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], + "border" => $xmlStyles->borders->border[intval($xf["borderId"])], + "alignment" => $xf->alignment, + "protection" => $xf->protection, + "quotePrefix" => $quotePrefix, + ); + $cellStyles[] = $cellStyle; - // add style to cellStyleXf collection - $objStyle = new PHPExcel_Style; - self::_readStyle($objStyle, $cellStyle); - $excel->addCellStyleXf($objStyle); - } - } + // add style to cellStyleXf collection + $objStyle = new PHPExcel_Style; + self::_readStyle($objStyle, $cellStyle); + $excel->addCellStyleXf($objStyle); + } + } - $dxfs = array(); - if (!$this->_readDataOnly && $xmlStyles) { - // Conditional Styles - if ($xmlStyles->dxfs) { - foreach ($xmlStyles->dxfs->dxf as $dxf) { - $style = new PHPExcel_Style(FALSE, TRUE); - self::_readStyle($style, $dxf); - $dxfs[] = $style; - } - } - // Cell Styles - if ($xmlStyles->cellStyles) { - foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { - if (intval($cellStyle['builtinId']) == 0) { - if (isset($cellStyles[intval($cellStyle['xfId'])])) { - // Set default style - $style = new PHPExcel_Style; - self::_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); + $dxfs = array(); + if (!$this->_readDataOnly && $xmlStyles) { + // Conditional Styles + if ($xmlStyles->dxfs) { + foreach ($xmlStyles->dxfs->dxf as $dxf) { + $style = new PHPExcel_Style(FALSE, TRUE); + self::_readStyle($style, $dxf); + $dxfs[] = $style; + } + } + // Cell Styles + if ($xmlStyles->cellStyles) { + foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { + if (intval($cellStyle['builtinId']) == 0) { + if (isset($cellStyles[intval($cellStyle['xfId'])])) { + // Set default style + $style = new PHPExcel_Style; + self::_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); - // normal style, currently not using it for anything - } - } - } - } - } + // normal style, currently not using it for anything + } + } + } + } + } - $xmlWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlWorkbook = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - // Set base date - if ($xmlWorkbook->workbookPr) { - PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); - if (isset($xmlWorkbook->workbookPr['date1904'])) { - if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) { - PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); - } - } - } + // Set base date + if ($xmlWorkbook->workbookPr) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); + if (isset($xmlWorkbook->workbookPr['date1904'])) { + if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); + } + } + } - $sheetId = 0; // keep track of new sheet id in final workbook - $oldSheetId = -1; // keep track of old sheet id in final workbook - $countSkippedSheets = 0; // keep track of number of skipped sheets - $mapSheetId = array(); // mapping of sheet ids from old to new + $sheetId = 0; // keep track of new sheet id in final workbook + $oldSheetId = -1; // keep track of old sheet id in final workbook + $countSkippedSheets = 0; // keep track of number of skipped sheets + $mapSheetId = array(); // mapping of sheet ids from old to new - $charts = $chartDetails = array(); + $charts = $chartDetails = array(); - if ($xmlWorkbook->sheets) { - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - ++$oldSheetId; + if ($xmlWorkbook->sheets) { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + ++$oldSheetId; - // Check if sheet should be skipped - if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { - ++$countSkippedSheets; - $mapSheetId[$oldSheetId] = null; - continue; - } + // Check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { + ++$countSkippedSheets; + $mapSheetId[$oldSheetId] = null; + continue; + } - // Map old sheet id in original workbook to new sheet id. - // They will differ if loadSheetsOnly() is being used - $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; + // Map old sheet id in original workbook to new sheet id. + // They will differ if loadSheetsOnly() is being used + $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; - // Load sheet - $docSheet = $excel->createSheet(); - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet - // references in formula cells... during the load, all formulae should be correct, - // and we're simply bringing the worksheet name in line with the formula, not the - // reverse - $docSheet->setTitle((string) $eleSheet["name"],false); - $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xmlSheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + // Load sheet + $docSheet = $excel->createSheet(); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet + // references in formula cells... during the load, all formulae should be correct, + // and we're simply bringing the worksheet name in line with the formula, not the + // reverse + $docSheet->setTitle((string) $eleSheet["name"],false); + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $xmlSheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - $sharedFormulas = array(); + $sharedFormulas = array(); - if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { - $docSheet->setSheetState( (string) $eleSheet["state"] ); - } + if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { + $docSheet->setSheetState( (string) $eleSheet["state"] ); + } - if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { - if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { - $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); - } + if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { + if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { + $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + } - if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { - $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); - } + if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { + $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + } - if (isset($xmlSheet->sheetViews->sheetView['view'])) { - $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']); - } + if (isset($xmlSheet->sheetViews->sheetView['view'])) { + $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']); + } - if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { - $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines'])); - } + if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { + $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines'])); + } - if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { - $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'])); - } + if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { + $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'])); + } - if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { - $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft'])); - } + if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { + $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft'])); + } - if (isset($xmlSheet->sheetViews->sheetView->pane)) { - if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { - $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); - } else { - $xSplit = 0; - $ySplit = 0; + if (isset($xmlSheet->sheetViews->sheetView->pane)) { + if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { + $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); + } else { + $xSplit = 0; + $ySplit = 0; - if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { - $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); - } + if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { + $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); + } - if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { - $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); - } + if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { + $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); + } - $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); - } - } + $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); + } + } - if (isset($xmlSheet->sheetViews->sheetView->selection)) { - if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { - $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; - $sqref = explode(' ', $sqref); - $sqref = $sqref[0]; - $docSheet->setSelectedCells($sqref); - } - } + if (isset($xmlSheet->sheetViews->sheetView->selection)) { + if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { + $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; + $sqref = explode(' ', $sqref); + $sqref = $sqref[0]; + $docSheet->setSelectedCells($sqref); + } + } - } + } - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { - if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { - $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); - } - } - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) { - $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']); - } - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { - if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && - !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) { - $docSheet->setShowSummaryRight(FALSE); - } else { - $docSheet->setShowSummaryRight(TRUE); - } + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { + if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { + $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); + } + } + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) { + $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']); + } + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { + if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) { + $docSheet->setShowSummaryRight(FALSE); + } else { + $docSheet->setShowSummaryRight(TRUE); + } - if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && - !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) { - $docSheet->setShowSummaryBelow(FALSE); - } else { - $docSheet->setShowSummaryBelow(TRUE); - } - } + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) { + $docSheet->setShowSummaryBelow(FALSE); + } else { + $docSheet->setShowSummaryBelow(TRUE); + } + } - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { - if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && - !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) { - $docSheet->getPageSetup()->setFitToPage(FALSE); - } else { - $docSheet->getPageSetup()->setFitToPage(TRUE); - } - } + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { + if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && + !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) { + $docSheet->getPageSetup()->setFitToPage(FALSE); + } else { + $docSheet->getPageSetup()->setFitToPage(TRUE); + } + } - if (isset($xmlSheet->sheetFormatPr)) { - if (isset($xmlSheet->sheetFormatPr['customHeight']) && - self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) && - isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { - $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); - } - if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { - $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); - } - if (isset($xmlSheet->sheetFormatPr['zeroHeight']) && - ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) { - $docSheet->getDefaultRowDimension()->setZeroHeight(true); - } - } + if (isset($xmlSheet->sheetFormatPr)) { + if (isset($xmlSheet->sheetFormatPr['customHeight']) && + self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) && + isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { + $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); + } + if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { + $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); + } + if (isset($xmlSheet->sheetFormatPr['zeroHeight']) && + ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) { + $docSheet->getDefaultRowDimension()->setZeroHeight(true); + } + } - if (isset($xmlSheet->cols) && !$this->_readDataOnly) { - foreach ($xmlSheet->cols->col as $col) { + if (isset($xmlSheet->cols) && !$this->_readDataOnly) { + foreach ($xmlSheet->cols->col as $col) { for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { - if ($col["style"] && !$this->_readDataOnly) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); - } - if (self::boolean($col["bestFit"])) { - //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(TRUE); - } - if (self::boolean($col["hidden"])) { + if ($col["style"] && !$this->_readDataOnly) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); + } + if (self::boolean($col["bestFit"])) { + //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(TRUE); + } + if (self::boolean($col["hidden"])) { // echo PHPExcel_Cell::stringFromColumnIndex($i),': HIDDEN COLUMN',PHP_EOL; - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(FALSE); - } - if (self::boolean($col["collapsed"])) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(TRUE); - } - if ($col["outlineLevel"] > 0) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); - } - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(FALSE); + } + if (self::boolean($col["collapsed"])) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(TRUE); + } + if ($col["outlineLevel"] > 0) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); + } + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); - if (intval($col["max"]) == 16384) { - break; - } - } - } - } + if (intval($col["max"]) == 16384) { + break; + } + } + } + } - if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { - if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) { - $docSheet->setShowGridlines(TRUE); - } + if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { + if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) { + $docSheet->setShowGridlines(TRUE); + } - if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) { - $docSheet->setPrintGridlines(TRUE); - } + if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) { + $docSheet->setPrintGridlines(TRUE); + } - if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) { - $docSheet->getPageSetup()->setHorizontalCentered(TRUE); - } - if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) { - $docSheet->getPageSetup()->setVerticalCentered(TRUE); - } - } + if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) { + $docSheet->getPageSetup()->setHorizontalCentered(TRUE); + } + if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) { + $docSheet->getPageSetup()->setVerticalCentered(TRUE); + } + } - if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { - foreach ($xmlSheet->sheetData->row as $row) { - if ($row["ht"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); - } - if (self::boolean($row["hidden"]) && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setVisible(FALSE); - } - if (self::boolean($row["collapsed"])) { - $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(TRUE); - } - if ($row["outlineLevel"] > 0) { - $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); - } - if ($row["s"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); - } + if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { + foreach ($xmlSheet->sheetData->row as $row) { + if ($row["ht"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); + } + if (self::boolean($row["hidden"]) && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setVisible(FALSE); + } + if (self::boolean($row["collapsed"])) { + $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(TRUE); + } + if ($row["outlineLevel"] > 0) { + $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); + } + if ($row["s"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); + } - foreach ($row->c as $c) { - $r = (string) $c["r"]; - $cellDataType = (string) $c["t"]; - $value = null; - $calculatedValue = null; + foreach ($row->c as $c) { + $r = (string) $c["r"]; + $cellDataType = (string) $c["t"]; + $value = null; + $calculatedValue = null; - // Read cell? - if ($this->getReadFilter() !== NULL) { - $coordinates = PHPExcel_Cell::coordinateFromString($r); + // Read cell? + if ($this->getReadFilter() !== NULL) { + $coordinates = PHPExcel_Cell::coordinateFromString($r); - if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { - continue; - } - } + if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { + continue; + } + } - // echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL; - // print_r($c); - // echo PHP_EOL; - // echo 'Cell Data Type is ', $cellDataType, ': '; - // - // Read cell! - switch ($cellDataType) { - case "s": - // echo 'String', PHP_EOL; - if ((string)$c->v != '') { - $value = $sharedStrings[intval($c->v)]; + // echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL; + // print_r($c); + // echo PHP_EOL; + // echo 'Cell Data Type is ', $cellDataType, ': '; + // + // Read cell! + switch ($cellDataType) { + case "s": + // echo 'String', PHP_EOL; + if ((string)$c->v != '') { + $value = $sharedStrings[intval($c->v)]; - if ($value instanceof PHPExcel_RichText) { - $value = clone $value; - } - } else { - $value = ''; - } + if ($value instanceof PHPExcel_RichText) { + $value = clone $value; + } + } else { + $value = ''; + } - break; - case "b": - // echo 'Boolean', PHP_EOL; - if (!isset($c->f)) { - $value = self::_castToBool($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); - if (isset($c->f['t'])) { - $att = array(); - $att = $c->f; - $docSheet->getCell($r)->setFormulaAttributes($att); - } - // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; - } - break; - case "inlineStr": - // echo 'Inline String', PHP_EOL; - $value = $this->_parseRichText($c->is); + break; + case "b": + // echo 'Boolean', PHP_EOL; + if (!isset($c->f)) { + $value = self::_castToBool($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); + if (isset($c->f['t'])) { + $att = array(); + $att = $c->f; + $docSheet->getCell($r)->setFormulaAttributes($att); + } + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; + } + break; + case "inlineStr": + // echo 'Inline String', PHP_EOL; + $value = $this->_parseRichText($c->is); - break; - case "e": - // echo 'Error', PHP_EOL; - if (!isset($c->f)) { - $value = self::_castToError($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); - // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; - } + break; + case "e": + // echo 'Error', PHP_EOL; + if (!isset($c->f)) { + $value = self::_castToError($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; + } - break; + break; - default: - // echo 'Default', PHP_EOL; - if (!isset($c->f)) { - // echo 'Not a Formula', PHP_EOL; - $value = self::_castToString($c); - } else { - // echo 'Treat as Formula', PHP_EOL; - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); - // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; - } + default: + // echo 'Default', PHP_EOL; + if (!isset($c->f)) { + // echo 'Not a Formula', PHP_EOL; + $value = self::_castToString($c); + } else { + // echo 'Treat as Formula', PHP_EOL; + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; + } - break; - } - // echo 'Value is ', $value, PHP_EOL; + break; + } + // echo 'Value is ', $value, PHP_EOL; - // Check for numeric values - if (is_numeric($value) && $cellDataType != 's') { - if ($value == (int)$value) $value = (int)$value; - elseif ($value == (float)$value) $value = (float)$value; - elseif ($value == (double)$value) $value = (double)$value; - } + // Check for numeric values + if (is_numeric($value) && $cellDataType != 's') { + if ($value == (int)$value) $value = (int)$value; + elseif ($value == (float)$value) $value = (float)$value; + elseif ($value == (double)$value) $value = (double)$value; + } - // Rich text? - if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { - $value = $value->getPlainText(); - } + // Rich text? + if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { + $value = $value->getPlainText(); + } - $cell = $docSheet->getCell($r); - // Assign value - if ($cellDataType != '') { - $cell->setValueExplicit($value, $cellDataType); - } else { - $cell->setValue($value); - } - if ($calculatedValue !== NULL) { - $cell->setCalculatedValue($calculatedValue); - } + $cell = $docSheet->getCell($r); + // Assign value + if ($cellDataType != '') { + $cell->setValueExplicit($value, $cellDataType); + } else { + $cell->setValue($value); + } + if ($calculatedValue !== NULL) { + $cell->setCalculatedValue($calculatedValue); + } - // Style information? - if ($c["s"] && !$this->_readDataOnly) { - // no style index means 0, it seems - $cell->setXfIndex(isset($styles[intval($c["s"])]) ? - intval($c["s"]) : 0); - } - } - } - } + // Style information? + if ($c["s"] && !$this->_readDataOnly) { + // no style index means 0, it seems + $cell->setXfIndex(isset($styles[intval($c["s"])]) ? + intval($c["s"]) : 0); + } + } + } + } - $conditionals = array(); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { - foreach ($xmlSheet->conditionalFormatting as $conditional) { - foreach ($conditional->cfRule as $cfRule) { - if ( - ( - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION - ) && isset($dxfs[intval($cfRule["dxfId"])]) - ) { - $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; - } - } - } + $conditionals = array(); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { + foreach ($xmlSheet->conditionalFormatting as $conditional) { + foreach ($conditional->cfRule as $cfRule) { + if ( + ( + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + ) && isset($dxfs[intval($cfRule["dxfId"])]) + ) { + $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; + } + } + } - foreach ($conditionals as $ref => $cfRules) { - ksort($cfRules); - $conditionalStyles = array(); - foreach ($cfRules as $cfRule) { - $objConditional = new PHPExcel_Style_Conditional(); - $objConditional->setConditionType((string)$cfRule["type"]); - $objConditional->setOperatorType((string)$cfRule["operator"]); + foreach ($conditionals as $ref => $cfRules) { + ksort($cfRules); + $conditionalStyles = array(); + foreach ($cfRules as $cfRule) { + $objConditional = new PHPExcel_Style_Conditional(); + $objConditional->setConditionType((string)$cfRule["type"]); + $objConditional->setOperatorType((string)$cfRule["operator"]); - if ((string)$cfRule["text"] != '') { - $objConditional->setText((string)$cfRule["text"]); - } + if ((string)$cfRule["text"] != '') { + $objConditional->setText((string)$cfRule["text"]); + } - if (count($cfRule->formula) > 1) { - foreach ($cfRule->formula as $formula) { - $objConditional->addCondition((string)$formula); - } - } else { - $objConditional->addCondition((string)$cfRule->formula); - } - $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); - $conditionalStyles[] = $objConditional; - } + if (count($cfRule->formula) > 1) { + foreach ($cfRule->formula as $formula) { + $objConditional->addCondition((string)$formula); + } + } else { + $objConditional->addCondition((string)$cfRule->formula); + } + $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); + $conditionalStyles[] = $objConditional; + } - // Extract all cell references in $ref - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); - foreach ($aReferences as $reference) { - $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); - } - } - } + // Extract all cell references in $ref + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); + foreach ($aReferences as $reference) { + $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); + } + } + } - $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - foreach ($aKeys as $key) { - $method = "set" . ucfirst($key); - $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key])); - } - } + $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + foreach ($aKeys as $key) { + $method = "set" . ucfirst($key); + $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key])); + } + } - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], TRUE); - if ($xmlSheet->protectedRanges->protectedRange) { - foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { - $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); - } - } - } + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], TRUE); + if ($xmlSheet->protectedRanges->protectedRange) { + foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { + $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); + } + } + } - if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { + if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { $autoFilterRange = (string) $xmlSheet->autoFilter["ref"]; if (strpos($autoFilterRange, ':') !== false) { $autoFilter = $docSheet->getAutoFilter(); @@ -1013,30 +1013,30 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) { $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]); - // Check for standard filters + // Check for standard filters if ($filterColumn->filters) { $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER); $filters = $filterColumn->filters; if ((isset($filters["blank"])) && ($filters["blank"] == 1)) { $column->createRule()->setRule( - NULL, // Operator is undefined, but always treated as EQUAL + NULL, // Operator is undefined, but always treated as EQUAL '' ) ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); } - // Standard filters are always an OR join, so no join rule needs to be set - // Entries can be either filter elements + // Standard filters are always an OR join, so no join rule needs to be set + // Entries can be either filter elements foreach ($filters->filter as $filterRule) { $column->createRule()->setRule( - NULL, // Operator is undefined, but always treated as EQUAL + NULL, // Operator is undefined, but always treated as EQUAL (string) $filterRule["val"] ) ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); } - // Or Date Group elements + // Or Date Group elements foreach ($filters->dateGroupItem as $dateGroupItem) { $column->createRule()->setRule( - NULL, // Operator is undefined, but always treated as EQUAL + NULL, // Operator is undefined, but always treated as EQUAL array( 'year' => (string) $dateGroupItem["year"], 'month' => (string) $dateGroupItem["month"], @@ -1050,12 +1050,12 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP); } } - // Check for custom filters + // Check for custom filters if ($filterColumn->customFilters) { $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); $customFilters = $filterColumn->customFilters; - // Custom filters can an AND or an OR join; - // and there should only ever be one or two entries + // Custom filters can an AND or an OR join; + // and there should only ever be one or two entries if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) { $column->setJoin(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND); } @@ -1067,13 +1067,13 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); } } - // Check for dynamic filters + // Check for dynamic filters if ($filterColumn->dynamicFilter) { $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); - // We should only ever have one dynamic filter + // We should only ever have one dynamic filter foreach ($filterColumn->dynamicFilter as $filterRule) { $column->createRule()->setRule( - NULL, // Operator is undefined, but always treated as EQUAL + NULL, // Operator is undefined, but always treated as EQUAL (string) $filterRule["val"], (string) $filterRule["type"] ) @@ -1086,10 +1086,10 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE } } } - // Check for dynamic filters + // Check for dynamic filters if ($filterColumn->top10) { $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER); - // We should only ever have one top10 filter + // We should only ever have one top10 filter foreach ($filterColumn->top10 as $filterRule) { $column->createRule()->setRule( (((isset($filterRule["percent"])) && ($filterRule["percent"] == 1)) @@ -1106,478 +1106,478 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE } } } - } - } + } + } - if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { - foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { - $mergeRef = (string) $mergeCell["ref"]; - if (strpos($mergeRef,':') !== FALSE) { - $docSheet->mergeCells((string) $mergeCell["ref"]); - } - } - } + if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { + foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { + $mergeRef = (string) $mergeCell["ref"]; + if (strpos($mergeRef,':') !== FALSE) { + $docSheet->mergeCells((string) $mergeCell["ref"]); + } + } + } - if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { - $docPageMargins = $docSheet->getPageMargins(); - $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); - $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); - $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); - $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); - $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); - $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); - } + if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { + $docPageMargins = $docSheet->getPageMargins(); + $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); + $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); + $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); + $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); + $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); + $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); + } - if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { - $docPageSetup = $docSheet->getPageSetup(); + if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { + $docPageSetup = $docSheet->getPageSetup(); - if (isset($xmlSheet->pageSetup["orientation"])) { - $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); - } - if (isset($xmlSheet->pageSetup["paperSize"])) { - $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); - } - if (isset($xmlSheet->pageSetup["scale"])) { - $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), FALSE); - } - if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { - $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), FALSE); - } - if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { - $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), FALSE); - } - if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && - self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) { - $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); - } - } + if (isset($xmlSheet->pageSetup["orientation"])) { + $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); + } + if (isset($xmlSheet->pageSetup["paperSize"])) { + $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); + } + if (isset($xmlSheet->pageSetup["scale"])) { + $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), FALSE); + } + if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { + $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), FALSE); + } + if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { + $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), FALSE); + } + if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && + self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) { + $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); + } + } - if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { - $docHeaderFooter = $docSheet->getHeaderFooter(); + if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { + $docHeaderFooter = $docSheet->getHeaderFooter(); - if (isset($xmlSheet->headerFooter["differentOddEven"]) && - self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) { - $docHeaderFooter->setDifferentOddEven(TRUE); - } else { - $docHeaderFooter->setDifferentOddEven(FALSE); - } - if (isset($xmlSheet->headerFooter["differentFirst"]) && - self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) { - $docHeaderFooter->setDifferentFirst(TRUE); - } else { - $docHeaderFooter->setDifferentFirst(FALSE); - } - if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && - !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) { - $docHeaderFooter->setScaleWithDocument(FALSE); - } else { - $docHeaderFooter->setScaleWithDocument(TRUE); - } - if (isset($xmlSheet->headerFooter["alignWithMargins"]) && - !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) { - $docHeaderFooter->setAlignWithMargins(FALSE); - } else { - $docHeaderFooter->setAlignWithMargins(TRUE); - } + if (isset($xmlSheet->headerFooter["differentOddEven"]) && + self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) { + $docHeaderFooter->setDifferentOddEven(TRUE); + } else { + $docHeaderFooter->setDifferentOddEven(FALSE); + } + if (isset($xmlSheet->headerFooter["differentFirst"]) && + self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) { + $docHeaderFooter->setDifferentFirst(TRUE); + } else { + $docHeaderFooter->setDifferentFirst(FALSE); + } + if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && + !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) { + $docHeaderFooter->setScaleWithDocument(FALSE); + } else { + $docHeaderFooter->setScaleWithDocument(TRUE); + } + if (isset($xmlSheet->headerFooter["alignWithMargins"]) && + !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) { + $docHeaderFooter->setAlignWithMargins(FALSE); + } else { + $docHeaderFooter->setAlignWithMargins(TRUE); + } - $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); - $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); - $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); - $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); - $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); - $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); - } + $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); + $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); + $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); + $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); + $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); + $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); + } - if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->rowBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); - } - } - } - if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->colBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex((string) $brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); - } - } - } + if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->rowBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); + } + } + } + if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->colBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex((string) $brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } - if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { - foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { - // Uppercase coordinate - $range = strtoupper($dataValidation["sqref"]); - $rangeSet = explode(' ',$range); - foreach($rangeSet as $range) { - $stRange = $docSheet->shrinkRangeToFit($range); + if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { + foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { + // Uppercase coordinate + $range = strtoupper($dataValidation["sqref"]); + $rangeSet = explode(' ',$range); + foreach($rangeSet as $range) { + $stRange = $docSheet->shrinkRangeToFit($range); - // Extract all cell references in $range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); - foreach ($aReferences as $reference) { - // Create validation - $docValidation = $docSheet->getCell($reference)->getDataValidation(); - $docValidation->setType((string) $dataValidation["type"]); - $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); - $docValidation->setOperator((string) $dataValidation["operator"]); - $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); - $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); - $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); - $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); - $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); - $docValidation->setError((string) $dataValidation["error"]); - $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); - $docValidation->setPrompt((string) $dataValidation["prompt"]); - $docValidation->setFormula1((string) $dataValidation->formula1); - $docValidation->setFormula2((string) $dataValidation->formula2); - } - } - } - } + // Extract all cell references in $range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($aReferences as $reference) { + // Create validation + $docValidation = $docSheet->getCell($reference)->getDataValidation(); + $docValidation->setType((string) $dataValidation["type"]); + $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); + $docValidation->setOperator((string) $dataValidation["operator"]); + $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); + $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); + $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); + $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); + $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); + $docValidation->setError((string) $dataValidation["error"]); + $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); + $docValidation->setPrompt((string) $dataValidation["prompt"]); + $docValidation->setFormula1((string) $dataValidation->formula1); + $docValidation->setFormula2((string) $dataValidation->formula2); + } + } + } + } - // Add hyperlinks - $hyperlinks = array(); - if (!$this->_readDataOnly) { - // Locate hyperlink relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { - $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } + // Add hyperlinks + $hyperlinks = array(); + if (!$this->_readDataOnly) { + // Locate hyperlink relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { + $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } - // Loop through hyperlinks - if ($xmlSheet && $xmlSheet->hyperlinks) { - foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { - // Link url - $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + // Loop through hyperlinks + if ($xmlSheet && $xmlSheet->hyperlinks) { + foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { + // Link url + $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { - $cell = $docSheet->getCell( $cellReference ); - if (isset($linkRel['id'])) { - $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ]; - if (isset($hyperlink['location'])) { - $hyperlinkUrl .= '#' . (string) $hyperlink['location']; - } - $cell->getHyperlink()->setUrl($hyperlinkUrl); - } elseif (isset($hyperlink['location'])) { - $cell->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); - } + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { + $cell = $docSheet->getCell( $cellReference ); + if (isset($linkRel['id'])) { + $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ]; + if (isset($hyperlink['location'])) { + $hyperlinkUrl .= '#' . (string) $hyperlink['location']; + } + $cell->getHyperlink()->setUrl($hyperlinkUrl); + } elseif (isset($hyperlink['location'])) { + $cell->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); + } - // Tooltip - if (isset($hyperlink['tooltip'])) { - $cell->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); - } - } - } - } - } + // Tooltip + if (isset($hyperlink['tooltip'])) { + $cell->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); + } + } + } + } + } - // Add comments - $comments = array(); - $vmlComments = array(); - if (!$this->_readDataOnly) { - // Locate comment relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { - $comments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } + // Add comments + $comments = array(); + $vmlComments = array(); + if (!$this->_readDataOnly) { + // Locate comment relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { + $comments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } - // Loop through comments - foreach ($comments as $relName => $relPath) { - // Load comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $commentsFile = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + // Loop through comments + foreach ($comments as $relName => $relPath) { + // Load comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $commentsFile = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - // Utility variables - $authors = array(); + // Utility variables + $authors = array(); - // Loop through authors - foreach ($commentsFile->authors->author as $author) { - $authors[] = (string)$author; - } + // Loop through authors + foreach ($commentsFile->authors->author as $author) { + $authors[] = (string)$author; + } - // Loop through contents - foreach ($commentsFile->commentList->comment as $comment) { - if(!empty($comment['authorId'])) - $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); - $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); - } - } + // Loop through contents + foreach ($commentsFile->commentList->comment as $comment) { + if(!empty($comment['authorId'])) + $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); + $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); + } + } - // Loop through VML comments - foreach ($vmlComments as $relName => $relPath) { - // Load VML comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $vmlCommentsFile = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + // Loop through VML comments + foreach ($vmlComments as $relName => $relPath) { + // Load VML comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $vmlCommentsFile = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - $shapes = $vmlCommentsFile->xpath('//v:shape'); - foreach ($shapes as $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + $shapes = $vmlCommentsFile->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - if (isset($shape['style'])) { - $style = (string)$shape['style']; - $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); - $column = null; - $row = null; + if (isset($shape['style'])) { + $style = (string)$shape['style']; + $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); + $column = null; + $row = null; - $clientData = $shape->xpath('.//x:ClientData'); - if (is_array($clientData) && !empty($clientData)) { - $clientData = $clientData[0]; + $clientData = $shape->xpath('.//x:ClientData'); + if (is_array($clientData) && !empty($clientData)) { + $clientData = $clientData[0]; - if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { - $temp = $clientData->xpath('.//x:Row'); - if (is_array($temp)) $row = $temp[0]; + if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { + $temp = $clientData->xpath('.//x:Row'); + if (is_array($temp)) $row = $temp[0]; - $temp = $clientData->xpath('.//x:Column'); - if (is_array($temp)) $column = $temp[0]; - } - } + $temp = $clientData->xpath('.//x:Column'); + if (is_array($temp)) $column = $temp[0]; + } + } - if (($column !== NULL) && ($row !== NULL)) { - // Set comment properties - $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1); - $comment->getFillColor()->setRGB( $fillColor ); + if (($column !== NULL) && ($row !== NULL)) { + // Set comment properties + $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1); + $comment->getFillColor()->setRGB( $fillColor ); - // Parse style - $styleArray = explode(';', str_replace(' ', '', $style)); - foreach ($styleArray as $stylePair) { - $stylePair = explode(':', $stylePair); + // Parse style + $styleArray = explode(';', str_replace(' ', '', $style)); + foreach ($styleArray as $stylePair) { + $stylePair = explode(':', $stylePair); - if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); - if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); - if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); - if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); - if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); + if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); + if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); + if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); + if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); + if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); - } - } - } - } - } + } + } + } + } + } - // Header/footer images - if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $vmlRelationship = ''; + // Header/footer images + if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $vmlRelationship = ''; - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } - if ($vmlRelationship != '') { - // Fetch linked images - $relsVML = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsVML->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); - } - } + if ($vmlRelationship != '') { + // Fetch linked images + $relsVML = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsVML->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); + } + } - // Fetch VML document - $vmlDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $vmlRelationship)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + // Fetch VML document + $vmlDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $vmlRelationship)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - $hfImages = array(); + $hfImages = array(); - $shapes = $vmlDrawing->xpath('//v:shape'); - foreach ($shapes as $idx => $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - $imageData = $shape->xpath('//v:imagedata'); - $imageData = $imageData[$idx]; + $shapes = $vmlDrawing->xpath('//v:shape'); + foreach ($shapes as $idx => $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + $imageData = $shape->xpath('//v:imagedata'); + $imageData = $imageData[$idx]; - $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); - $style = self::toCSSArray( (string)$shape['style'] ); + $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); + $style = self::toCSSArray( (string)$shape['style'] ); - $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); - if (isset($imageData['title'])) { - $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); - } + $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); + if (isset($imageData['title'])) { + $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); + } - $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); - $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); - $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); - if (isset($style['margin-left'])) { - $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); - } - $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); - } + $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); + $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); + $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); + if (isset($style['margin-left'])) { + $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + } + $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); + } - $docSheet->getHeaderFooter()->setImages($hfImages); - } - } - } + $docSheet->getHeaderFooter()->setImages($hfImages); + } + } + } - } + } // TODO: Autoshapes from twoCellAnchors! - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { - $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } - if ($xmlSheet->drawing && !$this->_readDataOnly) { - foreach ($xmlSheet->drawing as $drawing) { - $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $relsDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $images = array(); + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { + $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + if ($xmlSheet->drawing && !$this->_readDataOnly) { + foreach ($xmlSheet->drawing as $drawing) { + $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $relsDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $images = array(); - if ($relsDrawing && $relsDrawing->Relationship) { - foreach ($relsDrawing->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); - } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") { - if ($this->_includeCharts) { - $charts[self::dir_add($fileDrawing, $ele["Target"])] = array('id' => (string) $ele["Id"], - 'sheet' => $docSheet->getTitle() - ); - } - } - } - } - $xmlDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $fileDrawing)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); + if ($relsDrawing && $relsDrawing->Relationship) { + foreach ($relsDrawing->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); + } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") { + if ($this->_includeCharts) { + $charts[self::dir_add($fileDrawing, $ele["Target"])] = array('id' => (string) $ele["Id"], + 'sheet' => $docSheet->getTitle() + ); + } + } + } + } + $xmlDrawing = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $fileDrawing)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); - if ($xmlDrawing->oneCellAnchor) { - foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { - if ($oneCellAnchor->pic->blipFill) { - $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); - if ($xfrm) { - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } else { - // ? Can charts be positioned with a oneCellAnchor ? - $coordinates = PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1); - $offsetX = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff); - $offsetY = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff); - $width = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx")); - $height = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy")); - } - } - } - if ($xmlDrawing->twoCellAnchor) { - foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { - if ($twoCellAnchor->pic->blipFill) { - $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); + if ($xmlDrawing->oneCellAnchor) { + foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { + if ($oneCellAnchor->pic->blipFill) { + $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } else { + // ? Can charts be positioned with a oneCellAnchor ? + $coordinates = PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1); + $offsetX = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff); + $offsetY = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff); + $width = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx")); + $height = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy")); + } + } + } + if ($xmlDrawing->twoCellAnchor) { + foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { + if ($twoCellAnchor->pic->blipFill) { + $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); - if ($xfrm) { - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } elseif(($this->_includeCharts) && ($twoCellAnchor->graphicFrame)) { - $fromCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1); - $fromOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff); - $fromOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff); - $toCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1); - $toOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->colOff); - $toOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->rowOff); - $graphic = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic; - $chartRef = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart; - $thisChart = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + if ($xfrm) { + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } elseif(($this->_includeCharts) && ($twoCellAnchor->graphicFrame)) { + $fromCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1); + $fromOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff); + $fromOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff); + $toCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1); + $toOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->colOff); + $toOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->rowOff); + $graphic = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic; + $chartRef = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart; + $thisChart = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - $chartDetails[$docSheet->getTitle().'!'.$thisChart] = - array( 'fromCoordinate' => $fromCoordinate, - 'fromOffsetX' => $fromOffsetX, - 'fromOffsetY' => $fromOffsetY, - 'toCoordinate' => $toCoordinate, - 'toOffsetX' => $toOffsetX, - 'toOffsetY' => $toOffsetY, - 'worksheetTitle' => $docSheet->getTitle() - ); - } - } - } + $chartDetails[$docSheet->getTitle().'!'.$thisChart] = + array( 'fromCoordinate' => $fromCoordinate, + 'fromOffsetX' => $fromOffsetX, + 'fromOffsetY' => $fromOffsetY, + 'toCoordinate' => $toCoordinate, + 'toOffsetX' => $toOffsetX, + 'toOffsetY' => $toOffsetY, + 'worksheetTitle' => $docSheet->getTitle() + ); + } + } + } - } - } - } + } + } + } - // Loop through definedNames - if ($xmlWorkbook->definedNames) { - foreach ($xmlWorkbook->definedNames->definedName as $definedName) { - // Extract range - $extractedRange = (string)$definedName; - $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); - if (($spos = strpos($extractedRange,'!')) !== false) { - $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); - } else { - $extractedRange = str_replace('$', '', $extractedRange); - } + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + if (($spos = strpos($extractedRange,'!')) !== false) { + $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); + } else { + $extractedRange = str_replace('$', '', $extractedRange); + } - // Valid range? - if (stripos((string)$definedName, '#REF!') !== FALSE || $extractedRange == '') { - continue; - } + // Valid range? + if (stripos((string)$definedName, '#REF!') !== FALSE || $extractedRange == '') { + continue; + } - // Some definedNames are only applicable if we are on the same sheet... - if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { - // Switch on type - switch ((string)$definedName['name']) { + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { + // Switch on type + switch ((string)$definedName['name']) { - case '_xlnm._FilterDatabase': - if ((string)$definedName['hidden'] !== '1') { + case '_xlnm._FilterDatabase': + if ((string)$definedName['hidden'] !== '1') { $extractedRange = explode(',', $extractedRange); foreach ($extractedRange as $range) { $autoFilterRange = $range; @@ -1585,499 +1585,499 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE $docSheet->getAutoFilter()->setRange($autoFilterRange); } } - } - break; + } + break; - case '_xlnm.Print_Titles': - // Split $extractedRange - $extractedRange = explode(',', $extractedRange); + case '_xlnm.Print_Titles': + // Split $extractedRange + $extractedRange = explode(',', $extractedRange); - // Set print titles - foreach ($extractedRange as $range) { - $matches = array(); - $range = str_replace('$', '', $range); + // Set print titles + foreach ($extractedRange as $range) { + $matches = array(); + $range = str_replace('$', '', $range); - // check for repeating columns, e g. 'A:A' or 'A:D' - if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { - $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); - } - // check for repeating rows, e.g. '1:1' or '1:5' - elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) { - $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); - } - } - break; + // check for repeating columns, e g. 'A:A' or 'A:D' + if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); + } + // check for repeating rows, e.g. '1:1' or '1:5' + elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); + } + } + break; - case '_xlnm.Print_Area': - $rangeSets = explode(',', $extractedRange); // FIXME: what if sheetname contains comma? - $newRangeSets = array(); - foreach($rangeSets as $rangeSet) { - $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark? - $rangeSet = isset($range[1]) ? $range[1] : $range[0]; - if (strpos($rangeSet, ':') === FALSE) { - $rangeSet = $rangeSet . ':' . $rangeSet; - } - $newRangeSets[] = str_replace('$', '', $rangeSet); - } - $docSheet->getPageSetup()->setPrintArea(implode(',',$newRangeSets)); - break; + case '_xlnm.Print_Area': + $rangeSets = explode(',', $extractedRange); // FIXME: what if sheetname contains comma? + $newRangeSets = array(); + foreach($rangeSets as $rangeSet) { + $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark? + $rangeSet = isset($range[1]) ? $range[1] : $range[0]; + if (strpos($rangeSet, ':') === FALSE) { + $rangeSet = $rangeSet . ':' . $rangeSet; + } + $newRangeSets[] = str_replace('$', '', $rangeSet); + } + $docSheet->getPageSetup()->setPrintArea(implode(',',$newRangeSets)); + break; - default: - break; - } - } - } - } + default: + break; + } + } + } + } - // Next sheet id - ++$sheetId; - } + // Next sheet id + ++$sheetId; + } - // Loop through definedNames - if ($xmlWorkbook->definedNames) { - foreach ($xmlWorkbook->definedNames->definedName as $definedName) { - // Extract range - $extractedRange = (string)$definedName; - $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); - if (($spos = strpos($extractedRange,'!')) !== false) { - $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); - } else { - $extractedRange = str_replace('$', '', $extractedRange); - } + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + if (($spos = strpos($extractedRange,'!')) !== false) { + $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); + } else { + $extractedRange = str_replace('$', '', $extractedRange); + } - // Valid range? - if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { - continue; - } + // Valid range? + if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { + continue; + } - // Some definedNames are only applicable if we are on the same sheet... - if ((string)$definedName['localSheetId'] != '') { - // Local defined name - // Switch on type - switch ((string)$definedName['name']) { + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '') { + // Local defined name + // Switch on type + switch ((string)$definedName['name']) { - case '_xlnm._FilterDatabase': - case '_xlnm.Print_Titles': - case '_xlnm.Print_Area': - break; + case '_xlnm._FilterDatabase': + case '_xlnm.Print_Titles': + case '_xlnm.Print_Area': + break; - default: - if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { - $range = explode('!', (string)$definedName); - if (count($range) == 2) { - $range[0] = str_replace("''", "'", $range[0]); - $range[0] = str_replace("'", "", $range[0]); - if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { - $extractedRange = str_replace('$', '', $range[1]); - $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); - } - } - } - break; - } - } else if (!isset($definedName['localSheetId'])) { - // "Global" definedNames - $locatedSheet = null; - $extractedSheetName = ''; - if (strpos( (string)$definedName, '!' ) !== false) { - // Extract sheet name - $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); - $extractedSheetName = $extractedSheetName[0]; + default: + if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { + $range = explode('!', (string)$definedName); + if (count($range) == 2) { + $range[0] = str_replace("''", "'", $range[0]); + $range[0] = str_replace("'", "", $range[0]); + if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + } + } + } + break; + } + } else if (!isset($definedName['localSheetId'])) { + // "Global" definedNames + $locatedSheet = null; + $extractedSheetName = ''; + if (strpos( (string)$definedName, '!' ) !== false) { + // Extract sheet name + $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); + $extractedSheetName = $extractedSheetName[0]; - // Locate sheet - $locatedSheet = $excel->getSheetByName($extractedSheetName); + // Locate sheet + $locatedSheet = $excel->getSheetByName($extractedSheetName); - // Modify range - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - } + // Modify range + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + } - if ($locatedSheet !== NULL) { - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); - } - } - } - } - } + if ($locatedSheet !== NULL) { + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + } + } + } + } + } - if ((!$this->_readDataOnly) || (!empty($this->_loadSheetsOnly))) { - // active sheet index - $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index + if ((!$this->_readDataOnly) || (!empty($this->_loadSheetsOnly))) { + // active sheet index + $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index - // keep active sheet index if sheet is still loaded, else first sheet is set as the active - if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { - $excel->setActiveSheetIndex($mapSheetId[$activeTab]); - } else { - if ($excel->getSheetCount() == 0) { - $excel->createSheet(); - } - $excel->setActiveSheetIndex(0); - } - } - break; - } + // keep active sheet index if sheet is still loaded, else first sheet is set as the active + if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { + $excel->setActiveSheetIndex($mapSheetId[$activeTab]); + } else { + if ($excel->getSheetCount() == 0) { + $excel->createSheet(); + } + $excel->setActiveSheetIndex(0); + } + } + break; + } - } - - - if (!$this->_readDataOnly) { - $contentTypes = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "[Content_Types].xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - foreach ($contentTypes->Override as $contentType) { - switch ($contentType["ContentType"]) { - case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": - if ($this->_includeCharts) { - $chartEntryRef = ltrim($contentType['PartName'],'/'); - $chartElements = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $chartEntryRef)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); - -// echo 'Chart ',$chartEntryRef,'
'; -// var_dump($charts[$chartEntryRef]); -// - if (isset($charts[$chartEntryRef])) { - $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id']; -// echo 'Position Ref ',$chartPositionRef,'
'; - if (isset($chartDetails[$chartPositionRef])) { -// var_dump($chartDetails[$chartPositionRef]); - - $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart); - $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet'])); - $objChart->setTopLeftPosition( $chartDetails[$chartPositionRef]['fromCoordinate'], - $chartDetails[$chartPositionRef]['fromOffsetX'], - $chartDetails[$chartPositionRef]['fromOffsetY'] - ); - $objChart->setBottomRightPosition( $chartDetails[$chartPositionRef]['toCoordinate'], - $chartDetails[$chartPositionRef]['toOffsetX'], - $chartDetails[$chartPositionRef]['toOffsetY'] - ); - } - } - } - } - } - } - - $zip->close(); - - return $excel; - } - - - private static function _readColor($color, $background=FALSE) { - if (isset($color["rgb"])) { - return (string)$color["rgb"]; - } else if (isset($color["indexed"])) { - return PHPExcel_Style_Color::indexedColor($color["indexed"]-7,$background)->getARGB(); - } else if (isset($color["theme"])) { - if (self::$_theme !== NULL) { - $returnColour = self::$_theme->getColourByIndex((int)$color["theme"]); - if (isset($color["tint"])) { - $tintAdjust = (float) $color["tint"]; - $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust); - } - return 'FF'.$returnColour; - } - } - - if ($background) { - return 'FFFFFFFF'; - } - return 'FF000000'; - } - - - private static function _readStyle($docStyle, $style) { - // format code -// if (isset($style->numFmt)) { -// if (isset($style->numFmt['formatCode'])) { -// $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']); -// } else { - $docStyle->getNumberFormat()->setFormatCode($style->numFmt); -// } -// } - - // font - if (isset($style->font)) { - $docStyle->getFont()->setName((string) $style->font->name["val"]); - $docStyle->getFont()->setSize((string) $style->font->sz["val"]); - if (isset($style->font->b)) { - $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"])); - } - if (isset($style->font->i)) { - $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"])); - } - if (isset($style->font->strike)) { - $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"])); - } - $docStyle->getFont()->getColor()->setARGB(self::_readColor($style->font->color)); - - if (isset($style->font->u) && !isset($style->font->u["val"])) { - $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); - } else if (isset($style->font->u) && isset($style->font->u["val"])) { - $docStyle->getFont()->setUnderline((string)$style->font->u["val"]); - } - - if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) { - $vertAlign = strtolower((string)$style->font->vertAlign["val"]); - if ($vertAlign == 'superscript') { - $docStyle->getFont()->setSuperScript(true); - } - if ($vertAlign == 'subscript') { - $docStyle->getFont()->setSubScript(true); - } - } - } - - // fill - if (isset($style->fill)) { - if ($style->fill->gradientFill) { - $gradientFill = $style->fill->gradientFill[0]; - if(!empty($gradientFill["type"])) { - $docStyle->getFill()->setFillType((string) $gradientFill["type"]); - } - $docStyle->getFill()->setRotation(floatval($gradientFill["degree"])); - $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - $docStyle->getFill()->getStartColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"))->color) ); - $docStyle->getFill()->getEndColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"))->color) ); - } elseif ($style->fill->patternFill) { - $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid'; - $docStyle->getFill()->setFillType($patternType); - if ($style->fill->patternFill->fgColor) { - $docStyle->getFill()->getStartColor()->setARGB(self::_readColor($style->fill->patternFill->fgColor,true)); - } else { - $docStyle->getFill()->getStartColor()->setARGB('FF000000'); - } - if ($style->fill->patternFill->bgColor) { - $docStyle->getFill()->getEndColor()->setARGB(self::_readColor($style->fill->patternFill->bgColor,true)); - } - } - } - - // border - if (isset($style->border)) { - $diagonalUp = self::boolean((string) $style->border["diagonalUp"]); - $diagonalDown = self::boolean((string) $style->border["diagonalDown"]); - if (!$diagonalUp && !$diagonalDown) { - $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); - } elseif ($diagonalUp && !$diagonalDown) { - $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); - } elseif (!$diagonalUp && $diagonalDown) { - $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); - } else { - $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); - } - self::_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); - self::_readBorder($docStyle->getBorders()->getRight(), $style->border->right); - self::_readBorder($docStyle->getBorders()->getTop(), $style->border->top); - self::_readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom); - self::_readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal); - } - - // alignment - if (isset($style->alignment)) { - $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); - $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); - - $textRotation = 0; - if ((int)$style->alignment["textRotation"] <= 90) { - $textRotation = (int)$style->alignment["textRotation"]; - } else if ((int)$style->alignment["textRotation"] > 90) { - $textRotation = 90 - (int)$style->alignment["textRotation"]; - } - - $docStyle->getAlignment()->setTextRotation(intval($textRotation)); - $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"])); - $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"])); - $docStyle->getAlignment()->setIndent( intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0 ); - $docStyle->getAlignment()->setReadorder( intval((string)$style->alignment["readingOrder"]) > 0 ? intval((string)$style->alignment["readingOrder"]) : 0 ); - } - - // protection - if (isset($style->protection)) { - if (isset($style->protection['locked'])) { - if (self::boolean((string) $style->protection['locked'])) { - $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); - } else { - $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); - } - } - - if (isset($style->protection['hidden'])) { - if (self::boolean((string) $style->protection['hidden'])) { - $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED); - } else { - $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); - } - } - } - - // top-level style settings - if (isset($style->quotePrefix)) { - $docStyle->setQuotePrefix($style->quotePrefix); } - } - private static function _readBorder($docBorder, $eleBorder) { - if (isset($eleBorder["style"])) { - $docBorder->setBorderStyle((string) $eleBorder["style"]); - } - if (isset($eleBorder->color)) { - $docBorder->getColor()->setARGB(self::_readColor($eleBorder->color)); - } - } + if (!$this->_readDataOnly) { + $contentTypes = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, "[Content_Types].xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + foreach ($contentTypes->Override as $contentType) { + switch ($contentType["ContentType"]) { + case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": + if ($this->_includeCharts) { + $chartEntryRef = ltrim($contentType['PartName'],'/'); + $chartElements = simplexml_load_string($this->securityScan($this->_getFromZipArchive($zip, $chartEntryRef)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); + +// echo 'Chart ',$chartEntryRef,'
'; +// var_dump($charts[$chartEntryRef]); +// + if (isset($charts[$chartEntryRef])) { + $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id']; +// echo 'Position Ref ',$chartPositionRef,'
'; + if (isset($chartDetails[$chartPositionRef])) { +// var_dump($chartDetails[$chartPositionRef]); + + $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart); + $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet'])); + $objChart->setTopLeftPosition( $chartDetails[$chartPositionRef]['fromCoordinate'], + $chartDetails[$chartPositionRef]['fromOffsetX'], + $chartDetails[$chartPositionRef]['fromOffsetY'] + ); + $objChart->setBottomRightPosition( $chartDetails[$chartPositionRef]['toCoordinate'], + $chartDetails[$chartPositionRef]['toOffsetX'], + $chartDetails[$chartPositionRef]['toOffsetY'] + ); + } + } + } + } + } + } + + $zip->close(); + + return $excel; + } - private function _parseRichText($is = null) { - $value = new PHPExcel_RichText(); + private static function _readColor($color, $background=FALSE) { + if (isset($color["rgb"])) { + return (string)$color["rgb"]; + } else if (isset($color["indexed"])) { + return PHPExcel_Style_Color::indexedColor($color["indexed"]-7,$background)->getARGB(); + } else if (isset($color["theme"])) { + if (self::$_theme !== NULL) { + $returnColour = self::$_theme->getColourByIndex((int)$color["theme"]); + if (isset($color["tint"])) { + $tintAdjust = (float) $color["tint"]; + $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust); + } + return 'FF'.$returnColour; + } + } - if (isset($is->t)) { - $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $is->t ) ); - } else { - if(is_object($is->r)) { - foreach ($is->r as $run) { - if (!isset($run->rPr)) { - $objText = $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + if ($background) { + return 'FFFFFFFF'; + } + return 'FF000000'; + } - } else { - $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); - if (isset($run->rPr->rFont["val"])) { - $objText->getFont()->setName((string) $run->rPr->rFont["val"]); - } + private static function _readStyle($docStyle, $style) { + // format code +// if (isset($style->numFmt)) { +// if (isset($style->numFmt['formatCode'])) { +// $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']); +// } else { + $docStyle->getNumberFormat()->setFormatCode($style->numFmt); +// } +// } - if (isset($run->rPr->sz["val"])) { - $objText->getFont()->setSize((string) $run->rPr->sz["val"]); - } + // font + if (isset($style->font)) { + $docStyle->getFont()->setName((string) $style->font->name["val"]); + $docStyle->getFont()->setSize((string) $style->font->sz["val"]); + if (isset($style->font->b)) { + $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"])); + } + if (isset($style->font->i)) { + $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"])); + } + if (isset($style->font->strike)) { + $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"])); + } + $docStyle->getFont()->getColor()->setARGB(self::_readColor($style->font->color)); - if (isset($run->rPr->color)) { - $objText->getFont()->setColor( new PHPExcel_Style_Color( self::_readColor($run->rPr->color) ) ); - } + if (isset($style->font->u) && !isset($style->font->u["val"])) { + $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + } else if (isset($style->font->u) && isset($style->font->u["val"])) { + $docStyle->getFont()->setUnderline((string)$style->font->u["val"]); + } - if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) || - (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) { - $objText->getFont()->setBold(TRUE); - } + if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) { + $vertAlign = strtolower((string)$style->font->vertAlign["val"]); + if ($vertAlign == 'superscript') { + $docStyle->getFont()->setSuperScript(true); + } + if ($vertAlign == 'subscript') { + $docStyle->getFont()->setSubScript(true); + } + } + } - if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) || - (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) { - $objText->getFont()->setItalic(TRUE); - } + // fill + if (isset($style->fill)) { + if ($style->fill->gradientFill) { + $gradientFill = $style->fill->gradientFill[0]; + if(!empty($gradientFill["type"])) { + $docStyle->getFill()->setFillType((string) $gradientFill["type"]); + } + $docStyle->getFill()->setRotation(floatval($gradientFill["degree"])); + $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"))->color) ); + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"))->color) ); + } elseif ($style->fill->patternFill) { + $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid'; + $docStyle->getFill()->setFillType($patternType); + if ($style->fill->patternFill->fgColor) { + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor($style->fill->patternFill->fgColor,true)); + } else { + $docStyle->getFill()->getStartColor()->setARGB('FF000000'); + } + if ($style->fill->patternFill->bgColor) { + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor($style->fill->patternFill->bgColor,true)); + } + } + } - if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) { - $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]); - if ($vertAlign == 'superscript') { - $objText->getFont()->setSuperScript(TRUE); - } - if ($vertAlign == 'subscript') { - $objText->getFont()->setSubScript(TRUE); - } - } + // border + if (isset($style->border)) { + $diagonalUp = self::boolean((string) $style->border["diagonalUp"]); + $diagonalDown = self::boolean((string) $style->border["diagonalDown"]); + if (!$diagonalUp && !$diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp && !$diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif (!$diagonalUp && $diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } else { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + self::_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); + self::_readBorder($docStyle->getBorders()->getRight(), $style->border->right); + self::_readBorder($docStyle->getBorders()->getTop(), $style->border->top); + self::_readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom); + self::_readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal); + } - if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) { - $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); - } else if (isset($run->rPr->u) && isset($run->rPr->u["val"])) { - $objText->getFont()->setUnderline((string)$run->rPr->u["val"]); - } + // alignment + if (isset($style->alignment)) { + $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); + $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); - if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) || - (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) { - $objText->getFont()->setStrikethrough(TRUE); - } - } - } - } - } + $textRotation = 0; + if ((int)$style->alignment["textRotation"] <= 90) { + $textRotation = (int)$style->alignment["textRotation"]; + } else if ((int)$style->alignment["textRotation"] > 90) { + $textRotation = 90 - (int)$style->alignment["textRotation"]; + } - return $value; - } + $docStyle->getAlignment()->setTextRotation(intval($textRotation)); + $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"])); + $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"])); + $docStyle->getAlignment()->setIndent( intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0 ); + $docStyle->getAlignment()->setReadorder( intval((string)$style->alignment["readingOrder"]) > 0 ? intval((string)$style->alignment["readingOrder"]) : 0 ); + } - private function _readRibbon($excel, $customUITarget, $zip) + // protection + if (isset($style->protection)) { + if (isset($style->protection['locked'])) { + if (self::boolean((string) $style->protection['locked'])) { + $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); + } else { + $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + } + } + + if (isset($style->protection['hidden'])) { + if (self::boolean((string) $style->protection['hidden'])) { + $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED); + } else { + $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + } + } + } + + // top-level style settings + if (isset($style->quotePrefix)) { + $docStyle->setQuotePrefix($style->quotePrefix); + } + } + + + private static function _readBorder($docBorder, $eleBorder) { + if (isset($eleBorder["style"])) { + $docBorder->setBorderStyle((string) $eleBorder["style"]); + } + if (isset($eleBorder->color)) { + $docBorder->getColor()->setARGB(self::_readColor($eleBorder->color)); + } + } + + + private function _parseRichText($is = null) { + $value = new PHPExcel_RichText(); + + if (isset($is->t)) { + $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $is->t ) ); + } else { + if(is_object($is->r)) { + foreach ($is->r as $run) { + if (!isset($run->rPr)) { + $objText = $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + + } else { + $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + + if (isset($run->rPr->rFont["val"])) { + $objText->getFont()->setName((string) $run->rPr->rFont["val"]); + } + + if (isset($run->rPr->sz["val"])) { + $objText->getFont()->setSize((string) $run->rPr->sz["val"]); + } + + if (isset($run->rPr->color)) { + $objText->getFont()->setColor( new PHPExcel_Style_Color( self::_readColor($run->rPr->color) ) ); + } + + if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) || + (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) { + $objText->getFont()->setBold(TRUE); + } + + if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) || + (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) { + $objText->getFont()->setItalic(TRUE); + } + + if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) { + $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]); + if ($vertAlign == 'superscript') { + $objText->getFont()->setSuperScript(TRUE); + } + if ($vertAlign == 'subscript') { + $objText->getFont()->setSubScript(TRUE); + } + } + + if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) { + $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + } else if (isset($run->rPr->u) && isset($run->rPr->u["val"])) { + $objText->getFont()->setUnderline((string)$run->rPr->u["val"]); + } + + if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) || + (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) { + $objText->getFont()->setStrikethrough(TRUE); + } + } + } + } + } + + return $value; + } + + private function _readRibbon($excel, $customUITarget, $zip) { - $baseDir = dirname($customUITarget); - $nameCustomUI = basename($customUITarget); + $baseDir = dirname($customUITarget); + $nameCustomUI = basename($customUITarget); // get the xml file (ribbon) - $localRibbon = $this->_getFromZipArchive($zip, $customUITarget); - $customUIImagesNames = array(); + $localRibbon = $this->_getFromZipArchive($zip, $customUITarget); + $customUIImagesNames = array(); $customUIImagesBinaries = array(); // something like customUI/_rels/customUI.xml.rels - $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels'; - $dataRels = $this->_getFromZipArchive($zip, $pathRels); - if ($dataRels) { + $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels'; + $dataRels = $this->_getFromZipArchive($zip, $pathRels); + if ($dataRels) { // exists and not empty if the ribbon have some pictures (other than internal MSO) - $UIRels = simplexml_load_string($this->securityScan($dataRels), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - if ($UIRels) { - // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image - foreach ($UIRels->Relationship as $ele) { - if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') { + $UIRels = simplexml_load_string($this->securityScan($dataRels), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if ($UIRels) { + // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image + foreach ($UIRels->Relationship as $ele) { + if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') { // an image ? - $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target']; - $customUIImagesBinaries[(string)$ele['Target']] = $this->_getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']); - } - } - } - } - if ($localRibbon) { - $excel->setRibbonXMLData($customUITarget, $localRibbon); - if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) { - $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries); - } else { - $excel->setRibbonBinObjects(NULL); - } - } else { - $excel->setRibbonXMLData(NULL); - $excel->setRibbonBinObjects(NULL); - } - } + $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target']; + $customUIImagesBinaries[(string)$ele['Target']] = $this->_getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']); + } + } + } + } + if ($localRibbon) { + $excel->setRibbonXMLData($customUITarget, $localRibbon); + if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) { + $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries); + } else { + $excel->setRibbonBinObjects(NULL); + } + } else { + $excel->setRibbonXMLData(NULL); + $excel->setRibbonBinObjects(NULL); + } + } - private static function array_item($array, $key = 0) { - return (isset($array[$key]) ? $array[$key] : null); - } + private static function array_item($array, $key = 0) { + return (isset($array[$key]) ? $array[$key] : null); + } - private static function dir_add($base, $add) { - return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add"); - } + private static function dir_add($base, $add) { + return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add"); + } - private static function toCSSArray($style) { - $style = str_replace(array("\r","\n"), "", $style); + private static function toCSSArray($style) { + $style = str_replace(array("\r","\n"), "", $style); - $temp = explode(';', $style); - $style = array(); - foreach ($temp as $item) { - $item = explode(':', $item); + $temp = explode(';', $style); + $style = array(); + foreach ($temp as $item) { + $item = explode(':', $item); - if (strpos($item[1], 'px') !== false) { - $item[1] = str_replace('px', '', $item[1]); - } - if (strpos($item[1], 'pt') !== false) { - $item[1] = str_replace('pt', '', $item[1]); - $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]); - } - if (strpos($item[1], 'in') !== false) { - $item[1] = str_replace('in', '', $item[1]); - $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]); - } - if (strpos($item[1], 'cm') !== false) { - $item[1] = str_replace('cm', '', $item[1]); - $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]); - } + if (strpos($item[1], 'px') !== false) { + $item[1] = str_replace('px', '', $item[1]); + } + if (strpos($item[1], 'pt') !== false) { + $item[1] = str_replace('pt', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]); + } + if (strpos($item[1], 'in') !== false) { + $item[1] = str_replace('in', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]); + } + if (strpos($item[1], 'cm') !== false) { + $item[1] = str_replace('cm', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]); + } - $style[$item[0]] = $item[1]; - } + $style[$item[0]] = $item[1]; + } - return $style; - } + return $style; + } - private static function boolean($value = NULL) - { + private static function boolean($value = NULL) + { if (is_object($value)) { - $value = (string) $value; + $value = (string) $value; } - if (is_numeric($value)) { - return (bool) $value; + if (is_numeric($value)) { + return (bool) $value; } - return ($value === 'true' || $value === 'TRUE'); - } + return ($value === 'true' || $value === 'TRUE'); + } } diff --git a/Classes/PHPExcel/Reader/Excel5.php b/Classes/PHPExcel/Reader/Excel5.php index a9acfc47..b12bf3ef 100644 --- a/Classes/PHPExcel/Reader/Excel5.php +++ b/Classes/PHPExcel/Reader/Excel5.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Reader_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -31,39 +31,39 @@ // trex005, and mmp11 (SourceForge.net) // http://sourceforge.net/projects/phpexcelreader/ // Primary changes made by canyoncasa (dvc) for ParseXL 1.00 ... -// Modelled moreso after Perl Excel Parse/Write modules -// Added Parse_Excel_Spreadsheet object -// Reads a whole worksheet or tab as row,column array or as -// associated hash of indexed rows and named column fields -// Added variables for worksheet (tab) indexes and names -// Added an object call for loading individual woorksheets -// Changed default indexing defaults to 0 based arrays -// Fixed date/time and percent formats -// Includes patches found at SourceForge... -// unicode patch by nobody -// unpack("d") machine depedency patch by matchy -// boundsheet utf16 patch by bjaenichen -// Renamed functions for shorter names -// General code cleanup and rigor, including <80 column width -// Included a testcase Excel file and PHP example calls -// Code works for PHP 5.x +// Modelled moreso after Perl Excel Parse/Write modules +// Added Parse_Excel_Spreadsheet object +// Reads a whole worksheet or tab as row,column array or as +// associated hash of indexed rows and named column fields +// Added variables for worksheet (tab) indexes and names +// Added an object call for loading individual woorksheets +// Changed default indexing defaults to 0 based arrays +// Fixed date/time and percent formats +// Includes patches found at SourceForge... +// unicode patch by nobody +// unpack("d") machine depedency patch by matchy +// boundsheet utf16 patch by bjaenichen +// Renamed functions for shorter names +// General code cleanup and rigor, including <80 column width +// Included a testcase Excel file and PHP example calls +// Code works for PHP 5.x // Primary changes made by canyoncasa (dvc) for ParseXL 1.10 ... // http://sourceforge.net/tracker/index.php?func=detail&aid=1466964&group_id=99160&atid=623334 -// Decoding of formula conditions, results, and tokens. -// Support for user-defined named cells added as an array "namedcells" -// Patch code for user-defined named cells supports single cells only. -// NOTE: this patch only works for BIFF8 as BIFF5-7 use a different -// external sheet reference structure +// Decoding of formula conditions, results, and tokens. +// Support for user-defined named cells added as an array "namedcells" +// Patch code for user-defined named cells supports single cells only. +// NOTE: this patch only works for BIFF8 as BIFF5-7 use a different +// external sheet reference structure /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** @@ -71,7018 +71,7018 @@ if (!defined('PHPEXCEL_ROOT')) { * * This class uses {@link http://sourceforge.net/projects/phpexcelreader/parseXL} * - * @category PHPExcel - * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_Reader_Excel5 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - // ParseXL definitions - const XLS_BIFF8 = 0x0600; - const XLS_BIFF7 = 0x0500; - const XLS_WorkbookGlobals = 0x0005; - const XLS_Worksheet = 0x0010; - - // record identifiers - const XLS_Type_FORMULA = 0x0006; - const XLS_Type_EOF = 0x000a; - const XLS_Type_PROTECT = 0x0012; - const XLS_Type_OBJECTPROTECT = 0x0063; - const XLS_Type_SCENPROTECT = 0x00dd; - const XLS_Type_PASSWORD = 0x0013; - const XLS_Type_HEADER = 0x0014; - const XLS_Type_FOOTER = 0x0015; - const XLS_Type_EXTERNSHEET = 0x0017; - const XLS_Type_DEFINEDNAME = 0x0018; - const XLS_Type_VERTICALPAGEBREAKS = 0x001a; - const XLS_Type_HORIZONTALPAGEBREAKS = 0x001b; - const XLS_Type_NOTE = 0x001c; - const XLS_Type_SELECTION = 0x001d; - const XLS_Type_DATEMODE = 0x0022; - const XLS_Type_EXTERNNAME = 0x0023; - const XLS_Type_LEFTMARGIN = 0x0026; - const XLS_Type_RIGHTMARGIN = 0x0027; - const XLS_Type_TOPMARGIN = 0x0028; - const XLS_Type_BOTTOMMARGIN = 0x0029; - const XLS_Type_PRINTGRIDLINES = 0x002b; - const XLS_Type_FILEPASS = 0x002f; - const XLS_Type_FONT = 0x0031; - const XLS_Type_CONTINUE = 0x003c; - const XLS_Type_PANE = 0x0041; - const XLS_Type_CODEPAGE = 0x0042; - const XLS_Type_DEFCOLWIDTH = 0x0055; - const XLS_Type_OBJ = 0x005d; - const XLS_Type_COLINFO = 0x007d; - const XLS_Type_IMDATA = 0x007f; - const XLS_Type_SHEETPR = 0x0081; - const XLS_Type_HCENTER = 0x0083; - const XLS_Type_VCENTER = 0x0084; - const XLS_Type_SHEET = 0x0085; - const XLS_Type_PALETTE = 0x0092; - const XLS_Type_SCL = 0x00a0; - const XLS_Type_PAGESETUP = 0x00a1; - const XLS_Type_MULRK = 0x00bd; - const XLS_Type_MULBLANK = 0x00be; - const XLS_Type_DBCELL = 0x00d7; - const XLS_Type_XF = 0x00e0; - const XLS_Type_MERGEDCELLS = 0x00e5; - const XLS_Type_MSODRAWINGGROUP = 0x00eb; - const XLS_Type_MSODRAWING = 0x00ec; - const XLS_Type_SST = 0x00fc; - const XLS_Type_LABELSST = 0x00fd; - const XLS_Type_EXTSST = 0x00ff; - const XLS_Type_EXTERNALBOOK = 0x01ae; - const XLS_Type_DATAVALIDATIONS = 0x01b2; - const XLS_Type_TXO = 0x01b6; - const XLS_Type_HYPERLINK = 0x01b8; - const XLS_Type_DATAVALIDATION = 0x01be; - const XLS_Type_DIMENSION = 0x0200; - const XLS_Type_BLANK = 0x0201; - const XLS_Type_NUMBER = 0x0203; - const XLS_Type_LABEL = 0x0204; - const XLS_Type_BOOLERR = 0x0205; - const XLS_Type_STRING = 0x0207; - const XLS_Type_ROW = 0x0208; - const XLS_Type_INDEX = 0x020b; - const XLS_Type_ARRAY = 0x0221; - const XLS_Type_DEFAULTROWHEIGHT = 0x0225; - const XLS_Type_WINDOW2 = 0x023e; - const XLS_Type_RK = 0x027e; - const XLS_Type_STYLE = 0x0293; - const XLS_Type_FORMAT = 0x041e; - const XLS_Type_SHAREDFMLA = 0x04bc; - const XLS_Type_BOF = 0x0809; - const XLS_Type_SHEETPROTECTION = 0x0867; - const XLS_Type_RANGEPROTECTION = 0x0868; - const XLS_Type_SHEETLAYOUT = 0x0862; - const XLS_Type_XFEXT = 0x087d; - const XLS_Type_PAGELAYOUTVIEW = 0x088b; - const XLS_Type_UNKNOWN = 0xffff; - - // Encryption type - const MS_BIFF_CRYPTO_NONE = 0; - const MS_BIFF_CRYPTO_XOR = 1; - const MS_BIFF_CRYPTO_RC4 = 2; - - // Size of stream blocks when using RC4 encryption - const REKEY_BLOCK = 0x400; - - /** - * Summary Information stream data. - * - * @var string - */ - private $_summaryInformation; - - /** - * Extended Summary Information stream data. - * - * @var string - */ - private $_documentSummaryInformation; - - /** - * User-Defined Properties stream data. - * - * @var string - */ - private $_userDefinedProperties; - - /** - * Workbook stream data. (Includes workbook globals substream as well as sheet substreams) - * - * @var string - */ - private $_data; - - /** - * Size in bytes of $this->_data - * - * @var int - */ - private $_dataSize; - - /** - * Current position in stream - * - * @var integer - */ - private $_pos; - - /** - * Workbook to be returned by the reader. - * - * @var PHPExcel - */ - private $_phpExcel; - - /** - * Worksheet that is currently being built by the reader. - * - * @var PHPExcel_Worksheet - */ - private $_phpSheet; - - /** - * BIFF version - * - * @var int - */ - private $_version; - - /** - * Codepage set in the Excel file being read. Only important for BIFF5 (Excel 5.0 - Excel 95) - * For BIFF8 (Excel 97 - Excel 2003) this will always have the value 'UTF-16LE' - * - * @var string - */ - private $_codepage; - - /** - * Shared formats - * - * @var array - */ - private $_formats; - - /** - * Shared fonts - * - * @var array - */ - private $_objFonts; - - /** - * Color palette - * - * @var array - */ - private $_palette; - - /** - * Worksheets - * - * @var array - */ - private $_sheets; - - /** - * External books - * - * @var array - */ - private $_externalBooks; - - /** - * REF structures. Only applies to BIFF8. - * - * @var array - */ - private $_ref; - - /** - * External names - * - * @var array - */ - private $_externalNames; - - /** - * Defined names - * - * @var array - */ - private $_definedname; - - /** - * Shared strings. Only applies to BIFF8. - * - * @var array - */ - private $_sst; - - /** - * Panes are frozen? (in sheet currently being read). See WINDOW2 record. - * - * @var boolean - */ - private $_frozen; - - /** - * Fit printout to number of pages? (in sheet currently being read). See SHEETPR record. - * - * @var boolean - */ - private $_isFitToPages; - - /** - * Objects. One OBJ record contributes with one entry. - * - * @var array - */ - private $_objs; - - /** - * Text Objects. One TXO record corresponds with one entry. - * - * @var array - */ - private $_textObjects; - - /** - * Cell Annotations (BIFF8) - * - * @var array - */ - private $_cellNotes; - - /** - * The combined MSODRAWINGGROUP data - * - * @var string - */ - private $_drawingGroupData; - - /** - * The combined MSODRAWING data (per sheet) - * - * @var string - */ - private $_drawingData; - - /** - * Keep track of XF index - * - * @var int - */ - private $_xfIndex; - - /** - * Mapping of XF index (that is a cell XF) to final index in cellXf collection - * - * @var array - */ - private $_mapCellXfIndex; - - /** - * Mapping of XF index (that is a style XF) to final index in cellStyleXf collection - * - * @var array - */ - private $_mapCellStyleXfIndex; - - /** - * The shared formulas in a sheet. One SHAREDFMLA record contributes with one value. - * - * @var array - */ - private $_sharedFormulas; - - /** - * The shared formula parts in a sheet. One FORMULA record contributes with one value if it - * refers to a shared formula. - * - * @var array - */ - private $_sharedFormulaParts; - - /** - * The type of encryption in use - * - * @var int - */ - private $_encryption = 0; - - /** - * The position in the stream after which contents are encrypted - * - * @var int - */ - private $_encryptionStartPos = false; - - /** - * The current RC4 decryption object - * - * @var PHPExcel_Reader_Excel5_RC4 - */ - private $_rc4Key = null; - - /** - * The position in the stream that the RC4 decryption object was left at - * - * @var int - */ - private $_rc4Pos = 0; - - /** - * The current MD5 context state - * - * @var string - */ - private $_md5Ctxt = null; - - /** - * Create a new PHPExcel_Reader_Excel5 instance - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } - - - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - try { - // Use ParseXL for the hard work. - $ole = new PHPExcel_Shared_OLERead(); - - // get excel data - $res = $ole->read($pFilename); - return true; - } catch (PHPExcel_Exception $e) { - return false; - } - } - - - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $worksheetNames = array(); - - // Read the OLE file - $this->_loadOLE($pFilename); - - // total byte size of Excel data (workbook global substream + sheet substreams) - $this->_dataSize = strlen($this->_data); - - $this->_pos = 0; - $this->_sheets = array(); - - // Parse Workbook Global Substream - while ($this->_pos < $this->_dataSize) { - $code = self::_GetInt2d($this->_data, $this->_pos); - - switch ($code) { - case self::XLS_Type_BOF: $this->_readBof(); break; - case self::XLS_Type_SHEET: $this->_readSheet(); break; - case self::XLS_Type_EOF: $this->_readDefault(); break 2; - default: $this->_readDefault(); break; - } - } - - foreach ($this->_sheets as $sheet) { - if ($sheet['sheetType'] != 0x00) { - // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module - continue; - } - - $worksheetNames[] = $sheet['name']; - } - - return $worksheetNames; - } - - - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $worksheetInfo = array(); - - // Read the OLE file - $this->_loadOLE($pFilename); - - // total byte size of Excel data (workbook global substream + sheet substreams) - $this->_dataSize = strlen($this->_data); - - // initialize - $this->_pos = 0; - $this->_sheets = array(); - - // Parse Workbook Global Substream - while ($this->_pos < $this->_dataSize) { - $code = self::_GetInt2d($this->_data, $this->_pos); - - switch ($code) { - case self::XLS_Type_BOF: $this->_readBof(); break; - case self::XLS_Type_SHEET: $this->_readSheet(); break; - case self::XLS_Type_EOF: $this->_readDefault(); break 2; - default: $this->_readDefault(); break; - } - } - - // Parse the individual sheets - foreach ($this->_sheets as $sheet) { - - if ($sheet['sheetType'] != 0x00) { - // 0x00: Worksheet - // 0x02: Chart - // 0x06: Visual Basic module - continue; - } - - $tmpInfo = array(); - $tmpInfo['worksheetName'] = $sheet['name']; - $tmpInfo['lastColumnLetter'] = 'A'; - $tmpInfo['lastColumnIndex'] = 0; - $tmpInfo['totalRows'] = 0; - $tmpInfo['totalColumns'] = 0; - - $this->_pos = $sheet['offset']; - - while ($this->_pos <= $this->_dataSize - 4) { - $code = self::_GetInt2d($this->_data, $this->_pos); - - switch ($code) { - case self::XLS_Type_RK: - case self::XLS_Type_LABELSST: - case self::XLS_Type_NUMBER: - case self::XLS_Type_FORMULA: - case self::XLS_Type_BOOLERR: - case self::XLS_Type_LABEL: - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - $rowIndex = self::_GetInt2d($recordData, 0) + 1; - $columnIndex = self::_GetInt2d($recordData, 2); - - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); - break; - case self::XLS_Type_BOF: $this->_readBof(); break; - case self::XLS_Type_EOF: $this->_readDefault(); break 2; - default: $this->_readDefault(); break; - } - } - - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; - - $worksheetInfo[] = $tmpInfo; - } - - return $worksheetInfo; - } - - - /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Read the OLE file - $this->_loadOLE($pFilename); - - // Initialisations - $this->_phpExcel = new PHPExcel; - $this->_phpExcel->removeSheetByIndex(0); // remove 1st sheet - if (!$this->_readDataOnly) { - $this->_phpExcel->removeCellStyleXfByIndex(0); // remove the default style - $this->_phpExcel->removeCellXfByIndex(0); // remove the default style - } - - // Read the summary information stream (containing meta data) - $this->_readSummaryInformation(); - - // Read the Additional document summary information stream (containing application-specific meta data) - $this->_readDocumentSummaryInformation(); - - // total byte size of Excel data (workbook global substream + sheet substreams) - $this->_dataSize = strlen($this->_data); - - // initialize - $this->_pos = 0; - $this->_codepage = 'CP1252'; - $this->_formats = array(); - $this->_objFonts = array(); - $this->_palette = array(); - $this->_sheets = array(); - $this->_externalBooks = array(); - $this->_ref = array(); - $this->_definedname = array(); - $this->_sst = array(); - $this->_drawingGroupData = ''; - $this->_xfIndex = ''; - $this->_mapCellXfIndex = array(); - $this->_mapCellStyleXfIndex = array(); - - // Parse Workbook Global Substream - while ($this->_pos < $this->_dataSize) { - $code = self::_GetInt2d($this->_data, $this->_pos); - - switch ($code) { - case self::XLS_Type_BOF: $this->_readBof(); break; - case self::XLS_Type_FILEPASS: $this->_readFilepass(); break; - case self::XLS_Type_CODEPAGE: $this->_readCodepage(); break; - case self::XLS_Type_DATEMODE: $this->_readDateMode(); break; - case self::XLS_Type_FONT: $this->_readFont(); break; - case self::XLS_Type_FORMAT: $this->_readFormat(); break; - case self::XLS_Type_XF: $this->_readXf(); break; - case self::XLS_Type_XFEXT: $this->_readXfExt(); break; - case self::XLS_Type_STYLE: $this->_readStyle(); break; - case self::XLS_Type_PALETTE: $this->_readPalette(); break; - case self::XLS_Type_SHEET: $this->_readSheet(); break; - case self::XLS_Type_EXTERNALBOOK: $this->_readExternalBook(); break; - case self::XLS_Type_EXTERNNAME: $this->_readExternName(); break; - case self::XLS_Type_EXTERNSHEET: $this->_readExternSheet(); break; - case self::XLS_Type_DEFINEDNAME: $this->_readDefinedName(); break; - case self::XLS_Type_MSODRAWINGGROUP: $this->_readMsoDrawingGroup(); break; - case self::XLS_Type_SST: $this->_readSst(); break; - case self::XLS_Type_EOF: $this->_readDefault(); break 2; - default: $this->_readDefault(); break; - } - } - - // Resolve indexed colors for font, fill, and border colors - // Cannot be resolved already in XF record, because PALETTE record comes afterwards - if (!$this->_readDataOnly) { - foreach ($this->_objFonts as $objFont) { - if (isset($objFont->colorIndex)) { - $color = self::_readColor($objFont->colorIndex,$this->_palette,$this->_version); - $objFont->getColor()->setRGB($color['rgb']); - } - } - - foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) { - // fill start and end color - $fill = $objStyle->getFill(); - - if (isset($fill->startcolorIndex)) { - $startColor = self::_readColor($fill->startcolorIndex,$this->_palette,$this->_version); - $fill->getStartColor()->setRGB($startColor['rgb']); - } - - if (isset($fill->endcolorIndex)) { - $endColor = self::_readColor($fill->endcolorIndex,$this->_palette,$this->_version); - $fill->getEndColor()->setRGB($endColor['rgb']); - } - - // border colors - $top = $objStyle->getBorders()->getTop(); - $right = $objStyle->getBorders()->getRight(); - $bottom = $objStyle->getBorders()->getBottom(); - $left = $objStyle->getBorders()->getLeft(); - $diagonal = $objStyle->getBorders()->getDiagonal(); - - if (isset($top->colorIndex)) { - $borderTopColor = self::_readColor($top->colorIndex,$this->_palette,$this->_version); - $top->getColor()->setRGB($borderTopColor['rgb']); - } - - if (isset($right->colorIndex)) { - $borderRightColor = self::_readColor($right->colorIndex,$this->_palette,$this->_version); - $right->getColor()->setRGB($borderRightColor['rgb']); - } - - if (isset($bottom->colorIndex)) { - $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette,$this->_version); - $bottom->getColor()->setRGB($borderBottomColor['rgb']); - } - - if (isset($left->colorIndex)) { - $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette,$this->_version); - $left->getColor()->setRGB($borderLeftColor['rgb']); - } - - if (isset($diagonal->colorIndex)) { - $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette,$this->_version); - $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); - } - } - } - - // treat MSODRAWINGGROUP records, workbook-level Escher - if (!$this->_readDataOnly && $this->_drawingGroupData) { - $escherWorkbook = new PHPExcel_Shared_Escher(); - $reader = new PHPExcel_Reader_Excel5_Escher($escherWorkbook); - $escherWorkbook = $reader->load($this->_drawingGroupData); - - // debug Escher stream - //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); - //$debug->load($this->_drawingGroupData); - } - - // Parse the individual sheets - foreach ($this->_sheets as $sheet) { - - if ($sheet['sheetType'] != 0x00) { - // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module - continue; - } - - // check if sheet should be skipped - if (isset($this->_loadSheetsOnly) && !in_array($sheet['name'], $this->_loadSheetsOnly)) { - continue; - } - - // add sheet to PHPExcel object - $this->_phpSheet = $this->_phpExcel->createSheet(); - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula - // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet - // name in line with the formula, not the reverse - $this->_phpSheet->setTitle($sheet['name'],false); - $this->_phpSheet->setSheetState($sheet['sheetState']); - - $this->_pos = $sheet['offset']; - - // Initialize isFitToPages. May change after reading SHEETPR record. - $this->_isFitToPages = false; - - // Initialize drawingData - $this->_drawingData = ''; - - // Initialize objs - $this->_objs = array(); - - // Initialize shared formula parts - $this->_sharedFormulaParts = array(); - - // Initialize shared formulas - $this->_sharedFormulas = array(); - - // Initialize text objs - $this->_textObjects = array(); - - // Initialize cell annotations - $this->_cellNotes = array(); - $this->textObjRef = -1; - - while ($this->_pos <= $this->_dataSize - 4) { - $code = self::_GetInt2d($this->_data, $this->_pos); - - switch ($code) { - case self::XLS_Type_BOF: $this->_readBof(); break; - case self::XLS_Type_PRINTGRIDLINES: $this->_readPrintGridlines(); break; - case self::XLS_Type_DEFAULTROWHEIGHT: $this->_readDefaultRowHeight(); break; - case self::XLS_Type_SHEETPR: $this->_readSheetPr(); break; - case self::XLS_Type_HORIZONTALPAGEBREAKS: $this->_readHorizontalPageBreaks(); break; - case self::XLS_Type_VERTICALPAGEBREAKS: $this->_readVerticalPageBreaks(); break; - case self::XLS_Type_HEADER: $this->_readHeader(); break; - case self::XLS_Type_FOOTER: $this->_readFooter(); break; - case self::XLS_Type_HCENTER: $this->_readHcenter(); break; - case self::XLS_Type_VCENTER: $this->_readVcenter(); break; - case self::XLS_Type_LEFTMARGIN: $this->_readLeftMargin(); break; - case self::XLS_Type_RIGHTMARGIN: $this->_readRightMargin(); break; - case self::XLS_Type_TOPMARGIN: $this->_readTopMargin(); break; - case self::XLS_Type_BOTTOMMARGIN: $this->_readBottomMargin(); break; - case self::XLS_Type_PAGESETUP: $this->_readPageSetup(); break; - case self::XLS_Type_PROTECT: $this->_readProtect(); break; - case self::XLS_Type_SCENPROTECT: $this->_readScenProtect(); break; - case self::XLS_Type_OBJECTPROTECT: $this->_readObjectProtect(); break; - case self::XLS_Type_PASSWORD: $this->_readPassword(); break; - case self::XLS_Type_DEFCOLWIDTH: $this->_readDefColWidth(); break; - case self::XLS_Type_COLINFO: $this->_readColInfo(); break; - case self::XLS_Type_DIMENSION: $this->_readDefault(); break; - case self::XLS_Type_ROW: $this->_readRow(); break; - case self::XLS_Type_DBCELL: $this->_readDefault(); break; - case self::XLS_Type_RK: $this->_readRk(); break; - case self::XLS_Type_LABELSST: $this->_readLabelSst(); break; - case self::XLS_Type_MULRK: $this->_readMulRk(); break; - case self::XLS_Type_NUMBER: $this->_readNumber(); break; - case self::XLS_Type_FORMULA: $this->_readFormula(); break; - case self::XLS_Type_SHAREDFMLA: $this->_readSharedFmla(); break; - case self::XLS_Type_BOOLERR: $this->_readBoolErr(); break; - case self::XLS_Type_MULBLANK: $this->_readMulBlank(); break; - case self::XLS_Type_LABEL: $this->_readLabel(); break; - case self::XLS_Type_BLANK: $this->_readBlank(); break; - case self::XLS_Type_MSODRAWING: $this->_readMsoDrawing(); break; - case self::XLS_Type_OBJ: $this->_readObj(); break; - case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; - case self::XLS_Type_PAGELAYOUTVIEW: $this->_readPageLayoutView(); break; - case self::XLS_Type_SCL: $this->_readScl(); break; - case self::XLS_Type_PANE: $this->_readPane(); break; - case self::XLS_Type_SELECTION: $this->_readSelection(); break; - case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; - case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; - case self::XLS_Type_DATAVALIDATIONS: $this->_readDataValidations(); break; - case self::XLS_Type_DATAVALIDATION: $this->_readDataValidation(); break; - case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; - case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; - case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; - case self::XLS_Type_NOTE: $this->_readNote(); break; - //case self::XLS_Type_IMDATA: $this->_readImData(); break; - case self::XLS_Type_TXO: $this->_readTextObject(); break; - case self::XLS_Type_CONTINUE: $this->_readContinue(); break; - case self::XLS_Type_EOF: $this->_readDefault(); break 2; - default: $this->_readDefault(); break; - } - - } - - // treat MSODRAWING records, sheet-level Escher - if (!$this->_readDataOnly && $this->_drawingData) { - $escherWorksheet = new PHPExcel_Shared_Escher(); - $reader = new PHPExcel_Reader_Excel5_Escher($escherWorksheet); - $escherWorksheet = $reader->load($this->_drawingData); - - // debug Escher stream - //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); - //$debug->load($this->_drawingData); - - // get all spContainers in one long array, so they can be mapped to OBJ records - $allSpContainers = $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers(); - } - - // treat OBJ records - foreach ($this->_objs as $n => $obj) { -// echo '
Object reference is ',$n,'
'; -// var_dump($obj); -// echo '
'; - - // the first shape container never has a corresponding OBJ record, hence $n + 1 - if (isset($allSpContainers[$n + 1]) && is_object($allSpContainers[$n + 1])) { - $spContainer = $allSpContainers[$n + 1]; - - // we skip all spContainers that are a part of a group shape since we cannot yet handle those - if ($spContainer->getNestingLevel() > 1) { - continue; - } - - // calculate the width and height of the shape - list($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($spContainer->getStartCoordinates()); - list($endColumn, $endRow) = PHPExcel_Cell::coordinateFromString($spContainer->getEndCoordinates()); - - $startOffsetX = $spContainer->getStartOffsetX(); - $startOffsetY = $spContainer->getStartOffsetY(); - $endOffsetX = $spContainer->getEndOffsetX(); - $endOffsetY = $spContainer->getEndOffsetY(); - - $width = PHPExcel_Shared_Excel5::getDistanceX($this->_phpSheet, $startColumn, $startOffsetX, $endColumn, $endOffsetX); - $height = PHPExcel_Shared_Excel5::getDistanceY($this->_phpSheet, $startRow, $startOffsetY, $endRow, $endOffsetY); - - // calculate offsetX and offsetY of the shape - $offsetX = $startOffsetX * PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, $startColumn) / 1024; - $offsetY = $startOffsetY * PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $startRow) / 256; - - switch ($obj['otObjType']) { - case 0x19: - // Note -// echo 'Cell Annotation Object
'; -// echo 'Object ID is ',$obj['idObjID'],'
'; + // ParseXL definitions + const XLS_BIFF8 = 0x0600; + const XLS_BIFF7 = 0x0500; + const XLS_WorkbookGlobals = 0x0005; + const XLS_Worksheet = 0x0010; + + // record identifiers + const XLS_Type_FORMULA = 0x0006; + const XLS_Type_EOF = 0x000a; + const XLS_Type_PROTECT = 0x0012; + const XLS_Type_OBJECTPROTECT = 0x0063; + const XLS_Type_SCENPROTECT = 0x00dd; + const XLS_Type_PASSWORD = 0x0013; + const XLS_Type_HEADER = 0x0014; + const XLS_Type_FOOTER = 0x0015; + const XLS_Type_EXTERNSHEET = 0x0017; + const XLS_Type_DEFINEDNAME = 0x0018; + const XLS_Type_VERTICALPAGEBREAKS = 0x001a; + const XLS_Type_HORIZONTALPAGEBREAKS = 0x001b; + const XLS_Type_NOTE = 0x001c; + const XLS_Type_SELECTION = 0x001d; + const XLS_Type_DATEMODE = 0x0022; + const XLS_Type_EXTERNNAME = 0x0023; + const XLS_Type_LEFTMARGIN = 0x0026; + const XLS_Type_RIGHTMARGIN = 0x0027; + const XLS_Type_TOPMARGIN = 0x0028; + const XLS_Type_BOTTOMMARGIN = 0x0029; + const XLS_Type_PRINTGRIDLINES = 0x002b; + const XLS_Type_FILEPASS = 0x002f; + const XLS_Type_FONT = 0x0031; + const XLS_Type_CONTINUE = 0x003c; + const XLS_Type_PANE = 0x0041; + const XLS_Type_CODEPAGE = 0x0042; + const XLS_Type_DEFCOLWIDTH = 0x0055; + const XLS_Type_OBJ = 0x005d; + const XLS_Type_COLINFO = 0x007d; + const XLS_Type_IMDATA = 0x007f; + const XLS_Type_SHEETPR = 0x0081; + const XLS_Type_HCENTER = 0x0083; + const XLS_Type_VCENTER = 0x0084; + const XLS_Type_SHEET = 0x0085; + const XLS_Type_PALETTE = 0x0092; + const XLS_Type_SCL = 0x00a0; + const XLS_Type_PAGESETUP = 0x00a1; + const XLS_Type_MULRK = 0x00bd; + const XLS_Type_MULBLANK = 0x00be; + const XLS_Type_DBCELL = 0x00d7; + const XLS_Type_XF = 0x00e0; + const XLS_Type_MERGEDCELLS = 0x00e5; + const XLS_Type_MSODRAWINGGROUP = 0x00eb; + const XLS_Type_MSODRAWING = 0x00ec; + const XLS_Type_SST = 0x00fc; + const XLS_Type_LABELSST = 0x00fd; + const XLS_Type_EXTSST = 0x00ff; + const XLS_Type_EXTERNALBOOK = 0x01ae; + const XLS_Type_DATAVALIDATIONS = 0x01b2; + const XLS_Type_TXO = 0x01b6; + const XLS_Type_HYPERLINK = 0x01b8; + const XLS_Type_DATAVALIDATION = 0x01be; + const XLS_Type_DIMENSION = 0x0200; + const XLS_Type_BLANK = 0x0201; + const XLS_Type_NUMBER = 0x0203; + const XLS_Type_LABEL = 0x0204; + const XLS_Type_BOOLERR = 0x0205; + const XLS_Type_STRING = 0x0207; + const XLS_Type_ROW = 0x0208; + const XLS_Type_INDEX = 0x020b; + const XLS_Type_ARRAY = 0x0221; + const XLS_Type_DEFAULTROWHEIGHT = 0x0225; + const XLS_Type_WINDOW2 = 0x023e; + const XLS_Type_RK = 0x027e; + const XLS_Type_STYLE = 0x0293; + const XLS_Type_FORMAT = 0x041e; + const XLS_Type_SHAREDFMLA = 0x04bc; + const XLS_Type_BOF = 0x0809; + const XLS_Type_SHEETPROTECTION = 0x0867; + const XLS_Type_RANGEPROTECTION = 0x0868; + const XLS_Type_SHEETLAYOUT = 0x0862; + const XLS_Type_XFEXT = 0x087d; + const XLS_Type_PAGELAYOUTVIEW = 0x088b; + const XLS_Type_UNKNOWN = 0xffff; + + // Encryption type + const MS_BIFF_CRYPTO_NONE = 0; + const MS_BIFF_CRYPTO_XOR = 1; + const MS_BIFF_CRYPTO_RC4 = 2; + + // Size of stream blocks when using RC4 encryption + const REKEY_BLOCK = 0x400; + + /** + * Summary Information stream data. + * + * @var string + */ + private $_summaryInformation; + + /** + * Extended Summary Information stream data. + * + * @var string + */ + private $_documentSummaryInformation; + + /** + * User-Defined Properties stream data. + * + * @var string + */ + private $_userDefinedProperties; + + /** + * Workbook stream data. (Includes workbook globals substream as well as sheet substreams) + * + * @var string + */ + private $_data; + + /** + * Size in bytes of $this->_data + * + * @var int + */ + private $_dataSize; + + /** + * Current position in stream + * + * @var integer + */ + private $_pos; + + /** + * Workbook to be returned by the reader. + * + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Worksheet that is currently being built by the reader. + * + * @var PHPExcel_Worksheet + */ + private $_phpSheet; + + /** + * BIFF version + * + * @var int + */ + private $_version; + + /** + * Codepage set in the Excel file being read. Only important for BIFF5 (Excel 5.0 - Excel 95) + * For BIFF8 (Excel 97 - Excel 2003) this will always have the value 'UTF-16LE' + * + * @var string + */ + private $_codepage; + + /** + * Shared formats + * + * @var array + */ + private $_formats; + + /** + * Shared fonts + * + * @var array + */ + private $_objFonts; + + /** + * Color palette + * + * @var array + */ + private $_palette; + + /** + * Worksheets + * + * @var array + */ + private $_sheets; + + /** + * External books + * + * @var array + */ + private $_externalBooks; + + /** + * REF structures. Only applies to BIFF8. + * + * @var array + */ + private $_ref; + + /** + * External names + * + * @var array + */ + private $_externalNames; + + /** + * Defined names + * + * @var array + */ + private $_definedname; + + /** + * Shared strings. Only applies to BIFF8. + * + * @var array + */ + private $_sst; + + /** + * Panes are frozen? (in sheet currently being read). See WINDOW2 record. + * + * @var boolean + */ + private $_frozen; + + /** + * Fit printout to number of pages? (in sheet currently being read). See SHEETPR record. + * + * @var boolean + */ + private $_isFitToPages; + + /** + * Objects. One OBJ record contributes with one entry. + * + * @var array + */ + private $_objs; + + /** + * Text Objects. One TXO record corresponds with one entry. + * + * @var array + */ + private $_textObjects; + + /** + * Cell Annotations (BIFF8) + * + * @var array + */ + private $_cellNotes; + + /** + * The combined MSODRAWINGGROUP data + * + * @var string + */ + private $_drawingGroupData; + + /** + * The combined MSODRAWING data (per sheet) + * + * @var string + */ + private $_drawingData; + + /** + * Keep track of XF index + * + * @var int + */ + private $_xfIndex; + + /** + * Mapping of XF index (that is a cell XF) to final index in cellXf collection + * + * @var array + */ + private $_mapCellXfIndex; + + /** + * Mapping of XF index (that is a style XF) to final index in cellStyleXf collection + * + * @var array + */ + private $_mapCellStyleXfIndex; + + /** + * The shared formulas in a sheet. One SHAREDFMLA record contributes with one value. + * + * @var array + */ + private $_sharedFormulas; + + /** + * The shared formula parts in a sheet. One FORMULA record contributes with one value if it + * refers to a shared formula. + * + * @var array + */ + private $_sharedFormulaParts; + + /** + * The type of encryption in use + * + * @var int + */ + private $_encryption = 0; + + /** + * The position in the stream after which contents are encrypted + * + * @var int + */ + private $_encryptionStartPos = false; + + /** + * The current RC4 decryption object + * + * @var PHPExcel_Reader_Excel5_RC4 + */ + private $_rc4Key = null; + + /** + * The position in the stream that the RC4 decryption object was left at + * + * @var int + */ + private $_rc4Pos = 0; + + /** + * The current MD5 context state + * + * @var string + */ + private $_md5Ctxt = null; + + /** + * Create a new PHPExcel_Reader_Excel5 instance + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + try { + // Use ParseXL for the hard work. + $ole = new PHPExcel_Shared_OLERead(); + + // get excel data + $res = $ole->read($pFilename); + return true; + } catch (PHPExcel_Exception $e) { + return false; + } + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetNames = array(); + + // Read the OLE file + $this->_loadOLE($pFilename); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + $this->_pos = 0; + $this->_sheets = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + foreach ($this->_sheets as $sheet) { + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module + continue; + } + + $worksheetNames[] = $sheet['name']; + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + // Read the OLE file + $this->_loadOLE($pFilename); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + // initialize + $this->_pos = 0; + $this->_sheets = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + // Parse the individual sheets + foreach ($this->_sheets as $sheet) { + + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet + // 0x02: Chart + // 0x06: Visual Basic module + continue; + } + + $tmpInfo = array(); + $tmpInfo['worksheetName'] = $sheet['name']; + $tmpInfo['lastColumnLetter'] = 'A'; + $tmpInfo['lastColumnIndex'] = 0; + $tmpInfo['totalRows'] = 0; + $tmpInfo['totalColumns'] = 0; + + $this->_pos = $sheet['offset']; + + while ($this->_pos <= $this->_dataSize - 4) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_RK: + case self::XLS_Type_LABELSST: + case self::XLS_Type_NUMBER: + case self::XLS_Type_FORMULA: + case self::XLS_Type_BOOLERR: + case self::XLS_Type_LABEL: + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + $rowIndex = self::_GetInt2d($recordData, 0) + 1; + $columnIndex = self::_GetInt2d($recordData, 2); + + $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); + $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); + break; + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; + + $worksheetInfo[] = $tmpInfo; + } + + return $worksheetInfo; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Read the OLE file + $this->_loadOLE($pFilename); + + // Initialisations + $this->_phpExcel = new PHPExcel; + $this->_phpExcel->removeSheetByIndex(0); // remove 1st sheet + if (!$this->_readDataOnly) { + $this->_phpExcel->removeCellStyleXfByIndex(0); // remove the default style + $this->_phpExcel->removeCellXfByIndex(0); // remove the default style + } + + // Read the summary information stream (containing meta data) + $this->_readSummaryInformation(); + + // Read the Additional document summary information stream (containing application-specific meta data) + $this->_readDocumentSummaryInformation(); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + // initialize + $this->_pos = 0; + $this->_codepage = 'CP1252'; + $this->_formats = array(); + $this->_objFonts = array(); + $this->_palette = array(); + $this->_sheets = array(); + $this->_externalBooks = array(); + $this->_ref = array(); + $this->_definedname = array(); + $this->_sst = array(); + $this->_drawingGroupData = ''; + $this->_xfIndex = ''; + $this->_mapCellXfIndex = array(); + $this->_mapCellStyleXfIndex = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_FILEPASS: $this->_readFilepass(); break; + case self::XLS_Type_CODEPAGE: $this->_readCodepage(); break; + case self::XLS_Type_DATEMODE: $this->_readDateMode(); break; + case self::XLS_Type_FONT: $this->_readFont(); break; + case self::XLS_Type_FORMAT: $this->_readFormat(); break; + case self::XLS_Type_XF: $this->_readXf(); break; + case self::XLS_Type_XFEXT: $this->_readXfExt(); break; + case self::XLS_Type_STYLE: $this->_readStyle(); break; + case self::XLS_Type_PALETTE: $this->_readPalette(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EXTERNALBOOK: $this->_readExternalBook(); break; + case self::XLS_Type_EXTERNNAME: $this->_readExternName(); break; + case self::XLS_Type_EXTERNSHEET: $this->_readExternSheet(); break; + case self::XLS_Type_DEFINEDNAME: $this->_readDefinedName(); break; + case self::XLS_Type_MSODRAWINGGROUP: $this->_readMsoDrawingGroup(); break; + case self::XLS_Type_SST: $this->_readSst(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + // Resolve indexed colors for font, fill, and border colors + // Cannot be resolved already in XF record, because PALETTE record comes afterwards + if (!$this->_readDataOnly) { + foreach ($this->_objFonts as $objFont) { + if (isset($objFont->colorIndex)) { + $color = self::_readColor($objFont->colorIndex,$this->_palette,$this->_version); + $objFont->getColor()->setRGB($color['rgb']); + } + } + + foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) { + // fill start and end color + $fill = $objStyle->getFill(); + + if (isset($fill->startcolorIndex)) { + $startColor = self::_readColor($fill->startcolorIndex,$this->_palette,$this->_version); + $fill->getStartColor()->setRGB($startColor['rgb']); + } + + if (isset($fill->endcolorIndex)) { + $endColor = self::_readColor($fill->endcolorIndex,$this->_palette,$this->_version); + $fill->getEndColor()->setRGB($endColor['rgb']); + } + + // border colors + $top = $objStyle->getBorders()->getTop(); + $right = $objStyle->getBorders()->getRight(); + $bottom = $objStyle->getBorders()->getBottom(); + $left = $objStyle->getBorders()->getLeft(); + $diagonal = $objStyle->getBorders()->getDiagonal(); + + if (isset($top->colorIndex)) { + $borderTopColor = self::_readColor($top->colorIndex,$this->_palette,$this->_version); + $top->getColor()->setRGB($borderTopColor['rgb']); + } + + if (isset($right->colorIndex)) { + $borderRightColor = self::_readColor($right->colorIndex,$this->_palette,$this->_version); + $right->getColor()->setRGB($borderRightColor['rgb']); + } + + if (isset($bottom->colorIndex)) { + $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette,$this->_version); + $bottom->getColor()->setRGB($borderBottomColor['rgb']); + } + + if (isset($left->colorIndex)) { + $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette,$this->_version); + $left->getColor()->setRGB($borderLeftColor['rgb']); + } + + if (isset($diagonal->colorIndex)) { + $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette,$this->_version); + $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); + } + } + } + + // treat MSODRAWINGGROUP records, workbook-level Escher + if (!$this->_readDataOnly && $this->_drawingGroupData) { + $escherWorkbook = new PHPExcel_Shared_Escher(); + $reader = new PHPExcel_Reader_Excel5_Escher($escherWorkbook); + $escherWorkbook = $reader->load($this->_drawingGroupData); + + // debug Escher stream + //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); + //$debug->load($this->_drawingGroupData); + } + + // Parse the individual sheets + foreach ($this->_sheets as $sheet) { + + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module + continue; + } + + // check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array($sheet['name'], $this->_loadSheetsOnly)) { + continue; + } + + // add sheet to PHPExcel object + $this->_phpSheet = $this->_phpExcel->createSheet(); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula + // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet + // name in line with the formula, not the reverse + $this->_phpSheet->setTitle($sheet['name'],false); + $this->_phpSheet->setSheetState($sheet['sheetState']); + + $this->_pos = $sheet['offset']; + + // Initialize isFitToPages. May change after reading SHEETPR record. + $this->_isFitToPages = false; + + // Initialize drawingData + $this->_drawingData = ''; + + // Initialize objs + $this->_objs = array(); + + // Initialize shared formula parts + $this->_sharedFormulaParts = array(); + + // Initialize shared formulas + $this->_sharedFormulas = array(); + + // Initialize text objs + $this->_textObjects = array(); + + // Initialize cell annotations + $this->_cellNotes = array(); + $this->textObjRef = -1; + + while ($this->_pos <= $this->_dataSize - 4) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_PRINTGRIDLINES: $this->_readPrintGridlines(); break; + case self::XLS_Type_DEFAULTROWHEIGHT: $this->_readDefaultRowHeight(); break; + case self::XLS_Type_SHEETPR: $this->_readSheetPr(); break; + case self::XLS_Type_HORIZONTALPAGEBREAKS: $this->_readHorizontalPageBreaks(); break; + case self::XLS_Type_VERTICALPAGEBREAKS: $this->_readVerticalPageBreaks(); break; + case self::XLS_Type_HEADER: $this->_readHeader(); break; + case self::XLS_Type_FOOTER: $this->_readFooter(); break; + case self::XLS_Type_HCENTER: $this->_readHcenter(); break; + case self::XLS_Type_VCENTER: $this->_readVcenter(); break; + case self::XLS_Type_LEFTMARGIN: $this->_readLeftMargin(); break; + case self::XLS_Type_RIGHTMARGIN: $this->_readRightMargin(); break; + case self::XLS_Type_TOPMARGIN: $this->_readTopMargin(); break; + case self::XLS_Type_BOTTOMMARGIN: $this->_readBottomMargin(); break; + case self::XLS_Type_PAGESETUP: $this->_readPageSetup(); break; + case self::XLS_Type_PROTECT: $this->_readProtect(); break; + case self::XLS_Type_SCENPROTECT: $this->_readScenProtect(); break; + case self::XLS_Type_OBJECTPROTECT: $this->_readObjectProtect(); break; + case self::XLS_Type_PASSWORD: $this->_readPassword(); break; + case self::XLS_Type_DEFCOLWIDTH: $this->_readDefColWidth(); break; + case self::XLS_Type_COLINFO: $this->_readColInfo(); break; + case self::XLS_Type_DIMENSION: $this->_readDefault(); break; + case self::XLS_Type_ROW: $this->_readRow(); break; + case self::XLS_Type_DBCELL: $this->_readDefault(); break; + case self::XLS_Type_RK: $this->_readRk(); break; + case self::XLS_Type_LABELSST: $this->_readLabelSst(); break; + case self::XLS_Type_MULRK: $this->_readMulRk(); break; + case self::XLS_Type_NUMBER: $this->_readNumber(); break; + case self::XLS_Type_FORMULA: $this->_readFormula(); break; + case self::XLS_Type_SHAREDFMLA: $this->_readSharedFmla(); break; + case self::XLS_Type_BOOLERR: $this->_readBoolErr(); break; + case self::XLS_Type_MULBLANK: $this->_readMulBlank(); break; + case self::XLS_Type_LABEL: $this->_readLabel(); break; + case self::XLS_Type_BLANK: $this->_readBlank(); break; + case self::XLS_Type_MSODRAWING: $this->_readMsoDrawing(); break; + case self::XLS_Type_OBJ: $this->_readObj(); break; + case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; + case self::XLS_Type_PAGELAYOUTVIEW: $this->_readPageLayoutView(); break; + case self::XLS_Type_SCL: $this->_readScl(); break; + case self::XLS_Type_PANE: $this->_readPane(); break; + case self::XLS_Type_SELECTION: $this->_readSelection(); break; + case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; + case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; + case self::XLS_Type_DATAVALIDATIONS: $this->_readDataValidations(); break; + case self::XLS_Type_DATAVALIDATION: $this->_readDataValidation(); break; + case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; + case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; + case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; + case self::XLS_Type_NOTE: $this->_readNote(); break; + //case self::XLS_Type_IMDATA: $this->_readImData(); break; + case self::XLS_Type_TXO: $this->_readTextObject(); break; + case self::XLS_Type_CONTINUE: $this->_readContinue(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + + } + + // treat MSODRAWING records, sheet-level Escher + if (!$this->_readDataOnly && $this->_drawingData) { + $escherWorksheet = new PHPExcel_Shared_Escher(); + $reader = new PHPExcel_Reader_Excel5_Escher($escherWorksheet); + $escherWorksheet = $reader->load($this->_drawingData); + + // debug Escher stream + //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); + //$debug->load($this->_drawingData); + + // get all spContainers in one long array, so they can be mapped to OBJ records + $allSpContainers = $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers(); + } + + // treat OBJ records + foreach ($this->_objs as $n => $obj) { +// echo '
Object reference is ',$n,'
'; +// var_dump($obj); +// echo '
'; + + // the first shape container never has a corresponding OBJ record, hence $n + 1 + if (isset($allSpContainers[$n + 1]) && is_object($allSpContainers[$n + 1])) { + $spContainer = $allSpContainers[$n + 1]; + + // we skip all spContainers that are a part of a group shape since we cannot yet handle those + if ($spContainer->getNestingLevel() > 1) { + continue; + } + + // calculate the width and height of the shape + list($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($spContainer->getStartCoordinates()); + list($endColumn, $endRow) = PHPExcel_Cell::coordinateFromString($spContainer->getEndCoordinates()); + + $startOffsetX = $spContainer->getStartOffsetX(); + $startOffsetY = $spContainer->getStartOffsetY(); + $endOffsetX = $spContainer->getEndOffsetX(); + $endOffsetY = $spContainer->getEndOffsetY(); + + $width = PHPExcel_Shared_Excel5::getDistanceX($this->_phpSheet, $startColumn, $startOffsetX, $endColumn, $endOffsetX); + $height = PHPExcel_Shared_Excel5::getDistanceY($this->_phpSheet, $startRow, $startOffsetY, $endRow, $endOffsetY); + + // calculate offsetX and offsetY of the shape + $offsetX = $startOffsetX * PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, $startColumn) / 1024; + $offsetY = $startOffsetY * PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $startRow) / 256; + + switch ($obj['otObjType']) { + case 0x19: + // Note +// echo 'Cell Annotation Object
'; +// echo 'Object ID is ',$obj['idObjID'],'
'; // - if (isset($this->_cellNotes[$obj['idObjID']])) { - $cellNote = $this->_cellNotes[$obj['idObjID']]; + if (isset($this->_cellNotes[$obj['idObjID']])) { + $cellNote = $this->_cellNotes[$obj['idObjID']]; - if (isset($this->_textObjects[$obj['idObjID']])) { - $textObject = $this->_textObjects[$obj['idObjID']]; - $this->_cellNotes[$obj['idObjID']]['objTextData'] = $textObject; - } - } - break; + if (isset($this->_textObjects[$obj['idObjID']])) { + $textObject = $this->_textObjects[$obj['idObjID']]; + $this->_cellNotes[$obj['idObjID']]['objTextData'] = $textObject; + } + } + break; - case 0x08: -// echo 'Picture Object
'; - // picture + case 0x08: +// echo 'Picture Object
'; + // picture - // get index to BSE entry (1-based) - $BSEindex = $spContainer->getOPT(0x0104); - $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); - $BSE = $BSECollection[$BSEindex - 1]; - $blipType = $BSE->getBlipType(); + // get index to BSE entry (1-based) + $BSEindex = $spContainer->getOPT(0x0104); + $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); + $BSE = $BSECollection[$BSEindex - 1]; + $blipType = $BSE->getBlipType(); - // need check because some blip types are not supported by Escher reader such as EMF - if ($blip = $BSE->getBlip()) { - $ih = imagecreatefromstring($blip->getData()); - $drawing = new PHPExcel_Worksheet_MemoryDrawing(); - $drawing->setImageResource($ih); + // need check because some blip types are not supported by Escher reader such as EMF + if ($blip = $BSE->getBlip()) { + $ih = imagecreatefromstring($blip->getData()); + $drawing = new PHPExcel_Worksheet_MemoryDrawing(); + $drawing->setImageResource($ih); - // width, height, offsetX, offsetY - $drawing->setResizeProportional(false); - $drawing->setWidth($width); - $drawing->setHeight($height); - $drawing->setOffsetX($offsetX); - $drawing->setOffsetY($offsetY); + // width, height, offsetX, offsetY + $drawing->setResizeProportional(false); + $drawing->setWidth($width); + $drawing->setHeight($height); + $drawing->setOffsetX($offsetX); + $drawing->setOffsetY($offsetY); - switch ($blipType) { - case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: - $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG); - $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_JPEG); - break; + switch ($blipType) { + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: + $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG); + $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_JPEG); + break; - case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: - $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG); - $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_PNG); - break; - } + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: + $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG); + $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_PNG); + break; + } - $drawing->setWorksheet($this->_phpSheet); - $drawing->setCoordinates($spContainer->getStartCoordinates()); - } + $drawing->setWorksheet($this->_phpSheet); + $drawing->setCoordinates($spContainer->getStartCoordinates()); + } - break; + break; - default: - // other object type - break; + default: + // other object type + break; - } - } - } + } + } + } - // treat SHAREDFMLA records - if ($this->_version == self::XLS_BIFF8) { - foreach ($this->_sharedFormulaParts as $cell => $baseCell) { - list($column, $row) = PHPExcel_Cell::coordinateFromString($cell); - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle()) ) { - $formula = $this->_getFormulaFromStructure($this->_sharedFormulas[$baseCell], $cell); - $this->_phpSheet->getCell($cell)->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); - } - } - } + // treat SHAREDFMLA records + if ($this->_version == self::XLS_BIFF8) { + foreach ($this->_sharedFormulaParts as $cell => $baseCell) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($cell); + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle()) ) { + $formula = $this->_getFormulaFromStructure($this->_sharedFormulas[$baseCell], $cell); + $this->_phpSheet->getCell($cell)->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + } + } + } - if (!empty($this->_cellNotes)) { - foreach($this->_cellNotes as $note => $noteDetails) { - if (!isset($noteDetails['objTextData'])) { - if (isset($this->_textObjects[$note])) { - $textObject = $this->_textObjects[$note]; - $noteDetails['objTextData'] = $textObject; - } else { - $noteDetails['objTextData']['text'] = ''; - } - } -// echo 'Cell annotation ',$note,'
'; -// var_dump($noteDetails); -// echo '
'; - $cellAddress = str_replace('$','',$noteDetails['cellRef']); - $this->_phpSheet->getComment( $cellAddress ) - ->setAuthor( $noteDetails['author'] ) - ->setText($this->_parseRichText($noteDetails['objTextData']['text']) ); - } - } - } + if (!empty($this->_cellNotes)) { + foreach($this->_cellNotes as $note => $noteDetails) { + if (!isset($noteDetails['objTextData'])) { + if (isset($this->_textObjects[$note])) { + $textObject = $this->_textObjects[$note]; + $noteDetails['objTextData'] = $textObject; + } else { + $noteDetails['objTextData']['text'] = ''; + } + } +// echo 'Cell annotation ',$note,'
'; +// var_dump($noteDetails); +// echo '
'; + $cellAddress = str_replace('$','',$noteDetails['cellRef']); + $this->_phpSheet->getComment( $cellAddress ) + ->setAuthor( $noteDetails['author'] ) + ->setText($this->_parseRichText($noteDetails['objTextData']['text']) ); + } + } + } - // add the named ranges (defined names) - foreach ($this->_definedname as $definedName) { - if ($definedName['isBuiltInName']) { - switch ($definedName['name']) { + // add the named ranges (defined names) + foreach ($this->_definedname as $definedName) { + if ($definedName['isBuiltInName']) { + switch ($definedName['name']) { - case pack('C', 0x06): - // print area - // in general, formula looks like this: Foo!$C$7:$J$66,Bar!$A$1:$IV$2 - $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + case pack('C', 0x06): + // print area + // in general, formula looks like this: Foo!$C$7:$J$66,Bar!$A$1:$IV$2 + $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? - $extractedRanges = array(); - foreach ($ranges as $range) { - // $range should look like one of these - // Foo!$C$7:$J$66 - // Bar!$A$1:$IV$2 + $extractedRanges = array(); + foreach ($ranges as $range) { + // $range should look like one of these + // Foo!$C$7:$J$66 + // Bar!$A$1:$IV$2 - $explodes = explode('!', $range); // FIXME: what if sheetname contains exclamation mark? - $sheetName = trim($explodes[0], "'"); + $explodes = explode('!', $range); // FIXME: what if sheetname contains exclamation mark? + $sheetName = trim($explodes[0], "'"); - if (count($explodes) == 2) { - if (strpos($explodes[1], ':') === FALSE) { - $explodes[1] = $explodes[1] . ':' . $explodes[1]; - } - $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 - } - } - if ($docSheet = $this->_phpExcel->getSheetByName($sheetName)) { - $docSheet->getPageSetup()->setPrintArea(implode(',', $extractedRanges)); // C7:J66,A1:IV2 - } - break; + if (count($explodes) == 2) { + if (strpos($explodes[1], ':') === FALSE) { + $explodes[1] = $explodes[1] . ':' . $explodes[1]; + } + $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 + } + } + if ($docSheet = $this->_phpExcel->getSheetByName($sheetName)) { + $docSheet->getPageSetup()->setPrintArea(implode(',', $extractedRanges)); // C7:J66,A1:IV2 + } + break; - case pack('C', 0x07): - // print titles (repeating rows) - // Assuming BIFF8, there are 3 cases - // 1. repeating rows - // formula looks like this: Sheet!$A$1:$IV$2 - // rows 1-2 repeat - // 2. repeating columns - // formula looks like this: Sheet!$A$1:$B$65536 - // columns A-B repeat - // 3. both repeating rows and repeating columns - // formula looks like this: Sheet!$A$1:$B$65536,Sheet!$A$1:$IV$2 + case pack('C', 0x07): + // print titles (repeating rows) + // Assuming BIFF8, there are 3 cases + // 1. repeating rows + // formula looks like this: Sheet!$A$1:$IV$2 + // rows 1-2 repeat + // 2. repeating columns + // formula looks like this: Sheet!$A$1:$B$65536 + // columns A-B repeat + // 3. both repeating rows and repeating columns + // formula looks like this: Sheet!$A$1:$B$65536,Sheet!$A$1:$IV$2 - $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? - foreach ($ranges as $range) { - // $range should look like this one of these - // Sheet!$A$1:$B$65536 - // Sheet!$A$1:$IV$2 + foreach ($ranges as $range) { + // $range should look like this one of these + // Sheet!$A$1:$B$65536 + // Sheet!$A$1:$IV$2 - $explodes = explode('!', $range); + $explodes = explode('!', $range); - if (count($explodes) == 2) { - if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) { + if (count($explodes) == 2) { + if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) { - $extractedRange = $explodes[1]; - $extractedRange = str_replace('$', '', $extractedRange); + $extractedRange = $explodes[1]; + $extractedRange = str_replace('$', '', $extractedRange); - $coordinateStrings = explode(':', $extractedRange); - if (count($coordinateStrings) == 2) { - list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[0]); - list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[1]); + $coordinateStrings = explode(':', $extractedRange); + if (count($coordinateStrings) == 2) { + list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[0]); + list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[1]); - if ($firstColumn == 'A' and $lastColumn == 'IV') { - // then we have repeating rows - $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($firstRow, $lastRow)); - } elseif ($firstRow == 1 and $lastRow == 65536) { - // then we have repeating columns - $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($firstColumn, $lastColumn)); - } - } - } - } - } - break; + if ($firstColumn == 'A' and $lastColumn == 'IV') { + // then we have repeating rows + $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($firstRow, $lastRow)); + } elseif ($firstRow == 1 and $lastRow == 65536) { + // then we have repeating columns + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($firstColumn, $lastColumn)); + } + } + } + } + } + break; - } - } else { - // Extract range - $explodes = explode('!', $definedName['formula']); + } + } else { + // Extract range + $explodes = explode('!', $definedName['formula']); - if (count($explodes) == 2) { - if (($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) || - ($docSheet = $this->_phpExcel->getSheetByName(trim($explodes[0],"'")))) { - $extractedRange = $explodes[1]; - $extractedRange = str_replace('$', '', $extractedRange); + if (count($explodes) == 2) { + if (($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) || + ($docSheet = $this->_phpExcel->getSheetByName(trim($explodes[0],"'")))) { + $extractedRange = $explodes[1]; + $extractedRange = str_replace('$', '', $extractedRange); - $localOnly = ($definedName['scope'] == 0) ? false : true; + $localOnly = ($definedName['scope'] == 0) ? false : true; - $scope = ($definedName['scope'] == 0) ? - null : $this->_phpExcel->getSheetByName($this->_sheets[$definedName['scope'] - 1]['name']); + $scope = ($definedName['scope'] == 0) ? + null : $this->_phpExcel->getSheetByName($this->_sheets[$definedName['scope'] - 1]['name']); - $this->_phpExcel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, $localOnly, $scope) ); - } - } else { - // Named Value - // TODO Provide support for named values - } - } - } + $this->_phpExcel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, $localOnly, $scope) ); + } + } else { + // Named Value + // TODO Provide support for named values + } + } + } $this->_data = null; - return $this->_phpExcel; - } - - /** - * Read record data from stream, decrypting as required - * - * @param string $data Data stream to read from - * @param int $pos Position to start reading from - * @param int $length Record data length - * - * @return string Record data - */ - private function _readRecordData($data, $pos, $len) - { - $data = substr($data, $pos, $len); - - // File not encrypted, or record before encryption start point - if ($this->_encryption == self::MS_BIFF_CRYPTO_NONE || $pos < $this->_encryptionStartPos) { - return $data; - } - - $recordData = ''; - if ($this->_encryption == self::MS_BIFF_CRYPTO_RC4) { - - $oldBlock = floor($this->_rc4Pos / self::REKEY_BLOCK); - $block = floor($pos / self::REKEY_BLOCK); - $endBlock = floor(($pos + $len) / self::REKEY_BLOCK); - - // Spin an RC4 decryptor to the right spot. If we have a decryptor sitting - // at a point earlier in the current block, re-use it as we can save some time. - if ($block != $oldBlock || $pos < $this->_rc4Pos || !$this->_rc4Key) { - $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); - $step = $pos % self::REKEY_BLOCK; - } else { - $step = $pos - $this->_rc4Pos; - } - $this->_rc4Key->RC4(str_repeat("\0", $step)); - - // Decrypt record data (re-keying at the end of every block) - while ($block != $endBlock) { - $step = self::REKEY_BLOCK - ($pos % self::REKEY_BLOCK); - $recordData .= $this->_rc4Key->RC4(substr($data, 0, $step)); - $data = substr($data, $step); - $pos += $step; - $len -= $step; - $block++; - $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); - } - $recordData .= $this->_rc4Key->RC4(substr($data, 0, $len)); - - // Keep track of the position of this decryptor. - // We'll try and re-use it later if we can to speed things up - $this->_rc4Pos = $pos + $len; - - } elseif ($this->_encryption == self::MS_BIFF_CRYPTO_XOR) { - throw new PHPExcel_Reader_Exception('XOr encryption not supported'); - } - return $recordData; - } - - /** - * Use OLE reader to extract the relevant data streams from the OLE file - * - * @param string $pFilename - */ - private function _loadOLE($pFilename) - { - // OLE reader - $ole = new PHPExcel_Shared_OLERead(); - - // get excel data, - $res = $ole->read($pFilename); - // Get workbook data: workbook stream + sheet streams - $this->_data = $ole->getStream($ole->wrkbook); - - // Get summary information data - $this->_summaryInformation = $ole->getStream($ole->summaryInformation); - - // Get additional document summary information data - $this->_documentSummaryInformation = $ole->getStream($ole->documentSummaryInformation); - - // Get user-defined property data -// $this->_userDefinedProperties = $ole->getUserDefinedProperties(); - } - - - /** - * Read summary information - */ - private function _readSummaryInformation() - { - if (!isset($this->_summaryInformation)) { - return; - } - - // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) - // offset: 2; size: 2; - // offset: 4; size: 2; OS version - // offset: 6; size: 2; OS indicator - // offset: 8; size: 16 - // offset: 24; size: 4; section count - $secCount = self::_GetInt4d($this->_summaryInformation, 24); - - // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 - // offset: 44; size: 4 - $secOffset = self::_GetInt4d($this->_summaryInformation, 44); - - // section header - // offset: $secOffset; size: 4; section length - $secLength = self::_GetInt4d($this->_summaryInformation, $secOffset); - - // offset: $secOffset+4; size: 4; property count - $countProperties = self::_GetInt4d($this->_summaryInformation, $secOffset+4); - - // initialize code page (used to resolve string values) - $codePage = 'CP1252'; - - // offset: ($secOffset+8); size: var - // loop through property decarations and properties - for ($i = 0; $i < $countProperties; ++$i) { - - // offset: ($secOffset+8) + (8 * $i); size: 4; property ID - $id = self::_GetInt4d($this->_summaryInformation, ($secOffset+8) + (8 * $i)); - - // Use value of property id as appropriate - // offset: ($secOffset+12) + (8 * $i); size: 4; offset from beginning of section (48) - $offset = self::_GetInt4d($this->_summaryInformation, ($secOffset+12) + (8 * $i)); - - $type = self::_GetInt4d($this->_summaryInformation, $secOffset + $offset); - - // initialize property value - $value = null; - - // extract property value based on property type - switch ($type) { - case 0x02: // 2 byte signed integer - $value = self::_GetInt2d($this->_summaryInformation, $secOffset + 4 + $offset); - break; - - case 0x03: // 4 byte signed integer - $value = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); - break; - - case 0x13: // 4 byte unsigned integer - // not needed yet, fix later if necessary - break; - - case 0x1E: // null-terminated string prepended by dword string length - $byteLength = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); - $value = substr($this->_summaryInformation, $secOffset + 8 + $offset, $byteLength); - $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); - $value = rtrim($value); - break; - - case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - // PHP-time - $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_summaryInformation, $secOffset + 4 + $offset, 8)); - break; - - case 0x47: // Clipboard format - // not needed yet, fix later if necessary - break; - } - - switch ($id) { - case 0x01: // Code Page - $codePage = PHPExcel_Shared_CodePage::NumberToName($value); - break; - - case 0x02: // Title - $this->_phpExcel->getProperties()->setTitle($value); - break; - - case 0x03: // Subject - $this->_phpExcel->getProperties()->setSubject($value); - break; - - case 0x04: // Author (Creator) - $this->_phpExcel->getProperties()->setCreator($value); - break; - - case 0x05: // Keywords - $this->_phpExcel->getProperties()->setKeywords($value); - break; - - case 0x06: // Comments (Description) - $this->_phpExcel->getProperties()->setDescription($value); - break; - - case 0x07: // Template - // Not supported by PHPExcel - break; - - case 0x08: // Last Saved By (LastModifiedBy) - $this->_phpExcel->getProperties()->setLastModifiedBy($value); - break; - - case 0x09: // Revision - // Not supported by PHPExcel - break; - - case 0x0A: // Total Editing Time - // Not supported by PHPExcel - break; - - case 0x0B: // Last Printed - // Not supported by PHPExcel - break; - - case 0x0C: // Created Date/Time - $this->_phpExcel->getProperties()->setCreated($value); - break; - - case 0x0D: // Modified Date/Time - $this->_phpExcel->getProperties()->setModified($value); - break; - - case 0x0E: // Number of Pages - // Not supported by PHPExcel - break; - - case 0x0F: // Number of Words - // Not supported by PHPExcel - break; - - case 0x10: // Number of Characters - // Not supported by PHPExcel - break; - - case 0x11: // Thumbnail - // Not supported by PHPExcel - break; - - case 0x12: // Name of creating application - // Not supported by PHPExcel - break; - - case 0x13: // Security - // Not supported by PHPExcel - break; - - } - } - } - - - /** - * Read additional document summary information - */ - private function _readDocumentSummaryInformation() - { - if (!isset($this->_documentSummaryInformation)) { - return; - } - - // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) - // offset: 2; size: 2; - // offset: 4; size: 2; OS version - // offset: 6; size: 2; OS indicator - // offset: 8; size: 16 - // offset: 24; size: 4; section count - $secCount = self::_GetInt4d($this->_documentSummaryInformation, 24); -// echo '$secCount = ',$secCount,'
'; - - // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae - // offset: 44; size: 4; first section offset - $secOffset = self::_GetInt4d($this->_documentSummaryInformation, 44); -// echo '$secOffset = ',$secOffset,'
'; - - // section header - // offset: $secOffset; size: 4; section length - $secLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset); -// echo '$secLength = ',$secLength,'
'; - - // offset: $secOffset+4; size: 4; property count - $countProperties = self::_GetInt4d($this->_documentSummaryInformation, $secOffset+4); -// echo '$countProperties = ',$countProperties,'
'; - - // initialize code page (used to resolve string values) - $codePage = 'CP1252'; - - // offset: ($secOffset+8); size: var - // loop through property decarations and properties - for ($i = 0; $i < $countProperties; ++$i) { -// echo 'Property ',$i,'
'; - // offset: ($secOffset+8) + (8 * $i); size: 4; property ID - $id = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+8) + (8 * $i)); -// echo 'ID is ',$id,'
'; - - // Use value of property id as appropriate - // offset: 60 + 8 * $i; size: 4; offset from beginning of section (48) - $offset = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+12) + (8 * $i)); - - $type = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + $offset); -// echo 'Type is ',$type,', '; - - // initialize property value - $value = null; - - // extract property value based on property type - switch ($type) { - case 0x02: // 2 byte signed integer - $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); - break; - - case 0x03: // 4 byte signed integer - $value = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); - break; - - case 0x0B: // Boolean - $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); - $value = ($value == 0 ? false : true); - break; - - case 0x13: // 4 byte unsigned integer - // not needed yet, fix later if necessary - break; - - case 0x1E: // null-terminated string prepended by dword string length - $byteLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); - $value = substr($this->_documentSummaryInformation, $secOffset + 8 + $offset, $byteLength); - $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); - $value = rtrim($value); - break; - - case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - // PHP-Time - $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_documentSummaryInformation, $secOffset + 4 + $offset, 8)); - break; - - case 0x47: // Clipboard format - // not needed yet, fix later if necessary - break; - } - - switch ($id) { - case 0x01: // Code Page - $codePage = PHPExcel_Shared_CodePage::NumberToName($value); - break; - - case 0x02: // Category - $this->_phpExcel->getProperties()->setCategory($value); - break; - - case 0x03: // Presentation Target - // Not supported by PHPExcel - break; - - case 0x04: // Bytes - // Not supported by PHPExcel - break; - - case 0x05: // Lines - // Not supported by PHPExcel - break; - - case 0x06: // Paragraphs - // Not supported by PHPExcel - break; - - case 0x07: // Slides - // Not supported by PHPExcel - break; - - case 0x08: // Notes - // Not supported by PHPExcel - break; - - case 0x09: // Hidden Slides - // Not supported by PHPExcel - break; - - case 0x0A: // MM Clips - // Not supported by PHPExcel - break; - - case 0x0B: // Scale Crop - // Not supported by PHPExcel - break; - - case 0x0C: // Heading Pairs - // Not supported by PHPExcel - break; - - case 0x0D: // Titles of Parts - // Not supported by PHPExcel - break; - - case 0x0E: // Manager - $this->_phpExcel->getProperties()->setManager($value); - break; - - case 0x0F: // Company - $this->_phpExcel->getProperties()->setCompany($value); - break; - - case 0x10: // Links up-to-date - // Not supported by PHPExcel - break; - - } - } - } - - - /** - * Reads a general type of BIFF record. Does nothing except for moving stream pointer forward to next record. - */ - private function _readDefault() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); -// $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - } - - - /** - * The NOTE record specifies a comment associated with a particular cell. In Excel 95 (BIFF7) and earlier versions, - * this record stores a note (cell note). This feature was significantly enhanced in Excel 97. - */ - private function _readNote() - { -// echo 'Read Cell Annotation
'; - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_readDataOnly) { - return; - } - - $cellAddress = $this->_readBIFF8CellAddress(substr($recordData, 0, 4)); - if ($this->_version == self::XLS_BIFF8) { - $noteObjID = self::_GetInt2d($recordData, 6); - $noteAuthor = self::_readUnicodeStringLong(substr($recordData, 8)); - $noteAuthor = $noteAuthor['value']; -// echo 'Note Address=',$cellAddress,'
'; -// echo 'Note Object ID=',$noteObjID,'
'; -// echo 'Note Author=',$noteAuthor,'
'; + return $this->_phpExcel; + } + + /** + * Read record data from stream, decrypting as required + * + * @param string $data Data stream to read from + * @param int $pos Position to start reading from + * @param int $length Record data length + * + * @return string Record data + */ + private function _readRecordData($data, $pos, $len) + { + $data = substr($data, $pos, $len); + + // File not encrypted, or record before encryption start point + if ($this->_encryption == self::MS_BIFF_CRYPTO_NONE || $pos < $this->_encryptionStartPos) { + return $data; + } + + $recordData = ''; + if ($this->_encryption == self::MS_BIFF_CRYPTO_RC4) { + + $oldBlock = floor($this->_rc4Pos / self::REKEY_BLOCK); + $block = floor($pos / self::REKEY_BLOCK); + $endBlock = floor(($pos + $len) / self::REKEY_BLOCK); + + // Spin an RC4 decryptor to the right spot. If we have a decryptor sitting + // at a point earlier in the current block, re-use it as we can save some time. + if ($block != $oldBlock || $pos < $this->_rc4Pos || !$this->_rc4Key) { + $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); + $step = $pos % self::REKEY_BLOCK; + } else { + $step = $pos - $this->_rc4Pos; + } + $this->_rc4Key->RC4(str_repeat("\0", $step)); + + // Decrypt record data (re-keying at the end of every block) + while ($block != $endBlock) { + $step = self::REKEY_BLOCK - ($pos % self::REKEY_BLOCK); + $recordData .= $this->_rc4Key->RC4(substr($data, 0, $step)); + $data = substr($data, $step); + $pos += $step; + $len -= $step; + $block++; + $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); + } + $recordData .= $this->_rc4Key->RC4(substr($data, 0, $len)); + + // Keep track of the position of this decryptor. + // We'll try and re-use it later if we can to speed things up + $this->_rc4Pos = $pos + $len; + + } elseif ($this->_encryption == self::MS_BIFF_CRYPTO_XOR) { + throw new PHPExcel_Reader_Exception('XOr encryption not supported'); + } + return $recordData; + } + + /** + * Use OLE reader to extract the relevant data streams from the OLE file + * + * @param string $pFilename + */ + private function _loadOLE($pFilename) + { + // OLE reader + $ole = new PHPExcel_Shared_OLERead(); + + // get excel data, + $res = $ole->read($pFilename); + // Get workbook data: workbook stream + sheet streams + $this->_data = $ole->getStream($ole->wrkbook); + + // Get summary information data + $this->_summaryInformation = $ole->getStream($ole->summaryInformation); + + // Get additional document summary information data + $this->_documentSummaryInformation = $ole->getStream($ole->documentSummaryInformation); + + // Get user-defined property data +// $this->_userDefinedProperties = $ole->getUserDefinedProperties(); + } + + + /** + * Read summary information + */ + private function _readSummaryInformation() + { + if (!isset($this->_summaryInformation)) { + return; + } + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + // offset: 2; size: 2; + // offset: 4; size: 2; OS version + // offset: 6; size: 2; OS indicator + // offset: 8; size: 16 + // offset: 24; size: 4; section count + $secCount = self::_GetInt4d($this->_summaryInformation, 24); + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + // offset: 44; size: 4 + $secOffset = self::_GetInt4d($this->_summaryInformation, 44); + + // section header + // offset: $secOffset; size: 4; section length + $secLength = self::_GetInt4d($this->_summaryInformation, $secOffset); + + // offset: $secOffset+4; size: 4; property count + $countProperties = self::_GetInt4d($this->_summaryInformation, $secOffset+4); + + // initialize code page (used to resolve string values) + $codePage = 'CP1252'; + + // offset: ($secOffset+8); size: var + // loop through property decarations and properties + for ($i = 0; $i < $countProperties; ++$i) { + + // offset: ($secOffset+8) + (8 * $i); size: 4; property ID + $id = self::_GetInt4d($this->_summaryInformation, ($secOffset+8) + (8 * $i)); + + // Use value of property id as appropriate + // offset: ($secOffset+12) + (8 * $i); size: 4; offset from beginning of section (48) + $offset = self::_GetInt4d($this->_summaryInformation, ($secOffset+12) + (8 * $i)); + + $type = self::_GetInt4d($this->_summaryInformation, $secOffset + $offset); + + // initialize property value + $value = null; + + // extract property value based on property type + switch ($type) { + case 0x02: // 2 byte signed integer + $value = self::_GetInt2d($this->_summaryInformation, $secOffset + 4 + $offset); + break; + + case 0x03: // 4 byte signed integer + $value = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); + break; + + case 0x13: // 4 byte unsigned integer + // not needed yet, fix later if necessary + break; + + case 0x1E: // null-terminated string prepended by dword string length + $byteLength = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); + $value = substr($this->_summaryInformation, $secOffset + 8 + $offset, $byteLength); + $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); + $value = rtrim($value); + break; + + case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // PHP-time + $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_summaryInformation, $secOffset + 4 + $offset, 8)); + break; + + case 0x47: // Clipboard format + // not needed yet, fix later if necessary + break; + } + + switch ($id) { + case 0x01: // Code Page + $codePage = PHPExcel_Shared_CodePage::NumberToName($value); + break; + + case 0x02: // Title + $this->_phpExcel->getProperties()->setTitle($value); + break; + + case 0x03: // Subject + $this->_phpExcel->getProperties()->setSubject($value); + break; + + case 0x04: // Author (Creator) + $this->_phpExcel->getProperties()->setCreator($value); + break; + + case 0x05: // Keywords + $this->_phpExcel->getProperties()->setKeywords($value); + break; + + case 0x06: // Comments (Description) + $this->_phpExcel->getProperties()->setDescription($value); + break; + + case 0x07: // Template + // Not supported by PHPExcel + break; + + case 0x08: // Last Saved By (LastModifiedBy) + $this->_phpExcel->getProperties()->setLastModifiedBy($value); + break; + + case 0x09: // Revision + // Not supported by PHPExcel + break; + + case 0x0A: // Total Editing Time + // Not supported by PHPExcel + break; + + case 0x0B: // Last Printed + // Not supported by PHPExcel + break; + + case 0x0C: // Created Date/Time + $this->_phpExcel->getProperties()->setCreated($value); + break; + + case 0x0D: // Modified Date/Time + $this->_phpExcel->getProperties()->setModified($value); + break; + + case 0x0E: // Number of Pages + // Not supported by PHPExcel + break; + + case 0x0F: // Number of Words + // Not supported by PHPExcel + break; + + case 0x10: // Number of Characters + // Not supported by PHPExcel + break; + + case 0x11: // Thumbnail + // Not supported by PHPExcel + break; + + case 0x12: // Name of creating application + // Not supported by PHPExcel + break; + + case 0x13: // Security + // Not supported by PHPExcel + break; + + } + } + } + + + /** + * Read additional document summary information + */ + private function _readDocumentSummaryInformation() + { + if (!isset($this->_documentSummaryInformation)) { + return; + } + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + // offset: 2; size: 2; + // offset: 4; size: 2; OS version + // offset: 6; size: 2; OS indicator + // offset: 8; size: 16 + // offset: 24; size: 4; section count + $secCount = self::_GetInt4d($this->_documentSummaryInformation, 24); +// echo '$secCount = ',$secCount,'
'; + + // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae + // offset: 44; size: 4; first section offset + $secOffset = self::_GetInt4d($this->_documentSummaryInformation, 44); +// echo '$secOffset = ',$secOffset,'
'; + + // section header + // offset: $secOffset; size: 4; section length + $secLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset); +// echo '$secLength = ',$secLength,'
'; + + // offset: $secOffset+4; size: 4; property count + $countProperties = self::_GetInt4d($this->_documentSummaryInformation, $secOffset+4); +// echo '$countProperties = ',$countProperties,'
'; + + // initialize code page (used to resolve string values) + $codePage = 'CP1252'; + + // offset: ($secOffset+8); size: var + // loop through property decarations and properties + for ($i = 0; $i < $countProperties; ++$i) { +// echo 'Property ',$i,'
'; + // offset: ($secOffset+8) + (8 * $i); size: 4; property ID + $id = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+8) + (8 * $i)); +// echo 'ID is ',$id,'
'; + + // Use value of property id as appropriate + // offset: 60 + 8 * $i; size: 4; offset from beginning of section (48) + $offset = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+12) + (8 * $i)); + + $type = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + $offset); +// echo 'Type is ',$type,', '; + + // initialize property value + $value = null; + + // extract property value based on property type + switch ($type) { + case 0x02: // 2 byte signed integer + $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + break; + + case 0x03: // 4 byte signed integer + $value = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + break; + + case 0x0B: // Boolean + $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + $value = ($value == 0 ? false : true); + break; + + case 0x13: // 4 byte unsigned integer + // not needed yet, fix later if necessary + break; + + case 0x1E: // null-terminated string prepended by dword string length + $byteLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + $value = substr($this->_documentSummaryInformation, $secOffset + 8 + $offset, $byteLength); + $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); + $value = rtrim($value); + break; + + case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // PHP-Time + $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_documentSummaryInformation, $secOffset + 4 + $offset, 8)); + break; + + case 0x47: // Clipboard format + // not needed yet, fix later if necessary + break; + } + + switch ($id) { + case 0x01: // Code Page + $codePage = PHPExcel_Shared_CodePage::NumberToName($value); + break; + + case 0x02: // Category + $this->_phpExcel->getProperties()->setCategory($value); + break; + + case 0x03: // Presentation Target + // Not supported by PHPExcel + break; + + case 0x04: // Bytes + // Not supported by PHPExcel + break; + + case 0x05: // Lines + // Not supported by PHPExcel + break; + + case 0x06: // Paragraphs + // Not supported by PHPExcel + break; + + case 0x07: // Slides + // Not supported by PHPExcel + break; + + case 0x08: // Notes + // Not supported by PHPExcel + break; + + case 0x09: // Hidden Slides + // Not supported by PHPExcel + break; + + case 0x0A: // MM Clips + // Not supported by PHPExcel + break; + + case 0x0B: // Scale Crop + // Not supported by PHPExcel + break; + + case 0x0C: // Heading Pairs + // Not supported by PHPExcel + break; + + case 0x0D: // Titles of Parts + // Not supported by PHPExcel + break; + + case 0x0E: // Manager + $this->_phpExcel->getProperties()->setManager($value); + break; + + case 0x0F: // Company + $this->_phpExcel->getProperties()->setCompany($value); + break; + + case 0x10: // Links up-to-date + // Not supported by PHPExcel + break; + + } + } + } + + + /** + * Reads a general type of BIFF record. Does nothing except for moving stream pointer forward to next record. + */ + private function _readDefault() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); +// $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + } + + + /** + * The NOTE record specifies a comment associated with a particular cell. In Excel 95 (BIFF7) and earlier versions, + * this record stores a note (cell note). This feature was significantly enhanced in Excel 97. + */ + private function _readNote() + { +// echo 'Read Cell Annotation
'; + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + $cellAddress = $this->_readBIFF8CellAddress(substr($recordData, 0, 4)); + if ($this->_version == self::XLS_BIFF8) { + $noteObjID = self::_GetInt2d($recordData, 6); + $noteAuthor = self::_readUnicodeStringLong(substr($recordData, 8)); + $noteAuthor = $noteAuthor['value']; +// echo 'Note Address=',$cellAddress,'
'; +// echo 'Note Object ID=',$noteObjID,'
'; +// echo 'Note Author=',$noteAuthor,'
'; // - $this->_cellNotes[$noteObjID] = array('cellRef' => $cellAddress, - 'objectID' => $noteObjID, - 'author' => $noteAuthor - ); - } else { - $extension = false; - if ($cellAddress == '$B$65536') { - // If the address row is -1 and the column is 0, (which translates as $B$65536) then this is a continuation - // note from the previous cell annotation. We're not yet handling this, so annotations longer than the - // max 2048 bytes will probably throw a wobbly. - $row = self::_GetInt2d($recordData, 0); - $extension = true; - $cellAddress = array_pop(array_keys($this->_phpSheet->getComments())); - } -// echo 'Note Address=',$cellAddress,'
'; - - $cellAddress = str_replace('$','',$cellAddress); - $noteLength = self::_GetInt2d($recordData, 4); - $noteText = trim(substr($recordData, 6)); -// echo 'Note Length=',$noteLength,'
'; -// echo 'Note Text=',$noteText,'
'; - - if ($extension) { - // Concatenate this extension with the currently set comment for the cell - $comment = $this->_phpSheet->getComment( $cellAddress ); - $commentText = $comment->getText()->getPlainText(); - $comment->setText($this->_parseRichText($commentText.$noteText) ); - } else { - // Set comment for the cell - $this->_phpSheet->getComment( $cellAddress ) -// ->setAuthor( $author ) - ->setText($this->_parseRichText($noteText) ); - } - } - - } - - - /** - * The TEXT Object record contains the text associated with a cell annotation. - */ - private function _readTextObject() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_readDataOnly) { - return; - } - - // recordData consists of an array of subrecords looking like this: - // grbit: 2 bytes; Option Flags - // rot: 2 bytes; rotation - // cchText: 2 bytes; length of the text (in the first continue record) - // cbRuns: 2 bytes; length of the formatting (in the second continue record) - // followed by the continuation records containing the actual text and formatting - $grbitOpts = self::_GetInt2d($recordData, 0); - $rot = self::_GetInt2d($recordData, 2); - $cchText = self::_GetInt2d($recordData, 10); - $cbRuns = self::_GetInt2d($recordData, 12); - $text = $this->_getSplicedRecordData(); - - $this->_textObjects[$this->textObjRef] = array( - 'text' => substr($text["recordData"],$text["spliceOffsets"][0]+1,$cchText), - 'format' => substr($text["recordData"],$text["spliceOffsets"][1],$cbRuns), - 'alignment' => $grbitOpts, - 'rotation' => $rot - ); - -// echo '_readTextObject()
'; -// var_dump($this->_textObjects[$this->textObjRef]); -// echo '
'; - } - - - /** - * Read BOF - */ - private function _readBof() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 2; size: 2; type of the following data - $substreamType = self::_GetInt2d($recordData, 2); - - switch ($substreamType) { - case self::XLS_WorkbookGlobals: - $version = self::_GetInt2d($recordData, 0); - if (($version != self::XLS_BIFF8) && ($version != self::XLS_BIFF7)) { - throw new PHPExcel_Reader_Exception('Cannot read this Excel file. Version is too old.'); - } - $this->_version = $version; - break; - - case self::XLS_Worksheet: - // do not use this version information for anything - // it is unreliable (OpenOffice doc, 5.8), use only version information from the global stream - break; - - default: - // substream, e.g. chart - // just skip the entire substream - do { - $code = self::_GetInt2d($this->_data, $this->_pos); - $this->_readDefault(); - } while ($code != self::XLS_Type_EOF && $this->_pos < $this->_dataSize); - break; - } - } - - - /** - * FILEPASS - * - * This record is part of the File Protection Block. It - * contains information about the read/write password of the - * file. All record contents following this record will be - * encrypted. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - * - * The decryption functions and objects used from here on in - * are based on the source of Spreadsheet-ParseExcel: - * http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel/ - */ - private function _readFilepass() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - - if ($length != 54) { - throw new PHPExcel_Reader_Exception('Unexpected file pass record length'); - } - - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_verifyPassword( - 'VelvetSweatshop', - substr($recordData, 6, 16), - substr($recordData, 22, 16), - substr($recordData, 38, 16), - $this->_md5Ctxt - )) { - throw new PHPExcel_Reader_Exception('Decryption password incorrect'); - } - - $this->_encryption = self::MS_BIFF_CRYPTO_RC4; - - // Decryption required from the record after next onwards - $this->_encryptionStartPos = $this->_pos + self::_GetInt2d($this->_data, $this->_pos + 2); - } - - /** - * Make an RC4 decryptor for the given block - * - * @var int $block Block for which to create decrypto - * @var string $valContext MD5 context state - * - * @return PHPExcel_Reader_Excel5_RC4 - */ - private function _makeKey($block, $valContext) - { - $pwarray = str_repeat("\0", 64); - - for ($i = 0; $i < 5; $i++) { - $pwarray[$i] = $valContext[$i]; - } - - $pwarray[5] = chr($block & 0xff); - $pwarray[6] = chr(($block >> 8) & 0xff); - $pwarray[7] = chr(($block >> 16) & 0xff); - $pwarray[8] = chr(($block >> 24) & 0xff); - - $pwarray[9] = "\x80"; - $pwarray[56] = "\x48"; - - $md5 = new PHPExcel_Reader_Excel5_MD5(); - $md5->add($pwarray); - - $s = $md5->getContext(); - return new PHPExcel_Reader_Excel5_RC4($s); - } - - /** - * Verify RC4 file password - * - * @var string $password Password to check - * @var string $docid Document id - * @var string $salt_data Salt data - * @var string $hashedsalt_data Hashed salt data - * @var string &$valContext Set to the MD5 context of the value - * - * @return bool Success - */ - private function _verifyPassword($password, $docid, $salt_data, $hashedsalt_data, &$valContext) - { - $pwarray = str_repeat("\0", 64); - - for ($i = 0; $i < strlen($password); $i++) { - $o = ord(substr($password, $i, 1)); - $pwarray[2 * $i] = chr($o & 0xff); - $pwarray[2 * $i + 1] = chr(($o >> 8) & 0xff); - } - $pwarray[2 * $i] = chr(0x80); - $pwarray[56] = chr(($i << 4) & 0xff); - - $md5 = new PHPExcel_Reader_Excel5_MD5(); - $md5->add($pwarray); - - $mdContext1 = $md5->getContext(); - - $offset = 0; - $keyoffset = 0; - $tocopy = 5; - - $md5->reset(); - - while ($offset != 16) { - if ((64 - $offset) < 5) { - $tocopy = 64 - $offset; - } - - for ($i = 0; $i <= $tocopy; $i++) { - $pwarray[$offset + $i] = $mdContext1[$keyoffset + $i]; - } - - $offset += $tocopy; - - if ($offset == 64) { - $md5->add($pwarray); - $keyoffset = $tocopy; - $tocopy = 5 - $tocopy; - $offset = 0; - continue; - } - - $keyoffset = 0; - $tocopy = 5; - for ($i = 0; $i < 16; $i++) { - $pwarray[$offset + $i] = $docid[$i]; - } - $offset += 16; - } - - $pwarray[16] = "\x80"; - for ($i = 0; $i < 47; $i++) { - $pwarray[17 + $i] = "\0"; - } - $pwarray[56] = "\x80"; - $pwarray[57] = "\x0a"; - - $md5->add($pwarray); - $valContext = $md5->getContext(); - - $key = $this->_makeKey(0, $valContext); - - $salt = $key->RC4($salt_data); - $hashedsalt = $key->RC4($hashedsalt_data); - - $salt .= "\x80" . str_repeat("\0", 47); - $salt[56] = "\x80"; - - $md5->reset(); - $md5->add($salt); - $mdContext2 = $md5->getContext(); - - return $mdContext2 == $hashedsalt; - } - - /** - * CODEPAGE - * - * This record stores the text encoding used to write byte - * strings, stored as MS Windows code page identifier. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readCodepage() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; code page identifier - $codepage = self::_GetInt2d($recordData, 0); - - $this->_codepage = PHPExcel_Shared_CodePage::NumberToName($codepage); - } - - - /** - * DATEMODE - * - * This record specifies the base date for displaying date - * values. All dates are stored as count of days past this - * base date. In BIFF2-BIFF4 this record is part of the - * Calculation Settings Block. In BIFF5-BIFF8 it is - * stored in the Workbook Globals Substream. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readDateMode() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; 0 = base 1900, 1 = base 1904 - PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); - if (ord($recordData{0}) == 1) { - PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); - } - } - - - /** - * Read a FONT record - */ - private function _readFont() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - $objFont = new PHPExcel_Style_Font(); - - // offset: 0; size: 2; height of the font (in twips = 1/20 of a point) - $size = self::_GetInt2d($recordData, 0); - $objFont->setSize($size / 20); - - // offset: 2; size: 2; option flags - // bit: 0; mask 0x0001; bold (redundant in BIFF5-BIFF8) - // bit: 1; mask 0x0002; italic - $isItalic = (0x0002 & self::_GetInt2d($recordData, 2)) >> 1; - if ($isItalic) $objFont->setItalic(true); - - // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8) - // bit: 3; mask 0x0008; strike - $isStrike = (0x0008 & self::_GetInt2d($recordData, 2)) >> 3; - if ($isStrike) $objFont->setStrikethrough(true); - - // offset: 4; size: 2; colour index - $colorIndex = self::_GetInt2d($recordData, 4); - $objFont->colorIndex = $colorIndex; - - // offset: 6; size: 2; font weight - $weight = self::_GetInt2d($recordData, 6); - switch ($weight) { - case 0x02BC: - $objFont->setBold(true); - break; - } - - // offset: 8; size: 2; escapement type - $escapement = self::_GetInt2d($recordData, 8); - switch ($escapement) { - case 0x0001: - $objFont->setSuperScript(true); - break; - case 0x0002: - $objFont->setSubScript(true); - break; - } - - // offset: 10; size: 1; underline type - $underlineType = ord($recordData{10}); - switch ($underlineType) { - case 0x00: - break; // no underline - case 0x01: - $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); - break; - case 0x02: - $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE); - break; - case 0x21: - $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING); - break; - case 0x22: - $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING); - break; - } - - // offset: 11; size: 1; font family - // offset: 12; size: 1; character set - // offset: 13; size: 1; not used - // offset: 14; size: var; font name - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringShort(substr($recordData, 14)); - } else { - $string = $this->_readByteStringShort(substr($recordData, 14)); - } - $objFont->setName($string['value']); - - $this->_objFonts[] = $objFont; - } - } - - - /** - * FORMAT - * - * This record contains information about a number format. - * All FORMAT records occur together in a sequential list. - * - * In BIFF2-BIFF4 other records referencing a FORMAT record - * contain a zero-based index into this list. From BIFF5 on - * the FORMAT record contains the index itself that will be - * used by other records. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readFormat() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - $indexCode = self::_GetInt2d($recordData, 0); - - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringLong(substr($recordData, 2)); - } else { - // BIFF7 - $string = $this->_readByteStringShort(substr($recordData, 2)); - } - - $formatString = $string['value']; - $this->_formats[$indexCode] = $formatString; - } - } - - - /** - * XF - Extended Format - * - * This record contains formatting information for cells, rows, columns or styles. - * According to http://support.microsoft.com/kb/147732 there are always at least 15 cell style XF - * and 1 cell XF. - * Inspection of Excel files generated by MS Office Excel shows that XF records 0-14 are cell style XF - * and XF record 15 is a cell XF - * We only read the first cell style XF and skip the remaining cell style XF records - * We read all cell XF records. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readXf() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - $objStyle = new PHPExcel_Style(); - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; Index to FONT record - if (self::_GetInt2d($recordData, 0) < 4) { - $fontIndex = self::_GetInt2d($recordData, 0); - } else { - // this has to do with that index 4 is omitted in all BIFF versions for some strange reason - // check the OpenOffice documentation of the FONT record - $fontIndex = self::_GetInt2d($recordData, 0) - 1; - } - $objStyle->setFont($this->_objFonts[$fontIndex]); - - // offset: 2; size: 2; Index to FORMAT record - $numberFormatIndex = self::_GetInt2d($recordData, 2); - if (isset($this->_formats[$numberFormatIndex])) { - // then we have user-defined format code - $numberformat = array('code' => $this->_formats[$numberFormatIndex]); - } elseif (($code = PHPExcel_Style_NumberFormat::builtInFormatCode($numberFormatIndex)) !== '') { - // then we have built-in format code - $numberformat = array('code' => $code); - } else { - // we set the general format code - $numberformat = array('code' => 'General'); - } - $objStyle->getNumberFormat()->setFormatCode($numberformat['code']); - - // offset: 4; size: 2; XF type, cell protection, and parent style XF - // bit 2-0; mask 0x0007; XF_TYPE_PROT - $xfTypeProt = self::_GetInt2d($recordData, 4); - // bit 0; mask 0x01; 1 = cell is locked - $isLocked = (0x01 & $xfTypeProt) >> 0; - $objStyle->getProtection()->setLocked($isLocked ? - PHPExcel_Style_Protection::PROTECTION_INHERIT : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); - - // bit 1; mask 0x02; 1 = Formula is hidden - $isHidden = (0x02 & $xfTypeProt) >> 1; - $objStyle->getProtection()->setHidden($isHidden ? - PHPExcel_Style_Protection::PROTECTION_PROTECTED : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); - - // bit 2; mask 0x04; 0 = Cell XF, 1 = Cell Style XF - $isCellStyleXf = (0x04 & $xfTypeProt) >> 2; - - // offset: 6; size: 1; Alignment and text break - // bit 2-0, mask 0x07; horizontal alignment - $horAlign = (0x07 & ord($recordData{6})) >> 0; - switch ($horAlign) { - case 0: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_GENERAL); - break; - case 1: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT); - break; - case 2: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); - break; - case 3: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT); - break; - case 4: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_FILL); - break; - case 5: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY); - break; - case 6: - $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS); - break; - } - // bit 3, mask 0x08; wrap text - $wrapText = (0x08 & ord($recordData{6})) >> 3; - switch ($wrapText) { - case 0: - $objStyle->getAlignment()->setWrapText(false); - break; - case 1: - $objStyle->getAlignment()->setWrapText(true); - break; - } - // bit 6-4, mask 0x70; vertical alignment - $vertAlign = (0x70 & ord($recordData{6})) >> 4; - switch ($vertAlign) { - case 0: - $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_TOP); - break; - case 1: - $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER); - break; - case 2: - $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_BOTTOM); - break; - case 3: - $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_JUSTIFY); - break; - } - - if ($this->_version == self::XLS_BIFF8) { - // offset: 7; size: 1; XF_ROTATION: Text rotation angle - $angle = ord($recordData{7}); - $rotation = 0; - if ($angle <= 90) { - $rotation = $angle; - } else if ($angle <= 180) { - $rotation = 90 - $angle; - } else if ($angle == 255) { - $rotation = -165; - } - $objStyle->getAlignment()->setTextRotation($rotation); - - // offset: 8; size: 1; Indentation, shrink to cell size, and text direction - // bit: 3-0; mask: 0x0F; indent level - $indent = (0x0F & ord($recordData{8})) >> 0; - $objStyle->getAlignment()->setIndent($indent); - - // bit: 4; mask: 0x10; 1 = shrink content to fit into cell - $shrinkToFit = (0x10 & ord($recordData{8})) >> 4; - switch ($shrinkToFit) { - case 0: - $objStyle->getAlignment()->setShrinkToFit(false); - break; - case 1: - $objStyle->getAlignment()->setShrinkToFit(true); - break; - } - - // offset: 9; size: 1; Flags used for attribute groups - - // offset: 10; size: 4; Cell border lines and background area - // bit: 3-0; mask: 0x0000000F; left style - if ($bordersLeftStyle = self::_mapBorderStyle((0x0000000F & self::_GetInt4d($recordData, 10)) >> 0)) { - $objStyle->getBorders()->getLeft()->setBorderStyle($bordersLeftStyle); - } - // bit: 7-4; mask: 0x000000F0; right style - if ($bordersRightStyle = self::_mapBorderStyle((0x000000F0 & self::_GetInt4d($recordData, 10)) >> 4)) { - $objStyle->getBorders()->getRight()->setBorderStyle($bordersRightStyle); - } - // bit: 11-8; mask: 0x00000F00; top style - if ($bordersTopStyle = self::_mapBorderStyle((0x00000F00 & self::_GetInt4d($recordData, 10)) >> 8)) { - $objStyle->getBorders()->getTop()->setBorderStyle($bordersTopStyle); - } - // bit: 15-12; mask: 0x0000F000; bottom style - if ($bordersBottomStyle = self::_mapBorderStyle((0x0000F000 & self::_GetInt4d($recordData, 10)) >> 12)) { - $objStyle->getBorders()->getBottom()->setBorderStyle($bordersBottomStyle); - } - // bit: 22-16; mask: 0x007F0000; left color - $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & self::_GetInt4d($recordData, 10)) >> 16; - - // bit: 29-23; mask: 0x3F800000; right color - $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & self::_GetInt4d($recordData, 10)) >> 23; - - // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom - $diagonalDown = (0x40000000 & self::_GetInt4d($recordData, 10)) >> 30 ? - true : false; - - // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right - $diagonalUp = (0x80000000 & self::_GetInt4d($recordData, 10)) >> 31 ? - true : false; - - if ($diagonalUp == false && $diagonalDown == false) { - $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); - } elseif ($diagonalUp == true && $diagonalDown == false) { - $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); - } elseif ($diagonalUp == false && $diagonalDown == true) { - $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); - } elseif ($diagonalUp == true && $diagonalDown == true) { - $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); - } - - // offset: 14; size: 4; - // bit: 6-0; mask: 0x0000007F; top color - $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & self::_GetInt4d($recordData, 14)) >> 0; - - // bit: 13-7; mask: 0x00003F80; bottom color - $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & self::_GetInt4d($recordData, 14)) >> 7; - - // bit: 20-14; mask: 0x001FC000; diagonal color - $objStyle->getBorders()->getDiagonal()->colorIndex = (0x001FC000 & self::_GetInt4d($recordData, 14)) >> 14; - - // bit: 24-21; mask: 0x01E00000; diagonal style - if ($bordersDiagonalStyle = self::_mapBorderStyle((0x01E00000 & self::_GetInt4d($recordData, 14)) >> 21)) { - $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle); - } - - // bit: 31-26; mask: 0xFC000000 fill pattern - if ($fillType = self::_mapFillPattern((0xFC000000 & self::_GetInt4d($recordData, 14)) >> 26)) { - $objStyle->getFill()->setFillType($fillType); - } - // offset: 18; size: 2; pattern and background colour - // bit: 6-0; mask: 0x007F; color index for pattern color - $objStyle->getFill()->startcolorIndex = (0x007F & self::_GetInt2d($recordData, 18)) >> 0; - - // bit: 13-7; mask: 0x3F80; color index for pattern background - $objStyle->getFill()->endcolorIndex = (0x3F80 & self::_GetInt2d($recordData, 18)) >> 7; - } else { - // BIFF5 - - // offset: 7; size: 1; Text orientation and flags - $orientationAndFlags = ord($recordData{7}); - - // bit: 1-0; mask: 0x03; XF_ORIENTATION: Text orientation - $xfOrientation = (0x03 & $orientationAndFlags) >> 0; - switch ($xfOrientation) { - case 0: - $objStyle->getAlignment()->setTextRotation(0); - break; - case 1: - $objStyle->getAlignment()->setTextRotation(-165); - break; - case 2: - $objStyle->getAlignment()->setTextRotation(90); - break; - case 3: - $objStyle->getAlignment()->setTextRotation(-90); - break; - } - - // offset: 8; size: 4; cell border lines and background area - $borderAndBackground = self::_GetInt4d($recordData, 8); - - // bit: 6-0; mask: 0x0000007F; color index for pattern color - $objStyle->getFill()->startcolorIndex = (0x0000007F & $borderAndBackground) >> 0; - - // bit: 13-7; mask: 0x00003F80; color index for pattern background - $objStyle->getFill()->endcolorIndex = (0x00003F80 & $borderAndBackground) >> 7; - - // bit: 21-16; mask: 0x003F0000; fill pattern - $objStyle->getFill()->setFillType(self::_mapFillPattern((0x003F0000 & $borderAndBackground) >> 16)); - - // bit: 24-22; mask: 0x01C00000; bottom line style - $objStyle->getBorders()->getBottom()->setBorderStyle(self::_mapBorderStyle((0x01C00000 & $borderAndBackground) >> 22)); - - // bit: 31-25; mask: 0xFE000000; bottom line color - $objStyle->getBorders()->getBottom()->colorIndex = (0xFE000000 & $borderAndBackground) >> 25; - - // offset: 12; size: 4; cell border lines - $borderLines = self::_GetInt4d($recordData, 12); - - // bit: 2-0; mask: 0x00000007; top line style - $objStyle->getBorders()->getTop()->setBorderStyle(self::_mapBorderStyle((0x00000007 & $borderLines) >> 0)); - - // bit: 5-3; mask: 0x00000038; left line style - $objStyle->getBorders()->getLeft()->setBorderStyle(self::_mapBorderStyle((0x00000038 & $borderLines) >> 3)); - - // bit: 8-6; mask: 0x000001C0; right line style - $objStyle->getBorders()->getRight()->setBorderStyle(self::_mapBorderStyle((0x000001C0 & $borderLines) >> 6)); - - // bit: 15-9; mask: 0x0000FE00; top line color index - $objStyle->getBorders()->getTop()->colorIndex = (0x0000FE00 & $borderLines) >> 9; - - // bit: 22-16; mask: 0x007F0000; left line color index - $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & $borderLines) >> 16; - - // bit: 29-23; mask: 0x3F800000; right line color index - $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $borderLines) >> 23; - } - - // add cellStyleXf or cellXf and update mapping - if ($isCellStyleXf) { - // we only read one style XF record which is always the first - if ($this->_xfIndex == 0) { - $this->_phpExcel->addCellStyleXf($objStyle); - $this->_mapCellStyleXfIndex[$this->_xfIndex] = 0; - } - } else { - // we read all cell XF records - $this->_phpExcel->addCellXf($objStyle); - $this->_mapCellXfIndex[$this->_xfIndex] = count($this->_phpExcel->getCellXfCollection()) - 1; - } - - // update XF index for when we read next record - ++$this->_xfIndex; - } - } - - - /** - * - */ - private function _readXfExt() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; 0x087D = repeated header - - // offset: 2; size: 2 - - // offset: 4; size: 8; not used - - // offset: 12; size: 2; record version - - // offset: 14; size: 2; index to XF record which this record modifies - $ixfe = self::_GetInt2d($recordData, 14); - - // offset: 16; size: 2; not used - - // offset: 18; size: 2; number of extension properties that follow - $cexts = self::_GetInt2d($recordData, 18); - - // start reading the actual extension data - $offset = 20; - while ($offset < $length) { - // extension type - $extType = self::_GetInt2d($recordData, $offset); - - // extension length - $cb = self::_GetInt2d($recordData, $offset + 2); - - // extension data - $extData = substr($recordData, $offset + 4, $cb); - - switch ($extType) { - case 4: // fill start color - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); - $fill->getStartColor()->setRGB($rgb); - unset($fill->startcolorIndex); // normal color index does not apply, discard - } - } - break; - - case 5: // fill end color - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); - $fill->getEndColor()->setRGB($rgb); - unset($fill->endcolorIndex); // normal color index does not apply, discard - } - } - break; - - case 7: // border color top - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $top = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getTop(); - $top->getColor()->setRGB($rgb); - unset($top->colorIndex); // normal color index does not apply, discard - } - } - break; - - case 8: // border color bottom - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $bottom = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getBottom(); - $bottom->getColor()->setRGB($rgb); - unset($bottom->colorIndex); // normal color index does not apply, discard - } - } - break; - - case 9: // border color left - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $left = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getLeft(); - $left->getColor()->setRGB($rgb); - unset($left->colorIndex); // normal color index does not apply, discard - } - } - break; - - case 10: // border color right - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $right = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getRight(); - $right->getColor()->setRGB($rgb); - unset($right->colorIndex); // normal color index does not apply, discard - } - } - break; - - case 11: // border color diagonal - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $diagonal = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getDiagonal(); - $diagonal->getColor()->setRGB($rgb); - unset($diagonal->colorIndex); // normal color index does not apply, discard - } - } - break; - - case 13: // font color - $xclfType = self::_GetInt2d($extData, 0); // color type - $xclrValue = substr($extData, 4, 4); // color value (value based on color type) - - if ($xclfType == 2) { - $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); - - // modify the relevant style property - if ( isset($this->_mapCellXfIndex[$ixfe]) ) { - $font = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFont(); - $font->getColor()->setRGB($rgb); - unset($font->colorIndex); // normal color index does not apply, discard - } - } - break; - } - - $offset += $cb; - } - } - - } - - - /** - * Read STYLE record - */ - private function _readStyle() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; index to XF record and flag for built-in style - $ixfe = self::_GetInt2d($recordData, 0); - - // bit: 11-0; mask 0x0FFF; index to XF record - $xfIndex = (0x0FFF & $ixfe) >> 0; - - // bit: 15; mask 0x8000; 0 = user-defined style, 1 = built-in style - $isBuiltIn = (bool) ((0x8000 & $ixfe) >> 15); - - if ($isBuiltIn) { - // offset: 2; size: 1; identifier for built-in style - $builtInId = ord($recordData{2}); - - switch ($builtInId) { - case 0x00: - // currently, we are not using this for anything - break; - - default: - break; - } - - } else { - // user-defined; not supported by PHPExcel - } - } - } - - - /** - * Read PALETTE record - */ - private function _readPalette() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; number of following colors - $nm = self::_GetInt2d($recordData, 0); - - // list of RGB colors - for ($i = 0; $i < $nm; ++$i) { - $rgb = substr($recordData, 2 + 4 * $i, 4); - $this->_palette[] = self::_readRGB($rgb); - } - } - } - - - /** - * SHEET - * - * This record is located in the Workbook Globals - * Substream and represents a sheet inside the workbook. - * One SHEET record is written for each sheet. It stores the - * sheet name and a stream offset to the BOF record of the - * respective Sheet Substream within the Workbook Stream. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readSheet() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // offset: 0; size: 4; absolute stream position of the BOF record of the sheet - // NOTE: not encrypted - $rec_offset = self::_GetInt4d($this->_data, $this->_pos + 4); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 4; size: 1; sheet state - switch (ord($recordData{4})) { - case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; - case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; - case 0x02: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN; break; - default: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; - } - - // offset: 5; size: 1; sheet type - $sheetType = ord($recordData{5}); - - // offset: 6; size: var; sheet name - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringShort(substr($recordData, 6)); - $rec_name = $string['value']; - } elseif ($this->_version == self::XLS_BIFF7) { - $string = $this->_readByteStringShort(substr($recordData, 6)); - $rec_name = $string['value']; - } - - $this->_sheets[] = array( - 'name' => $rec_name, - 'offset' => $rec_offset, - 'sheetState' => $sheetState, - 'sheetType' => $sheetType, - ); - } - - - /** - * Read EXTERNALBOOK record - */ - private function _readExternalBook() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset within record data - $offset = 0; - - // there are 4 types of records - if (strlen($recordData) > 4) { - // external reference - // offset: 0; size: 2; number of sheet names ($nm) - $nm = self::_GetInt2d($recordData, 0); - $offset += 2; - - // offset: 2; size: var; encoded URL without sheet name (Unicode string, 16-bit length) - $encodedUrlString = self::_readUnicodeStringLong(substr($recordData, 2)); - $offset += $encodedUrlString['size']; - - // offset: var; size: var; list of $nm sheet names (Unicode strings, 16-bit length) - $externalSheetNames = array(); - for ($i = 0; $i < $nm; ++$i) { - $externalSheetNameString = self::_readUnicodeStringLong(substr($recordData, $offset)); - $externalSheetNames[] = $externalSheetNameString['value']; - $offset += $externalSheetNameString['size']; - } - - // store the record data - $this->_externalBooks[] = array( - 'type' => 'external', - 'encodedUrl' => $encodedUrlString['value'], - 'externalSheetNames' => $externalSheetNames, - ); - - } elseif (substr($recordData, 2, 2) == pack('CC', 0x01, 0x04)) { - // internal reference - // offset: 0; size: 2; number of sheet in this document - // offset: 2; size: 2; 0x01 0x04 - $this->_externalBooks[] = array( - 'type' => 'internal', - ); - } elseif (substr($recordData, 0, 4) == pack('vCC', 0x0001, 0x01, 0x3A)) { - // add-in function - // offset: 0; size: 2; 0x0001 - $this->_externalBooks[] = array( - 'type' => 'addInFunction', - ); - } elseif (substr($recordData, 0, 2) == pack('v', 0x0000)) { - // DDE links, OLE links - // offset: 0; size: 2; 0x0000 - // offset: 2; size: var; encoded source document name - $this->_externalBooks[] = array( - 'type' => 'DDEorOLE', - ); - } - } - - - /** - * Read EXTERNNAME record. - */ - private function _readExternName() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // external sheet references provided for named cells - if ($this->_version == self::XLS_BIFF8) { - // offset: 0; size: 2; options - $options = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; - - // offset: 4; size: 2; not used - - // offset: 6; size: var - $nameString = self::_readUnicodeStringShort(substr($recordData, 6)); - - // offset: var; size: var; formula data - $offset = 6 + $nameString['size']; - $formula = $this->_getFormulaFromStructure(substr($recordData, $offset)); - - $this->_externalNames[] = array( - 'name' => $nameString['value'], - 'formula' => $formula, - ); - } - } - - - /** - * Read EXTERNSHEET record - */ - private function _readExternSheet() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // external sheet references provided for named cells - if ($this->_version == self::XLS_BIFF8) { - // offset: 0; size: 2; number of following ref structures - $nm = self::_GetInt2d($recordData, 0); - for ($i = 0; $i < $nm; ++$i) { - $this->_ref[] = array( - // offset: 2 + 6 * $i; index to EXTERNALBOOK record - 'externalBookIndex' => self::_GetInt2d($recordData, 2 + 6 * $i), - // offset: 4 + 6 * $i; index to first sheet in EXTERNALBOOK record - 'firstSheetIndex' => self::_GetInt2d($recordData, 4 + 6 * $i), - // offset: 6 + 6 * $i; index to last sheet in EXTERNALBOOK record - 'lastSheetIndex' => self::_GetInt2d($recordData, 6 + 6 * $i), - ); - } - } - } - - - /** - * DEFINEDNAME - * - * This record is part of a Link Table. It contains the name - * and the token array of an internal defined name. Token - * arrays of defined names contain tokens with aberrant - * token classes. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readDefinedName() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8) { - // retrieves named cells - - // offset: 0; size: 2; option flags - $opts = self::_GetInt2d($recordData, 0); - - // bit: 5; mask: 0x0020; 0 = user-defined name, 1 = built-in-name - $isBuiltInName = (0x0020 & $opts) >> 5; - - // offset: 2; size: 1; keyboard shortcut - - // offset: 3; size: 1; length of the name (character count) - $nlen = ord($recordData{3}); - - // offset: 4; size: 2; size of the formula data (it can happen that this is zero) - // note: there can also be additional data, this is not included in $flen - $flen = self::_GetInt2d($recordData, 4); - - // offset: 8; size: 2; 0=Global name, otherwise index to sheet (1-based) - $scope = self::_GetInt2d($recordData, 8); - - // offset: 14; size: var; Name (Unicode string without length field) - $string = self::_readUnicodeString(substr($recordData, 14), $nlen); - - // offset: var; size: $flen; formula data - $offset = 14 + $string['size']; - $formulaStructure = pack('v', $flen) . substr($recordData, $offset); - - try { - $formula = $this->_getFormulaFromStructure($formulaStructure); - } catch (PHPExcel_Exception $e) { - $formula = ''; - } - - $this->_definedname[] = array( - 'isBuiltInName' => $isBuiltInName, - 'name' => $string['value'], - 'formula' => $formula, - 'scope' => $scope, - ); - } - } - - - /** - * Read MSODRAWINGGROUP record - */ - private function _readMsoDrawingGroup() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - - // get spliced record data - $splicedRecordData = $this->_getSplicedRecordData(); - $recordData = $splicedRecordData['recordData']; - - $this->_drawingGroupData .= $recordData; - } - - - /** - * SST - Shared String Table - * - * This record contains a list of all strings used anywhere - * in the workbook. Each string occurs only once. The - * workbook uses indexes into the list to reference the - * strings. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - **/ - private function _readSst() - { - // offset within (spliced) record data - $pos = 0; - - // get spliced record data - $splicedRecordData = $this->_getSplicedRecordData(); - - $recordData = $splicedRecordData['recordData']; - $spliceOffsets = $splicedRecordData['spliceOffsets']; - - // offset: 0; size: 4; total number of strings in the workbook - $pos += 4; - - // offset: 4; size: 4; number of following strings ($nm) - $nm = self::_GetInt4d($recordData, 4); - $pos += 4; - - // loop through the Unicode strings (16-bit length) - for ($i = 0; $i < $nm; ++$i) { - - // number of characters in the Unicode string - $numChars = self::_GetInt2d($recordData, $pos); - $pos += 2; - - // option flags - $optionFlags = ord($recordData{$pos}); - ++$pos; - - // bit: 0; mask: 0x01; 0 = compressed; 1 = uncompressed - $isCompressed = (($optionFlags & 0x01) == 0) ; - - // bit: 2; mask: 0x02; 0 = ordinary; 1 = Asian phonetic - $hasAsian = (($optionFlags & 0x04) != 0); - - // bit: 3; mask: 0x03; 0 = ordinary; 1 = Rich-Text - $hasRichText = (($optionFlags & 0x08) != 0); - - if ($hasRichText) { - // number of Rich-Text formatting runs - $formattingRuns = self::_GetInt2d($recordData, $pos); - $pos += 2; - } - - if ($hasAsian) { - // size of Asian phonetic setting - $extendedRunLength = self::_GetInt4d($recordData, $pos); - $pos += 4; - } - - // expected byte length of character array if not split - $len = ($isCompressed) ? $numChars : $numChars * 2; - - // look up limit position - foreach ($spliceOffsets as $spliceOffset) { - // it can happen that the string is empty, therefore we need - // <= and not just < - if ($pos <= $spliceOffset) { - $limitpos = $spliceOffset; - break; - } - } - - if ($pos + $len <= $limitpos) { - // character array is not split between records - - $retstr = substr($recordData, $pos, $len); - $pos += $len; - - } else { - // character array is split between records - - // first part of character array - $retstr = substr($recordData, $pos, $limitpos - $pos); - - $bytesRead = $limitpos - $pos; - - // remaining characters in Unicode string - $charsLeft = $numChars - (($isCompressed) ? $bytesRead : ($bytesRead / 2)); - - $pos = $limitpos; - - // keep reading the characters - while ($charsLeft > 0) { - - // look up next limit position, in case the string span more than one continue record - foreach ($spliceOffsets as $spliceOffset) { - if ($pos < $spliceOffset) { - $limitpos = $spliceOffset; - break; - } - } - - // repeated option flags - // OpenOffice.org documentation 5.21 - $option = ord($recordData{$pos}); - ++$pos; - - if ($isCompressed && ($option == 0)) { - // 1st fragment compressed - // this fragment compressed - $len = min($charsLeft, $limitpos - $pos); - $retstr .= substr($recordData, $pos, $len); - $charsLeft -= $len; - $isCompressed = true; - - } elseif (!$isCompressed && ($option != 0)) { - // 1st fragment uncompressed - // this fragment uncompressed - $len = min($charsLeft * 2, $limitpos - $pos); - $retstr .= substr($recordData, $pos, $len); - $charsLeft -= $len / 2; - $isCompressed = false; - - } elseif (!$isCompressed && ($option == 0)) { - // 1st fragment uncompressed - // this fragment compressed - $len = min($charsLeft, $limitpos - $pos); - for ($j = 0; $j < $len; ++$j) { - $retstr .= $recordData{$pos + $j} . chr(0); - } - $charsLeft -= $len; - $isCompressed = false; - - } else { - // 1st fragment compressed - // this fragment uncompressed - $newstr = ''; - for ($j = 0; $j < strlen($retstr); ++$j) { - $newstr .= $retstr[$j] . chr(0); - } - $retstr = $newstr; - $len = min($charsLeft * 2, $limitpos - $pos); - $retstr .= substr($recordData, $pos, $len); - $charsLeft -= $len / 2; - $isCompressed = false; - } - - $pos += $len; - } - } - - // convert to UTF-8 - $retstr = self::_encodeUTF16($retstr, $isCompressed); - - // read additional Rich-Text information, if any - $fmtRuns = array(); - if ($hasRichText) { - // list of formatting runs - for ($j = 0; $j < $formattingRuns; ++$j) { - // first formatted character; zero-based - $charPos = self::_GetInt2d($recordData, $pos + $j * 4); - - // index to font record - $fontIndex = self::_GetInt2d($recordData, $pos + 2 + $j * 4); - - $fmtRuns[] = array( - 'charPos' => $charPos, - 'fontIndex' => $fontIndex, - ); - } - $pos += 4 * $formattingRuns; - } - - // read additional Asian phonetics information, if any - if ($hasAsian) { - // For Asian phonetic settings, we skip the extended string data - $pos += $extendedRunLength; - } - - // store the shared sting - $this->_sst[] = array( - 'value' => $retstr, - 'fmtRuns' => $fmtRuns, - ); - } - - // _getSplicedRecordData() takes care of moving current position in data stream - } - - - /** - * Read PRINTGRIDLINES record - */ - private function _readPrintGridlines() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { - // offset: 0; size: 2; 0 = do not print sheet grid lines; 1 = print sheet gridlines - $printGridlines = (bool) self::_GetInt2d($recordData, 0); - $this->_phpSheet->setPrintGridlines($printGridlines); - } - } - - - /** - * Read DEFAULTROWHEIGHT record - */ - private function _readDefaultRowHeight() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; option flags - // offset: 2; size: 2; default height for unused rows, (twips 1/20 point) - $height = self::_GetInt2d($recordData, 2); - $this->_phpSheet->getDefaultRowDimension()->setRowHeight($height / 20); - } - - - /** - * Read SHEETPR record - */ - private function _readSheetPr() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2 - - // bit: 6; mask: 0x0040; 0 = outline buttons above outline group - $isSummaryBelow = (0x0040 & self::_GetInt2d($recordData, 0)) >> 6; - $this->_phpSheet->setShowSummaryBelow($isSummaryBelow); - - // bit: 7; mask: 0x0080; 0 = outline buttons left of outline group - $isSummaryRight = (0x0080 & self::_GetInt2d($recordData, 0)) >> 7; - $this->_phpSheet->setShowSummaryRight($isSummaryRight); - - // bit: 8; mask: 0x100; 0 = scale printout in percent, 1 = fit printout to number of pages - // this corresponds to radio button setting in page setup dialog in Excel - $this->_isFitToPages = (bool) ((0x0100 & self::_GetInt2d($recordData, 0)) >> 8); - } - - - /** - * Read HORIZONTALPAGEBREAKS record - */ - private function _readHorizontalPageBreaks() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { - - // offset: 0; size: 2; number of the following row index structures - $nm = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 6 * $nm; list of $nm row index structures - for ($i = 0; $i < $nm; ++$i) { - $r = self::_GetInt2d($recordData, 2 + 6 * $i); - $cf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); - $cl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); - - // not sure why two column indexes are necessary? - $this->_phpSheet->setBreakByColumnAndRow($cf, $r, PHPExcel_Worksheet::BREAK_ROW); - } - } - } - - - /** - * Read VERTICALPAGEBREAKS record - */ - private function _readVerticalPageBreaks() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { - // offset: 0; size: 2; number of the following column index structures - $nm = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 6 * $nm; list of $nm row index structures - for ($i = 0; $i < $nm; ++$i) { - $c = self::_GetInt2d($recordData, 2 + 6 * $i); - $rf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); - $rl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); - - // not sure why two row indexes are necessary? - $this->_phpSheet->setBreakByColumnAndRow($c, $rf, PHPExcel_Worksheet::BREAK_COLUMN); - } - } - } - - - /** - * Read HEADER record - */ - private function _readHeader() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: var - // realized that $recordData can be empty even when record exists - if ($recordData) { - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringLong($recordData); - } else { - $string = $this->_readByteStringShort($recordData); - } - - $this->_phpSheet->getHeaderFooter()->setOddHeader($string['value']); - $this->_phpSheet->getHeaderFooter()->setEvenHeader($string['value']); - } - } - } - - - /** - * Read FOOTER record - */ - private function _readFooter() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: var - // realized that $recordData can be empty even when record exists - if ($recordData) { - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringLong($recordData); - } else { - $string = $this->_readByteStringShort($recordData); - } - $this->_phpSheet->getHeaderFooter()->setOddFooter($string['value']); - $this->_phpSheet->getHeaderFooter()->setEvenFooter($string['value']); - } - } - } - - - /** - * Read HCENTER record - */ - private function _readHcenter() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; 0 = print sheet left aligned, 1 = print sheet centered horizontally - $isHorizontalCentered = (bool) self::_GetInt2d($recordData, 0); - - $this->_phpSheet->getPageSetup()->setHorizontalCentered($isHorizontalCentered); - } - } - - - /** - * Read VCENTER record - */ - private function _readVcenter() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; 0 = print sheet aligned at top page border, 1 = print sheet vertically centered - $isVerticalCentered = (bool) self::_GetInt2d($recordData, 0); - - $this->_phpSheet->getPageSetup()->setVerticalCentered($isVerticalCentered); - } - } - - - /** - * Read LEFTMARGIN record - */ - private function _readLeftMargin() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 8 - $this->_phpSheet->getPageMargins()->setLeft(self::_extractNumber($recordData)); - } - } - - - /** - * Read RIGHTMARGIN record - */ - private function _readRightMargin() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 8 - $this->_phpSheet->getPageMargins()->setRight(self::_extractNumber($recordData)); - } - } - - - /** - * Read TOPMARGIN record - */ - private function _readTopMargin() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 8 - $this->_phpSheet->getPageMargins()->setTop(self::_extractNumber($recordData)); - } - } - - - /** - * Read BOTTOMMARGIN record - */ - private function _readBottomMargin() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 8 - $this->_phpSheet->getPageMargins()->setBottom(self::_extractNumber($recordData)); - } - } - - - /** - * Read PAGESETUP record - */ - private function _readPageSetup() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; paper size - $paperSize = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; scaling factor - $scale = self::_GetInt2d($recordData, 2); - - // offset: 6; size: 2; fit worksheet width to this number of pages, 0 = use as many as needed - $fitToWidth = self::_GetInt2d($recordData, 6); - - // offset: 8; size: 2; fit worksheet height to this number of pages, 0 = use as many as needed - $fitToHeight = self::_GetInt2d($recordData, 8); - - // offset: 10; size: 2; option flags + $this->_cellNotes[$noteObjID] = array('cellRef' => $cellAddress, + 'objectID' => $noteObjID, + 'author' => $noteAuthor + ); + } else { + $extension = false; + if ($cellAddress == '$B$65536') { + // If the address row is -1 and the column is 0, (which translates as $B$65536) then this is a continuation + // note from the previous cell annotation. We're not yet handling this, so annotations longer than the + // max 2048 bytes will probably throw a wobbly. + $row = self::_GetInt2d($recordData, 0); + $extension = true; + $cellAddress = array_pop(array_keys($this->_phpSheet->getComments())); + } +// echo 'Note Address=',$cellAddress,'
'; + + $cellAddress = str_replace('$','',$cellAddress); + $noteLength = self::_GetInt2d($recordData, 4); + $noteText = trim(substr($recordData, 6)); +// echo 'Note Length=',$noteLength,'
'; +// echo 'Note Text=',$noteText,'
'; + + if ($extension) { + // Concatenate this extension with the currently set comment for the cell + $comment = $this->_phpSheet->getComment( $cellAddress ); + $commentText = $comment->getText()->getPlainText(); + $comment->setText($this->_parseRichText($commentText.$noteText) ); + } else { + // Set comment for the cell + $this->_phpSheet->getComment( $cellAddress ) +// ->setAuthor( $author ) + ->setText($this->_parseRichText($noteText) ); + } + } + + } + + + /** + * The TEXT Object record contains the text associated with a cell annotation. + */ + private function _readTextObject() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // recordData consists of an array of subrecords looking like this: + // grbit: 2 bytes; Option Flags + // rot: 2 bytes; rotation + // cchText: 2 bytes; length of the text (in the first continue record) + // cbRuns: 2 bytes; length of the formatting (in the second continue record) + // followed by the continuation records containing the actual text and formatting + $grbitOpts = self::_GetInt2d($recordData, 0); + $rot = self::_GetInt2d($recordData, 2); + $cchText = self::_GetInt2d($recordData, 10); + $cbRuns = self::_GetInt2d($recordData, 12); + $text = $this->_getSplicedRecordData(); + + $this->_textObjects[$this->textObjRef] = array( + 'text' => substr($text["recordData"],$text["spliceOffsets"][0]+1,$cchText), + 'format' => substr($text["recordData"],$text["spliceOffsets"][1],$cbRuns), + 'alignment' => $grbitOpts, + 'rotation' => $rot + ); + +// echo '_readTextObject()
'; +// var_dump($this->_textObjects[$this->textObjRef]); +// echo '
'; + } + + + /** + * Read BOF + */ + private function _readBof() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 2; size: 2; type of the following data + $substreamType = self::_GetInt2d($recordData, 2); + + switch ($substreamType) { + case self::XLS_WorkbookGlobals: + $version = self::_GetInt2d($recordData, 0); + if (($version != self::XLS_BIFF8) && ($version != self::XLS_BIFF7)) { + throw new PHPExcel_Reader_Exception('Cannot read this Excel file. Version is too old.'); + } + $this->_version = $version; + break; + + case self::XLS_Worksheet: + // do not use this version information for anything + // it is unreliable (OpenOffice doc, 5.8), use only version information from the global stream + break; + + default: + // substream, e.g. chart + // just skip the entire substream + do { + $code = self::_GetInt2d($this->_data, $this->_pos); + $this->_readDefault(); + } while ($code != self::XLS_Type_EOF && $this->_pos < $this->_dataSize); + break; + } + } + + + /** + * FILEPASS + * + * This record is part of the File Protection Block. It + * contains information about the read/write password of the + * file. All record contents following this record will be + * encrypted. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + * + * The decryption functions and objects used from here on in + * are based on the source of Spreadsheet-ParseExcel: + * http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel/ + */ + private function _readFilepass() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + if ($length != 54) { + throw new PHPExcel_Reader_Exception('Unexpected file pass record length'); + } + + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_verifyPassword( + 'VelvetSweatshop', + substr($recordData, 6, 16), + substr($recordData, 22, 16), + substr($recordData, 38, 16), + $this->_md5Ctxt + )) { + throw new PHPExcel_Reader_Exception('Decryption password incorrect'); + } + + $this->_encryption = self::MS_BIFF_CRYPTO_RC4; + + // Decryption required from the record after next onwards + $this->_encryptionStartPos = $this->_pos + self::_GetInt2d($this->_data, $this->_pos + 2); + } + + /** + * Make an RC4 decryptor for the given block + * + * @var int $block Block for which to create decrypto + * @var string $valContext MD5 context state + * + * @return PHPExcel_Reader_Excel5_RC4 + */ + private function _makeKey($block, $valContext) + { + $pwarray = str_repeat("\0", 64); + + for ($i = 0; $i < 5; $i++) { + $pwarray[$i] = $valContext[$i]; + } + + $pwarray[5] = chr($block & 0xff); + $pwarray[6] = chr(($block >> 8) & 0xff); + $pwarray[7] = chr(($block >> 16) & 0xff); + $pwarray[8] = chr(($block >> 24) & 0xff); + + $pwarray[9] = "\x80"; + $pwarray[56] = "\x48"; + + $md5 = new PHPExcel_Reader_Excel5_MD5(); + $md5->add($pwarray); + + $s = $md5->getContext(); + return new PHPExcel_Reader_Excel5_RC4($s); + } + + /** + * Verify RC4 file password + * + * @var string $password Password to check + * @var string $docid Document id + * @var string $salt_data Salt data + * @var string $hashedsalt_data Hashed salt data + * @var string &$valContext Set to the MD5 context of the value + * + * @return bool Success + */ + private function _verifyPassword($password, $docid, $salt_data, $hashedsalt_data, &$valContext) + { + $pwarray = str_repeat("\0", 64); + + for ($i = 0; $i < strlen($password); $i++) { + $o = ord(substr($password, $i, 1)); + $pwarray[2 * $i] = chr($o & 0xff); + $pwarray[2 * $i + 1] = chr(($o >> 8) & 0xff); + } + $pwarray[2 * $i] = chr(0x80); + $pwarray[56] = chr(($i << 4) & 0xff); + + $md5 = new PHPExcel_Reader_Excel5_MD5(); + $md5->add($pwarray); + + $mdContext1 = $md5->getContext(); + + $offset = 0; + $keyoffset = 0; + $tocopy = 5; + + $md5->reset(); + + while ($offset != 16) { + if ((64 - $offset) < 5) { + $tocopy = 64 - $offset; + } + + for ($i = 0; $i <= $tocopy; $i++) { + $pwarray[$offset + $i] = $mdContext1[$keyoffset + $i]; + } + + $offset += $tocopy; + + if ($offset == 64) { + $md5->add($pwarray); + $keyoffset = $tocopy; + $tocopy = 5 - $tocopy; + $offset = 0; + continue; + } + + $keyoffset = 0; + $tocopy = 5; + for ($i = 0; $i < 16; $i++) { + $pwarray[$offset + $i] = $docid[$i]; + } + $offset += 16; + } + + $pwarray[16] = "\x80"; + for ($i = 0; $i < 47; $i++) { + $pwarray[17 + $i] = "\0"; + } + $pwarray[56] = "\x80"; + $pwarray[57] = "\x0a"; + + $md5->add($pwarray); + $valContext = $md5->getContext(); + + $key = $this->_makeKey(0, $valContext); + + $salt = $key->RC4($salt_data); + $hashedsalt = $key->RC4($hashedsalt_data); + + $salt .= "\x80" . str_repeat("\0", 47); + $salt[56] = "\x80"; + + $md5->reset(); + $md5->add($salt); + $mdContext2 = $md5->getContext(); + + return $mdContext2 == $hashedsalt; + } + + /** + * CODEPAGE + * + * This record stores the text encoding used to write byte + * strings, stored as MS Windows code page identifier. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readCodepage() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; code page identifier + $codepage = self::_GetInt2d($recordData, 0); + + $this->_codepage = PHPExcel_Shared_CodePage::NumberToName($codepage); + } + + + /** + * DATEMODE + * + * This record specifies the base date for displaying date + * values. All dates are stored as count of days past this + * base date. In BIFF2-BIFF4 this record is part of the + * Calculation Settings Block. In BIFF5-BIFF8 it is + * stored in the Workbook Globals Substream. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readDateMode() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; 0 = base 1900, 1 = base 1904 + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); + if (ord($recordData{0}) == 1) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); + } + } + + + /** + * Read a FONT record + */ + private function _readFont() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + $objFont = new PHPExcel_Style_Font(); + + // offset: 0; size: 2; height of the font (in twips = 1/20 of a point) + $size = self::_GetInt2d($recordData, 0); + $objFont->setSize($size / 20); + + // offset: 2; size: 2; option flags + // bit: 0; mask 0x0001; bold (redundant in BIFF5-BIFF8) + // bit: 1; mask 0x0002; italic + $isItalic = (0x0002 & self::_GetInt2d($recordData, 2)) >> 1; + if ($isItalic) $objFont->setItalic(true); + + // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8) + // bit: 3; mask 0x0008; strike + $isStrike = (0x0008 & self::_GetInt2d($recordData, 2)) >> 3; + if ($isStrike) $objFont->setStrikethrough(true); + + // offset: 4; size: 2; colour index + $colorIndex = self::_GetInt2d($recordData, 4); + $objFont->colorIndex = $colorIndex; + + // offset: 6; size: 2; font weight + $weight = self::_GetInt2d($recordData, 6); + switch ($weight) { + case 0x02BC: + $objFont->setBold(true); + break; + } + + // offset: 8; size: 2; escapement type + $escapement = self::_GetInt2d($recordData, 8); + switch ($escapement) { + case 0x0001: + $objFont->setSuperScript(true); + break; + case 0x0002: + $objFont->setSubScript(true); + break; + } + + // offset: 10; size: 1; underline type + $underlineType = ord($recordData{10}); + switch ($underlineType) { + case 0x00: + break; // no underline + case 0x01: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + break; + case 0x02: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE); + break; + case 0x21: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING); + break; + case 0x22: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING); + break; + } + + // offset: 11; size: 1; font family + // offset: 12; size: 1; character set + // offset: 13; size: 1; not used + // offset: 14; size: var; font name + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringShort(substr($recordData, 14)); + } else { + $string = $this->_readByteStringShort(substr($recordData, 14)); + } + $objFont->setName($string['value']); + + $this->_objFonts[] = $objFont; + } + } + + + /** + * FORMAT + * + * This record contains information about a number format. + * All FORMAT records occur together in a sequential list. + * + * In BIFF2-BIFF4 other records referencing a FORMAT record + * contain a zero-based index into this list. From BIFF5 on + * the FORMAT record contains the index itself that will be + * used by other records. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readFormat() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + $indexCode = self::_GetInt2d($recordData, 0); + + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong(substr($recordData, 2)); + } else { + // BIFF7 + $string = $this->_readByteStringShort(substr($recordData, 2)); + } + + $formatString = $string['value']; + $this->_formats[$indexCode] = $formatString; + } + } + + + /** + * XF - Extended Format + * + * This record contains formatting information for cells, rows, columns or styles. + * According to http://support.microsoft.com/kb/147732 there are always at least 15 cell style XF + * and 1 cell XF. + * Inspection of Excel files generated by MS Office Excel shows that XF records 0-14 are cell style XF + * and XF record 15 is a cell XF + * We only read the first cell style XF and skip the remaining cell style XF records + * We read all cell XF records. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readXf() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + $objStyle = new PHPExcel_Style(); + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; Index to FONT record + if (self::_GetInt2d($recordData, 0) < 4) { + $fontIndex = self::_GetInt2d($recordData, 0); + } else { + // this has to do with that index 4 is omitted in all BIFF versions for some strange reason + // check the OpenOffice documentation of the FONT record + $fontIndex = self::_GetInt2d($recordData, 0) - 1; + } + $objStyle->setFont($this->_objFonts[$fontIndex]); + + // offset: 2; size: 2; Index to FORMAT record + $numberFormatIndex = self::_GetInt2d($recordData, 2); + if (isset($this->_formats[$numberFormatIndex])) { + // then we have user-defined format code + $numberformat = array('code' => $this->_formats[$numberFormatIndex]); + } elseif (($code = PHPExcel_Style_NumberFormat::builtInFormatCode($numberFormatIndex)) !== '') { + // then we have built-in format code + $numberformat = array('code' => $code); + } else { + // we set the general format code + $numberformat = array('code' => 'General'); + } + $objStyle->getNumberFormat()->setFormatCode($numberformat['code']); + + // offset: 4; size: 2; XF type, cell protection, and parent style XF + // bit 2-0; mask 0x0007; XF_TYPE_PROT + $xfTypeProt = self::_GetInt2d($recordData, 4); + // bit 0; mask 0x01; 1 = cell is locked + $isLocked = (0x01 & $xfTypeProt) >> 0; + $objStyle->getProtection()->setLocked($isLocked ? + PHPExcel_Style_Protection::PROTECTION_INHERIT : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + + // bit 1; mask 0x02; 1 = Formula is hidden + $isHidden = (0x02 & $xfTypeProt) >> 1; + $objStyle->getProtection()->setHidden($isHidden ? + PHPExcel_Style_Protection::PROTECTION_PROTECTED : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + + // bit 2; mask 0x04; 0 = Cell XF, 1 = Cell Style XF + $isCellStyleXf = (0x04 & $xfTypeProt) >> 2; + + // offset: 6; size: 1; Alignment and text break + // bit 2-0, mask 0x07; horizontal alignment + $horAlign = (0x07 & ord($recordData{6})) >> 0; + switch ($horAlign) { + case 0: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_GENERAL); + break; + case 1: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT); + break; + case 2: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); + break; + case 3: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT); + break; + case 4: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_FILL); + break; + case 5: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY); + break; + case 6: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS); + break; + } + // bit 3, mask 0x08; wrap text + $wrapText = (0x08 & ord($recordData{6})) >> 3; + switch ($wrapText) { + case 0: + $objStyle->getAlignment()->setWrapText(false); + break; + case 1: + $objStyle->getAlignment()->setWrapText(true); + break; + } + // bit 6-4, mask 0x70; vertical alignment + $vertAlign = (0x70 & ord($recordData{6})) >> 4; + switch ($vertAlign) { + case 0: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_TOP); + break; + case 1: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER); + break; + case 2: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_BOTTOM); + break; + case 3: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_JUSTIFY); + break; + } + + if ($this->_version == self::XLS_BIFF8) { + // offset: 7; size: 1; XF_ROTATION: Text rotation angle + $angle = ord($recordData{7}); + $rotation = 0; + if ($angle <= 90) { + $rotation = $angle; + } else if ($angle <= 180) { + $rotation = 90 - $angle; + } else if ($angle == 255) { + $rotation = -165; + } + $objStyle->getAlignment()->setTextRotation($rotation); + + // offset: 8; size: 1; Indentation, shrink to cell size, and text direction + // bit: 3-0; mask: 0x0F; indent level + $indent = (0x0F & ord($recordData{8})) >> 0; + $objStyle->getAlignment()->setIndent($indent); + + // bit: 4; mask: 0x10; 1 = shrink content to fit into cell + $shrinkToFit = (0x10 & ord($recordData{8})) >> 4; + switch ($shrinkToFit) { + case 0: + $objStyle->getAlignment()->setShrinkToFit(false); + break; + case 1: + $objStyle->getAlignment()->setShrinkToFit(true); + break; + } + + // offset: 9; size: 1; Flags used for attribute groups + + // offset: 10; size: 4; Cell border lines and background area + // bit: 3-0; mask: 0x0000000F; left style + if ($bordersLeftStyle = self::_mapBorderStyle((0x0000000F & self::_GetInt4d($recordData, 10)) >> 0)) { + $objStyle->getBorders()->getLeft()->setBorderStyle($bordersLeftStyle); + } + // bit: 7-4; mask: 0x000000F0; right style + if ($bordersRightStyle = self::_mapBorderStyle((0x000000F0 & self::_GetInt4d($recordData, 10)) >> 4)) { + $objStyle->getBorders()->getRight()->setBorderStyle($bordersRightStyle); + } + // bit: 11-8; mask: 0x00000F00; top style + if ($bordersTopStyle = self::_mapBorderStyle((0x00000F00 & self::_GetInt4d($recordData, 10)) >> 8)) { + $objStyle->getBorders()->getTop()->setBorderStyle($bordersTopStyle); + } + // bit: 15-12; mask: 0x0000F000; bottom style + if ($bordersBottomStyle = self::_mapBorderStyle((0x0000F000 & self::_GetInt4d($recordData, 10)) >> 12)) { + $objStyle->getBorders()->getBottom()->setBorderStyle($bordersBottomStyle); + } + // bit: 22-16; mask: 0x007F0000; left color + $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & self::_GetInt4d($recordData, 10)) >> 16; + + // bit: 29-23; mask: 0x3F800000; right color + $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & self::_GetInt4d($recordData, 10)) >> 23; + + // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom + $diagonalDown = (0x40000000 & self::_GetInt4d($recordData, 10)) >> 30 ? + true : false; + + // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right + $diagonalUp = (0x80000000 & self::_GetInt4d($recordData, 10)) >> 31 ? + true : false; + + if ($diagonalUp == false && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif ($diagonalUp == false && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + + // offset: 14; size: 4; + // bit: 6-0; mask: 0x0000007F; top color + $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & self::_GetInt4d($recordData, 14)) >> 0; + + // bit: 13-7; mask: 0x00003F80; bottom color + $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & self::_GetInt4d($recordData, 14)) >> 7; + + // bit: 20-14; mask: 0x001FC000; diagonal color + $objStyle->getBorders()->getDiagonal()->colorIndex = (0x001FC000 & self::_GetInt4d($recordData, 14)) >> 14; + + // bit: 24-21; mask: 0x01E00000; diagonal style + if ($bordersDiagonalStyle = self::_mapBorderStyle((0x01E00000 & self::_GetInt4d($recordData, 14)) >> 21)) { + $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle); + } + + // bit: 31-26; mask: 0xFC000000 fill pattern + if ($fillType = self::_mapFillPattern((0xFC000000 & self::_GetInt4d($recordData, 14)) >> 26)) { + $objStyle->getFill()->setFillType($fillType); + } + // offset: 18; size: 2; pattern and background colour + // bit: 6-0; mask: 0x007F; color index for pattern color + $objStyle->getFill()->startcolorIndex = (0x007F & self::_GetInt2d($recordData, 18)) >> 0; + + // bit: 13-7; mask: 0x3F80; color index for pattern background + $objStyle->getFill()->endcolorIndex = (0x3F80 & self::_GetInt2d($recordData, 18)) >> 7; + } else { + // BIFF5 + + // offset: 7; size: 1; Text orientation and flags + $orientationAndFlags = ord($recordData{7}); + + // bit: 1-0; mask: 0x03; XF_ORIENTATION: Text orientation + $xfOrientation = (0x03 & $orientationAndFlags) >> 0; + switch ($xfOrientation) { + case 0: + $objStyle->getAlignment()->setTextRotation(0); + break; + case 1: + $objStyle->getAlignment()->setTextRotation(-165); + break; + case 2: + $objStyle->getAlignment()->setTextRotation(90); + break; + case 3: + $objStyle->getAlignment()->setTextRotation(-90); + break; + } + + // offset: 8; size: 4; cell border lines and background area + $borderAndBackground = self::_GetInt4d($recordData, 8); + + // bit: 6-0; mask: 0x0000007F; color index for pattern color + $objStyle->getFill()->startcolorIndex = (0x0000007F & $borderAndBackground) >> 0; + + // bit: 13-7; mask: 0x00003F80; color index for pattern background + $objStyle->getFill()->endcolorIndex = (0x00003F80 & $borderAndBackground) >> 7; + + // bit: 21-16; mask: 0x003F0000; fill pattern + $objStyle->getFill()->setFillType(self::_mapFillPattern((0x003F0000 & $borderAndBackground) >> 16)); + + // bit: 24-22; mask: 0x01C00000; bottom line style + $objStyle->getBorders()->getBottom()->setBorderStyle(self::_mapBorderStyle((0x01C00000 & $borderAndBackground) >> 22)); + + // bit: 31-25; mask: 0xFE000000; bottom line color + $objStyle->getBorders()->getBottom()->colorIndex = (0xFE000000 & $borderAndBackground) >> 25; + + // offset: 12; size: 4; cell border lines + $borderLines = self::_GetInt4d($recordData, 12); + + // bit: 2-0; mask: 0x00000007; top line style + $objStyle->getBorders()->getTop()->setBorderStyle(self::_mapBorderStyle((0x00000007 & $borderLines) >> 0)); + + // bit: 5-3; mask: 0x00000038; left line style + $objStyle->getBorders()->getLeft()->setBorderStyle(self::_mapBorderStyle((0x00000038 & $borderLines) >> 3)); + + // bit: 8-6; mask: 0x000001C0; right line style + $objStyle->getBorders()->getRight()->setBorderStyle(self::_mapBorderStyle((0x000001C0 & $borderLines) >> 6)); + + // bit: 15-9; mask: 0x0000FE00; top line color index + $objStyle->getBorders()->getTop()->colorIndex = (0x0000FE00 & $borderLines) >> 9; + + // bit: 22-16; mask: 0x007F0000; left line color index + $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & $borderLines) >> 16; + + // bit: 29-23; mask: 0x3F800000; right line color index + $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $borderLines) >> 23; + } + + // add cellStyleXf or cellXf and update mapping + if ($isCellStyleXf) { + // we only read one style XF record which is always the first + if ($this->_xfIndex == 0) { + $this->_phpExcel->addCellStyleXf($objStyle); + $this->_mapCellStyleXfIndex[$this->_xfIndex] = 0; + } + } else { + // we read all cell XF records + $this->_phpExcel->addCellXf($objStyle); + $this->_mapCellXfIndex[$this->_xfIndex] = count($this->_phpExcel->getCellXfCollection()) - 1; + } + + // update XF index for when we read next record + ++$this->_xfIndex; + } + } + + + /** + * + */ + private function _readXfExt() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0x087D = repeated header + + // offset: 2; size: 2 + + // offset: 4; size: 8; not used + + // offset: 12; size: 2; record version + + // offset: 14; size: 2; index to XF record which this record modifies + $ixfe = self::_GetInt2d($recordData, 14); + + // offset: 16; size: 2; not used + + // offset: 18; size: 2; number of extension properties that follow + $cexts = self::_GetInt2d($recordData, 18); + + // start reading the actual extension data + $offset = 20; + while ($offset < $length) { + // extension type + $extType = self::_GetInt2d($recordData, $offset); + + // extension length + $cb = self::_GetInt2d($recordData, $offset + 2); + + // extension data + $extData = substr($recordData, $offset + 4, $cb); + + switch ($extType) { + case 4: // fill start color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getStartColor()->setRGB($rgb); + unset($fill->startcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 5: // fill end color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getEndColor()->setRGB($rgb); + unset($fill->endcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 7: // border color top + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $top = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getTop(); + $top->getColor()->setRGB($rgb); + unset($top->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 8: // border color bottom + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $bottom = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getBottom(); + $bottom->getColor()->setRGB($rgb); + unset($bottom->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 9: // border color left + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $left = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getLeft(); + $left->getColor()->setRGB($rgb); + unset($left->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 10: // border color right + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $right = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getRight(); + $right->getColor()->setRGB($rgb); + unset($right->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 11: // border color diagonal + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $diagonal = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getDiagonal(); + $diagonal->getColor()->setRGB($rgb); + unset($diagonal->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 13: // font color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $font = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFont(); + $font->getColor()->setRGB($rgb); + unset($font->colorIndex); // normal color index does not apply, discard + } + } + break; + } + + $offset += $cb; + } + } + + } + + + /** + * Read STYLE record + */ + private function _readStyle() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index to XF record and flag for built-in style + $ixfe = self::_GetInt2d($recordData, 0); + + // bit: 11-0; mask 0x0FFF; index to XF record + $xfIndex = (0x0FFF & $ixfe) >> 0; + + // bit: 15; mask 0x8000; 0 = user-defined style, 1 = built-in style + $isBuiltIn = (bool) ((0x8000 & $ixfe) >> 15); + + if ($isBuiltIn) { + // offset: 2; size: 1; identifier for built-in style + $builtInId = ord($recordData{2}); + + switch ($builtInId) { + case 0x00: + // currently, we are not using this for anything + break; + + default: + break; + } + + } else { + // user-defined; not supported by PHPExcel + } + } + } + + + /** + * Read PALETTE record + */ + private function _readPalette() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; number of following colors + $nm = self::_GetInt2d($recordData, 0); + + // list of RGB colors + for ($i = 0; $i < $nm; ++$i) { + $rgb = substr($recordData, 2 + 4 * $i, 4); + $this->_palette[] = self::_readRGB($rgb); + } + } + } + + + /** + * SHEET + * + * This record is located in the Workbook Globals + * Substream and represents a sheet inside the workbook. + * One SHEET record is written for each sheet. It stores the + * sheet name and a stream offset to the BOF record of the + * respective Sheet Substream within the Workbook Stream. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readSheet() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // offset: 0; size: 4; absolute stream position of the BOF record of the sheet + // NOTE: not encrypted + $rec_offset = self::_GetInt4d($this->_data, $this->_pos + 4); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 4; size: 1; sheet state + switch (ord($recordData{4})) { + case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; + case 0x02: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN; break; + default: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + } + + // offset: 5; size: 1; sheet type + $sheetType = ord($recordData{5}); + + // offset: 6; size: var; sheet name + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringShort(substr($recordData, 6)); + $rec_name = $string['value']; + } elseif ($this->_version == self::XLS_BIFF7) { + $string = $this->_readByteStringShort(substr($recordData, 6)); + $rec_name = $string['value']; + } + + $this->_sheets[] = array( + 'name' => $rec_name, + 'offset' => $rec_offset, + 'sheetState' => $sheetState, + 'sheetType' => $sheetType, + ); + } + + + /** + * Read EXTERNALBOOK record + */ + private function _readExternalBook() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset within record data + $offset = 0; + + // there are 4 types of records + if (strlen($recordData) > 4) { + // external reference + // offset: 0; size: 2; number of sheet names ($nm) + $nm = self::_GetInt2d($recordData, 0); + $offset += 2; + + // offset: 2; size: var; encoded URL without sheet name (Unicode string, 16-bit length) + $encodedUrlString = self::_readUnicodeStringLong(substr($recordData, 2)); + $offset += $encodedUrlString['size']; + + // offset: var; size: var; list of $nm sheet names (Unicode strings, 16-bit length) + $externalSheetNames = array(); + for ($i = 0; $i < $nm; ++$i) { + $externalSheetNameString = self::_readUnicodeStringLong(substr($recordData, $offset)); + $externalSheetNames[] = $externalSheetNameString['value']; + $offset += $externalSheetNameString['size']; + } + + // store the record data + $this->_externalBooks[] = array( + 'type' => 'external', + 'encodedUrl' => $encodedUrlString['value'], + 'externalSheetNames' => $externalSheetNames, + ); + + } elseif (substr($recordData, 2, 2) == pack('CC', 0x01, 0x04)) { + // internal reference + // offset: 0; size: 2; number of sheet in this document + // offset: 2; size: 2; 0x01 0x04 + $this->_externalBooks[] = array( + 'type' => 'internal', + ); + } elseif (substr($recordData, 0, 4) == pack('vCC', 0x0001, 0x01, 0x3A)) { + // add-in function + // offset: 0; size: 2; 0x0001 + $this->_externalBooks[] = array( + 'type' => 'addInFunction', + ); + } elseif (substr($recordData, 0, 2) == pack('v', 0x0000)) { + // DDE links, OLE links + // offset: 0; size: 2; 0x0000 + // offset: 2; size: var; encoded source document name + $this->_externalBooks[] = array( + 'type' => 'DDEorOLE', + ); + } + } + + + /** + * Read EXTERNNAME record. + */ + private function _readExternName() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // external sheet references provided for named cells + if ($this->_version == self::XLS_BIFF8) { + // offset: 0; size: 2; options + $options = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; + + // offset: 4; size: 2; not used + + // offset: 6; size: var + $nameString = self::_readUnicodeStringShort(substr($recordData, 6)); + + // offset: var; size: var; formula data + $offset = 6 + $nameString['size']; + $formula = $this->_getFormulaFromStructure(substr($recordData, $offset)); + + $this->_externalNames[] = array( + 'name' => $nameString['value'], + 'formula' => $formula, + ); + } + } + + + /** + * Read EXTERNSHEET record + */ + private function _readExternSheet() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // external sheet references provided for named cells + if ($this->_version == self::XLS_BIFF8) { + // offset: 0; size: 2; number of following ref structures + $nm = self::_GetInt2d($recordData, 0); + for ($i = 0; $i < $nm; ++$i) { + $this->_ref[] = array( + // offset: 2 + 6 * $i; index to EXTERNALBOOK record + 'externalBookIndex' => self::_GetInt2d($recordData, 2 + 6 * $i), + // offset: 4 + 6 * $i; index to first sheet in EXTERNALBOOK record + 'firstSheetIndex' => self::_GetInt2d($recordData, 4 + 6 * $i), + // offset: 6 + 6 * $i; index to last sheet in EXTERNALBOOK record + 'lastSheetIndex' => self::_GetInt2d($recordData, 6 + 6 * $i), + ); + } + } + } + + + /** + * DEFINEDNAME + * + * This record is part of a Link Table. It contains the name + * and the token array of an internal defined name. Token + * arrays of defined names contain tokens with aberrant + * token classes. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readDefinedName() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8) { + // retrieves named cells + + // offset: 0; size: 2; option flags + $opts = self::_GetInt2d($recordData, 0); + + // bit: 5; mask: 0x0020; 0 = user-defined name, 1 = built-in-name + $isBuiltInName = (0x0020 & $opts) >> 5; + + // offset: 2; size: 1; keyboard shortcut + + // offset: 3; size: 1; length of the name (character count) + $nlen = ord($recordData{3}); + + // offset: 4; size: 2; size of the formula data (it can happen that this is zero) + // note: there can also be additional data, this is not included in $flen + $flen = self::_GetInt2d($recordData, 4); + + // offset: 8; size: 2; 0=Global name, otherwise index to sheet (1-based) + $scope = self::_GetInt2d($recordData, 8); + + // offset: 14; size: var; Name (Unicode string without length field) + $string = self::_readUnicodeString(substr($recordData, 14), $nlen); + + // offset: var; size: $flen; formula data + $offset = 14 + $string['size']; + $formulaStructure = pack('v', $flen) . substr($recordData, $offset); + + try { + $formula = $this->_getFormulaFromStructure($formulaStructure); + } catch (PHPExcel_Exception $e) { + $formula = ''; + } + + $this->_definedname[] = array( + 'isBuiltInName' => $isBuiltInName, + 'name' => $string['value'], + 'formula' => $formula, + 'scope' => $scope, + ); + } + } + + + /** + * Read MSODRAWINGGROUP record + */ + private function _readMsoDrawingGroup() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + $this->_drawingGroupData .= $recordData; + } + + + /** + * SST - Shared String Table + * + * This record contains a list of all strings used anywhere + * in the workbook. Each string occurs only once. The + * workbook uses indexes into the list to reference the + * strings. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + **/ + private function _readSst() + { + // offset within (spliced) record data + $pos = 0; + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + + $recordData = $splicedRecordData['recordData']; + $spliceOffsets = $splicedRecordData['spliceOffsets']; + + // offset: 0; size: 4; total number of strings in the workbook + $pos += 4; + + // offset: 4; size: 4; number of following strings ($nm) + $nm = self::_GetInt4d($recordData, 4); + $pos += 4; + + // loop through the Unicode strings (16-bit length) + for ($i = 0; $i < $nm; ++$i) { + + // number of characters in the Unicode string + $numChars = self::_GetInt2d($recordData, $pos); + $pos += 2; + + // option flags + $optionFlags = ord($recordData{$pos}); + ++$pos; + + // bit: 0; mask: 0x01; 0 = compressed; 1 = uncompressed + $isCompressed = (($optionFlags & 0x01) == 0) ; + + // bit: 2; mask: 0x02; 0 = ordinary; 1 = Asian phonetic + $hasAsian = (($optionFlags & 0x04) != 0); + + // bit: 3; mask: 0x03; 0 = ordinary; 1 = Rich-Text + $hasRichText = (($optionFlags & 0x08) != 0); + + if ($hasRichText) { + // number of Rich-Text formatting runs + $formattingRuns = self::_GetInt2d($recordData, $pos); + $pos += 2; + } + + if ($hasAsian) { + // size of Asian phonetic setting + $extendedRunLength = self::_GetInt4d($recordData, $pos); + $pos += 4; + } + + // expected byte length of character array if not split + $len = ($isCompressed) ? $numChars : $numChars * 2; + + // look up limit position + foreach ($spliceOffsets as $spliceOffset) { + // it can happen that the string is empty, therefore we need + // <= and not just < + if ($pos <= $spliceOffset) { + $limitpos = $spliceOffset; + break; + } + } + + if ($pos + $len <= $limitpos) { + // character array is not split between records + + $retstr = substr($recordData, $pos, $len); + $pos += $len; + + } else { + // character array is split between records + + // first part of character array + $retstr = substr($recordData, $pos, $limitpos - $pos); + + $bytesRead = $limitpos - $pos; + + // remaining characters in Unicode string + $charsLeft = $numChars - (($isCompressed) ? $bytesRead : ($bytesRead / 2)); + + $pos = $limitpos; + + // keep reading the characters + while ($charsLeft > 0) { + + // look up next limit position, in case the string span more than one continue record + foreach ($spliceOffsets as $spliceOffset) { + if ($pos < $spliceOffset) { + $limitpos = $spliceOffset; + break; + } + } + + // repeated option flags + // OpenOffice.org documentation 5.21 + $option = ord($recordData{$pos}); + ++$pos; + + if ($isCompressed && ($option == 0)) { + // 1st fragment compressed + // this fragment compressed + $len = min($charsLeft, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len; + $isCompressed = true; + + } elseif (!$isCompressed && ($option != 0)) { + // 1st fragment uncompressed + // this fragment uncompressed + $len = min($charsLeft * 2, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len / 2; + $isCompressed = false; + + } elseif (!$isCompressed && ($option == 0)) { + // 1st fragment uncompressed + // this fragment compressed + $len = min($charsLeft, $limitpos - $pos); + for ($j = 0; $j < $len; ++$j) { + $retstr .= $recordData{$pos + $j} . chr(0); + } + $charsLeft -= $len; + $isCompressed = false; + + } else { + // 1st fragment compressed + // this fragment uncompressed + $newstr = ''; + for ($j = 0; $j < strlen($retstr); ++$j) { + $newstr .= $retstr[$j] . chr(0); + } + $retstr = $newstr; + $len = min($charsLeft * 2, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len / 2; + $isCompressed = false; + } + + $pos += $len; + } + } + + // convert to UTF-8 + $retstr = self::_encodeUTF16($retstr, $isCompressed); + + // read additional Rich-Text information, if any + $fmtRuns = array(); + if ($hasRichText) { + // list of formatting runs + for ($j = 0; $j < $formattingRuns; ++$j) { + // first formatted character; zero-based + $charPos = self::_GetInt2d($recordData, $pos + $j * 4); + + // index to font record + $fontIndex = self::_GetInt2d($recordData, $pos + 2 + $j * 4); + + $fmtRuns[] = array( + 'charPos' => $charPos, + 'fontIndex' => $fontIndex, + ); + } + $pos += 4 * $formattingRuns; + } + + // read additional Asian phonetics information, if any + if ($hasAsian) { + // For Asian phonetic settings, we skip the extended string data + $pos += $extendedRunLength; + } + + // store the shared sting + $this->_sst[] = array( + 'value' => $retstr, + 'fmtRuns' => $fmtRuns, + ); + } + + // _getSplicedRecordData() takes care of moving current position in data stream + } + + + /** + * Read PRINTGRIDLINES record + */ + private function _readPrintGridlines() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + // offset: 0; size: 2; 0 = do not print sheet grid lines; 1 = print sheet gridlines + $printGridlines = (bool) self::_GetInt2d($recordData, 0); + $this->_phpSheet->setPrintGridlines($printGridlines); + } + } + + + /** + * Read DEFAULTROWHEIGHT record + */ + private function _readDefaultRowHeight() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; option flags + // offset: 2; size: 2; default height for unused rows, (twips 1/20 point) + $height = self::_GetInt2d($recordData, 2); + $this->_phpSheet->getDefaultRowDimension()->setRowHeight($height / 20); + } + + + /** + * Read SHEETPR record + */ + private function _readSheetPr() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2 + + // bit: 6; mask: 0x0040; 0 = outline buttons above outline group + $isSummaryBelow = (0x0040 & self::_GetInt2d($recordData, 0)) >> 6; + $this->_phpSheet->setShowSummaryBelow($isSummaryBelow); + + // bit: 7; mask: 0x0080; 0 = outline buttons left of outline group + $isSummaryRight = (0x0080 & self::_GetInt2d($recordData, 0)) >> 7; + $this->_phpSheet->setShowSummaryRight($isSummaryRight); + + // bit: 8; mask: 0x100; 0 = scale printout in percent, 1 = fit printout to number of pages + // this corresponds to radio button setting in page setup dialog in Excel + $this->_isFitToPages = (bool) ((0x0100 & self::_GetInt2d($recordData, 0)) >> 8); + } + + + /** + * Read HORIZONTALPAGEBREAKS record + */ + private function _readHorizontalPageBreaks() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + + // offset: 0; size: 2; number of the following row index structures + $nm = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 6 * $nm; list of $nm row index structures + for ($i = 0; $i < $nm; ++$i) { + $r = self::_GetInt2d($recordData, 2 + 6 * $i); + $cf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); + $cl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); + + // not sure why two column indexes are necessary? + $this->_phpSheet->setBreakByColumnAndRow($cf, $r, PHPExcel_Worksheet::BREAK_ROW); + } + } + } + + + /** + * Read VERTICALPAGEBREAKS record + */ + private function _readVerticalPageBreaks() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + // offset: 0; size: 2; number of the following column index structures + $nm = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 6 * $nm; list of $nm row index structures + for ($i = 0; $i < $nm; ++$i) { + $c = self::_GetInt2d($recordData, 2 + 6 * $i); + $rf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); + $rl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); + + // not sure why two row indexes are necessary? + $this->_phpSheet->setBreakByColumnAndRow($c, $rf, PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } + + + /** + * Read HEADER record + */ + private function _readHeader() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: var + // realized that $recordData can be empty even when record exists + if ($recordData) { + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + } else { + $string = $this->_readByteStringShort($recordData); + } + + $this->_phpSheet->getHeaderFooter()->setOddHeader($string['value']); + $this->_phpSheet->getHeaderFooter()->setEvenHeader($string['value']); + } + } + } + + + /** + * Read FOOTER record + */ + private function _readFooter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: var + // realized that $recordData can be empty even when record exists + if ($recordData) { + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + } else { + $string = $this->_readByteStringShort($recordData); + } + $this->_phpSheet->getHeaderFooter()->setOddFooter($string['value']); + $this->_phpSheet->getHeaderFooter()->setEvenFooter($string['value']); + } + } + } + + + /** + * Read HCENTER record + */ + private function _readHcenter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0 = print sheet left aligned, 1 = print sheet centered horizontally + $isHorizontalCentered = (bool) self::_GetInt2d($recordData, 0); + + $this->_phpSheet->getPageSetup()->setHorizontalCentered($isHorizontalCentered); + } + } + + + /** + * Read VCENTER record + */ + private function _readVcenter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0 = print sheet aligned at top page border, 1 = print sheet vertically centered + $isVerticalCentered = (bool) self::_GetInt2d($recordData, 0); + + $this->_phpSheet->getPageSetup()->setVerticalCentered($isVerticalCentered); + } + } + + + /** + * Read LEFTMARGIN record + */ + private function _readLeftMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setLeft(self::_extractNumber($recordData)); + } + } + + + /** + * Read RIGHTMARGIN record + */ + private function _readRightMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setRight(self::_extractNumber($recordData)); + } + } + + + /** + * Read TOPMARGIN record + */ + private function _readTopMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setTop(self::_extractNumber($recordData)); + } + } + + + /** + * Read BOTTOMMARGIN record + */ + private function _readBottomMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setBottom(self::_extractNumber($recordData)); + } + } + + + /** + * Read PAGESETUP record + */ + private function _readPageSetup() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; paper size + $paperSize = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; scaling factor + $scale = self::_GetInt2d($recordData, 2); + + // offset: 6; size: 2; fit worksheet width to this number of pages, 0 = use as many as needed + $fitToWidth = self::_GetInt2d($recordData, 6); + + // offset: 8; size: 2; fit worksheet height to this number of pages, 0 = use as many as needed + $fitToHeight = self::_GetInt2d($recordData, 8); + + // offset: 10; size: 2; option flags - // bit: 1; mask: 0x0002; 0=landscape, 1=portrait - $isPortrait = (0x0002 & self::_GetInt2d($recordData, 10)) >> 1; + // bit: 1; mask: 0x0002; 0=landscape, 1=portrait + $isPortrait = (0x0002 & self::_GetInt2d($recordData, 10)) >> 1; - // bit: 2; mask: 0x0004; 1= paper size, scaling factor, paper orient. not init - // when this bit is set, do not use flags for those properties - $isNotInit = (0x0004 & self::_GetInt2d($recordData, 10)) >> 2; + // bit: 2; mask: 0x0004; 1= paper size, scaling factor, paper orient. not init + // when this bit is set, do not use flags for those properties + $isNotInit = (0x0004 & self::_GetInt2d($recordData, 10)) >> 2; - if (!$isNotInit) { - $this->_phpSheet->getPageSetup()->setPaperSize($paperSize); - switch ($isPortrait) { - case 0: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE); break; - case 1: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); break; - } + if (!$isNotInit) { + $this->_phpSheet->getPageSetup()->setPaperSize($paperSize); + switch ($isPortrait) { + case 0: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE); break; + case 1: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); break; + } - $this->_phpSheet->getPageSetup()->setScale($scale, false); - $this->_phpSheet->getPageSetup()->setFitToPage((bool) $this->_isFitToPages); - $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth, false); - $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight, false); - } - - // offset: 16; size: 8; header margin (IEEE 754 floating-point value) - $marginHeader = self::_extractNumber(substr($recordData, 16, 8)); - $this->_phpSheet->getPageMargins()->setHeader($marginHeader); + $this->_phpSheet->getPageSetup()->setScale($scale, false); + $this->_phpSheet->getPageSetup()->setFitToPage((bool) $this->_isFitToPages); + $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth, false); + $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight, false); + } + + // offset: 16; size: 8; header margin (IEEE 754 floating-point value) + $marginHeader = self::_extractNumber(substr($recordData, 16, 8)); + $this->_phpSheet->getPageMargins()->setHeader($marginHeader); - // offset: 24; size: 8; footer margin (IEEE 754 floating-point value) - $marginFooter = self::_extractNumber(substr($recordData, 24, 8)); - $this->_phpSheet->getPageMargins()->setFooter($marginFooter); - } - } + // offset: 24; size: 8; footer margin (IEEE 754 floating-point value) + $marginFooter = self::_extractNumber(substr($recordData, 24, 8)); + $this->_phpSheet->getPageMargins()->setFooter($marginFooter); + } + } - /** - * PROTECT - Sheet protection (BIFF2 through BIFF8) - * if this record is omitted, then it also means no sheet protection - */ - private function _readProtect() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; + /** + * PROTECT - Sheet protection (BIFF2 through BIFF8) + * if this record is omitted, then it also means no sheet protection + */ + private function _readProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; - if ($this->_readDataOnly) { - return; - } - - // offset: 0; size: 2; + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; - // bit 0, mask 0x01; 1 = sheet is protected - $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; - $this->_phpSheet->getProtection()->setSheet((bool)$bool); - } + // bit 0, mask 0x01; 1 = sheet is protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + $this->_phpSheet->getProtection()->setSheet((bool)$bool); + } - /** - * SCENPROTECT - */ - private function _readScenProtect() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + /** + * SCENPROTECT + */ + private function _readScenProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // move stream pointer to next record + $this->_pos += 4 + $length; - if ($this->_readDataOnly) { - return; - } + if ($this->_readDataOnly) { + return; + } - // offset: 0; size: 2; + // offset: 0; size: 2; - // bit: 0, mask 0x01; 1 = scenarios are protected - $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + // bit: 0, mask 0x01; 1 = scenarios are protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; - $this->_phpSheet->getProtection()->setScenarios((bool)$bool); - } + $this->_phpSheet->getProtection()->setScenarios((bool)$bool); + } - /** - * OBJECTPROTECT - */ - private function _readObjectProtect() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + /** + * OBJECTPROTECT + */ + private function _readObjectProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // move stream pointer to next record + $this->_pos += 4 + $length; - if ($this->_readDataOnly) { - return; - } + if ($this->_readDataOnly) { + return; + } - // offset: 0; size: 2; + // offset: 0; size: 2; - // bit: 0, mask 0x01; 1 = objects are protected - $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; - - $this->_phpSheet->getProtection()->setObjects((bool)$bool); - } - - - /** - * PASSWORD - Sheet protection (hashed) password (BIFF2 through BIFF8) - */ - private function _readPassword() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; 16-bit hash value of password - $password = strtoupper(dechex(self::_GetInt2d($recordData, 0))); // the hashed password - $this->_phpSheet->getProtection()->setPassword($password, true); - } - } + // bit: 0, mask 0x01; 1 = objects are protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setObjects((bool)$bool); + } + + + /** + * PASSWORD - Sheet protection (hashed) password (BIFF2 through BIFF8) + */ + private function _readPassword() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 16-bit hash value of password + $password = strtoupper(dechex(self::_GetInt2d($recordData, 0))); // the hashed password + $this->_phpSheet->getProtection()->setPassword($password, true); + } + } - /** - * Read DEFCOLWIDTH record - */ - private function _readDefColWidth() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + /** + * Read DEFCOLWIDTH record + */ + private function _readDefColWidth() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // move stream pointer to next record + $this->_pos += 4 + $length; - // offset: 0; size: 2; default column width - $width = self::_GetInt2d($recordData, 0); - if ($width != 8) { - $this->_phpSheet->getDefaultColumnDimension()->setWidth($width); - } - } + // offset: 0; size: 2; default column width + $width = self::_GetInt2d($recordData, 0); + if ($width != 8) { + $this->_phpSheet->getDefaultColumnDimension()->setWidth($width); + } + } - /** - * Read COLINFO record - */ - private function _readColInfo() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + /** + * Read COLINFO record + */ + private function _readColInfo() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // move stream pointer to next record + $this->_pos += 4 + $length; - if (!$this->_readDataOnly) { - // offset: 0; size: 2; index to first column in range - $fc = self::_GetInt2d($recordData, 0); // first column index + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index to first column in range + $fc = self::_GetInt2d($recordData, 0); // first column index - // offset: 2; size: 2; index to last column in range - $lc = self::_GetInt2d($recordData, 2); // first column index + // offset: 2; size: 2; index to last column in range + $lc = self::_GetInt2d($recordData, 2); // first column index - // offset: 4; size: 2; width of the column in 1/256 of the width of the zero character - $width = self::_GetInt2d($recordData, 4); + // offset: 4; size: 2; width of the column in 1/256 of the width of the zero character + $width = self::_GetInt2d($recordData, 4); - // offset: 6; size: 2; index to XF record for default column formatting - $xfIndex = self::_GetInt2d($recordData, 6); + // offset: 6; size: 2; index to XF record for default column formatting + $xfIndex = self::_GetInt2d($recordData, 6); - // offset: 8; size: 2; option flags + // offset: 8; size: 2; option flags - // bit: 0; mask: 0x0001; 1= columns are hidden - $isHidden = (0x0001 & self::_GetInt2d($recordData, 8)) >> 0; + // bit: 0; mask: 0x0001; 1= columns are hidden + $isHidden = (0x0001 & self::_GetInt2d($recordData, 8)) >> 0; - // bit: 10-8; mask: 0x0700; outline level of the columns (0 = no outline) - $level = (0x0700 & self::_GetInt2d($recordData, 8)) >> 8; + // bit: 10-8; mask: 0x0700; outline level of the columns (0 = no outline) + $level = (0x0700 & self::_GetInt2d($recordData, 8)) >> 8; - // bit: 12; mask: 0x1000; 1 = collapsed - $isCollapsed = (0x1000 & self::_GetInt2d($recordData, 8)) >> 12; - - // offset: 10; size: 2; not used - - for ($i = $fc; $i <= $lc; ++$i) { - if ($lc == 255 || $lc == 256) { - $this->_phpSheet->getDefaultColumnDimension()->setWidth($width / 256); - break; - } - $this->_phpSheet->getColumnDimensionByColumn($i)->setWidth($width / 256); - $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden); - $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level); - $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed); - $this->_phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } + // bit: 12; mask: 0x1000; 1 = collapsed + $isCollapsed = (0x1000 & self::_GetInt2d($recordData, 8)) >> 12; + + // offset: 10; size: 2; not used + + for ($i = $fc; $i <= $lc; ++$i) { + if ($lc == 255 || $lc == 256) { + $this->_phpSheet->getDefaultColumnDimension()->setWidth($width / 256); + break; + } + $this->_phpSheet->getColumnDimensionByColumn($i)->setWidth($width / 256); + $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden); + $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level); + $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed); + $this->_phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } - /** - * ROW - * - * This record contains the properties of a single row in a - * sheet. Rows and cells in a sheet are divided into blocks - * of 32 rows. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readRow() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; index of this row - $r = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to column of the first cell which is described by a cell record - - // offset: 4; size: 2; index to column of the last cell which is described by a cell record, increased by 1 - - // offset: 6; size: 2; - - // bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point - $height = (0x7FFF & self::_GetInt2d($recordData, 6)) >> 0; - - // bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height - $useDefaultHeight = (0x8000 & self::_GetInt2d($recordData, 6)) >> 15; - - if (!$useDefaultHeight) { - $this->_phpSheet->getRowDimension($r + 1)->setRowHeight($height / 20); - } - - // offset: 8; size: 2; not used - - // offset: 10; size: 2; not used in BIFF5-BIFF8 - - // offset: 12; size: 4; option flags and default row formatting - - // bit: 2-0: mask: 0x00000007; outline level of the row - $level = (0x00000007 & self::_GetInt4d($recordData, 12)) >> 0; - $this->_phpSheet->getRowDimension($r + 1)->setOutlineLevel($level); - - // bit: 4; mask: 0x00000010; 1 = outline group start or ends here... and is collapsed - $isCollapsed = (0x00000010 & self::_GetInt4d($recordData, 12)) >> 4; - $this->_phpSheet->getRowDimension($r + 1)->setCollapsed($isCollapsed); - - // bit: 5; mask: 0x00000020; 1 = row is hidden - $isHidden = (0x00000020 & self::_GetInt4d($recordData, 12)) >> 5; - $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden); - - // bit: 7; mask: 0x00000080; 1 = row has explicit format - $hasExplicitFormat = (0x00000080 & self::_GetInt4d($recordData, 12)) >> 7; - - // bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record - $xfIndex = (0x0FFF0000 & self::_GetInt4d($recordData, 12)) >> 16; - - if ($hasExplicitFormat) { - $this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } - - - /** - * Read RK record - * This record represents a cell that contains an RK value - * (encoded integer or floating-point value). If a - * floating-point value cannot be encoded to an RK value, - * a NUMBER record will be written. This record replaces the - * record INTEGER written in BIFF2. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readRk() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to column - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 4; size: 2; index to XF record - $xfIndex = self::_GetInt2d($recordData, 4); - - // offset: 6; size: 4; RK value - $rknum = self::_GetInt4d($recordData, 6); - $numValue = self::_GetIEEE754($rknum); - - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - if (!$this->_readDataOnly) { - // add style information - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - - // add cell - $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); - } - } - - - /** - * Read LABELSST record - * This record represents a cell that contains a string. It - * replaces the LABEL record and RSTRING record used in - * BIFF2-BIFF5. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readLabelSst() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to column - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 4; size: 2; index to XF record - $xfIndex = self::_GetInt2d($recordData, 4); - - // offset: 6; size: 4; index to SST record - $index = self::_GetInt4d($recordData, 6); - - // add cell - if (($fmtRuns = $this->_sst[$index]['fmtRuns']) && !$this->_readDataOnly) { - // then we should treat as rich text - $richText = new PHPExcel_RichText(); - $charPos = 0; - $sstCount = count($this->_sst[$index]['fmtRuns']); - for ($i = 0; $i <= $sstCount; ++$i) { - if (isset($fmtRuns[$i])) { - $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, $fmtRuns[$i]['charPos'] - $charPos); - $charPos = $fmtRuns[$i]['charPos']; - } else { - $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, PHPExcel_Shared_String::CountCharacters($this->_sst[$index]['value'])); - } - - if (PHPExcel_Shared_String::CountCharacters($text) > 0) { - if ($i == 0) { // first text run, no style - $richText->createText($text); - } else { - $textRun = $richText->createTextRun($text); - if (isset($fmtRuns[$i - 1])) { - if ($fmtRuns[$i - 1]['fontIndex'] < 4) { - $fontIndex = $fmtRuns[$i - 1]['fontIndex']; - } else { - // this has to do with that index 4 is omitted in all BIFF versions for some strange reason - // check the OpenOffice documentation of the FONT record - $fontIndex = $fmtRuns[$i - 1]['fontIndex'] - 1; - } - $textRun->setFont(clone $this->_objFonts[$fontIndex]); - } - } - } - } - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - $cell->setValueExplicit($richText, PHPExcel_Cell_DataType::TYPE_STRING); - } else { - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - $cell->setValueExplicit($this->_sst[$index]['value'], PHPExcel_Cell_DataType::TYPE_STRING); - } - - if (!$this->_readDataOnly) { - // add style information - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } - - - /** - * Read MULRK record - * This record represents a cell range containing RK value - * cells. All cells are located in the same row. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readMulRk() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to first column - $colFirst = self::_GetInt2d($recordData, 2); - - // offset: var; size: 2; index to last column - $colLast = self::_GetInt2d($recordData, $length - 2); - $columns = $colLast - $colFirst + 1; - - // offset within record data - $offset = 4; - - for ($i = 0; $i < $columns; ++$i) { - $columnString = PHPExcel_Cell::stringFromColumnIndex($colFirst + $i); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - - // offset: var; size: 2; index to XF record - $xfIndex = self::_GetInt2d($recordData, $offset); - - // offset: var; size: 4; RK value - $numValue = self::_GetIEEE754(self::_GetInt4d($recordData, $offset + 2)); - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - if (!$this->_readDataOnly) { - // add style - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - - // add cell value - $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); - } - - $offset += 6; - } - } - - - /** - * Read NUMBER record - * This record represents a cell that contains a - * floating-point value. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readNumber() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size 2; index to column - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset 4; size: 2; index to XF record - $xfIndex = self::_GetInt2d($recordData, 4); - - $numValue = self::_extractNumber(substr($recordData, 6, 8)); - - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - if (!$this->_readDataOnly) { - // add cell style - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - - // add cell value - $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); - } - } - - - /** - * Read FORMULA record + perhaps a following STRING record if formula result is a string - * This record contains the token array and the result of a - * formula cell. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readFormula() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; row index - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; col index - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // offset: 20: size: variable; formula structure - $formulaStructure = substr($recordData, 20); - - // offset: 14: size: 2; option flags, recalculate always, recalculate on open etc. - $options = self::_GetInt2d($recordData, 14); - - // bit: 0; mask: 0x0001; 1 = recalculate always - // bit: 1; mask: 0x0002; 1 = calculate on open - // bit: 2; mask: 0x0008; 1 = part of a shared formula - $isPartOfSharedFormula = (bool) (0x0008 & $options); - - // WARNING: - // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true - // the formula data may be ordinary formula data, therefore we need to check - // explicitly for the tExp token (0x01) - $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; - - if ($isPartOfSharedFormula) { - // part of shared formula which means there will be a formula with a tExp token and nothing else - // get the base cell, grab tExp token - $baseRow = self::_GetInt2d($formulaStructure, 3); - $baseCol = self::_GetInt2d($formulaStructure, 5); - $this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1); - } - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - - if ($isPartOfSharedFormula) { - // formula is added to this cell after the sheet has been read - $this->_sharedFormulaParts[$columnString . ($row + 1)] = $this->_baseCell; - } - - // offset: 16: size: 4; not used - - // offset: 4; size: 2; XF index - $xfIndex = self::_GetInt2d($recordData, 4); - - // offset: 6; size: 8; result of the formula - if ( (ord($recordData{6}) == 0) - && (ord($recordData{12}) == 255) - && (ord($recordData{13}) == 255) ) { - - // String formula. Result follows in appended STRING record - $dataType = PHPExcel_Cell_DataType::TYPE_STRING; - - // read possible SHAREDFMLA record - $code = self::_GetInt2d($this->_data, $this->_pos); - if ($code == self::XLS_Type_SHAREDFMLA) { - $this->_readSharedFmla(); - } - - // read STRING record - $value = $this->_readString(); - - } elseif ((ord($recordData{6}) == 1) - && (ord($recordData{12}) == 255) - && (ord($recordData{13}) == 255)) { - - // Boolean formula. Result is in +2; 0=false, 1=true - $dataType = PHPExcel_Cell_DataType::TYPE_BOOL; - $value = (bool) ord($recordData{8}); - - } elseif ((ord($recordData{6}) == 2) - && (ord($recordData{12}) == 255) - && (ord($recordData{13}) == 255)) { - - // Error formula. Error code is in +2 - $dataType = PHPExcel_Cell_DataType::TYPE_ERROR; - $value = self::_mapErrorCode(ord($recordData{8})); - - } elseif ((ord($recordData{6}) == 3) - && (ord($recordData{12}) == 255) - && (ord($recordData{13}) == 255)) { - - // Formula result is a null string - $dataType = PHPExcel_Cell_DataType::TYPE_NULL; - $value = ''; - - } else { - - // forumla result is a number, first 14 bytes like _NUMBER record - $dataType = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $value = self::_extractNumber(substr($recordData, 6, 8)); - - } - - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - if (!$this->_readDataOnly) { - // add cell style - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - - // store the formula - if (!$isPartOfSharedFormula) { - // not part of shared formula - // add cell value. If we can read formula, populate with formula, otherwise just used cached value - try { - if ($this->_version != self::XLS_BIFF8) { - throw new PHPExcel_Reader_Exception('Not BIFF8. Can only read BIFF8 formulas'); - } - $formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language - $cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); - - } catch (PHPExcel_Exception $e) { - $cell->setValueExplicit($value, $dataType); - } - } else { - if ($this->_version == self::XLS_BIFF8) { - // do nothing at this point, formula id added later in the code - } else { - $cell->setValueExplicit($value, $dataType); - } - } - - // store the cached calculated value - $cell->setCalculatedValue($value); - } - } - - - /** - * Read a SHAREDFMLA record. This function just stores the binary shared formula in the reader, - * which usually contains relative references. - * These will be used to construct the formula in each shared formula part after the sheet is read. - */ - private function _readSharedFmla() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0, size: 6; cell range address of the area used by the shared formula, not used for anything - $cellRange = substr($recordData, 0, 6); - $cellRange = $this->_readBIFF5CellRangeAddressFixed($cellRange); // note: even BIFF8 uses BIFF5 syntax - - // offset: 6, size: 1; not used - - // offset: 7, size: 1; number of existing FORMULA records for this shared formula - $no = ord($recordData{7}); - - // offset: 8, size: var; Binary token array of the shared formula - $formula = substr($recordData, 8); - - // at this point we only store the shared formula for later use - $this->_sharedFormulas[$this->_baseCell] = $formula; - - } - - - /** - * Read a STRING record from current stream position and advance the stream pointer to next record - * This record is used for storing result from FORMULA record when it is a string, and - * it occurs directly after the FORMULA record - * - * @return string The string contents as UTF-8 - */ - private function _readString() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringLong($recordData); - $value = $string['value']; - } else { - $string = $this->_readByteStringLong($recordData); - $value = $string['value']; - } - - return $value; - } - - - /** - * Read BOOLERR record - * This record represents a Boolean value or error value - * cell. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readBoolErr() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; row index - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; column index - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 4; size: 2; index to XF record - $xfIndex = self::_GetInt2d($recordData, 4); - - // offset: 6; size: 1; the boolean value or error value - $boolErr = ord($recordData{6}); - - // offset: 7; size: 1; 0=boolean; 1=error - $isError = ord($recordData{7}); - - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - switch ($isError) { - case 0: // boolean - $value = (bool) $boolErr; - - // add cell value - $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_BOOL); - break; - - case 1: // error type - $value = self::_mapErrorCode($boolErr); - - // add cell value - $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_ERROR); - break; - } - - if (!$this->_readDataOnly) { - // add cell style - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } - - - /** - * Read MULBLANK record - * This record represents a cell range of empty cells. All - * cells are located in the same row - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readMulBlank() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to first column - $fc = self::_GetInt2d($recordData, 2); - - // offset: 4; size: 2 x nc; list of indexes to XF records - // add style information - if (!$this->_readDataOnly) { - for ($i = 0; $i < $length / 2 - 3; ++$i) { - $columnString = PHPExcel_Cell::stringFromColumnIndex($fc + $i); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - $xfIndex = self::_GetInt2d($recordData, 4 + 2 * $i); - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } - - // offset: 6; size 2; index to last column (not needed) - } - - - /** - * Read LABEL record - * This record represents a cell that contains a string. In - * BIFF8 it is usually replaced by the LABELSST record. - * Excel still uses this record, if it copies unformatted - * text cells to the clipboard. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readLabel() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; index to row - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to column - $column = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($column); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 4; size: 2; XF index - $xfIndex = self::_GetInt2d($recordData, 4); - - // add cell value - // todo: what if string is very long? continue record - if ($this->_version == self::XLS_BIFF8) { - $string = self::_readUnicodeStringLong(substr($recordData, 6)); - $value = $string['value']; - } else { - $string = $this->_readByteStringLong(substr($recordData, 6)); - $value = $string['value']; - } - $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); - $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); - - if (!$this->_readDataOnly) { - // add cell style - $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - } - - - /** - * Read BLANK record - */ - private function _readBlank() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; row index - $row = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; col index - $col = self::_GetInt2d($recordData, 2); - $columnString = PHPExcel_Cell::stringFromColumnIndex($col); - - // Read cell? - if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 4; size: 2; XF index - $xfIndex = self::_GetInt2d($recordData, 4); - - // add style information - if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); - } - } - - } - - - /** - * Read MSODRAWING record - */ - private function _readMsoDrawing() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - - // get spliced record data - $splicedRecordData = $this->_getSplicedRecordData(); - $recordData = $splicedRecordData['recordData']; - - $this->_drawingData .= $recordData; - } - - - /** - * Read OBJ record - */ - private function _readObj() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_readDataOnly || $this->_version != self::XLS_BIFF8) { - return; - } - - // recordData consists of an array of subrecords looking like this: - // ft: 2 bytes; ftCmo type (0x15) - // cb: 2 bytes; size in bytes of ftCmo data - // ot: 2 bytes; Object Type - // id: 2 bytes; Object id number - // grbit: 2 bytes; Option Flags - // data: var; subrecord data - - // for now, we are just interested in the second subrecord containing the object type - $ftCmoType = self::_GetInt2d($recordData, 0); - $cbCmoSize = self::_GetInt2d($recordData, 2); - $otObjType = self::_GetInt2d($recordData, 4); - $idObjID = self::_GetInt2d($recordData, 6); - $grbitOpts = self::_GetInt2d($recordData, 6); - - $this->_objs[] = array( - 'ftCmoType' => $ftCmoType, - 'cbCmoSize' => $cbCmoSize, - 'otObjType' => $otObjType, - 'idObjID' => $idObjID, - 'grbitOpts' => $grbitOpts - ); - $this->textObjRef = $idObjID; - -// echo '_readObj()
'; -// var_dump(end($this->_objs)); -// echo '
'; - } - - - /** - * Read WINDOW2 record - */ - private function _readWindow2() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; option flags - $options = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; index to first visible row - $firstVisibleRow = self::_GetInt2d($recordData, 2); - - // offset: 4; size: 2; index to first visible colum - $firstVisibleColumn = self::_GetInt2d($recordData, 4); - if ($this->_version === self::XLS_BIFF8) { - // offset: 8; size: 2; not used - // offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%) - // offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%) - // offset: 14; size: 4; not used - $zoomscaleInPageBreakPreview = self::_GetInt2d($recordData, 10); - if ($zoomscaleInPageBreakPreview === 0) $zoomscaleInPageBreakPreview = 60; - $zoomscaleInNormalView = self::_GetInt2d($recordData, 12); - if ($zoomscaleInNormalView === 0) $zoomscaleInNormalView = 100; - } - - // bit: 1; mask: 0x0002; 0 = do not show gridlines, 1 = show gridlines - $showGridlines = (bool) ((0x0002 & $options) >> 1); - $this->_phpSheet->setShowGridlines($showGridlines); - - // bit: 2; mask: 0x0004; 0 = do not show headers, 1 = show headers - $showRowColHeaders = (bool) ((0x0004 & $options) >> 2); - $this->_phpSheet->setShowRowColHeaders($showRowColHeaders); - - // bit: 3; mask: 0x0008; 0 = panes are not frozen, 1 = panes are frozen - $this->_frozen = (bool) ((0x0008 & $options) >> 3); - - // bit: 6; mask: 0x0040; 0 = columns from left to right, 1 = columns from right to left - $this->_phpSheet->setRightToLeft((bool)((0x0040 & $options) >> 6)); - - // bit: 10; mask: 0x0400; 0 = sheet not active, 1 = sheet active - $isActive = (bool) ((0x0400 & $options) >> 10); - if ($isActive) { - $this->_phpExcel->setActiveSheetIndex($this->_phpExcel->getIndex($this->_phpSheet)); - } - - // bit: 11; mask: 0x0800; 0 = normal view, 1 = page break view - $isPageBreakPreview = (bool) ((0x0800 & $options) >> 11); - - //FIXME: set $firstVisibleRow and $firstVisibleColumn - - if ($this->_phpSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT) { - //NOTE: this setting is inferior to page layout view(Excel2007-) - $view = $isPageBreakPreview? PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW : - PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL; - $this->_phpSheet->getSheetView()->setView($view); - if ($this->_version === self::XLS_BIFF8) { - $zoomScale = $isPageBreakPreview? $zoomscaleInPageBreakPreview : $zoomscaleInNormalView; - $this->_phpSheet->getSheetView()->setZoomScale($zoomScale); - $this->_phpSheet->getSheetView()->setZoomScaleNormal($zoomscaleInNormalView); - } - } - } - - /** - * Read PLV Record(Created by Excel2007 or upper) - */ - private function _readPageLayoutView(){ - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - //var_dump(unpack("vrt/vgrbitFrt/V2reserved/vwScalePLV/vgrbit", $recordData)); - - // offset: 0; size: 2; rt - //->ignore - $rt = self::_GetInt2d($recordData, 0); - // offset: 2; size: 2; grbitfr - //->ignore - $grbitFrt = self::_GetInt2d($recordData, 2); - // offset: 4; size: 8; reserved - //->ignore - - // offset: 12; size 2; zoom scale - $wScalePLV = self::_GetInt2d($recordData, 12); - // offset: 14; size 2; grbit - $grbit = self::_GetInt2d($recordData, 14); - - // decomprise grbit - $fPageLayoutView = $grbit & 0x01; - $fRulerVisible = ($grbit >> 1) & 0x01; //no support - $fWhitespaceHidden = ($grbit >> 3) & 0x01; //no support - - if ($fPageLayoutView === 1) { - $this->_phpSheet->getSheetView()->setView(PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT); - $this->_phpSheet->getSheetView()->setZoomScale($wScalePLV); //set by Excel2007 only if SHEETVIEW_PAGE_LAYOUT - } - //otherwise, we cannot know whether SHEETVIEW_PAGE_LAYOUT or SHEETVIEW_PAGE_BREAK_PREVIEW. - } - - /** - * Read SCL record - */ - private function _readScl() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // offset: 0; size: 2; numerator of the view magnification - $numerator = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; numerator of the view magnification - $denumerator = self::_GetInt2d($recordData, 2); - - // set the zoom scale (in percent) - $this->_phpSheet->getSheetView()->setZoomScale($numerator * 100 / $denumerator); - } - - - /** - * Read PANE record - */ - private function _readPane() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; position of vertical split - $px = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; position of horizontal split - $py = self::_GetInt2d($recordData, 2); - - if ($this->_frozen) { - // frozen panes - $this->_phpSheet->freezePane(PHPExcel_Cell::stringFromColumnIndex($px) . ($py + 1)); - } else { - // unfrozen panes; split windows; not supported by PHPExcel core - } - } - } - - - /** - * Read SELECTION record. There is one such record for each pane in the sheet. - */ - private function _readSelection() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 1; pane identifier - $paneId = ord($recordData{0}); - - // offset: 1; size: 2; index to row of the active cell - $r = self::_GetInt2d($recordData, 1); - - // offset: 3; size: 2; index to column of the active cell - $c = self::_GetInt2d($recordData, 3); - - // offset: 5; size: 2; index into the following cell range list to the - // entry that contains the active cell - $index = self::_GetInt2d($recordData, 5); - - // offset: 7; size: var; cell range address list containing all selected cell ranges - $data = substr($recordData, 7); - $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax - - $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; - - // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) - if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { - $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); - } - - // first row '1' + last row '65536' indicates that full column is selected - if (preg_match('/^([A-Z]+1\:[A-Z]+)65536$/', $selectedCells)) { - $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)65536$/', '${1}1048576', $selectedCells); - } - - // first column 'A' + last column 'IV' indicates that full row is selected - if (preg_match('/^(A[0-9]+\:)IV([0-9]+)$/', $selectedCells)) { - $selectedCells = preg_replace('/^(A[0-9]+\:)IV([0-9]+)$/', '${1}XFD${2}', $selectedCells); - } - - $this->_phpSheet->setSelectedCells($selectedCells); - } - } - - - private function _includeCellRangeFiltered($cellRangeAddress) - { - $includeCellRange = true; - if ($this->getReadFilter() !== NULL) { - $includeCellRange = false; - $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($cellRangeAddress); - $rangeBoundaries[1][0]++; - for ($row = $rangeBoundaries[0][1]; $row <= $rangeBoundaries[1][1]; $row++) { - for ($column = $rangeBoundaries[0][0]; $column != $rangeBoundaries[1][0]; $column++) { - if ($this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle())) { - $includeCellRange = true; - break 2; - } - } - } - } - return $includeCellRange; - } - - - /** - * MERGEDCELLS - * - * This record contains the addresses of merged cell ranges - * in the current sheet. - * - * -- "OpenOffice.org's Documentation of the Microsoft - * Excel File Format" - */ - private function _readMergedCells() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { - $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($recordData); - foreach ($cellRangeAddressList['cellRangeAddresses'] as $cellRangeAddress) { - if ((strpos($cellRangeAddress,':') !== FALSE) && - ($this->_includeCellRangeFiltered($cellRangeAddress))) { - $this->_phpSheet->mergeCells($cellRangeAddress); - } - } - } - } - - - /** - * Read HYPERLINK record - */ - private function _readHyperLink() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer forward to next record - $this->_pos += 4 + $length; - - if (!$this->_readDataOnly) { - // offset: 0; size: 8; cell range address of all cells containing this hyperlink - try { - $cellRange = $this->_readBIFF8CellRangeAddressFixed($recordData, 0, 8); - } catch (PHPExcel_Exception $e) { - return; - } - - // offset: 8, size: 16; GUID of StdLink - - // offset: 24, size: 4; unknown value - - // offset: 28, size: 4; option flags - - // bit: 0; mask: 0x00000001; 0 = no link or extant, 1 = file link or URL - $isFileLinkOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 0; - - // bit: 1; mask: 0x00000002; 0 = relative path, 1 = absolute path or URL - $isAbsPathOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 1; - - // bit: 2 (and 4); mask: 0x00000014; 0 = no description - $hasDesc = (0x00000014 & self::_GetInt2d($recordData, 28)) >> 2; - - // bit: 3; mask: 0x00000008; 0 = no text, 1 = has text - $hasText = (0x00000008 & self::_GetInt2d($recordData, 28)) >> 3; - - // bit: 7; mask: 0x00000080; 0 = no target frame, 1 = has target frame - $hasFrame = (0x00000080 & self::_GetInt2d($recordData, 28)) >> 7; - - // bit: 8; mask: 0x00000100; 0 = file link or URL, 1 = UNC path (inc. server name) - $isUNC = (0x00000100 & self::_GetInt2d($recordData, 28)) >> 8; - - // offset within record data - $offset = 32; - - if ($hasDesc) { - // offset: 32; size: var; character count of description text - $dl = self::_GetInt4d($recordData, 32); - // offset: 36; size: var; character array of description text, no Unicode string header, always 16-bit characters, zero terminated - $desc = self::_encodeUTF16(substr($recordData, 36, 2 * ($dl - 1)), false); - $offset += 4 + 2 * $dl; - } - if ($hasFrame) { - $fl = self::_GetInt4d($recordData, $offset); - $offset += 4 + 2 * $fl; - } - - // detect type of hyperlink (there are 4 types) - $hyperlinkType = null; - - if ($isUNC) { - $hyperlinkType = 'UNC'; - } else if (!$isFileLinkOrUrl) { - $hyperlinkType = 'workbook'; - } else if (ord($recordData{$offset}) == 0x03) { - $hyperlinkType = 'local'; - } else if (ord($recordData{$offset}) == 0xE0) { - $hyperlinkType = 'URL'; - } - - switch ($hyperlinkType) { - case 'URL': - // section 5.58.2: Hyperlink containing a URL - // e.g. http://example.org/index.php - - // offset: var; size: 16; GUID of URL Moniker - $offset += 16; - // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word - $us = self::_GetInt4d($recordData, $offset); - $offset += 4; - // offset: var; size: $us; character array of the URL, no Unicode string header, always 16-bit characters, zero-terminated - $url = self::_encodeUTF16(substr($recordData, $offset, $us - 2), false); + /** + * ROW + * + * This record contains the properties of a single row in a + * sheet. Rows and cells in a sheet are divided into blocks + * of 32 rows. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readRow() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index of this row + $r = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column of the first cell which is described by a cell record + + // offset: 4; size: 2; index to column of the last cell which is described by a cell record, increased by 1 + + // offset: 6; size: 2; + + // bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point + $height = (0x7FFF & self::_GetInt2d($recordData, 6)) >> 0; + + // bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height + $useDefaultHeight = (0x8000 & self::_GetInt2d($recordData, 6)) >> 15; + + if (!$useDefaultHeight) { + $this->_phpSheet->getRowDimension($r + 1)->setRowHeight($height / 20); + } + + // offset: 8; size: 2; not used + + // offset: 10; size: 2; not used in BIFF5-BIFF8 + + // offset: 12; size: 4; option flags and default row formatting + + // bit: 2-0: mask: 0x00000007; outline level of the row + $level = (0x00000007 & self::_GetInt4d($recordData, 12)) >> 0; + $this->_phpSheet->getRowDimension($r + 1)->setOutlineLevel($level); + + // bit: 4; mask: 0x00000010; 1 = outline group start or ends here... and is collapsed + $isCollapsed = (0x00000010 & self::_GetInt4d($recordData, 12)) >> 4; + $this->_phpSheet->getRowDimension($r + 1)->setCollapsed($isCollapsed); + + // bit: 5; mask: 0x00000020; 1 = row is hidden + $isHidden = (0x00000020 & self::_GetInt4d($recordData, 12)) >> 5; + $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden); + + // bit: 7; mask: 0x00000080; 1 = row has explicit format + $hasExplicitFormat = (0x00000080 & self::_GetInt4d($recordData, 12)) >> 7; + + // bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record + $xfIndex = (0x0FFF0000 & self::_GetInt4d($recordData, 12)) >> 16; + + if ($hasExplicitFormat) { + $this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read RK record + * This record represents a cell that contains an RK value + * (encoded integer or floating-point value). If a + * floating-point value cannot be encoded to an RK value, + * a NUMBER record will be written. This record replaces the + * record INTEGER written in BIFF2. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readRk() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 4; RK value + $rknum = self::_GetInt4d($recordData, 6); + $numValue = self::_GetIEEE754($rknum); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + } + + + /** + * Read LABELSST record + * This record represents a cell that contains a string. It + * replaces the LABEL record and RSTRING record used in + * BIFF2-BIFF5. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readLabelSst() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 4; index to SST record + $index = self::_GetInt4d($recordData, 6); + + // add cell + if (($fmtRuns = $this->_sst[$index]['fmtRuns']) && !$this->_readDataOnly) { + // then we should treat as rich text + $richText = new PHPExcel_RichText(); + $charPos = 0; + $sstCount = count($this->_sst[$index]['fmtRuns']); + for ($i = 0; $i <= $sstCount; ++$i) { + if (isset($fmtRuns[$i])) { + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, $fmtRuns[$i]['charPos'] - $charPos); + $charPos = $fmtRuns[$i]['charPos']; + } else { + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, PHPExcel_Shared_String::CountCharacters($this->_sst[$index]['value'])); + } + + if (PHPExcel_Shared_String::CountCharacters($text) > 0) { + if ($i == 0) { // first text run, no style + $richText->createText($text); + } else { + $textRun = $richText->createTextRun($text); + if (isset($fmtRuns[$i - 1])) { + if ($fmtRuns[$i - 1]['fontIndex'] < 4) { + $fontIndex = $fmtRuns[$i - 1]['fontIndex']; + } else { + // this has to do with that index 4 is omitted in all BIFF versions for some strange reason + // check the OpenOffice documentation of the FONT record + $fontIndex = $fmtRuns[$i - 1]['fontIndex'] - 1; + } + $textRun->setFont(clone $this->_objFonts[$fontIndex]); + } + } + } + } + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($richText, PHPExcel_Cell_DataType::TYPE_STRING); + } else { + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($this->_sst[$index]['value'], PHPExcel_Cell_DataType::TYPE_STRING); + } + + if (!$this->_readDataOnly) { + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read MULRK record + * This record represents a cell range containing RK value + * cells. All cells are located in the same row. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMulRk() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first column + $colFirst = self::_GetInt2d($recordData, 2); + + // offset: var; size: 2; index to last column + $colLast = self::_GetInt2d($recordData, $length - 2); + $columns = $colLast - $colFirst + 1; + + // offset within record data + $offset = 4; + + for ($i = 0; $i < $columns; ++$i) { + $columnString = PHPExcel_Cell::stringFromColumnIndex($colFirst + $i); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + + // offset: var; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, $offset); + + // offset: var; size: 4; RK value + $numValue = self::_GetIEEE754(self::_GetInt4d($recordData, $offset + 2)); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell value + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + + $offset += 6; + } + } + + + /** + * Read NUMBER record + * This record represents a cell that contains a + * floating-point value. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readNumber() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + $numValue = self::_extractNumber(substr($recordData, 6, 8)); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell value + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + } + + + /** + * Read FORMULA record + perhaps a following STRING record if formula result is a string + * This record contains the token array and the result of a + * formula cell. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readFormula() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; col index + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // offset: 20: size: variable; formula structure + $formulaStructure = substr($recordData, 20); + + // offset: 14: size: 2; option flags, recalculate always, recalculate on open etc. + $options = self::_GetInt2d($recordData, 14); + + // bit: 0; mask: 0x0001; 1 = recalculate always + // bit: 1; mask: 0x0002; 1 = calculate on open + // bit: 2; mask: 0x0008; 1 = part of a shared formula + $isPartOfSharedFormula = (bool) (0x0008 & $options); + + // WARNING: + // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true + // the formula data may be ordinary formula data, therefore we need to check + // explicitly for the tExp token (0x01) + $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; + + if ($isPartOfSharedFormula) { + // part of shared formula which means there will be a formula with a tExp token and nothing else + // get the base cell, grab tExp token + $baseRow = self::_GetInt2d($formulaStructure, 3); + $baseCol = self::_GetInt2d($formulaStructure, 5); + $this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1); + } + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + + if ($isPartOfSharedFormula) { + // formula is added to this cell after the sheet has been read + $this->_sharedFormulaParts[$columnString . ($row + 1)] = $this->_baseCell; + } + + // offset: 16: size: 4; not used + + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 8; result of the formula + if ( (ord($recordData{6}) == 0) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255) ) { + + // String formula. Result follows in appended STRING record + $dataType = PHPExcel_Cell_DataType::TYPE_STRING; + + // read possible SHAREDFMLA record + $code = self::_GetInt2d($this->_data, $this->_pos); + if ($code == self::XLS_Type_SHAREDFMLA) { + $this->_readSharedFmla(); + } + + // read STRING record + $value = $this->_readString(); + + } elseif ((ord($recordData{6}) == 1) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Boolean formula. Result is in +2; 0=false, 1=true + $dataType = PHPExcel_Cell_DataType::TYPE_BOOL; + $value = (bool) ord($recordData{8}); + + } elseif ((ord($recordData{6}) == 2) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Error formula. Error code is in +2 + $dataType = PHPExcel_Cell_DataType::TYPE_ERROR; + $value = self::_mapErrorCode(ord($recordData{8})); + + } elseif ((ord($recordData{6}) == 3) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Formula result is a null string + $dataType = PHPExcel_Cell_DataType::TYPE_NULL; + $value = ''; + + } else { + + // forumla result is a number, first 14 bytes like _NUMBER record + $dataType = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $value = self::_extractNumber(substr($recordData, 6, 8)); + + } + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // store the formula + if (!$isPartOfSharedFormula) { + // not part of shared formula + // add cell value. If we can read formula, populate with formula, otherwise just used cached value + try { + if ($this->_version != self::XLS_BIFF8) { + throw new PHPExcel_Reader_Exception('Not BIFF8. Can only read BIFF8 formulas'); + } + $formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language + $cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + + } catch (PHPExcel_Exception $e) { + $cell->setValueExplicit($value, $dataType); + } + } else { + if ($this->_version == self::XLS_BIFF8) { + // do nothing at this point, formula id added later in the code + } else { + $cell->setValueExplicit($value, $dataType); + } + } + + // store the cached calculated value + $cell->setCalculatedValue($value); + } + } + + + /** + * Read a SHAREDFMLA record. This function just stores the binary shared formula in the reader, + * which usually contains relative references. + * These will be used to construct the formula in each shared formula part after the sheet is read. + */ + private function _readSharedFmla() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0, size: 6; cell range address of the area used by the shared formula, not used for anything + $cellRange = substr($recordData, 0, 6); + $cellRange = $this->_readBIFF5CellRangeAddressFixed($cellRange); // note: even BIFF8 uses BIFF5 syntax + + // offset: 6, size: 1; not used + + // offset: 7, size: 1; number of existing FORMULA records for this shared formula + $no = ord($recordData{7}); + + // offset: 8, size: var; Binary token array of the shared formula + $formula = substr($recordData, 8); + + // at this point we only store the shared formula for later use + $this->_sharedFormulas[$this->_baseCell] = $formula; + + } + + + /** + * Read a STRING record from current stream position and advance the stream pointer to next record + * This record is used for storing result from FORMULA record when it is a string, and + * it occurs directly after the FORMULA record + * + * @return string The string contents as UTF-8 + */ + private function _readString() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + $value = $string['value']; + } else { + $string = $this->_readByteStringLong($recordData); + $value = $string['value']; + } + + return $value; + } + + + /** + * Read BOOLERR record + * This record represents a Boolean value or error value + * cell. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readBoolErr() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; column index + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 1; the boolean value or error value + $boolErr = ord($recordData{6}); + + // offset: 7; size: 1; 0=boolean; 1=error + $isError = ord($recordData{7}); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + switch ($isError) { + case 0: // boolean + $value = (bool) $boolErr; + + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_BOOL); + break; + + case 1: // error type + $value = self::_mapErrorCode($boolErr); + + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_ERROR); + break; + } + + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read MULBLANK record + * This record represents a cell range of empty cells. All + * cells are located in the same row + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMulBlank() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first column + $fc = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 2 x nc; list of indexes to XF records + // add style information + if (!$this->_readDataOnly) { + for ($i = 0; $i < $length / 2 - 3; ++$i) { + $columnString = PHPExcel_Cell::stringFromColumnIndex($fc + $i); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + $xfIndex = self::_GetInt2d($recordData, 4 + 2 * $i); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + // offset: 6; size 2; index to last column (not needed) + } + + + /** + * Read LABEL record + * This record represents a cell that contains a string. In + * BIFF8 it is usually replaced by the LABELSST record. + * Excel still uses this record, if it copies unformatted + * text cells to the clipboard. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readLabel() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // add cell value + // todo: what if string is very long? continue record + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong(substr($recordData, 6)); + $value = $string['value']; + } else { + $string = $this->_readByteStringLong(substr($recordData, 6)); + $value = $string['value']; + } + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); + + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read BLANK record + */ + private function _readBlank() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; col index + $col = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($col); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // add style information + if (!$this->_readDataOnly) { + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + + } + + + /** + * Read MSODRAWING record + */ + private function _readMsoDrawing() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + $this->_drawingData .= $recordData; + } + + + /** + * Read OBJ record + */ + private function _readObj() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly || $this->_version != self::XLS_BIFF8) { + return; + } + + // recordData consists of an array of subrecords looking like this: + // ft: 2 bytes; ftCmo type (0x15) + // cb: 2 bytes; size in bytes of ftCmo data + // ot: 2 bytes; Object Type + // id: 2 bytes; Object id number + // grbit: 2 bytes; Option Flags + // data: var; subrecord data + + // for now, we are just interested in the second subrecord containing the object type + $ftCmoType = self::_GetInt2d($recordData, 0); + $cbCmoSize = self::_GetInt2d($recordData, 2); + $otObjType = self::_GetInt2d($recordData, 4); + $idObjID = self::_GetInt2d($recordData, 6); + $grbitOpts = self::_GetInt2d($recordData, 6); + + $this->_objs[] = array( + 'ftCmoType' => $ftCmoType, + 'cbCmoSize' => $cbCmoSize, + 'otObjType' => $otObjType, + 'idObjID' => $idObjID, + 'grbitOpts' => $grbitOpts + ); + $this->textObjRef = $idObjID; + +// echo '_readObj()
'; +// var_dump(end($this->_objs)); +// echo '
'; + } + + + /** + * Read WINDOW2 record + */ + private function _readWindow2() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; option flags + $options = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first visible row + $firstVisibleRow = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 2; index to first visible colum + $firstVisibleColumn = self::_GetInt2d($recordData, 4); + if ($this->_version === self::XLS_BIFF8) { + // offset: 8; size: 2; not used + // offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%) + // offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%) + // offset: 14; size: 4; not used + $zoomscaleInPageBreakPreview = self::_GetInt2d($recordData, 10); + if ($zoomscaleInPageBreakPreview === 0) $zoomscaleInPageBreakPreview = 60; + $zoomscaleInNormalView = self::_GetInt2d($recordData, 12); + if ($zoomscaleInNormalView === 0) $zoomscaleInNormalView = 100; + } + + // bit: 1; mask: 0x0002; 0 = do not show gridlines, 1 = show gridlines + $showGridlines = (bool) ((0x0002 & $options) >> 1); + $this->_phpSheet->setShowGridlines($showGridlines); + + // bit: 2; mask: 0x0004; 0 = do not show headers, 1 = show headers + $showRowColHeaders = (bool) ((0x0004 & $options) >> 2); + $this->_phpSheet->setShowRowColHeaders($showRowColHeaders); + + // bit: 3; mask: 0x0008; 0 = panes are not frozen, 1 = panes are frozen + $this->_frozen = (bool) ((0x0008 & $options) >> 3); + + // bit: 6; mask: 0x0040; 0 = columns from left to right, 1 = columns from right to left + $this->_phpSheet->setRightToLeft((bool)((0x0040 & $options) >> 6)); + + // bit: 10; mask: 0x0400; 0 = sheet not active, 1 = sheet active + $isActive = (bool) ((0x0400 & $options) >> 10); + if ($isActive) { + $this->_phpExcel->setActiveSheetIndex($this->_phpExcel->getIndex($this->_phpSheet)); + } + + // bit: 11; mask: 0x0800; 0 = normal view, 1 = page break view + $isPageBreakPreview = (bool) ((0x0800 & $options) >> 11); + + //FIXME: set $firstVisibleRow and $firstVisibleColumn + + if ($this->_phpSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT) { + //NOTE: this setting is inferior to page layout view(Excel2007-) + $view = $isPageBreakPreview? PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW : + PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL; + $this->_phpSheet->getSheetView()->setView($view); + if ($this->_version === self::XLS_BIFF8) { + $zoomScale = $isPageBreakPreview? $zoomscaleInPageBreakPreview : $zoomscaleInNormalView; + $this->_phpSheet->getSheetView()->setZoomScale($zoomScale); + $this->_phpSheet->getSheetView()->setZoomScaleNormal($zoomscaleInNormalView); + } + } + } + + /** + * Read PLV Record(Created by Excel2007 or upper) + */ + private function _readPageLayoutView(){ + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + //var_dump(unpack("vrt/vgrbitFrt/V2reserved/vwScalePLV/vgrbit", $recordData)); + + // offset: 0; size: 2; rt + //->ignore + $rt = self::_GetInt2d($recordData, 0); + // offset: 2; size: 2; grbitfr + //->ignore + $grbitFrt = self::_GetInt2d($recordData, 2); + // offset: 4; size: 8; reserved + //->ignore + + // offset: 12; size 2; zoom scale + $wScalePLV = self::_GetInt2d($recordData, 12); + // offset: 14; size 2; grbit + $grbit = self::_GetInt2d($recordData, 14); + + // decomprise grbit + $fPageLayoutView = $grbit & 0x01; + $fRulerVisible = ($grbit >> 1) & 0x01; //no support + $fWhitespaceHidden = ($grbit >> 3) & 0x01; //no support + + if ($fPageLayoutView === 1) { + $this->_phpSheet->getSheetView()->setView(PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT); + $this->_phpSheet->getSheetView()->setZoomScale($wScalePLV); //set by Excel2007 only if SHEETVIEW_PAGE_LAYOUT + } + //otherwise, we cannot know whether SHEETVIEW_PAGE_LAYOUT or SHEETVIEW_PAGE_BREAK_PREVIEW. + } + + /** + * Read SCL record + */ + private function _readScl() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; numerator of the view magnification + $numerator = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; numerator of the view magnification + $denumerator = self::_GetInt2d($recordData, 2); + + // set the zoom scale (in percent) + $this->_phpSheet->getSheetView()->setZoomScale($numerator * 100 / $denumerator); + } + + + /** + * Read PANE record + */ + private function _readPane() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; position of vertical split + $px = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; position of horizontal split + $py = self::_GetInt2d($recordData, 2); + + if ($this->_frozen) { + // frozen panes + $this->_phpSheet->freezePane(PHPExcel_Cell::stringFromColumnIndex($px) . ($py + 1)); + } else { + // unfrozen panes; split windows; not supported by PHPExcel core + } + } + } + + + /** + * Read SELECTION record. There is one such record for each pane in the sheet. + */ + private function _readSelection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 1; pane identifier + $paneId = ord($recordData{0}); + + // offset: 1; size: 2; index to row of the active cell + $r = self::_GetInt2d($recordData, 1); + + // offset: 3; size: 2; index to column of the active cell + $c = self::_GetInt2d($recordData, 3); + + // offset: 5; size: 2; index into the following cell range list to the + // entry that contains the active cell + $index = self::_GetInt2d($recordData, 5); + + // offset: 7; size: var; cell range address list containing all selected cell ranges + $data = substr($recordData, 7); + $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax + + $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; + + // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) + if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); + } + + // first row '1' + last row '65536' indicates that full column is selected + if (preg_match('/^([A-Z]+1\:[A-Z]+)65536$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)65536$/', '${1}1048576', $selectedCells); + } + + // first column 'A' + last column 'IV' indicates that full row is selected + if (preg_match('/^(A[0-9]+\:)IV([0-9]+)$/', $selectedCells)) { + $selectedCells = preg_replace('/^(A[0-9]+\:)IV([0-9]+)$/', '${1}XFD${2}', $selectedCells); + } + + $this->_phpSheet->setSelectedCells($selectedCells); + } + } + + + private function _includeCellRangeFiltered($cellRangeAddress) + { + $includeCellRange = true; + if ($this->getReadFilter() !== NULL) { + $includeCellRange = false; + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($cellRangeAddress); + $rangeBoundaries[1][0]++; + for ($row = $rangeBoundaries[0][1]; $row <= $rangeBoundaries[1][1]; $row++) { + for ($column = $rangeBoundaries[0][0]; $column != $rangeBoundaries[1][0]; $column++) { + if ($this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle())) { + $includeCellRange = true; + break 2; + } + } + } + } + return $includeCellRange; + } + + + /** + * MERGEDCELLS + * + * This record contains the addresses of merged cell ranges + * in the current sheet. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMergedCells() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($recordData); + foreach ($cellRangeAddressList['cellRangeAddresses'] as $cellRangeAddress) { + if ((strpos($cellRangeAddress,':') !== FALSE) && + ($this->_includeCellRangeFiltered($cellRangeAddress))) { + $this->_phpSheet->mergeCells($cellRangeAddress); + } + } + } + } + + + /** + * Read HYPERLINK record + */ + private function _readHyperLink() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8; cell range address of all cells containing this hyperlink + try { + $cellRange = $this->_readBIFF8CellRangeAddressFixed($recordData, 0, 8); + } catch (PHPExcel_Exception $e) { + return; + } + + // offset: 8, size: 16; GUID of StdLink + + // offset: 24, size: 4; unknown value + + // offset: 28, size: 4; option flags + + // bit: 0; mask: 0x00000001; 0 = no link or extant, 1 = file link or URL + $isFileLinkOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 0; + + // bit: 1; mask: 0x00000002; 0 = relative path, 1 = absolute path or URL + $isAbsPathOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 1; + + // bit: 2 (and 4); mask: 0x00000014; 0 = no description + $hasDesc = (0x00000014 & self::_GetInt2d($recordData, 28)) >> 2; + + // bit: 3; mask: 0x00000008; 0 = no text, 1 = has text + $hasText = (0x00000008 & self::_GetInt2d($recordData, 28)) >> 3; + + // bit: 7; mask: 0x00000080; 0 = no target frame, 1 = has target frame + $hasFrame = (0x00000080 & self::_GetInt2d($recordData, 28)) >> 7; + + // bit: 8; mask: 0x00000100; 0 = file link or URL, 1 = UNC path (inc. server name) + $isUNC = (0x00000100 & self::_GetInt2d($recordData, 28)) >> 8; + + // offset within record data + $offset = 32; + + if ($hasDesc) { + // offset: 32; size: var; character count of description text + $dl = self::_GetInt4d($recordData, 32); + // offset: 36; size: var; character array of description text, no Unicode string header, always 16-bit characters, zero terminated + $desc = self::_encodeUTF16(substr($recordData, 36, 2 * ($dl - 1)), false); + $offset += 4 + 2 * $dl; + } + if ($hasFrame) { + $fl = self::_GetInt4d($recordData, $offset); + $offset += 4 + 2 * $fl; + } + + // detect type of hyperlink (there are 4 types) + $hyperlinkType = null; + + if ($isUNC) { + $hyperlinkType = 'UNC'; + } else if (!$isFileLinkOrUrl) { + $hyperlinkType = 'workbook'; + } else if (ord($recordData{$offset}) == 0x03) { + $hyperlinkType = 'local'; + } else if (ord($recordData{$offset}) == 0xE0) { + $hyperlinkType = 'URL'; + } + + switch ($hyperlinkType) { + case 'URL': + // section 5.58.2: Hyperlink containing a URL + // e.g. http://example.org/index.php + + // offset: var; size: 16; GUID of URL Moniker + $offset += 16; + // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word + $us = self::_GetInt4d($recordData, $offset); + $offset += 4; + // offset: var; size: $us; character array of the URL, no Unicode string header, always 16-bit characters, zero-terminated + $url = self::_encodeUTF16(substr($recordData, $offset, $us - 2), false); $nullOffset = strpos($url, 0x00); - if ($nullOffset) + if ($nullOffset) $url = substr($url,0,$nullOffset); - $url .= $hasText ? '#' : ''; - $offset += $us; - break; - - case 'local': - // section 5.58.3: Hyperlink to local file - // examples: - // mydoc.txt - // ../../somedoc.xls#Sheet!A1 - - // offset: var; size: 16; GUI of File Moniker - $offset += 16; - - // offset: var; size: 2; directory up-level count. - $upLevelCount = self::_GetInt2d($recordData, $offset); - $offset += 2; - - // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word - $sl = self::_GetInt4d($recordData, $offset); - $offset += 4; - - // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string) - $shortenedFilePath = substr($recordData, $offset, $sl); - $shortenedFilePath = self::_encodeUTF16($shortenedFilePath, true); - $shortenedFilePath = substr($shortenedFilePath, 0, -1); // remove trailing zero - - $offset += $sl; - - // offset: var; size: 24; unknown sequence - $offset += 24; - - // extended file path - // offset: var; size: 4; size of the following file link field including string lenth mark - $sz = self::_GetInt4d($recordData, $offset); - $offset += 4; - - // only present if $sz > 0 - if ($sz > 0) { - // offset: var; size: 4; size of the character array of the extended file path and name - $xl = self::_GetInt4d($recordData, $offset); - $offset += 4; - - // offset: var; size 2; unknown - $offset += 2; - - // offset: var; size $xl; character array of the extended file path and name. - $extendedFilePath = substr($recordData, $offset, $xl); - $extendedFilePath = self::_encodeUTF16($extendedFilePath, false); - $offset += $xl; - } - - // construct the path - $url = str_repeat('..\\', $upLevelCount); - $url .= ($sz > 0) ? - $extendedFilePath : $shortenedFilePath; // use extended path if available - $url .= $hasText ? '#' : ''; - - break; - - - case 'UNC': - // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path - // todo: implement - return; - - case 'workbook': - // section 5.58.5: Hyperlink to the Current Workbook - // e.g. Sheet2!B1:C2, stored in text mark field - $url = 'sheet://'; - break; - - default: - return; - - } - - if ($hasText) { - // offset: var; size: 4; character count of text mark including trailing zero word - $tl = self::_GetInt4d($recordData, $offset); - $offset += 4; - // offset: var; size: var; character array of the text mark without the # sign, no Unicode header, always 16-bit characters, zero-terminated - $text = self::_encodeUTF16(substr($recordData, $offset, 2 * ($tl - 1)), false); - $url .= $text; - } - - // apply the hyperlink to all the relevant cells - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cellRange) as $coordinate) { - $this->_phpSheet->getCell($coordinate)->getHyperLink()->setUrl($url); - } - } - } - - - /** - * Read DATAVALIDATIONS record - */ - private function _readDataValidations() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer forward to next record - $this->_pos += 4 + $length; - } - - - /** - * Read DATAVALIDATION record - */ - private function _readDataValidation() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer forward to next record - $this->_pos += 4 + $length; - - if ($this->_readDataOnly) { - return; - } - - // offset: 0; size: 4; Options - $options = self::_GetInt4d($recordData, 0); - - // bit: 0-3; mask: 0x0000000F; type - $type = (0x0000000F & $options) >> 0; - switch ($type) { - case 0x00: $type = PHPExcel_Cell_DataValidation::TYPE_NONE; break; - case 0x01: $type = PHPExcel_Cell_DataValidation::TYPE_WHOLE; break; - case 0x02: $type = PHPExcel_Cell_DataValidation::TYPE_DECIMAL; break; - case 0x03: $type = PHPExcel_Cell_DataValidation::TYPE_LIST; break; - case 0x04: $type = PHPExcel_Cell_DataValidation::TYPE_DATE; break; - case 0x05: $type = PHPExcel_Cell_DataValidation::TYPE_TIME; break; - case 0x06: $type = PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH; break; - case 0x07: $type = PHPExcel_Cell_DataValidation::TYPE_CUSTOM; break; - } - - // bit: 4-6; mask: 0x00000070; error type - $errorStyle = (0x00000070 & $options) >> 4; - switch ($errorStyle) { - case 0x00: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; break; - case 0x01: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_WARNING; break; - case 0x02: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_INFORMATION; break; - } - - // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list) - // I have only seen cases where this is 1 - $explicitFormula = (0x00000080 & $options) >> 7; - - // bit: 8; mask: 0x00000100; 1= empty cells allowed - $allowBlank = (0x00000100 & $options) >> 8; - - // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity - $suppressDropDown = (0x00000200 & $options) >> 9; - - // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected - $showInputMessage = (0x00040000 & $options) >> 18; - - // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered - $showErrorMessage = (0x00080000 & $options) >> 19; - - // bit: 20-23; mask: 0x00F00000; condition operator - $operator = (0x00F00000 & $options) >> 20; - switch ($operator) { - case 0x00: $operator = PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN ; break; - case 0x01: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN ; break; - case 0x02: $operator = PHPExcel_Cell_DataValidation::OPERATOR_EQUAL ; break; - case 0x03: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL ; break; - case 0x04: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN ; break; - case 0x05: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN ; break; - case 0x06: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL; break; - case 0x07: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL ; break; - } - - // offset: 4; size: var; title of the prompt box - $offset = 4; - $string = self::_readUnicodeStringLong(substr($recordData, $offset)); - $promptTitle = $string['value'] !== chr(0) ? - $string['value'] : ''; - $offset += $string['size']; - - // offset: var; size: var; title of the error box - $string = self::_readUnicodeStringLong(substr($recordData, $offset)); - $errorTitle = $string['value'] !== chr(0) ? - $string['value'] : ''; - $offset += $string['size']; - - // offset: var; size: var; text of the prompt box - $string = self::_readUnicodeStringLong(substr($recordData, $offset)); - $prompt = $string['value'] !== chr(0) ? - $string['value'] : ''; - $offset += $string['size']; - - // offset: var; size: var; text of the error box - $string = self::_readUnicodeStringLong(substr($recordData, $offset)); - $error = $string['value'] !== chr(0) ? - $string['value'] : ''; - $offset += $string['size']; - - // offset: var; size: 2; size of the formula data for the first condition - $sz1 = self::_GetInt2d($recordData, $offset); - $offset += 2; - - // offset: var; size: 2; not used - $offset += 2; - - // offset: var; size: $sz1; formula data for first condition (without size field) - $formula1 = substr($recordData, $offset, $sz1); - $formula1 = pack('v', $sz1) . $formula1; // prepend the length - try { - $formula1 = $this->_getFormulaFromStructure($formula1); - - // in list type validity, null characters are used as item separators - if ($type == PHPExcel_Cell_DataValidation::TYPE_LIST) { - $formula1 = str_replace(chr(0), ',', $formula1); - } - } catch (PHPExcel_Exception $e) { - return; - } - $offset += $sz1; - - // offset: var; size: 2; size of the formula data for the first condition - $sz2 = self::_GetInt2d($recordData, $offset); - $offset += 2; - - // offset: var; size: 2; not used - $offset += 2; - - // offset: var; size: $sz2; formula data for second condition (without size field) - $formula2 = substr($recordData, $offset, $sz2); - $formula2 = pack('v', $sz2) . $formula2; // prepend the length - try { - $formula2 = $this->_getFormulaFromStructure($formula2); - } catch (PHPExcel_Exception $e) { - return; - } - $offset += $sz2; - - // offset: var; size: var; cell range address list with - $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList(substr($recordData, $offset)); - $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses']; - - foreach ($cellRangeAddresses as $cellRange) { - $stRange = $this->_phpSheet->shrinkRangeToFit($cellRange); - $stRange = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); - foreach ($stRange as $coordinate) { - $objValidation = $this->_phpSheet->getCell($coordinate)->getDataValidation(); - $objValidation->setType($type); - $objValidation->setErrorStyle($errorStyle); - $objValidation->setAllowBlank((bool)$allowBlank); - $objValidation->setShowInputMessage((bool)$showInputMessage); - $objValidation->setShowErrorMessage((bool)$showErrorMessage); - $objValidation->setShowDropDown(!$suppressDropDown); - $objValidation->setOperator($operator); - $objValidation->setErrorTitle($errorTitle); - $objValidation->setError($error); - $objValidation->setPromptTitle($promptTitle); - $objValidation->setPrompt($prompt); - $objValidation->setFormula1($formula1); - $objValidation->setFormula2($formula2); - } - } - - } - - - /** - * Read SHEETLAYOUT record. Stores sheet tab color information. - */ - private function _readSheetLayout() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // local pointer in record data - $offset = 0; - - if (!$this->_readDataOnly) { - // offset: 0; size: 2; repeated record identifier 0x0862 - - // offset: 2; size: 10; not used - - // offset: 12; size: 4; size of record data - // Excel 2003 uses size of 0x14 (documented), Excel 2007 uses size of 0x28 (not documented?) - $sz = self::_GetInt4d($recordData, 12); - - switch ($sz) { - case 0x14: - // offset: 16; size: 2; color index for sheet tab - $colorIndex = self::_GetInt2d($recordData, 16); - $color = self::_readColor($colorIndex,$this->_palette,$this->_version); - $this->_phpSheet->getTabColor()->setRGB($color['rgb']); - break; - - case 0x28: - // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 - return; - break; - } - } - } - - - /** - * Read SHEETPROTECTION record (FEATHEADR) - */ - private function _readSheetProtection() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - if ($this->_readDataOnly) { - return; - } - - // offset: 0; size: 2; repeated record header - - // offset: 2; size: 2; FRT cell reference flag (=0 currently) - - // offset: 4; size: 8; Currently not used and set to 0 - - // offset: 12; size: 2; Shared feature type index (2=Enhanced Protetion, 4=SmartTag) - $isf = self::_GetInt2d($recordData, 12); - if ($isf != 2) { - return; - } - - // offset: 14; size: 1; =1 since this is a feat header - - // offset: 15; size: 4; size of rgbHdrSData - - // rgbHdrSData, assume "Enhanced Protection" - // offset: 19; size: 2; option flags - $options = self::_GetInt2d($recordData, 19); - - // bit: 0; mask 0x0001; 1 = user may edit objects, 0 = users must not edit objects - $bool = (0x0001 & $options) >> 0; - $this->_phpSheet->getProtection()->setObjects(!$bool); - - // bit: 1; mask 0x0002; edit scenarios - $bool = (0x0002 & $options) >> 1; - $this->_phpSheet->getProtection()->setScenarios(!$bool); - - // bit: 2; mask 0x0004; format cells - $bool = (0x0004 & $options) >> 2; - $this->_phpSheet->getProtection()->setFormatCells(!$bool); - - // bit: 3; mask 0x0008; format columns - $bool = (0x0008 & $options) >> 3; - $this->_phpSheet->getProtection()->setFormatColumns(!$bool); - - // bit: 4; mask 0x0010; format rows - $bool = (0x0010 & $options) >> 4; - $this->_phpSheet->getProtection()->setFormatRows(!$bool); + $url .= $hasText ? '#' : ''; + $offset += $us; + break; + + case 'local': + // section 5.58.3: Hyperlink to local file + // examples: + // mydoc.txt + // ../../somedoc.xls#Sheet!A1 + + // offset: var; size: 16; GUI of File Moniker + $offset += 16; + + // offset: var; size: 2; directory up-level count. + $upLevelCount = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word + $sl = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string) + $shortenedFilePath = substr($recordData, $offset, $sl); + $shortenedFilePath = self::_encodeUTF16($shortenedFilePath, true); + $shortenedFilePath = substr($shortenedFilePath, 0, -1); // remove trailing zero + + $offset += $sl; + + // offset: var; size: 24; unknown sequence + $offset += 24; + + // extended file path + // offset: var; size: 4; size of the following file link field including string lenth mark + $sz = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // only present if $sz > 0 + if ($sz > 0) { + // offset: var; size: 4; size of the character array of the extended file path and name + $xl = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size 2; unknown + $offset += 2; + + // offset: var; size $xl; character array of the extended file path and name. + $extendedFilePath = substr($recordData, $offset, $xl); + $extendedFilePath = self::_encodeUTF16($extendedFilePath, false); + $offset += $xl; + } + + // construct the path + $url = str_repeat('..\\', $upLevelCount); + $url .= ($sz > 0) ? + $extendedFilePath : $shortenedFilePath; // use extended path if available + $url .= $hasText ? '#' : ''; + + break; + + + case 'UNC': + // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path + // todo: implement + return; + + case 'workbook': + // section 5.58.5: Hyperlink to the Current Workbook + // e.g. Sheet2!B1:C2, stored in text mark field + $url = 'sheet://'; + break; + + default: + return; + + } + + if ($hasText) { + // offset: var; size: 4; character count of text mark including trailing zero word + $tl = self::_GetInt4d($recordData, $offset); + $offset += 4; + // offset: var; size: var; character array of the text mark without the # sign, no Unicode header, always 16-bit characters, zero-terminated + $text = self::_encodeUTF16(substr($recordData, $offset, 2 * ($tl - 1)), false); + $url .= $text; + } + + // apply the hyperlink to all the relevant cells + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cellRange) as $coordinate) { + $this->_phpSheet->getCell($coordinate)->getHyperLink()->setUrl($url); + } + } + } + + + /** + * Read DATAVALIDATIONS record + */ + private function _readDataValidations() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + } + + + /** + * Read DATAVALIDATION record + */ + private function _readDataValidation() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 4; Options + $options = self::_GetInt4d($recordData, 0); + + // bit: 0-3; mask: 0x0000000F; type + $type = (0x0000000F & $options) >> 0; + switch ($type) { + case 0x00: $type = PHPExcel_Cell_DataValidation::TYPE_NONE; break; + case 0x01: $type = PHPExcel_Cell_DataValidation::TYPE_WHOLE; break; + case 0x02: $type = PHPExcel_Cell_DataValidation::TYPE_DECIMAL; break; + case 0x03: $type = PHPExcel_Cell_DataValidation::TYPE_LIST; break; + case 0x04: $type = PHPExcel_Cell_DataValidation::TYPE_DATE; break; + case 0x05: $type = PHPExcel_Cell_DataValidation::TYPE_TIME; break; + case 0x06: $type = PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH; break; + case 0x07: $type = PHPExcel_Cell_DataValidation::TYPE_CUSTOM; break; + } + + // bit: 4-6; mask: 0x00000070; error type + $errorStyle = (0x00000070 & $options) >> 4; + switch ($errorStyle) { + case 0x00: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; break; + case 0x01: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_WARNING; break; + case 0x02: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_INFORMATION; break; + } + + // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list) + // I have only seen cases where this is 1 + $explicitFormula = (0x00000080 & $options) >> 7; + + // bit: 8; mask: 0x00000100; 1= empty cells allowed + $allowBlank = (0x00000100 & $options) >> 8; + + // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity + $suppressDropDown = (0x00000200 & $options) >> 9; + + // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected + $showInputMessage = (0x00040000 & $options) >> 18; + + // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered + $showErrorMessage = (0x00080000 & $options) >> 19; + + // bit: 20-23; mask: 0x00F00000; condition operator + $operator = (0x00F00000 & $options) >> 20; + switch ($operator) { + case 0x00: $operator = PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN ; break; + case 0x01: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN ; break; + case 0x02: $operator = PHPExcel_Cell_DataValidation::OPERATOR_EQUAL ; break; + case 0x03: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL ; break; + case 0x04: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN ; break; + case 0x05: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN ; break; + case 0x06: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL; break; + case 0x07: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL ; break; + } + + // offset: 4; size: var; title of the prompt box + $offset = 4; + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $promptTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; title of the error box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $errorTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the prompt box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $prompt = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the error box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $error = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: 2; size of the formula data for the first condition + $sz1 = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz1; formula data for first condition (without size field) + $formula1 = substr($recordData, $offset, $sz1); + $formula1 = pack('v', $sz1) . $formula1; // prepend the length + try { + $formula1 = $this->_getFormulaFromStructure($formula1); + + // in list type validity, null characters are used as item separators + if ($type == PHPExcel_Cell_DataValidation::TYPE_LIST) { + $formula1 = str_replace(chr(0), ',', $formula1); + } + } catch (PHPExcel_Exception $e) { + return; + } + $offset += $sz1; + + // offset: var; size: 2; size of the formula data for the first condition + $sz2 = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz2; formula data for second condition (without size field) + $formula2 = substr($recordData, $offset, $sz2); + $formula2 = pack('v', $sz2) . $formula2; // prepend the length + try { + $formula2 = $this->_getFormulaFromStructure($formula2); + } catch (PHPExcel_Exception $e) { + return; + } + $offset += $sz2; + + // offset: var; size: var; cell range address list with + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList(substr($recordData, $offset)); + $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses']; + + foreach ($cellRangeAddresses as $cellRange) { + $stRange = $this->_phpSheet->shrinkRangeToFit($cellRange); + $stRange = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($stRange as $coordinate) { + $objValidation = $this->_phpSheet->getCell($coordinate)->getDataValidation(); + $objValidation->setType($type); + $objValidation->setErrorStyle($errorStyle); + $objValidation->setAllowBlank((bool)$allowBlank); + $objValidation->setShowInputMessage((bool)$showInputMessage); + $objValidation->setShowErrorMessage((bool)$showErrorMessage); + $objValidation->setShowDropDown(!$suppressDropDown); + $objValidation->setOperator($operator); + $objValidation->setErrorTitle($errorTitle); + $objValidation->setError($error); + $objValidation->setPromptTitle($promptTitle); + $objValidation->setPrompt($prompt); + $objValidation->setFormula1($formula1); + $objValidation->setFormula2($formula2); + } + } + + } + + + /** + * Read SHEETLAYOUT record. Stores sheet tab color information. + */ + private function _readSheetLayout() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // local pointer in record data + $offset = 0; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; repeated record identifier 0x0862 + + // offset: 2; size: 10; not used + + // offset: 12; size: 4; size of record data + // Excel 2003 uses size of 0x14 (documented), Excel 2007 uses size of 0x28 (not documented?) + $sz = self::_GetInt4d($recordData, 12); + + switch ($sz) { + case 0x14: + // offset: 16; size: 2; color index for sheet tab + $colorIndex = self::_GetInt2d($recordData, 16); + $color = self::_readColor($colorIndex,$this->_palette,$this->_version); + $this->_phpSheet->getTabColor()->setRGB($color['rgb']); + break; + + case 0x28: + // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 + return; + break; + } + } + } + + + /** + * Read SHEETPROTECTION record (FEATHEADR) + */ + private function _readSheetProtection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; repeated record header + + // offset: 2; size: 2; FRT cell reference flag (=0 currently) + + // offset: 4; size: 8; Currently not used and set to 0 + + // offset: 12; size: 2; Shared feature type index (2=Enhanced Protetion, 4=SmartTag) + $isf = self::_GetInt2d($recordData, 12); + if ($isf != 2) { + return; + } + + // offset: 14; size: 1; =1 since this is a feat header + + // offset: 15; size: 4; size of rgbHdrSData + + // rgbHdrSData, assume "Enhanced Protection" + // offset: 19; size: 2; option flags + $options = self::_GetInt2d($recordData, 19); + + // bit: 0; mask 0x0001; 1 = user may edit objects, 0 = users must not edit objects + $bool = (0x0001 & $options) >> 0; + $this->_phpSheet->getProtection()->setObjects(!$bool); + + // bit: 1; mask 0x0002; edit scenarios + $bool = (0x0002 & $options) >> 1; + $this->_phpSheet->getProtection()->setScenarios(!$bool); + + // bit: 2; mask 0x0004; format cells + $bool = (0x0004 & $options) >> 2; + $this->_phpSheet->getProtection()->setFormatCells(!$bool); + + // bit: 3; mask 0x0008; format columns + $bool = (0x0008 & $options) >> 3; + $this->_phpSheet->getProtection()->setFormatColumns(!$bool); + + // bit: 4; mask 0x0010; format rows + $bool = (0x0010 & $options) >> 4; + $this->_phpSheet->getProtection()->setFormatRows(!$bool); - // bit: 5; mask 0x0020; insert columns - $bool = (0x0020 & $options) >> 5; - $this->_phpSheet->getProtection()->setInsertColumns(!$bool); - - // bit: 6; mask 0x0040; insert rows - $bool = (0x0040 & $options) >> 6; - $this->_phpSheet->getProtection()->setInsertRows(!$bool); - - // bit: 7; mask 0x0080; insert hyperlinks - $bool = (0x0080 & $options) >> 7; - $this->_phpSheet->getProtection()->setInsertHyperlinks(!$bool); - - // bit: 8; mask 0x0100; delete columns - $bool = (0x0100 & $options) >> 8; - $this->_phpSheet->getProtection()->setDeleteColumns(!$bool); - - // bit: 9; mask 0x0200; delete rows - $bool = (0x0200 & $options) >> 9; - $this->_phpSheet->getProtection()->setDeleteRows(!$bool); - - // bit: 10; mask 0x0400; select locked cells - $bool = (0x0400 & $options) >> 10; - $this->_phpSheet->getProtection()->setSelectLockedCells(!$bool); - - // bit: 11; mask 0x0800; sort cell range - $bool = (0x0800 & $options) >> 11; - $this->_phpSheet->getProtection()->setSort(!$bool); - - // bit: 12; mask 0x1000; auto filter - $bool = (0x1000 & $options) >> 12; - $this->_phpSheet->getProtection()->setAutoFilter(!$bool); + // bit: 5; mask 0x0020; insert columns + $bool = (0x0020 & $options) >> 5; + $this->_phpSheet->getProtection()->setInsertColumns(!$bool); + + // bit: 6; mask 0x0040; insert rows + $bool = (0x0040 & $options) >> 6; + $this->_phpSheet->getProtection()->setInsertRows(!$bool); + + // bit: 7; mask 0x0080; insert hyperlinks + $bool = (0x0080 & $options) >> 7; + $this->_phpSheet->getProtection()->setInsertHyperlinks(!$bool); + + // bit: 8; mask 0x0100; delete columns + $bool = (0x0100 & $options) >> 8; + $this->_phpSheet->getProtection()->setDeleteColumns(!$bool); + + // bit: 9; mask 0x0200; delete rows + $bool = (0x0200 & $options) >> 9; + $this->_phpSheet->getProtection()->setDeleteRows(!$bool); + + // bit: 10; mask 0x0400; select locked cells + $bool = (0x0400 & $options) >> 10; + $this->_phpSheet->getProtection()->setSelectLockedCells(!$bool); + + // bit: 11; mask 0x0800; sort cell range + $bool = (0x0800 & $options) >> 11; + $this->_phpSheet->getProtection()->setSort(!$bool); + + // bit: 12; mask 0x1000; auto filter + $bool = (0x1000 & $options) >> 12; + $this->_phpSheet->getProtection()->setAutoFilter(!$bool); - // bit: 13; mask 0x2000; pivot tables - $bool = (0x2000 & $options) >> 13; - $this->_phpSheet->getProtection()->setPivotTables(!$bool); + // bit: 13; mask 0x2000; pivot tables + $bool = (0x2000 & $options) >> 13; + $this->_phpSheet->getProtection()->setPivotTables(!$bool); - // bit: 14; mask 0x4000; select unlocked cells - $bool = (0x4000 & $options) >> 14; - $this->_phpSheet->getProtection()->setSelectUnlockedCells(!$bool); + // bit: 14; mask 0x4000; select unlocked cells + $bool = (0x4000 & $options) >> 14; + $this->_phpSheet->getProtection()->setSelectUnlockedCells(!$bool); - // offset: 21; size: 2; not used - } + // offset: 21; size: 2; not used + } - /** - * Read RANGEPROTECTION record - * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, - * where it is referred to as FEAT record - */ - private function _readRangeProtection() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + /** + * Read RANGEPROTECTION record + * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, + * where it is referred to as FEAT record + */ + private function _readRangeProtection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // move stream pointer to next record + $this->_pos += 4 + $length; - // local pointer in record data - $offset = 0; + // local pointer in record data + $offset = 0; - if (!$this->_readDataOnly) { - $offset += 12; - - // offset: 12; size: 2; shared feature type, 2 = enhanced protection, 4 = smart tag - $isf = self::_GetInt2d($recordData, 12); - if ($isf != 2) { - // we only read FEAT records of type 2 - return; - } - $offset += 2; - - $offset += 5; - - // offset: 19; size: 2; count of ref ranges this feature is on - $cref = self::_GetInt2d($recordData, 19); - $offset += 2; - - $offset += 6; - - // offset: 27; size: 8 * $cref; list of cell ranges (like in hyperlink record) - $cellRanges = array(); - for ($i = 0; $i < $cref; ++$i) { - try { - $cellRange = $this->_readBIFF8CellRangeAddressFixed(substr($recordData, 27 + 8 * $i, 8)); - } catch (PHPExcel_Exception $e) { - return; - } - $cellRanges[] = $cellRange; - $offset += 8; - } - - // offset: var; size: var; variable length of feature specific data - $rgbFeat = substr($recordData, $offset); - $offset += 4; - - // offset: var; size: 4; the encrypted password (only 16-bit although field is 32-bit) - $wPassword = self::_GetInt4d($recordData, $offset); - $offset += 4; - - // Apply range protection to sheet - if ($cellRanges) { - $this->_phpSheet->protectCells(implode(' ', $cellRanges), strtoupper(dechex($wPassword)), true); - } - } - } - - - /** - * Read IMDATA record - */ - private function _readImData() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - - // get spliced record data - $splicedRecordData = $this->_getSplicedRecordData(); - $recordData = $splicedRecordData['recordData']; - - // UNDER CONSTRUCTION - - // offset: 0; size: 2; image format - $cf = self::_GetInt2d($recordData, 0); - - // offset: 2; size: 2; environment from which the file was written - $env = self::_GetInt2d($recordData, 2); - - // offset: 4; size: 4; length of the image data - $lcb = self::_GetInt4d($recordData, 4); - - // offset: 8; size: var; image data - $iData = substr($recordData, 8); - - switch ($cf) { - case 0x09: // Windows bitmap format - // BITMAPCOREINFO - // 1. BITMAPCOREHEADER - // offset: 0; size: 4; bcSize, Specifies the number of bytes required by the structure - $bcSize = self::_GetInt4d($iData, 0); -// var_dump($bcSize); - - // offset: 4; size: 2; bcWidth, specifies the width of the bitmap, in pixels - $bcWidth = self::_GetInt2d($iData, 4); -// var_dump($bcWidth); - - // offset: 6; size: 2; bcHeight, specifies the height of the bitmap, in pixels. - $bcHeight = self::_GetInt2d($iData, 6); -// var_dump($bcHeight); - $ih = imagecreatetruecolor($bcWidth, $bcHeight); - - // offset: 8; size: 2; bcPlanes, specifies the number of planes for the target device. This value must be 1 - - // offset: 10; size: 2; bcBitCount specifies the number of bits-per-pixel. This value must be 1, 4, 8, or 24 - $bcBitCount = self::_GetInt2d($iData, 10); -// var_dump($bcBitCount); - - $rgbString = substr($iData, 12); - $rgbTriples = array(); - while (strlen($rgbString) > 0) { - $rgbTriples[] = unpack('Cb/Cg/Cr', $rgbString); - $rgbString = substr($rgbString, 3); - } - $x = 0; - $y = 0; - foreach ($rgbTriples as $i => $rgbTriple) { - $color = imagecolorallocate($ih, $rgbTriple['r'], $rgbTriple['g'], $rgbTriple['b']); - imagesetpixel($ih, $x, $bcHeight - 1 - $y, $color); - $x = ($x + 1) % $bcWidth; - $y = $y + floor(($x + 1) / $bcWidth); - } - //imagepng($ih, 'image.png'); - - $drawing = new PHPExcel_Worksheet_Drawing(); - $drawing->setPath($filename); - $drawing->setWorksheet($this->_phpSheet); - - break; - - case 0x02: // Windows metafile or Macintosh PICT format - case 0x0e: // native format - default; - break; - - } - - // _getSplicedRecordData() takes care of moving current position in data stream - } - - - /** - * Read a free CONTINUE record. Free CONTINUE record may be a camouflaged MSODRAWING record - * When MSODRAWING data on a sheet exceeds 8224 bytes, CONTINUE records are used instead. Undocumented. - * In this case, we must treat the CONTINUE record as a MSODRAWING record - */ - private function _readContinue() - { - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - // check if we are reading drawing data - // this is in case a free CONTINUE record occurs in other circumstances we are unaware of - if ($this->_drawingData == '') { - // move stream pointer to next record - $this->_pos += 4 + $length; - - return; - } - - // check if record data is at least 4 bytes long, otherwise there is no chance this is MSODRAWING data - if ($length < 4) { - // move stream pointer to next record - $this->_pos += 4 + $length; - - return; - } - - // dirty check to see if CONTINUE record could be a camouflaged MSODRAWING record - // look inside CONTINUE record to see if it looks like a part of an Escher stream - // we know that Escher stream may be split at least at - // 0xF003 MsofbtSpgrContainer - // 0xF004 MsofbtSpContainer - // 0xF00D MsofbtClientTextbox - $validSplitPoints = array(0xF003, 0xF004, 0xF00D); // add identifiers if we find more - - $splitPoint = self::_GetInt2d($recordData, 2); - if (in_array($splitPoint, $validSplitPoints)) { - // get spliced record data (and move pointer to next record) - $splicedRecordData = $this->_getSplicedRecordData(); - $this->_drawingData .= $splicedRecordData['recordData']; - - return; - } - - // move stream pointer to next record - $this->_pos += 4 + $length; - - } - - - /** - * Reads a record from current position in data stream and continues reading data as long as CONTINUE - * records are found. Splices the record data pieces and returns the combined string as if record data - * is in one piece. - * Moves to next current position in data stream to start of next record different from a CONtINUE record - * - * @return array - */ - private function _getSplicedRecordData() - { - $data = ''; - $spliceOffsets = array(); - - $i = 0; - $spliceOffsets[0] = 0; - - do { - ++$i; - - // offset: 0; size: 2; identifier - $identifier = self::_GetInt2d($this->_data, $this->_pos); - // offset: 2; size: 2; length - $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $data .= $this->_readRecordData($this->_data, $this->_pos + 4, $length); - - $spliceOffsets[$i] = $spliceOffsets[$i - 1] + $length; - - $this->_pos += 4 + $length; - $nextIdentifier = self::_GetInt2d($this->_data, $this->_pos); - } - while ($nextIdentifier == self::XLS_Type_CONTINUE); - - $splicedData = array( - 'recordData' => $data, - 'spliceOffsets' => $spliceOffsets, - ); - - return $splicedData; - - } - - - /** - * Convert formula structure into human readable Excel formula like 'A3+A5*5' - * - * @param string $formulaStructure The complete binary data for the formula - * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas - * @return string Human readable formula - */ - private function _getFormulaFromStructure($formulaStructure, $baseCell = 'A1') - { - // offset: 0; size: 2; size of the following formula data - $sz = self::_GetInt2d($formulaStructure, 0); - - // offset: 2; size: sz - $formulaData = substr($formulaStructure, 2, $sz); - - // for debug: dump the formula data - //echo ''; - //echo 'size: ' . $sz . "\n"; - //echo 'the entire formula data: '; - //Debug::dump($formulaData); - //echo "\n----\n"; - - // offset: 2 + sz; size: variable (optional) - if (strlen($formulaStructure) > 2 + $sz) { - $additionalData = substr($formulaStructure, 2 + $sz); - - // for debug: dump the additional data - //echo 'the entire additional data: '; - //Debug::dump($additionalData); - //echo "\n----\n"; - - } else { - $additionalData = ''; - } - - return $this->_getFormulaFromData($formulaData, $additionalData, $baseCell); - } - - - /** - * Take formula data and additional data for formula and return human readable formula - * - * @param string $formulaData The binary data for the formula itself - * @param string $additionalData Additional binary data going with the formula - * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas - * @return string Human readable formula - */ - private function _getFormulaFromData($formulaData, $additionalData = '', $baseCell = 'A1') - { - // start parsing the formula data - $tokens = array(); - - while (strlen($formulaData) > 0 and $token = $this->_getNextToken($formulaData, $baseCell)) { - $tokens[] = $token; - $formulaData = substr($formulaData, $token['size']); - - // for debug: dump the token - //var_dump($token); - } - - $formulaString = $this->_createFormulaFromTokens($tokens, $additionalData); - - return $formulaString; - } - - - /** - * Take array of tokens together with additional data for formula and return human readable formula - * - * @param array $tokens - * @param array $additionalData Additional binary data going with the formula - * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas - * @return string Human readable formula - */ - private function _createFormulaFromTokens($tokens, $additionalData) - { - // empty formula? - if (empty($tokens)) { - return ''; - } - - $formulaStrings = array(); - foreach ($tokens as $token) { - // initialize spaces - $space0 = isset($space0) ? $space0 : ''; // spaces before next token, not tParen - $space1 = isset($space1) ? $space1 : ''; // carriage returns before next token, not tParen - $space2 = isset($space2) ? $space2 : ''; // spaces before opening parenthesis - $space3 = isset($space3) ? $space3 : ''; // carriage returns before opening parenthesis - $space4 = isset($space4) ? $space4 : ''; // spaces before closing parenthesis - $space5 = isset($space5) ? $space5 : ''; // carriage returns before closing parenthesis - - switch ($token['name']) { - case 'tAdd': // addition - case 'tConcat': // addition - case 'tDiv': // division - case 'tEQ': // equality - case 'tGE': // greater than or equal - case 'tGT': // greater than - case 'tIsect': // intersection - case 'tLE': // less than or equal - case 'tList': // less than or equal - case 'tLT': // less than - case 'tMul': // multiplication - case 'tNE': // multiplication - case 'tPower': // power - case 'tRange': // range - case 'tSub': // subtraction - $op2 = array_pop($formulaStrings); - $op1 = array_pop($formulaStrings); - $formulaStrings[] = "$op1$space1$space0{$token['data']}$op2"; - unset($space0, $space1); - break; - case 'tUplus': // unary plus - case 'tUminus': // unary minus - $op = array_pop($formulaStrings); - $formulaStrings[] = "$space1$space0{$token['data']}$op"; - unset($space0, $space1); - break; - case 'tPercent': // percent sign - $op = array_pop($formulaStrings); - $formulaStrings[] = "$op$space1$space0{$token['data']}"; - unset($space0, $space1); - break; - case 'tAttrVolatile': // indicates volatile function - case 'tAttrIf': - case 'tAttrSkip': - case 'tAttrChoose': - // token is only important for Excel formula evaluator - // do nothing - break; - case 'tAttrSpace': // space / carriage return - // space will be used when next token arrives, do not alter formulaString stack - switch ($token['data']['spacetype']) { - case 'type0': - $space0 = str_repeat(' ', $token['data']['spacecount']); - break; - case 'type1': - $space1 = str_repeat("\n", $token['data']['spacecount']); - break; - case 'type2': - $space2 = str_repeat(' ', $token['data']['spacecount']); - break; - case 'type3': - $space3 = str_repeat("\n", $token['data']['spacecount']); - break; - case 'type4': - $space4 = str_repeat(' ', $token['data']['spacecount']); - break; - case 'type5': - $space5 = str_repeat("\n", $token['data']['spacecount']); - break; - } - break; - case 'tAttrSum': // SUM function with one parameter - $op = array_pop($formulaStrings); - $formulaStrings[] = "{$space1}{$space0}SUM($op)"; - unset($space0, $space1); - break; - case 'tFunc': // function with fixed number of arguments - case 'tFuncV': // function with variable number of arguments - if ($token['data']['function'] != '') { - // normal function - $ops = array(); // array of operators - for ($i = 0; $i < $token['data']['args']; ++$i) { - $ops[] = array_pop($formulaStrings); - } - $ops = array_reverse($ops); - $formulaStrings[] = "$space1$space0{$token['data']['function']}(" . implode(',', $ops) . ")"; - unset($space0, $space1); - } else { - // add-in function - $ops = array(); // array of operators - for ($i = 0; $i < $token['data']['args'] - 1; ++$i) { - $ops[] = array_pop($formulaStrings); - } - $ops = array_reverse($ops); - $function = array_pop($formulaStrings); - $formulaStrings[] = "$space1$space0$function(" . implode(',', $ops) . ")"; - unset($space0, $space1); - } - break; - case 'tParen': // parenthesis - $expression = array_pop($formulaStrings); - $formulaStrings[] = "$space3$space2($expression$space5$space4)"; - unset($space2, $space3, $space4, $space5); - break; - case 'tArray': // array constant - $constantArray = self::_readBIFF8ConstantArray($additionalData); - $formulaStrings[] = $space1 . $space0 . $constantArray['value']; - $additionalData = substr($additionalData, $constantArray['size']); // bite of chunk of additional data - unset($space0, $space1); - break; - case 'tMemArea': - // bite off chunk of additional data - $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($additionalData); - $additionalData = substr($additionalData, $cellRangeAddressList['size']); - $formulaStrings[] = "$space1$space0{$token['data']}"; - unset($space0, $space1); - break; - case 'tArea': // cell range address - case 'tBool': // boolean - case 'tErr': // error code - case 'tInt': // integer - case 'tMemErr': - case 'tMemFunc': - case 'tMissArg': - case 'tName': - case 'tNameX': - case 'tNum': // number - case 'tRef': // single cell reference - case 'tRef3d': // 3d cell reference - case 'tArea3d': // 3d cell range reference - case 'tRefN': - case 'tAreaN': - case 'tStr': // string - $formulaStrings[] = "$space1$space0{$token['data']}"; - unset($space0, $space1); - break; - } - } - $formulaString = $formulaStrings[0]; - - // for debug: dump the human readable formula - //echo '----' . "\n"; - //echo 'Formula: ' . $formulaString; - - return $formulaString; - } - - - /** - * Fetch next token from binary formula data - * - * @param string Formula data - * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas - * @return array - * @throws PHPExcel_Reader_Exception - */ - private function _getNextToken($formulaData, $baseCell = 'A1') - { - // offset: 0; size: 1; token id - $id = ord($formulaData[0]); // token id - $name = false; // initialize token name - - switch ($id) { - case 0x03: $name = 'tAdd'; $size = 1; $data = '+'; break; - case 0x04: $name = 'tSub'; $size = 1; $data = '-'; break; - case 0x05: $name = 'tMul'; $size = 1; $data = '*'; break; - case 0x06: $name = 'tDiv'; $size = 1; $data = '/'; break; - case 0x07: $name = 'tPower'; $size = 1; $data = '^'; break; - case 0x08: $name = 'tConcat'; $size = 1; $data = '&'; break; - case 0x09: $name = 'tLT'; $size = 1; $data = '<'; break; - case 0x0A: $name = 'tLE'; $size = 1; $data = '<='; break; - case 0x0B: $name = 'tEQ'; $size = 1; $data = '='; break; - case 0x0C: $name = 'tGE'; $size = 1; $data = '>='; break; - case 0x0D: $name = 'tGT'; $size = 1; $data = '>'; break; - case 0x0E: $name = 'tNE'; $size = 1; $data = '<>'; break; - case 0x0F: $name = 'tIsect'; $size = 1; $data = ' '; break; - case 0x10: $name = 'tList'; $size = 1; $data = ','; break; - case 0x11: $name = 'tRange'; $size = 1; $data = ':'; break; - case 0x12: $name = 'tUplus'; $size = 1; $data = '+'; break; - case 0x13: $name = 'tUminus'; $size = 1; $data = '-'; break; - case 0x14: $name = 'tPercent'; $size = 1; $data = '%'; break; - case 0x15: // parenthesis - $name = 'tParen'; - $size = 1; - $data = null; - break; - case 0x16: // missing argument - $name = 'tMissArg'; - $size = 1; - $data = ''; - break; - case 0x17: // string - $name = 'tStr'; - // offset: 1; size: var; Unicode string, 8-bit string length - $string = self::_readUnicodeStringShort(substr($formulaData, 1)); - $size = 1 + $string['size']; - $data = self::_UTF8toExcelDoubleQuoted($string['value']); - break; - case 0x19: // Special attribute - // offset: 1; size: 1; attribute type flags: - switch (ord($formulaData[1])) { - case 0x01: - $name = 'tAttrVolatile'; - $size = 4; - $data = null; - break; - case 0x02: - $name = 'tAttrIf'; - $size = 4; - $data = null; - break; - case 0x04: - $name = 'tAttrChoose'; - // offset: 2; size: 2; number of choices in the CHOOSE function ($nc, number of parameters decreased by 1) - $nc = self::_GetInt2d($formulaData, 2); - // offset: 4; size: 2 * $nc - // offset: 4 + 2 * $nc; size: 2 - $size = 2 * $nc + 6; - $data = null; - break; - case 0x08: - $name = 'tAttrSkip'; - $size = 4; - $data = null; - break; - case 0x10: - $name = 'tAttrSum'; - $size = 4; - $data = null; - break; - case 0x40: - case 0x41: - $name = 'tAttrSpace'; - $size = 4; - // offset: 2; size: 2; space type and position - switch (ord($formulaData[2])) { - case 0x00: - $spacetype = 'type0'; - break; - case 0x01: - $spacetype = 'type1'; - break; - case 0x02: - $spacetype = 'type2'; - break; - case 0x03: - $spacetype = 'type3'; - break; - case 0x04: - $spacetype = 'type4'; - break; - case 0x05: - $spacetype = 'type5'; - break; - default: - throw new PHPExcel_Reader_Exception('Unrecognized space type in tAttrSpace token'); - break; - } - // offset: 3; size: 1; number of inserted spaces/carriage returns - $spacecount = ord($formulaData[3]); - - $data = array('spacetype' => $spacetype, 'spacecount' => $spacecount); - break; - default: - throw new PHPExcel_Reader_Exception('Unrecognized attribute flag in tAttr token'); - break; - } - break; - case 0x1C: // error code - // offset: 1; size: 1; error code - $name = 'tErr'; - $size = 2; - $data = self::_mapErrorCode(ord($formulaData[1])); - break; - case 0x1D: // boolean - // offset: 1; size: 1; 0 = false, 1 = true; - $name = 'tBool'; - $size = 2; - $data = ord($formulaData[1]) ? 'TRUE' : 'FALSE'; - break; - case 0x1E: // integer - // offset: 1; size: 2; unsigned 16-bit integer - $name = 'tInt'; - $size = 3; - $data = self::_GetInt2d($formulaData, 1); - break; - case 0x1F: // number - // offset: 1; size: 8; - $name = 'tNum'; - $size = 9; - $data = self::_extractNumber(substr($formulaData, 1)); - $data = str_replace(',', '.', (string)$data); // in case non-English locale - break; - case 0x20: // array constant - case 0x40: - case 0x60: - // offset: 1; size: 7; not used - $name = 'tArray'; - $size = 8; - $data = null; - break; - case 0x21: // function with fixed number of arguments - case 0x41: - case 0x61: - $name = 'tFunc'; - $size = 3; - // offset: 1; size: 2; index to built-in sheet function - switch (self::_GetInt2d($formulaData, 1)) { - case 2: $function = 'ISNA'; $args = 1; break; - case 3: $function = 'ISERROR'; $args = 1; break; - case 10: $function = 'NA'; $args = 0; break; - case 15: $function = 'SIN'; $args = 1; break; - case 16: $function = 'COS'; $args = 1; break; - case 17: $function = 'TAN'; $args = 1; break; - case 18: $function = 'ATAN'; $args = 1; break; - case 19: $function = 'PI'; $args = 0; break; - case 20: $function = 'SQRT'; $args = 1; break; - case 21: $function = 'EXP'; $args = 1; break; - case 22: $function = 'LN'; $args = 1; break; - case 23: $function = 'LOG10'; $args = 1; break; - case 24: $function = 'ABS'; $args = 1; break; - case 25: $function = 'INT'; $args = 1; break; - case 26: $function = 'SIGN'; $args = 1; break; - case 27: $function = 'ROUND'; $args = 2; break; - case 30: $function = 'REPT'; $args = 2; break; - case 31: $function = 'MID'; $args = 3; break; - case 32: $function = 'LEN'; $args = 1; break; - case 33: $function = 'VALUE'; $args = 1; break; - case 34: $function = 'TRUE'; $args = 0; break; - case 35: $function = 'FALSE'; $args = 0; break; - case 38: $function = 'NOT'; $args = 1; break; - case 39: $function = 'MOD'; $args = 2; break; - case 40: $function = 'DCOUNT'; $args = 3; break; - case 41: $function = 'DSUM'; $args = 3; break; - case 42: $function = 'DAVERAGE'; $args = 3; break; - case 43: $function = 'DMIN'; $args = 3; break; - case 44: $function = 'DMAX'; $args = 3; break; - case 45: $function = 'DSTDEV'; $args = 3; break; - case 48: $function = 'TEXT'; $args = 2; break; - case 61: $function = 'MIRR'; $args = 3; break; - case 63: $function = 'RAND'; $args = 0; break; - case 65: $function = 'DATE'; $args = 3; break; - case 66: $function = 'TIME'; $args = 3; break; - case 67: $function = 'DAY'; $args = 1; break; - case 68: $function = 'MONTH'; $args = 1; break; - case 69: $function = 'YEAR'; $args = 1; break; - case 71: $function = 'HOUR'; $args = 1; break; - case 72: $function = 'MINUTE'; $args = 1; break; - case 73: $function = 'SECOND'; $args = 1; break; - case 74: $function = 'NOW'; $args = 0; break; - case 75: $function = 'AREAS'; $args = 1; break; - case 76: $function = 'ROWS'; $args = 1; break; - case 77: $function = 'COLUMNS'; $args = 1; break; - case 83: $function = 'TRANSPOSE'; $args = 1; break; - case 86: $function = 'TYPE'; $args = 1; break; - case 97: $function = 'ATAN2'; $args = 2; break; - case 98: $function = 'ASIN'; $args = 1; break; - case 99: $function = 'ACOS'; $args = 1; break; - case 105: $function = 'ISREF'; $args = 1; break; - case 111: $function = 'CHAR'; $args = 1; break; - case 112: $function = 'LOWER'; $args = 1; break; - case 113: $function = 'UPPER'; $args = 1; break; - case 114: $function = 'PROPER'; $args = 1; break; - case 117: $function = 'EXACT'; $args = 2; break; - case 118: $function = 'TRIM'; $args = 1; break; - case 119: $function = 'REPLACE'; $args = 4; break; - case 121: $function = 'CODE'; $args = 1; break; - case 126: $function = 'ISERR'; $args = 1; break; - case 127: $function = 'ISTEXT'; $args = 1; break; - case 128: $function = 'ISNUMBER'; $args = 1; break; - case 129: $function = 'ISBLANK'; $args = 1; break; - case 130: $function = 'T'; $args = 1; break; - case 131: $function = 'N'; $args = 1; break; - case 140: $function = 'DATEVALUE'; $args = 1; break; - case 141: $function = 'TIMEVALUE'; $args = 1; break; - case 142: $function = 'SLN'; $args = 3; break; - case 143: $function = 'SYD'; $args = 4; break; - case 162: $function = 'CLEAN'; $args = 1; break; - case 163: $function = 'MDETERM'; $args = 1; break; - case 164: $function = 'MINVERSE'; $args = 1; break; - case 165: $function = 'MMULT'; $args = 2; break; - case 184: $function = 'FACT'; $args = 1; break; - case 189: $function = 'DPRODUCT'; $args = 3; break; - case 190: $function = 'ISNONTEXT'; $args = 1; break; - case 195: $function = 'DSTDEVP'; $args = 3; break; - case 196: $function = 'DVARP'; $args = 3; break; - case 198: $function = 'ISLOGICAL'; $args = 1; break; - case 199: $function = 'DCOUNTA'; $args = 3; break; - case 207: $function = 'REPLACEB'; $args = 4; break; - case 210: $function = 'MIDB'; $args = 3; break; - case 211: $function = 'LENB'; $args = 1; break; - case 212: $function = 'ROUNDUP'; $args = 2; break; - case 213: $function = 'ROUNDDOWN'; $args = 2; break; - case 214: $function = 'ASC'; $args = 1; break; - case 215: $function = 'DBCS'; $args = 1; break; - case 221: $function = 'TODAY'; $args = 0; break; - case 229: $function = 'SINH'; $args = 1; break; - case 230: $function = 'COSH'; $args = 1; break; - case 231: $function = 'TANH'; $args = 1; break; - case 232: $function = 'ASINH'; $args = 1; break; - case 233: $function = 'ACOSH'; $args = 1; break; - case 234: $function = 'ATANH'; $args = 1; break; - case 235: $function = 'DGET'; $args = 3; break; - case 244: $function = 'INFO'; $args = 1; break; - case 252: $function = 'FREQUENCY'; $args = 2; break; - case 261: $function = 'ERROR.TYPE'; $args = 1; break; - case 271: $function = 'GAMMALN'; $args = 1; break; - case 273: $function = 'BINOMDIST'; $args = 4; break; - case 274: $function = 'CHIDIST'; $args = 2; break; - case 275: $function = 'CHIINV'; $args = 2; break; - case 276: $function = 'COMBIN'; $args = 2; break; - case 277: $function = 'CONFIDENCE'; $args = 3; break; - case 278: $function = 'CRITBINOM'; $args = 3; break; - case 279: $function = 'EVEN'; $args = 1; break; - case 280: $function = 'EXPONDIST'; $args = 3; break; - case 281: $function = 'FDIST'; $args = 3; break; - case 282: $function = 'FINV'; $args = 3; break; - case 283: $function = 'FISHER'; $args = 1; break; - case 284: $function = 'FISHERINV'; $args = 1; break; - case 285: $function = 'FLOOR'; $args = 2; break; - case 286: $function = 'GAMMADIST'; $args = 4; break; - case 287: $function = 'GAMMAINV'; $args = 3; break; - case 288: $function = 'CEILING'; $args = 2; break; - case 289: $function = 'HYPGEOMDIST'; $args = 4; break; - case 290: $function = 'LOGNORMDIST'; $args = 3; break; - case 291: $function = 'LOGINV'; $args = 3; break; - case 292: $function = 'NEGBINOMDIST'; $args = 3; break; - case 293: $function = 'NORMDIST'; $args = 4; break; - case 294: $function = 'NORMSDIST'; $args = 1; break; - case 295: $function = 'NORMINV'; $args = 3; break; - case 296: $function = 'NORMSINV'; $args = 1; break; - case 297: $function = 'STANDARDIZE'; $args = 3; break; - case 298: $function = 'ODD'; $args = 1; break; - case 299: $function = 'PERMUT'; $args = 2; break; - case 300: $function = 'POISSON'; $args = 3; break; - case 301: $function = 'TDIST'; $args = 3; break; - case 302: $function = 'WEIBULL'; $args = 4; break; - case 303: $function = 'SUMXMY2'; $args = 2; break; - case 304: $function = 'SUMX2MY2'; $args = 2; break; - case 305: $function = 'SUMX2PY2'; $args = 2; break; - case 306: $function = 'CHITEST'; $args = 2; break; - case 307: $function = 'CORREL'; $args = 2; break; - case 308: $function = 'COVAR'; $args = 2; break; - case 309: $function = 'FORECAST'; $args = 3; break; - case 310: $function = 'FTEST'; $args = 2; break; - case 311: $function = 'INTERCEPT'; $args = 2; break; - case 312: $function = 'PEARSON'; $args = 2; break; - case 313: $function = 'RSQ'; $args = 2; break; - case 314: $function = 'STEYX'; $args = 2; break; - case 315: $function = 'SLOPE'; $args = 2; break; - case 316: $function = 'TTEST'; $args = 4; break; - case 325: $function = 'LARGE'; $args = 2; break; - case 326: $function = 'SMALL'; $args = 2; break; - case 327: $function = 'QUARTILE'; $args = 2; break; - case 328: $function = 'PERCENTILE'; $args = 2; break; - case 331: $function = 'TRIMMEAN'; $args = 2; break; - case 332: $function = 'TINV'; $args = 2; break; - case 337: $function = 'POWER'; $args = 2; break; - case 342: $function = 'RADIANS'; $args = 1; break; - case 343: $function = 'DEGREES'; $args = 1; break; - case 346: $function = 'COUNTIF'; $args = 2; break; - case 347: $function = 'COUNTBLANK'; $args = 1; break; - case 350: $function = 'ISPMT'; $args = 4; break; - case 351: $function = 'DATEDIF'; $args = 3; break; - case 352: $function = 'DATESTRING'; $args = 1; break; - case 353: $function = 'NUMBERSTRING'; $args = 2; break; - case 360: $function = 'PHONETIC'; $args = 1; break; - case 368: $function = 'BAHTTEXT'; $args = 1; break; - default: - throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); - break; - } - $data = array('function' => $function, 'args' => $args); - break; - case 0x22: // function with variable number of arguments - case 0x42: - case 0x62: - $name = 'tFuncV'; - $size = 4; - // offset: 1; size: 1; number of arguments - $args = ord($formulaData[1]); - // offset: 2: size: 2; index to built-in sheet function - $index = self::_GetInt2d($formulaData, 2); - switch ($index) { - case 0: $function = 'COUNT'; break; - case 1: $function = 'IF'; break; - case 4: $function = 'SUM'; break; - case 5: $function = 'AVERAGE'; break; - case 6: $function = 'MIN'; break; - case 7: $function = 'MAX'; break; - case 8: $function = 'ROW'; break; - case 9: $function = 'COLUMN'; break; - case 11: $function = 'NPV'; break; - case 12: $function = 'STDEV'; break; - case 13: $function = 'DOLLAR'; break; - case 14: $function = 'FIXED'; break; - case 28: $function = 'LOOKUP'; break; - case 29: $function = 'INDEX'; break; - case 36: $function = 'AND'; break; - case 37: $function = 'OR'; break; - case 46: $function = 'VAR'; break; - case 49: $function = 'LINEST'; break; - case 50: $function = 'TREND'; break; - case 51: $function = 'LOGEST'; break; - case 52: $function = 'GROWTH'; break; - case 56: $function = 'PV'; break; - case 57: $function = 'FV'; break; - case 58: $function = 'NPER'; break; - case 59: $function = 'PMT'; break; - case 60: $function = 'RATE'; break; - case 62: $function = 'IRR'; break; - case 64: $function = 'MATCH'; break; - case 70: $function = 'WEEKDAY'; break; - case 78: $function = 'OFFSET'; break; - case 82: $function = 'SEARCH'; break; - case 100: $function = 'CHOOSE'; break; - case 101: $function = 'HLOOKUP'; break; - case 102: $function = 'VLOOKUP'; break; - case 109: $function = 'LOG'; break; - case 115: $function = 'LEFT'; break; - case 116: $function = 'RIGHT'; break; - case 120: $function = 'SUBSTITUTE'; break; - case 124: $function = 'FIND'; break; - case 125: $function = 'CELL'; break; - case 144: $function = 'DDB'; break; - case 148: $function = 'INDIRECT'; break; - case 167: $function = 'IPMT'; break; - case 168: $function = 'PPMT'; break; - case 169: $function = 'COUNTA'; break; - case 183: $function = 'PRODUCT'; break; - case 193: $function = 'STDEVP'; break; - case 194: $function = 'VARP'; break; - case 197: $function = 'TRUNC'; break; - case 204: $function = 'USDOLLAR'; break; - case 205: $function = 'FINDB'; break; - case 206: $function = 'SEARCHB'; break; - case 208: $function = 'LEFTB'; break; - case 209: $function = 'RIGHTB'; break; - case 216: $function = 'RANK'; break; - case 219: $function = 'ADDRESS'; break; - case 220: $function = 'DAYS360'; break; - case 222: $function = 'VDB'; break; - case 227: $function = 'MEDIAN'; break; - case 228: $function = 'SUMPRODUCT'; break; - case 247: $function = 'DB'; break; - case 255: $function = ''; break; - case 269: $function = 'AVEDEV'; break; - case 270: $function = 'BETADIST'; break; - case 272: $function = 'BETAINV'; break; - case 317: $function = 'PROB'; break; - case 318: $function = 'DEVSQ'; break; - case 319: $function = 'GEOMEAN'; break; - case 320: $function = 'HARMEAN'; break; - case 321: $function = 'SUMSQ'; break; - case 322: $function = 'KURT'; break; - case 323: $function = 'SKEW'; break; - case 324: $function = 'ZTEST'; break; - case 329: $function = 'PERCENTRANK'; break; - case 330: $function = 'MODE'; break; - case 336: $function = 'CONCATENATE'; break; - case 344: $function = 'SUBTOTAL'; break; - case 345: $function = 'SUMIF'; break; - case 354: $function = 'ROMAN'; break; - case 358: $function = 'GETPIVOTDATA'; break; - case 359: $function = 'HYPERLINK'; break; - case 361: $function = 'AVERAGEA'; break; - case 362: $function = 'MAXA'; break; - case 363: $function = 'MINA'; break; - case 364: $function = 'STDEVPA'; break; - case 365: $function = 'VARPA'; break; - case 366: $function = 'STDEVA'; break; - case 367: $function = 'VARA'; break; - default: - throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); - break; - } - $data = array('function' => $function, 'args' => $args); - break; - case 0x23: // index to defined name - case 0x43: - case 0x63: - $name = 'tName'; - $size = 5; - // offset: 1; size: 2; one-based index to definedname record - $definedNameIndex = self::_GetInt2d($formulaData, 1) - 1; - // offset: 2; size: 2; not used - $data = $this->_definedname[$definedNameIndex]['name']; - break; - case 0x24: // single cell reference e.g. A5 - case 0x44: - case 0x64: - $name = 'tRef'; - $size = 5; - $data = $this->_readBIFF8CellAddress(substr($formulaData, 1, 4)); - break; - case 0x25: // cell range reference to cells in the same sheet (2d) - case 0x45: - case 0x65: - $name = 'tArea'; - $size = 9; - $data = $this->_readBIFF8CellRangeAddress(substr($formulaData, 1, 8)); - break; - case 0x26: // Constant reference sub-expression - case 0x46: - case 0x66: - $name = 'tMemArea'; - // offset: 1; size: 4; not used - // offset: 5; size: 2; size of the following subexpression - $subSize = self::_GetInt2d($formulaData, 5); - $size = 7 + $subSize; - $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); - break; - case 0x27: // Deleted constant reference sub-expression - case 0x47: - case 0x67: - $name = 'tMemErr'; - // offset: 1; size: 4; not used - // offset: 5; size: 2; size of the following subexpression - $subSize = self::_GetInt2d($formulaData, 5); - $size = 7 + $subSize; - $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); - break; - case 0x29: // Variable reference sub-expression - case 0x49: - case 0x69: - $name = 'tMemFunc'; - // offset: 1; size: 2; size of the following sub-expression - $subSize = self::_GetInt2d($formulaData, 1); - $size = 3 + $subSize; - $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); - break; - - case 0x2C: // Relative 2d cell reference reference, used in shared formulas and some other places - case 0x4C: - case 0x6C: - $name = 'tRefN'; - $size = 5; - $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); - break; - - case 0x2D: // Relative 2d range reference - case 0x4D: - case 0x6D: - $name = 'tAreaN'; - $size = 9; - $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); - break; - - case 0x39: // External name - case 0x59: - case 0x79: - $name = 'tNameX'; - $size = 7; - // offset: 1; size: 2; index to REF entry in EXTERNSHEET record - // offset: 3; size: 2; one-based index to DEFINEDNAME or EXTERNNAME record - $index = self::_GetInt2d($formulaData, 3); - // assume index is to EXTERNNAME record - $data = $this->_externalNames[$index - 1]['name']; - // offset: 5; size: 2; not used - break; - - case 0x3A: // 3d reference to cell - case 0x5A: - case 0x7A: - $name = 'tRef3d'; - $size = 7; - - try { - // offset: 1; size: 2; index to REF entry - $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); - // offset: 3; size: 4; cell address - $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); - - $data = "$sheetRange!$cellAddress"; - } catch (PHPExcel_Exception $e) { - // deleted sheet reference - $data = '#REF!'; - } - - break; - case 0x3B: // 3d reference to cell range - case 0x5B: - case 0x7B: - $name = 'tArea3d'; - $size = 11; - - try { - // offset: 1; size: 2; index to REF entry - $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); - // offset: 3; size: 8; cell address - $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); - - $data = "$sheetRange!$cellRangeAddress"; - } catch (PHPExcel_Exception $e) { - // deleted sheet reference - $data = '#REF!'; - } - - break; - // Unknown cases // don't know how to deal with - default: - throw new PHPExcel_Reader_Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); - break; - } - - return array( - 'id' => $id, - 'name' => $name, - 'size' => $size, - 'data' => $data, - ); - } - - - /** - * Reads a cell address in BIFF8 e.g. 'A2' or '$A$2' - * section 3.3.4 - * - * @param string $cellAddressStructure - * @return string - */ - private function _readBIFF8CellAddress($cellAddressStructure) - { - // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) - $row = self::_GetInt2d($cellAddressStructure, 0) + 1; - - // offset: 2; size: 2; index to column or column offset + relative flags - - // bit: 7-0; mask 0x00FF; column index - $column = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($cellAddressStructure, 2)); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { - $column = '$' . $column; - } - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { - $row = '$' . $row; - } - - return $column . $row; - } - - - /** - * Reads a cell address in BIFF8 for shared formulas. Uses positive and negative values for row and column - * to indicate offsets from a base cell - * section 3.3.4 - * - * @param string $cellAddressStructure - * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas - * @return string - */ - private function _readBIFF8CellAddressB($cellAddressStructure, $baseCell = 'A1') - { - list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); - $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; - - // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) - $rowIndex = self::_GetInt2d($cellAddressStructure, 0); - $row = self::_GetInt2d($cellAddressStructure, 0) + 1; - - // offset: 2; size: 2; index to column or column offset + relative flags - - // bit: 7-0; mask 0x00FF; column index - $colIndex = 0x00FF & self::_GetInt2d($cellAddressStructure, 2); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { - $column = PHPExcel_Cell::stringFromColumnIndex($colIndex); - $column = '$' . $column; - } else { - $colIndex = ($colIndex <= 127) ? $colIndex : $colIndex - 256; - $column = PHPExcel_Cell::stringFromColumnIndex($baseCol + $colIndex); - } - - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { - $row = '$' . $row; - } else { - $rowIndex = ($rowIndex <= 32767) ? $rowIndex : $rowIndex - 65536; - $row = $baseRow + $rowIndex; - } - - return $column . $row; - } - - - /** - * Reads a cell range address in BIFF5 e.g. 'A2:B6' or 'A1' - * always fixed range - * section 2.5.14 - * - * @param string $subData - * @return string - * @throws PHPExcel_Reader_Exception - */ - private function _readBIFF5CellRangeAddressFixed($subData) - { - // offset: 0; size: 2; index to first row - $fr = self::_GetInt2d($subData, 0) + 1; - - // offset: 2; size: 2; index to last row - $lr = self::_GetInt2d($subData, 2) + 1; - - // offset: 4; size: 1; index to first column - $fc = ord($subData{4}); - - // offset: 5; size: 1; index to last column - $lc = ord($subData{5}); - - // check values - if ($fr > $lr || $fc > $lc) { - throw new PHPExcel_Reader_Exception('Not a cell range address'); - } - - // column index to letter - $fc = PHPExcel_Cell::stringFromColumnIndex($fc); - $lc = PHPExcel_Cell::stringFromColumnIndex($lc); - - if ($fr == $lr and $fc == $lc) { - return "$fc$fr"; - } - return "$fc$fr:$lc$lr"; - } - - - /** - * Reads a cell range address in BIFF8 e.g. 'A2:B6' or 'A1' - * always fixed range - * section 2.5.14 - * - * @param string $subData - * @return string - * @throws PHPExcel_Reader_Exception - */ - private function _readBIFF8CellRangeAddressFixed($subData) - { - // offset: 0; size: 2; index to first row - $fr = self::_GetInt2d($subData, 0) + 1; - - // offset: 2; size: 2; index to last row - $lr = self::_GetInt2d($subData, 2) + 1; - - // offset: 4; size: 2; index to first column - $fc = self::_GetInt2d($subData, 4); - - // offset: 6; size: 2; index to last column - $lc = self::_GetInt2d($subData, 6); - - // check values - if ($fr > $lr || $fc > $lc) { - throw new PHPExcel_Reader_Exception('Not a cell range address'); - } - - // column index to letter - $fc = PHPExcel_Cell::stringFromColumnIndex($fc); - $lc = PHPExcel_Cell::stringFromColumnIndex($lc); - - if ($fr == $lr and $fc == $lc) { - return "$fc$fr"; - } - return "$fc$fr:$lc$lr"; - } - - - /** - * Reads a cell range address in BIFF8 e.g. 'A2:B6' or '$A$2:$B$6' - * there are flags indicating whether column/row index is relative - * section 3.3.4 - * - * @param string $subData - * @return string - */ - private function _readBIFF8CellRangeAddress($subData) - { - // todo: if cell range is just a single cell, should this funciton - // not just return e.g. 'A1' and not 'A1:A1' ? - - // offset: 0; size: 2; index to first row (0... 65535) (or offset (-32768... 32767)) - $fr = self::_GetInt2d($subData, 0) + 1; - - // offset: 2; size: 2; index to last row (0... 65535) (or offset (-32768... 32767)) - $lr = self::_GetInt2d($subData, 2) + 1; - - // offset: 4; size: 2; index to first column or column offset + relative flags - - // bit: 7-0; mask 0x00FF; column index - $fc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 4)); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($subData, 4))) { - $fc = '$' . $fc; - } - - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($subData, 4))) { - $fr = '$' . $fr; - } - - // offset: 6; size: 2; index to last column or column offset + relative flags - - // bit: 7-0; mask 0x00FF; column index - $lc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 6)); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($subData, 6))) { - $lc = '$' . $lc; - } - - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($subData, 6))) { - $lr = '$' . $lr; - } - - return "$fc$fr:$lc$lr"; - } - - - /** - * Reads a cell range address in BIFF8 for shared formulas. Uses positive and negative values for row and column - * to indicate offsets from a base cell - * section 3.3.4 - * - * @param string $subData - * @param string $baseCell Base cell - * @return string Cell range address - */ - private function _readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') - { - list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); - $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; - - // TODO: if cell range is just a single cell, should this funciton - // not just return e.g. 'A1' and not 'A1:A1' ? - - // offset: 0; size: 2; first row - $frIndex = self::_GetInt2d($subData, 0); // adjust below - - // offset: 2; size: 2; relative index to first row (0... 65535) should be treated as offset (-32768... 32767) - $lrIndex = self::_GetInt2d($subData, 2); // adjust below - - // offset: 4; size: 2; first column with relative/absolute flags - - // bit: 7-0; mask 0x00FF; column index - $fcIndex = 0x00FF & self::_GetInt2d($subData, 4); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($subData, 4))) { - // absolute column index - $fc = PHPExcel_Cell::stringFromColumnIndex($fcIndex); - $fc = '$' . $fc; - } else { - // column offset - $fcIndex = ($fcIndex <= 127) ? $fcIndex : $fcIndex - 256; - $fc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $fcIndex); - } - - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($subData, 4))) { - // absolute row index - $fr = $frIndex + 1; - $fr = '$' . $fr; - } else { - // row offset - $frIndex = ($frIndex <= 32767) ? $frIndex : $frIndex - 65536; - $fr = $baseRow + $frIndex; - } - - // offset: 6; size: 2; last column with relative/absolute flags - - // bit: 7-0; mask 0x00FF; column index - $lcIndex = 0x00FF & self::_GetInt2d($subData, 6); - $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; - $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); - - // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) - if (!(0x4000 & self::_GetInt2d($subData, 6))) { - // absolute column index - $lc = PHPExcel_Cell::stringFromColumnIndex($lcIndex); - $lc = '$' . $lc; - } else { - // column offset - $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; - $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); - } - - // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) - if (!(0x8000 & self::_GetInt2d($subData, 6))) { - // absolute row index - $lr = $lrIndex + 1; - $lr = '$' . $lr; - } else { - // row offset - $lrIndex = ($lrIndex <= 32767) ? $lrIndex : $lrIndex - 65536; - $lr = $baseRow + $lrIndex; - } - - return "$fc$fr:$lc$lr"; - } - - - /** - * Read BIFF8 cell range address list - * section 2.5.15 - * - * @param string $subData - * @return array - */ - private function _readBIFF8CellRangeAddressList($subData) - { - $cellRangeAddresses = array(); - - // offset: 0; size: 2; number of the following cell range addresses - $nm = self::_GetInt2d($subData, 0); - - $offset = 2; - // offset: 2; size: 8 * $nm; list of $nm (fixed) cell range addresses - for ($i = 0; $i < $nm; ++$i) { - $cellRangeAddresses[] = $this->_readBIFF8CellRangeAddressFixed(substr($subData, $offset, 8)); - $offset += 8; - } - - return array( - 'size' => 2 + 8 * $nm, - 'cellRangeAddresses' => $cellRangeAddresses, - ); - } - - - /** - * Read BIFF5 cell range address list - * section 2.5.15 - * - * @param string $subData - * @return array - */ - private function _readBIFF5CellRangeAddressList($subData) - { - $cellRangeAddresses = array(); - - // offset: 0; size: 2; number of the following cell range addresses - $nm = self::_GetInt2d($subData, 0); - - $offset = 2; - // offset: 2; size: 6 * $nm; list of $nm (fixed) cell range addresses - for ($i = 0; $i < $nm; ++$i) { - $cellRangeAddresses[] = $this->_readBIFF5CellRangeAddressFixed(substr($subData, $offset, 6)); - $offset += 6; - } - - return array( - 'size' => 2 + 6 * $nm, - 'cellRangeAddresses' => $cellRangeAddresses, - ); - } - - - /** - * Get a sheet range like Sheet1:Sheet3 from REF index - * Note: If there is only one sheet in the range, one gets e.g Sheet1 - * It can also happen that the REF structure uses the -1 (FFFF) code to indicate deleted sheets, - * in which case an PHPExcel_Reader_Exception is thrown - * - * @param int $index - * @return string|false - * @throws PHPExcel_Reader_Exception - */ - private function _readSheetRangeByRefIndex($index) - { - if (isset($this->_ref[$index])) { - - $type = $this->_externalBooks[$this->_ref[$index]['externalBookIndex']]['type']; - - switch ($type) { - case 'internal': - // check if we have a deleted 3d reference - if ($this->_ref[$index]['firstSheetIndex'] == 0xFFFF or $this->_ref[$index]['lastSheetIndex'] == 0xFFFF) { - throw new PHPExcel_Reader_Exception('Deleted sheet reference'); - } - - // we have normal sheet range (collapsed or uncollapsed) - $firstSheetName = $this->_sheets[$this->_ref[$index]['firstSheetIndex']]['name']; - $lastSheetName = $this->_sheets[$this->_ref[$index]['lastSheetIndex']]['name']; - - if ($firstSheetName == $lastSheetName) { - // collapsed sheet range - $sheetRange = $firstSheetName; - } else { - $sheetRange = "$firstSheetName:$lastSheetName"; - } - - // escape the single-quotes - $sheetRange = str_replace("'", "''", $sheetRange); - - // if there are special characters, we need to enclose the range in single-quotes - // todo: check if we have identified the whole set of special characters - // it seems that the following characters are not accepted for sheet names - // and we may assume that they are not present: []*/:\? - if (preg_match("/[ !\"@#£$%&{()}<>=+'|^,;-]/", $sheetRange)) { - $sheetRange = "'$sheetRange'"; - } - - return $sheetRange; - break; - - default: - // TODO: external sheet support - throw new PHPExcel_Reader_Exception('Excel5 reader only supports internal sheets in fomulas'); - break; - } - } - return false; - } - - - /** - * read BIFF8 constant value array from array data - * returns e.g. array('value' => '{1,2;3,4}', 'size' => 40} - * section 2.5.8 - * - * @param string $arrayData - * @return array - */ - private static function _readBIFF8ConstantArray($arrayData) - { - // offset: 0; size: 1; number of columns decreased by 1 - $nc = ord($arrayData[0]); - - // offset: 1; size: 2; number of rows decreased by 1 - $nr = self::_GetInt2d($arrayData, 1); - $size = 3; // initialize - $arrayData = substr($arrayData, 3); - - // offset: 3; size: var; list of ($nc + 1) * ($nr + 1) constant values - $matrixChunks = array(); - for ($r = 1; $r <= $nr + 1; ++$r) { - $items = array(); - for ($c = 1; $c <= $nc + 1; ++$c) { - $constant = self::_readBIFF8Constant($arrayData); - $items[] = $constant['value']; - $arrayData = substr($arrayData, $constant['size']); - $size += $constant['size']; - } - $matrixChunks[] = implode(',', $items); // looks like e.g. '1,"hello"' - } - $matrix = '{' . implode(';', $matrixChunks) . '}'; - - return array( - 'value' => $matrix, - 'size' => $size, - ); - } - - - /** - * read BIFF8 constant value which may be 'Empty Value', 'Number', 'String Value', 'Boolean Value', 'Error Value' - * section 2.5.7 - * returns e.g. array('value' => '5', 'size' => 9) - * - * @param string $valueData - * @return array - */ - private static function _readBIFF8Constant($valueData) - { - // offset: 0; size: 1; identifier for type of constant - $identifier = ord($valueData[0]); - - switch ($identifier) { - case 0x00: // empty constant (what is this?) - $value = ''; - $size = 9; - break; - case 0x01: // number - // offset: 1; size: 8; IEEE 754 floating-point value - $value = self::_extractNumber(substr($valueData, 1, 8)); - $size = 9; - break; - case 0x02: // string value - // offset: 1; size: var; Unicode string, 16-bit string length - $string = self::_readUnicodeStringLong(substr($valueData, 1)); - $value = '"' . $string['value'] . '"'; - $size = 1 + $string['size']; - break; - case 0x04: // boolean - // offset: 1; size: 1; 0 = FALSE, 1 = TRUE - if (ord($valueData[1])) { - $value = 'TRUE'; - } else { - $value = 'FALSE'; - } - $size = 9; - break; - case 0x10: // error code - // offset: 1; size: 1; error code - $value = self::_mapErrorCode(ord($valueData[1])); - $size = 9; - break; - } - return array( - 'value' => $value, - 'size' => $size, - ); - } - - - /** - * Extract RGB color - * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.4 - * - * @param string $rgb Encoded RGB value (4 bytes) - * @return array - */ - private static function _readRGB($rgb) - { - // offset: 0; size 1; Red component - $r = ord($rgb{0}); - - // offset: 1; size: 1; Green component - $g = ord($rgb{1}); - - // offset: 2; size: 1; Blue component - $b = ord($rgb{2}); - - // HEX notation, e.g. 'FF00FC' - $rgb = sprintf('%02X%02X%02X', $r, $g, $b); - - return array('rgb' => $rgb); - } - - - /** - * Read byte string (8-bit string length) - * OpenOffice documentation: 2.5.2 - * - * @param string $subData - * @return array - */ - private function _readByteStringShort($subData) - { - // offset: 0; size: 1; length of the string (character count) - $ln = ord($subData[0]); - - // offset: 1: size: var; character array (8-bit characters) - $value = $this->_decodeCodepage(substr($subData, 1, $ln)); - - return array( - 'value' => $value, - 'size' => 1 + $ln, // size in bytes of data structure - ); - } - - - /** - * Read byte string (16-bit string length) - * OpenOffice documentation: 2.5.2 - * - * @param string $subData - * @return array - */ - private function _readByteStringLong($subData) - { - // offset: 0; size: 2; length of the string (character count) - $ln = self::_GetInt2d($subData, 0); - - // offset: 2: size: var; character array (8-bit characters) - $value = $this->_decodeCodepage(substr($subData, 2)); - - //return $string; - return array( - 'value' => $value, - 'size' => 2 + $ln, // size in bytes of data structure - ); - } - - - /** - * Extracts an Excel Unicode short string (8-bit string length) - * OpenOffice documentation: 2.5.3 - * function will automatically find out where the Unicode string ends. - * - * @param string $subData - * @return array - */ - private static function _readUnicodeStringShort($subData) - { - $value = ''; - - // offset: 0: size: 1; length of the string (character count) - $characterCount = ord($subData[0]); - - $string = self::_readUnicodeString(substr($subData, 1), $characterCount); - - // add 1 for the string length - $string['size'] += 1; - - return $string; - } - - - /** - * Extracts an Excel Unicode long string (16-bit string length) - * OpenOffice documentation: 2.5.3 - * this function is under construction, needs to support rich text, and Asian phonetic settings - * - * @param string $subData - * @return array - */ - private static function _readUnicodeStringLong($subData) - { - $value = ''; - - // offset: 0: size: 2; length of the string (character count) - $characterCount = self::_GetInt2d($subData, 0); - - $string = self::_readUnicodeString(substr($subData, 2), $characterCount); - - // add 2 for the string length - $string['size'] += 2; - - return $string; - } - - - /** - * Read Unicode string with no string length field, but with known character count - * this function is under construction, needs to support rich text, and Asian phonetic settings - * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.3 - * - * @param string $subData - * @param int $characterCount - * @return array - */ - private static function _readUnicodeString($subData, $characterCount) - { - $value = ''; - - // offset: 0: size: 1; option flags - - // bit: 0; mask: 0x01; character compression (0 = compressed 8-bit, 1 = uncompressed 16-bit) - $isCompressed = !((0x01 & ord($subData[0])) >> 0); - - // bit: 2; mask: 0x04; Asian phonetic settings - $hasAsian = (0x04) & ord($subData[0]) >> 2; - - // bit: 3; mask: 0x08; Rich-Text settings - $hasRichText = (0x08) & ord($subData[0]) >> 3; - - // offset: 1: size: var; character array - // this offset assumes richtext and Asian phonetic settings are off which is generally wrong - // needs to be fixed - $value = self::_encodeUTF16(substr($subData, 1, $isCompressed ? $characterCount : 2 * $characterCount), $isCompressed); - - return array( - 'value' => $value, - 'size' => $isCompressed ? 1 + $characterCount : 1 + 2 * $characterCount, // the size in bytes including the option flags - ); - } - - - /** - * Convert UTF-8 string to string surounded by double quotes. Used for explicit string tokens in formulas. - * Example: hello"world --> "hello""world" - * - * @param string $value UTF-8 encoded string - * @return string - */ - private static function _UTF8toExcelDoubleQuoted($value) - { - return '"' . str_replace('"', '""', $value) . '"'; - } - - - /** - * Reads first 8 bytes of a string and return IEEE 754 float - * - * @param string $data Binary string that is at least 8 bytes long - * @return float - */ - private static function _extractNumber($data) - { - $rknumhigh = self::_GetInt4d($data, 4); - $rknumlow = self::_GetInt4d($data, 0); - $sign = ($rknumhigh & 0x80000000) >> 31; - $exp = (($rknumhigh & 0x7ff00000) >> 20) - 1023; - $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); - $mantissalow1 = ($rknumlow & 0x80000000) >> 31; - $mantissalow2 = ($rknumlow & 0x7fffffff); - $value = $mantissa / pow( 2 , (20 - $exp)); - - if ($mantissalow1 != 0) { - $value += 1 / pow (2 , (21 - $exp)); - } - - $value += $mantissalow2 / pow (2 , (52 - $exp)); - if ($sign) { - $value *= -1; - } - - return $value; - } - - - private static function _GetIEEE754($rknum) - { - if (($rknum & 0x02) != 0) { - $value = $rknum >> 2; - } else { - // changes by mmp, info on IEEE754 encoding from - // 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; - } - - - /** - * Get UTF-8 string from (compressed or uncompressed) UTF-16 string - * - * @param string $string - * @param bool $compressed - * @return string - */ - private static function _encodeUTF16($string, $compressed = '') - { - if ($compressed) { - $string = self::_uncompressByteString($string); - } - - return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', 'UTF-16LE'); - } - - - /** - * Convert UTF-16 string in compressed notation to uncompressed form. Only used for BIFF8. - * - * @param string $string - * @return string - */ - private static function _uncompressByteString($string) - { - $uncompressedString = ''; - $strLen = strlen($string); - for ($i = 0; $i < $strLen; ++$i) { - $uncompressedString .= $string[$i] . "\0"; - } - - return $uncompressedString; - } - - - /** - * Convert string to UTF-8. Only used for BIFF5. - * - * @param string $string - * @return string - */ - private function _decodeCodepage($string) - { - return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $this->_codepage); - } - - - /** - * Read 16-bit unsigned integer - * - * @param string $data - * @param int $pos - * @return int - */ - public static function _GetInt2d($data, $pos) - { - return ord($data[$pos]) | (ord($data[$pos+1]) << 8); - } - - - /** - * Read 32-bit signed integer - * - * @param string $data - * @param int $pos - * @return int - */ - public 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 - $_or_24 = ord($data[$pos + 3]); - if ($_or_24 >= 128) { - // 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; - } - - - /** - * Read color - * - * @param int $color Indexed color - * @param array $palette Color palette - * @return array RGB color value, example: array('rgb' => 'FF0000') - */ - private static function _readColor($color,$palette,$version) - { - if ($color <= 0x07 || $color >= 0x40) { - // special built-in color - return self::_mapBuiltInColor($color); - } elseif (isset($palette) && isset($palette[$color - 8])) { - // palette color, color index 0x08 maps to pallete index 0 - return $palette[$color - 8]; - } else { - // default color table - if ($version == self::XLS_BIFF8) { - return self::_mapColor($color); - } else { - // BIFF5 - return self::_mapColorBIFF5($color); - } - } - - return $color; - } - - - /** - * Map border style - * OpenOffice documentation: 2.5.11 - * - * @param int $index - * @return string - */ - private static function _mapBorderStyle($index) - { - switch ($index) { - case 0x00: return PHPExcel_Style_Border::BORDER_NONE; - case 0x01: return PHPExcel_Style_Border::BORDER_THIN; - case 0x02: return PHPExcel_Style_Border::BORDER_MEDIUM; - case 0x03: return PHPExcel_Style_Border::BORDER_DASHED; - case 0x04: return PHPExcel_Style_Border::BORDER_DOTTED; - case 0x05: return PHPExcel_Style_Border::BORDER_THICK; - case 0x06: return PHPExcel_Style_Border::BORDER_DOUBLE; - case 0x07: return PHPExcel_Style_Border::BORDER_HAIR; - case 0x08: return PHPExcel_Style_Border::BORDER_MEDIUMDASHED; - case 0x09: return PHPExcel_Style_Border::BORDER_DASHDOT; - case 0x0A: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; - case 0x0B: return PHPExcel_Style_Border::BORDER_DASHDOTDOT; - case 0x0C: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; - case 0x0D: return PHPExcel_Style_Border::BORDER_SLANTDASHDOT; - default: return PHPExcel_Style_Border::BORDER_NONE; - } - } - - - /** - * Get fill pattern from index - * OpenOffice documentation: 2.5.12 - * - * @param int $index - * @return string - */ - private static function _mapFillPattern($index) - { - switch ($index) { - case 0x00: return PHPExcel_Style_Fill::FILL_NONE; - case 0x01: return PHPExcel_Style_Fill::FILL_SOLID; - case 0x02: return PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; - case 0x03: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; - case 0x04: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; - case 0x05: return PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; - case 0x06: return PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; - case 0x07: return PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; - case 0x08: return PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; - case 0x09: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; - case 0x0A: return PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; - case 0x0B: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; - case 0x0C: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; - case 0x0D: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; - case 0x0E: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; - case 0x0F: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; - case 0x10: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; - case 0x11: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; - case 0x12: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; - default: return PHPExcel_Style_Fill::FILL_NONE; - } - } - - - /** - * Map error code, e.g. '#N/A' - * - * @param int $subData - * @return string - */ - private static function _mapErrorCode($subData) - { - switch ($subData) { - case 0x00: return '#NULL!'; break; - case 0x07: return '#DIV/0!'; break; - case 0x0F: return '#VALUE!'; break; - case 0x17: return '#REF!'; break; - case 0x1D: return '#NAME?'; break; - case 0x24: return '#NUM!'; break; - case 0x2A: return '#N/A'; break; - default: return false; - } - } - - - /** - * Map built-in color to RGB value - * - * @param int $color Indexed color - * @return array - */ - private static function _mapBuiltInColor($color) - { - switch ($color) { - case 0x00: return array('rgb' => '000000'); - case 0x01: return array('rgb' => 'FFFFFF'); - case 0x02: return array('rgb' => 'FF0000'); - case 0x03: return array('rgb' => '00FF00'); - case 0x04: return array('rgb' => '0000FF'); - case 0x05: return array('rgb' => 'FFFF00'); - case 0x06: return array('rgb' => 'FF00FF'); - case 0x07: return array('rgb' => '00FFFF'); - case 0x40: return array('rgb' => '000000'); // system window text color - case 0x41: return array('rgb' => 'FFFFFF'); // system window background color - default: return array('rgb' => '000000'); - } - } - - - /** - * Map color array from BIFF5 built-in color index - * - * @param int $subData - * @return array - */ - private static function _mapColorBIFF5($subData) - { - switch ($subData) { - case 0x08: return array('rgb' => '000000'); - case 0x09: return array('rgb' => 'FFFFFF'); - case 0x0A: return array('rgb' => 'FF0000'); - case 0x0B: return array('rgb' => '00FF00'); - case 0x0C: return array('rgb' => '0000FF'); - case 0x0D: return array('rgb' => 'FFFF00'); - case 0x0E: return array('rgb' => 'FF00FF'); - case 0x0F: return array('rgb' => '00FFFF'); - case 0x10: return array('rgb' => '800000'); - case 0x11: return array('rgb' => '008000'); - case 0x12: return array('rgb' => '000080'); - case 0x13: return array('rgb' => '808000'); - case 0x14: return array('rgb' => '800080'); - case 0x15: return array('rgb' => '008080'); - case 0x16: return array('rgb' => 'C0C0C0'); - case 0x17: return array('rgb' => '808080'); - case 0x18: return array('rgb' => '8080FF'); - case 0x19: return array('rgb' => '802060'); - case 0x1A: return array('rgb' => 'FFFFC0'); - case 0x1B: return array('rgb' => 'A0E0F0'); - case 0x1C: return array('rgb' => '600080'); - case 0x1D: return array('rgb' => 'FF8080'); - case 0x1E: return array('rgb' => '0080C0'); - case 0x1F: return array('rgb' => 'C0C0FF'); - case 0x20: return array('rgb' => '000080'); - case 0x21: return array('rgb' => 'FF00FF'); - case 0x22: return array('rgb' => 'FFFF00'); - case 0x23: return array('rgb' => '00FFFF'); - case 0x24: return array('rgb' => '800080'); - case 0x25: return array('rgb' => '800000'); - case 0x26: return array('rgb' => '008080'); - case 0x27: return array('rgb' => '0000FF'); - case 0x28: return array('rgb' => '00CFFF'); - case 0x29: return array('rgb' => '69FFFF'); - case 0x2A: return array('rgb' => 'E0FFE0'); - case 0x2B: return array('rgb' => 'FFFF80'); - case 0x2C: return array('rgb' => 'A6CAF0'); - case 0x2D: return array('rgb' => 'DD9CB3'); - case 0x2E: return array('rgb' => 'B38FEE'); - case 0x2F: return array('rgb' => 'E3E3E3'); - case 0x30: return array('rgb' => '2A6FF9'); - case 0x31: return array('rgb' => '3FB8CD'); - case 0x32: return array('rgb' => '488436'); - case 0x33: return array('rgb' => '958C41'); - case 0x34: return array('rgb' => '8E5E42'); - case 0x35: return array('rgb' => 'A0627A'); - case 0x36: return array('rgb' => '624FAC'); - case 0x37: return array('rgb' => '969696'); - case 0x38: return array('rgb' => '1D2FBE'); - case 0x39: return array('rgb' => '286676'); - case 0x3A: return array('rgb' => '004500'); - case 0x3B: return array('rgb' => '453E01'); - case 0x3C: return array('rgb' => '6A2813'); - case 0x3D: return array('rgb' => '85396A'); - case 0x3E: return array('rgb' => '4A3285'); - case 0x3F: return array('rgb' => '424242'); - default: return array('rgb' => '000000'); - } - } - - - /** - * Map color array from BIFF8 built-in color index - * - * @param int $subData - * @return array - */ - private static function _mapColor($subData) - { - switch ($subData) { - case 0x08: return array('rgb' => '000000'); - case 0x09: return array('rgb' => 'FFFFFF'); - case 0x0A: return array('rgb' => 'FF0000'); - case 0x0B: return array('rgb' => '00FF00'); - case 0x0C: return array('rgb' => '0000FF'); - case 0x0D: return array('rgb' => 'FFFF00'); - case 0x0E: return array('rgb' => 'FF00FF'); - case 0x0F: return array('rgb' => '00FFFF'); - case 0x10: return array('rgb' => '800000'); - case 0x11: return array('rgb' => '008000'); - case 0x12: return array('rgb' => '000080'); - case 0x13: return array('rgb' => '808000'); - case 0x14: return array('rgb' => '800080'); - case 0x15: return array('rgb' => '008080'); - case 0x16: return array('rgb' => 'C0C0C0'); - case 0x17: return array('rgb' => '808080'); - case 0x18: return array('rgb' => '9999FF'); - case 0x19: return array('rgb' => '993366'); - case 0x1A: return array('rgb' => 'FFFFCC'); - case 0x1B: return array('rgb' => 'CCFFFF'); - case 0x1C: return array('rgb' => '660066'); - case 0x1D: return array('rgb' => 'FF8080'); - case 0x1E: return array('rgb' => '0066CC'); - case 0x1F: return array('rgb' => 'CCCCFF'); - case 0x20: return array('rgb' => '000080'); - case 0x21: return array('rgb' => 'FF00FF'); - case 0x22: return array('rgb' => 'FFFF00'); - case 0x23: return array('rgb' => '00FFFF'); - case 0x24: return array('rgb' => '800080'); - case 0x25: return array('rgb' => '800000'); - case 0x26: return array('rgb' => '008080'); - case 0x27: return array('rgb' => '0000FF'); - case 0x28: return array('rgb' => '00CCFF'); - case 0x29: return array('rgb' => 'CCFFFF'); - case 0x2A: return array('rgb' => 'CCFFCC'); - case 0x2B: return array('rgb' => 'FFFF99'); - case 0x2C: return array('rgb' => '99CCFF'); - case 0x2D: return array('rgb' => 'FF99CC'); - case 0x2E: return array('rgb' => 'CC99FF'); - case 0x2F: return array('rgb' => 'FFCC99'); - case 0x30: return array('rgb' => '3366FF'); - case 0x31: return array('rgb' => '33CCCC'); - case 0x32: return array('rgb' => '99CC00'); - case 0x33: return array('rgb' => 'FFCC00'); - case 0x34: return array('rgb' => 'FF9900'); - case 0x35: return array('rgb' => 'FF6600'); - case 0x36: return array('rgb' => '666699'); - case 0x37: return array('rgb' => '969696'); - case 0x38: return array('rgb' => '003366'); - case 0x39: return array('rgb' => '339966'); - case 0x3A: return array('rgb' => '003300'); - case 0x3B: return array('rgb' => '333300'); - case 0x3C: return array('rgb' => '993300'); - case 0x3D: return array('rgb' => '993366'); - case 0x3E: return array('rgb' => '333399'); - case 0x3F: return array('rgb' => '333333'); - default: return array('rgb' => '000000'); - } - } - - - private function _parseRichText($is = '') { - $value = new PHPExcel_RichText(); - - $value->createText($is); - - return $value; - } + if (!$this->_readDataOnly) { + $offset += 12; + + // offset: 12; size: 2; shared feature type, 2 = enhanced protection, 4 = smart tag + $isf = self::_GetInt2d($recordData, 12); + if ($isf != 2) { + // we only read FEAT records of type 2 + return; + } + $offset += 2; + + $offset += 5; + + // offset: 19; size: 2; count of ref ranges this feature is on + $cref = self::_GetInt2d($recordData, 19); + $offset += 2; + + $offset += 6; + + // offset: 27; size: 8 * $cref; list of cell ranges (like in hyperlink record) + $cellRanges = array(); + for ($i = 0; $i < $cref; ++$i) { + try { + $cellRange = $this->_readBIFF8CellRangeAddressFixed(substr($recordData, 27 + 8 * $i, 8)); + } catch (PHPExcel_Exception $e) { + return; + } + $cellRanges[] = $cellRange; + $offset += 8; + } + + // offset: var; size: var; variable length of feature specific data + $rgbFeat = substr($recordData, $offset); + $offset += 4; + + // offset: var; size: 4; the encrypted password (only 16-bit although field is 32-bit) + $wPassword = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // Apply range protection to sheet + if ($cellRanges) { + $this->_phpSheet->protectCells(implode(' ', $cellRanges), strtoupper(dechex($wPassword)), true); + } + } + } + + + /** + * Read IMDATA record + */ + private function _readImData() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + // UNDER CONSTRUCTION + + // offset: 0; size: 2; image format + $cf = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; environment from which the file was written + $env = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 4; length of the image data + $lcb = self::_GetInt4d($recordData, 4); + + // offset: 8; size: var; image data + $iData = substr($recordData, 8); + + switch ($cf) { + case 0x09: // Windows bitmap format + // BITMAPCOREINFO + // 1. BITMAPCOREHEADER + // offset: 0; size: 4; bcSize, Specifies the number of bytes required by the structure + $bcSize = self::_GetInt4d($iData, 0); +// var_dump($bcSize); + + // offset: 4; size: 2; bcWidth, specifies the width of the bitmap, in pixels + $bcWidth = self::_GetInt2d($iData, 4); +// var_dump($bcWidth); + + // offset: 6; size: 2; bcHeight, specifies the height of the bitmap, in pixels. + $bcHeight = self::_GetInt2d($iData, 6); +// var_dump($bcHeight); + $ih = imagecreatetruecolor($bcWidth, $bcHeight); + + // offset: 8; size: 2; bcPlanes, specifies the number of planes for the target device. This value must be 1 + + // offset: 10; size: 2; bcBitCount specifies the number of bits-per-pixel. This value must be 1, 4, 8, or 24 + $bcBitCount = self::_GetInt2d($iData, 10); +// var_dump($bcBitCount); + + $rgbString = substr($iData, 12); + $rgbTriples = array(); + while (strlen($rgbString) > 0) { + $rgbTriples[] = unpack('Cb/Cg/Cr', $rgbString); + $rgbString = substr($rgbString, 3); + } + $x = 0; + $y = 0; + foreach ($rgbTriples as $i => $rgbTriple) { + $color = imagecolorallocate($ih, $rgbTriple['r'], $rgbTriple['g'], $rgbTriple['b']); + imagesetpixel($ih, $x, $bcHeight - 1 - $y, $color); + $x = ($x + 1) % $bcWidth; + $y = $y + floor(($x + 1) / $bcWidth); + } + //imagepng($ih, 'image.png'); + + $drawing = new PHPExcel_Worksheet_Drawing(); + $drawing->setPath($filename); + $drawing->setWorksheet($this->_phpSheet); + + break; + + case 0x02: // Windows metafile or Macintosh PICT format + case 0x0e: // native format + default; + break; + + } + + // _getSplicedRecordData() takes care of moving current position in data stream + } + + + /** + * Read a free CONTINUE record. Free CONTINUE record may be a camouflaged MSODRAWING record + * When MSODRAWING data on a sheet exceeds 8224 bytes, CONTINUE records are used instead. Undocumented. + * In this case, we must treat the CONTINUE record as a MSODRAWING record + */ + private function _readContinue() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // check if we are reading drawing data + // this is in case a free CONTINUE record occurs in other circumstances we are unaware of + if ($this->_drawingData == '') { + // move stream pointer to next record + $this->_pos += 4 + $length; + + return; + } + + // check if record data is at least 4 bytes long, otherwise there is no chance this is MSODRAWING data + if ($length < 4) { + // move stream pointer to next record + $this->_pos += 4 + $length; + + return; + } + + // dirty check to see if CONTINUE record could be a camouflaged MSODRAWING record + // look inside CONTINUE record to see if it looks like a part of an Escher stream + // we know that Escher stream may be split at least at + // 0xF003 MsofbtSpgrContainer + // 0xF004 MsofbtSpContainer + // 0xF00D MsofbtClientTextbox + $validSplitPoints = array(0xF003, 0xF004, 0xF00D); // add identifiers if we find more + + $splitPoint = self::_GetInt2d($recordData, 2); + if (in_array($splitPoint, $validSplitPoints)) { + // get spliced record data (and move pointer to next record) + $splicedRecordData = $this->_getSplicedRecordData(); + $this->_drawingData .= $splicedRecordData['recordData']; + + return; + } + + // move stream pointer to next record + $this->_pos += 4 + $length; + + } + + + /** + * Reads a record from current position in data stream and continues reading data as long as CONTINUE + * records are found. Splices the record data pieces and returns the combined string as if record data + * is in one piece. + * Moves to next current position in data stream to start of next record different from a CONtINUE record + * + * @return array + */ + private function _getSplicedRecordData() + { + $data = ''; + $spliceOffsets = array(); + + $i = 0; + $spliceOffsets[0] = 0; + + do { + ++$i; + + // offset: 0; size: 2; identifier + $identifier = self::_GetInt2d($this->_data, $this->_pos); + // offset: 2; size: 2; length + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $data .= $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + $spliceOffsets[$i] = $spliceOffsets[$i - 1] + $length; + + $this->_pos += 4 + $length; + $nextIdentifier = self::_GetInt2d($this->_data, $this->_pos); + } + while ($nextIdentifier == self::XLS_Type_CONTINUE); + + $splicedData = array( + 'recordData' => $data, + 'spliceOffsets' => $spliceOffsets, + ); + + return $splicedData; + + } + + + /** + * Convert formula structure into human readable Excel formula like 'A3+A5*5' + * + * @param string $formulaStructure The complete binary data for the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _getFormulaFromStructure($formulaStructure, $baseCell = 'A1') + { + // offset: 0; size: 2; size of the following formula data + $sz = self::_GetInt2d($formulaStructure, 0); + + // offset: 2; size: sz + $formulaData = substr($formulaStructure, 2, $sz); + + // for debug: dump the formula data + //echo '<xmp>'; + //echo 'size: ' . $sz . "\n"; + //echo 'the entire formula data: '; + //Debug::dump($formulaData); + //echo "\n----\n"; + + // offset: 2 + sz; size: variable (optional) + if (strlen($formulaStructure) > 2 + $sz) { + $additionalData = substr($formulaStructure, 2 + $sz); + + // for debug: dump the additional data + //echo 'the entire additional data: '; + //Debug::dump($additionalData); + //echo "\n----\n"; + + } else { + $additionalData = ''; + } + + return $this->_getFormulaFromData($formulaData, $additionalData, $baseCell); + } + + + /** + * Take formula data and additional data for formula and return human readable formula + * + * @param string $formulaData The binary data for the formula itself + * @param string $additionalData Additional binary data going with the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _getFormulaFromData($formulaData, $additionalData = '', $baseCell = 'A1') + { + // start parsing the formula data + $tokens = array(); + + while (strlen($formulaData) > 0 and $token = $this->_getNextToken($formulaData, $baseCell)) { + $tokens[] = $token; + $formulaData = substr($formulaData, $token['size']); + + // for debug: dump the token + //var_dump($token); + } + + $formulaString = $this->_createFormulaFromTokens($tokens, $additionalData); + + return $formulaString; + } + + + /** + * Take array of tokens together with additional data for formula and return human readable formula + * + * @param array $tokens + * @param array $additionalData Additional binary data going with the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _createFormulaFromTokens($tokens, $additionalData) + { + // empty formula? + if (empty($tokens)) { + return ''; + } + + $formulaStrings = array(); + foreach ($tokens as $token) { + // initialize spaces + $space0 = isset($space0) ? $space0 : ''; // spaces before next token, not tParen + $space1 = isset($space1) ? $space1 : ''; // carriage returns before next token, not tParen + $space2 = isset($space2) ? $space2 : ''; // spaces before opening parenthesis + $space3 = isset($space3) ? $space3 : ''; // carriage returns before opening parenthesis + $space4 = isset($space4) ? $space4 : ''; // spaces before closing parenthesis + $space5 = isset($space5) ? $space5 : ''; // carriage returns before closing parenthesis + + switch ($token['name']) { + case 'tAdd': // addition + case 'tConcat': // addition + case 'tDiv': // division + case 'tEQ': // equality + case 'tGE': // greater than or equal + case 'tGT': // greater than + case 'tIsect': // intersection + case 'tLE': // less than or equal + case 'tList': // less than or equal + case 'tLT': // less than + case 'tMul': // multiplication + case 'tNE': // multiplication + case 'tPower': // power + case 'tRange': // range + case 'tSub': // subtraction + $op2 = array_pop($formulaStrings); + $op1 = array_pop($formulaStrings); + $formulaStrings[] = "$op1$space1$space0{$token['data']}$op2"; + unset($space0, $space1); + break; + case 'tUplus': // unary plus + case 'tUminus': // unary minus + $op = array_pop($formulaStrings); + $formulaStrings[] = "$space1$space0{$token['data']}$op"; + unset($space0, $space1); + break; + case 'tPercent': // percent sign + $op = array_pop($formulaStrings); + $formulaStrings[] = "$op$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + case 'tAttrVolatile': // indicates volatile function + case 'tAttrIf': + case 'tAttrSkip': + case 'tAttrChoose': + // token is only important for Excel formula evaluator + // do nothing + break; + case 'tAttrSpace': // space / carriage return + // space will be used when next token arrives, do not alter formulaString stack + switch ($token['data']['spacetype']) { + case 'type0': + $space0 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type1': + $space1 = str_repeat("\n", $token['data']['spacecount']); + break; + case 'type2': + $space2 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type3': + $space3 = str_repeat("\n", $token['data']['spacecount']); + break; + case 'type4': + $space4 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type5': + $space5 = str_repeat("\n", $token['data']['spacecount']); + break; + } + break; + case 'tAttrSum': // SUM function with one parameter + $op = array_pop($formulaStrings); + $formulaStrings[] = "{$space1}{$space0}SUM($op)"; + unset($space0, $space1); + break; + case 'tFunc': // function with fixed number of arguments + case 'tFuncV': // function with variable number of arguments + if ($token['data']['function'] != '') { + // normal function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args']; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $formulaStrings[] = "$space1$space0{$token['data']['function']}(" . implode(',', $ops) . ")"; + unset($space0, $space1); + } else { + // add-in function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args'] - 1; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $function = array_pop($formulaStrings); + $formulaStrings[] = "$space1$space0$function(" . implode(',', $ops) . ")"; + unset($space0, $space1); + } + break; + case 'tParen': // parenthesis + $expression = array_pop($formulaStrings); + $formulaStrings[] = "$space3$space2($expression$space5$space4)"; + unset($space2, $space3, $space4, $space5); + break; + case 'tArray': // array constant + $constantArray = self::_readBIFF8ConstantArray($additionalData); + $formulaStrings[] = $space1 . $space0 . $constantArray['value']; + $additionalData = substr($additionalData, $constantArray['size']); // bite of chunk of additional data + unset($space0, $space1); + break; + case 'tMemArea': + // bite off chunk of additional data + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($additionalData); + $additionalData = substr($additionalData, $cellRangeAddressList['size']); + $formulaStrings[] = "$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + case 'tArea': // cell range address + case 'tBool': // boolean + case 'tErr': // error code + case 'tInt': // integer + case 'tMemErr': + case 'tMemFunc': + case 'tMissArg': + case 'tName': + case 'tNameX': + case 'tNum': // number + case 'tRef': // single cell reference + case 'tRef3d': // 3d cell reference + case 'tArea3d': // 3d cell range reference + case 'tRefN': + case 'tAreaN': + case 'tStr': // string + $formulaStrings[] = "$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + } + } + $formulaString = $formulaStrings[0]; + + // for debug: dump the human readable formula + //echo '----' . "\n"; + //echo 'Formula: ' . $formulaString; + + return $formulaString; + } + + + /** + * Fetch next token from binary formula data + * + * @param string Formula data + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return array + * @throws PHPExcel_Reader_Exception + */ + private function _getNextToken($formulaData, $baseCell = 'A1') + { + // offset: 0; size: 1; token id + $id = ord($formulaData[0]); // token id + $name = false; // initialize token name + + switch ($id) { + case 0x03: $name = 'tAdd'; $size = 1; $data = '+'; break; + case 0x04: $name = 'tSub'; $size = 1; $data = '-'; break; + case 0x05: $name = 'tMul'; $size = 1; $data = '*'; break; + case 0x06: $name = 'tDiv'; $size = 1; $data = '/'; break; + case 0x07: $name = 'tPower'; $size = 1; $data = '^'; break; + case 0x08: $name = 'tConcat'; $size = 1; $data = '&'; break; + case 0x09: $name = 'tLT'; $size = 1; $data = '<'; break; + case 0x0A: $name = 'tLE'; $size = 1; $data = '<='; break; + case 0x0B: $name = 'tEQ'; $size = 1; $data = '='; break; + case 0x0C: $name = 'tGE'; $size = 1; $data = '>='; break; + case 0x0D: $name = 'tGT'; $size = 1; $data = '>'; break; + case 0x0E: $name = 'tNE'; $size = 1; $data = '<>'; break; + case 0x0F: $name = 'tIsect'; $size = 1; $data = ' '; break; + case 0x10: $name = 'tList'; $size = 1; $data = ','; break; + case 0x11: $name = 'tRange'; $size = 1; $data = ':'; break; + case 0x12: $name = 'tUplus'; $size = 1; $data = '+'; break; + case 0x13: $name = 'tUminus'; $size = 1; $data = '-'; break; + case 0x14: $name = 'tPercent'; $size = 1; $data = '%'; break; + case 0x15: // parenthesis + $name = 'tParen'; + $size = 1; + $data = null; + break; + case 0x16: // missing argument + $name = 'tMissArg'; + $size = 1; + $data = ''; + break; + case 0x17: // string + $name = 'tStr'; + // offset: 1; size: var; Unicode string, 8-bit string length + $string = self::_readUnicodeStringShort(substr($formulaData, 1)); + $size = 1 + $string['size']; + $data = self::_UTF8toExcelDoubleQuoted($string['value']); + break; + case 0x19: // Special attribute + // offset: 1; size: 1; attribute type flags: + switch (ord($formulaData[1])) { + case 0x01: + $name = 'tAttrVolatile'; + $size = 4; + $data = null; + break; + case 0x02: + $name = 'tAttrIf'; + $size = 4; + $data = null; + break; + case 0x04: + $name = 'tAttrChoose'; + // offset: 2; size: 2; number of choices in the CHOOSE function ($nc, number of parameters decreased by 1) + $nc = self::_GetInt2d($formulaData, 2); + // offset: 4; size: 2 * $nc + // offset: 4 + 2 * $nc; size: 2 + $size = 2 * $nc + 6; + $data = null; + break; + case 0x08: + $name = 'tAttrSkip'; + $size = 4; + $data = null; + break; + case 0x10: + $name = 'tAttrSum'; + $size = 4; + $data = null; + break; + case 0x40: + case 0x41: + $name = 'tAttrSpace'; + $size = 4; + // offset: 2; size: 2; space type and position + switch (ord($formulaData[2])) { + case 0x00: + $spacetype = 'type0'; + break; + case 0x01: + $spacetype = 'type1'; + break; + case 0x02: + $spacetype = 'type2'; + break; + case 0x03: + $spacetype = 'type3'; + break; + case 0x04: + $spacetype = 'type4'; + break; + case 0x05: + $spacetype = 'type5'; + break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized space type in tAttrSpace token'); + break; + } + // offset: 3; size: 1; number of inserted spaces/carriage returns + $spacecount = ord($formulaData[3]); + + $data = array('spacetype' => $spacetype, 'spacecount' => $spacecount); + break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized attribute flag in tAttr token'); + break; + } + break; + case 0x1C: // error code + // offset: 1; size: 1; error code + $name = 'tErr'; + $size = 2; + $data = self::_mapErrorCode(ord($formulaData[1])); + break; + case 0x1D: // boolean + // offset: 1; size: 1; 0 = false, 1 = true; + $name = 'tBool'; + $size = 2; + $data = ord($formulaData[1]) ? 'TRUE' : 'FALSE'; + break; + case 0x1E: // integer + // offset: 1; size: 2; unsigned 16-bit integer + $name = 'tInt'; + $size = 3; + $data = self::_GetInt2d($formulaData, 1); + break; + case 0x1F: // number + // offset: 1; size: 8; + $name = 'tNum'; + $size = 9; + $data = self::_extractNumber(substr($formulaData, 1)); + $data = str_replace(',', '.', (string)$data); // in case non-English locale + break; + case 0x20: // array constant + case 0x40: + case 0x60: + // offset: 1; size: 7; not used + $name = 'tArray'; + $size = 8; + $data = null; + break; + case 0x21: // function with fixed number of arguments + case 0x41: + case 0x61: + $name = 'tFunc'; + $size = 3; + // offset: 1; size: 2; index to built-in sheet function + switch (self::_GetInt2d($formulaData, 1)) { + case 2: $function = 'ISNA'; $args = 1; break; + case 3: $function = 'ISERROR'; $args = 1; break; + case 10: $function = 'NA'; $args = 0; break; + case 15: $function = 'SIN'; $args = 1; break; + case 16: $function = 'COS'; $args = 1; break; + case 17: $function = 'TAN'; $args = 1; break; + case 18: $function = 'ATAN'; $args = 1; break; + case 19: $function = 'PI'; $args = 0; break; + case 20: $function = 'SQRT'; $args = 1; break; + case 21: $function = 'EXP'; $args = 1; break; + case 22: $function = 'LN'; $args = 1; break; + case 23: $function = 'LOG10'; $args = 1; break; + case 24: $function = 'ABS'; $args = 1; break; + case 25: $function = 'INT'; $args = 1; break; + case 26: $function = 'SIGN'; $args = 1; break; + case 27: $function = 'ROUND'; $args = 2; break; + case 30: $function = 'REPT'; $args = 2; break; + case 31: $function = 'MID'; $args = 3; break; + case 32: $function = 'LEN'; $args = 1; break; + case 33: $function = 'VALUE'; $args = 1; break; + case 34: $function = 'TRUE'; $args = 0; break; + case 35: $function = 'FALSE'; $args = 0; break; + case 38: $function = 'NOT'; $args = 1; break; + case 39: $function = 'MOD'; $args = 2; break; + case 40: $function = 'DCOUNT'; $args = 3; break; + case 41: $function = 'DSUM'; $args = 3; break; + case 42: $function = 'DAVERAGE'; $args = 3; break; + case 43: $function = 'DMIN'; $args = 3; break; + case 44: $function = 'DMAX'; $args = 3; break; + case 45: $function = 'DSTDEV'; $args = 3; break; + case 48: $function = 'TEXT'; $args = 2; break; + case 61: $function = 'MIRR'; $args = 3; break; + case 63: $function = 'RAND'; $args = 0; break; + case 65: $function = 'DATE'; $args = 3; break; + case 66: $function = 'TIME'; $args = 3; break; + case 67: $function = 'DAY'; $args = 1; break; + case 68: $function = 'MONTH'; $args = 1; break; + case 69: $function = 'YEAR'; $args = 1; break; + case 71: $function = 'HOUR'; $args = 1; break; + case 72: $function = 'MINUTE'; $args = 1; break; + case 73: $function = 'SECOND'; $args = 1; break; + case 74: $function = 'NOW'; $args = 0; break; + case 75: $function = 'AREAS'; $args = 1; break; + case 76: $function = 'ROWS'; $args = 1; break; + case 77: $function = 'COLUMNS'; $args = 1; break; + case 83: $function = 'TRANSPOSE'; $args = 1; break; + case 86: $function = 'TYPE'; $args = 1; break; + case 97: $function = 'ATAN2'; $args = 2; break; + case 98: $function = 'ASIN'; $args = 1; break; + case 99: $function = 'ACOS'; $args = 1; break; + case 105: $function = 'ISREF'; $args = 1; break; + case 111: $function = 'CHAR'; $args = 1; break; + case 112: $function = 'LOWER'; $args = 1; break; + case 113: $function = 'UPPER'; $args = 1; break; + case 114: $function = 'PROPER'; $args = 1; break; + case 117: $function = 'EXACT'; $args = 2; break; + case 118: $function = 'TRIM'; $args = 1; break; + case 119: $function = 'REPLACE'; $args = 4; break; + case 121: $function = 'CODE'; $args = 1; break; + case 126: $function = 'ISERR'; $args = 1; break; + case 127: $function = 'ISTEXT'; $args = 1; break; + case 128: $function = 'ISNUMBER'; $args = 1; break; + case 129: $function = 'ISBLANK'; $args = 1; break; + case 130: $function = 'T'; $args = 1; break; + case 131: $function = 'N'; $args = 1; break; + case 140: $function = 'DATEVALUE'; $args = 1; break; + case 141: $function = 'TIMEVALUE'; $args = 1; break; + case 142: $function = 'SLN'; $args = 3; break; + case 143: $function = 'SYD'; $args = 4; break; + case 162: $function = 'CLEAN'; $args = 1; break; + case 163: $function = 'MDETERM'; $args = 1; break; + case 164: $function = 'MINVERSE'; $args = 1; break; + case 165: $function = 'MMULT'; $args = 2; break; + case 184: $function = 'FACT'; $args = 1; break; + case 189: $function = 'DPRODUCT'; $args = 3; break; + case 190: $function = 'ISNONTEXT'; $args = 1; break; + case 195: $function = 'DSTDEVP'; $args = 3; break; + case 196: $function = 'DVARP'; $args = 3; break; + case 198: $function = 'ISLOGICAL'; $args = 1; break; + case 199: $function = 'DCOUNTA'; $args = 3; break; + case 207: $function = 'REPLACEB'; $args = 4; break; + case 210: $function = 'MIDB'; $args = 3; break; + case 211: $function = 'LENB'; $args = 1; break; + case 212: $function = 'ROUNDUP'; $args = 2; break; + case 213: $function = 'ROUNDDOWN'; $args = 2; break; + case 214: $function = 'ASC'; $args = 1; break; + case 215: $function = 'DBCS'; $args = 1; break; + case 221: $function = 'TODAY'; $args = 0; break; + case 229: $function = 'SINH'; $args = 1; break; + case 230: $function = 'COSH'; $args = 1; break; + case 231: $function = 'TANH'; $args = 1; break; + case 232: $function = 'ASINH'; $args = 1; break; + case 233: $function = 'ACOSH'; $args = 1; break; + case 234: $function = 'ATANH'; $args = 1; break; + case 235: $function = 'DGET'; $args = 3; break; + case 244: $function = 'INFO'; $args = 1; break; + case 252: $function = 'FREQUENCY'; $args = 2; break; + case 261: $function = 'ERROR.TYPE'; $args = 1; break; + case 271: $function = 'GAMMALN'; $args = 1; break; + case 273: $function = 'BINOMDIST'; $args = 4; break; + case 274: $function = 'CHIDIST'; $args = 2; break; + case 275: $function = 'CHIINV'; $args = 2; break; + case 276: $function = 'COMBIN'; $args = 2; break; + case 277: $function = 'CONFIDENCE'; $args = 3; break; + case 278: $function = 'CRITBINOM'; $args = 3; break; + case 279: $function = 'EVEN'; $args = 1; break; + case 280: $function = 'EXPONDIST'; $args = 3; break; + case 281: $function = 'FDIST'; $args = 3; break; + case 282: $function = 'FINV'; $args = 3; break; + case 283: $function = 'FISHER'; $args = 1; break; + case 284: $function = 'FISHERINV'; $args = 1; break; + case 285: $function = 'FLOOR'; $args = 2; break; + case 286: $function = 'GAMMADIST'; $args = 4; break; + case 287: $function = 'GAMMAINV'; $args = 3; break; + case 288: $function = 'CEILING'; $args = 2; break; + case 289: $function = 'HYPGEOMDIST'; $args = 4; break; + case 290: $function = 'LOGNORMDIST'; $args = 3; break; + case 291: $function = 'LOGINV'; $args = 3; break; + case 292: $function = 'NEGBINOMDIST'; $args = 3; break; + case 293: $function = 'NORMDIST'; $args = 4; break; + case 294: $function = 'NORMSDIST'; $args = 1; break; + case 295: $function = 'NORMINV'; $args = 3; break; + case 296: $function = 'NORMSINV'; $args = 1; break; + case 297: $function = 'STANDARDIZE'; $args = 3; break; + case 298: $function = 'ODD'; $args = 1; break; + case 299: $function = 'PERMUT'; $args = 2; break; + case 300: $function = 'POISSON'; $args = 3; break; + case 301: $function = 'TDIST'; $args = 3; break; + case 302: $function = 'WEIBULL'; $args = 4; break; + case 303: $function = 'SUMXMY2'; $args = 2; break; + case 304: $function = 'SUMX2MY2'; $args = 2; break; + case 305: $function = 'SUMX2PY2'; $args = 2; break; + case 306: $function = 'CHITEST'; $args = 2; break; + case 307: $function = 'CORREL'; $args = 2; break; + case 308: $function = 'COVAR'; $args = 2; break; + case 309: $function = 'FORECAST'; $args = 3; break; + case 310: $function = 'FTEST'; $args = 2; break; + case 311: $function = 'INTERCEPT'; $args = 2; break; + case 312: $function = 'PEARSON'; $args = 2; break; + case 313: $function = 'RSQ'; $args = 2; break; + case 314: $function = 'STEYX'; $args = 2; break; + case 315: $function = 'SLOPE'; $args = 2; break; + case 316: $function = 'TTEST'; $args = 4; break; + case 325: $function = 'LARGE'; $args = 2; break; + case 326: $function = 'SMALL'; $args = 2; break; + case 327: $function = 'QUARTILE'; $args = 2; break; + case 328: $function = 'PERCENTILE'; $args = 2; break; + case 331: $function = 'TRIMMEAN'; $args = 2; break; + case 332: $function = 'TINV'; $args = 2; break; + case 337: $function = 'POWER'; $args = 2; break; + case 342: $function = 'RADIANS'; $args = 1; break; + case 343: $function = 'DEGREES'; $args = 1; break; + case 346: $function = 'COUNTIF'; $args = 2; break; + case 347: $function = 'COUNTBLANK'; $args = 1; break; + case 350: $function = 'ISPMT'; $args = 4; break; + case 351: $function = 'DATEDIF'; $args = 3; break; + case 352: $function = 'DATESTRING'; $args = 1; break; + case 353: $function = 'NUMBERSTRING'; $args = 2; break; + case 360: $function = 'PHONETIC'; $args = 1; break; + case 368: $function = 'BAHTTEXT'; $args = 1; break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); + break; + } + $data = array('function' => $function, 'args' => $args); + break; + case 0x22: // function with variable number of arguments + case 0x42: + case 0x62: + $name = 'tFuncV'; + $size = 4; + // offset: 1; size: 1; number of arguments + $args = ord($formulaData[1]); + // offset: 2: size: 2; index to built-in sheet function + $index = self::_GetInt2d($formulaData, 2); + switch ($index) { + case 0: $function = 'COUNT'; break; + case 1: $function = 'IF'; break; + case 4: $function = 'SUM'; break; + case 5: $function = 'AVERAGE'; break; + case 6: $function = 'MIN'; break; + case 7: $function = 'MAX'; break; + case 8: $function = 'ROW'; break; + case 9: $function = 'COLUMN'; break; + case 11: $function = 'NPV'; break; + case 12: $function = 'STDEV'; break; + case 13: $function = 'DOLLAR'; break; + case 14: $function = 'FIXED'; break; + case 28: $function = 'LOOKUP'; break; + case 29: $function = 'INDEX'; break; + case 36: $function = 'AND'; break; + case 37: $function = 'OR'; break; + case 46: $function = 'VAR'; break; + case 49: $function = 'LINEST'; break; + case 50: $function = 'TREND'; break; + case 51: $function = 'LOGEST'; break; + case 52: $function = 'GROWTH'; break; + case 56: $function = 'PV'; break; + case 57: $function = 'FV'; break; + case 58: $function = 'NPER'; break; + case 59: $function = 'PMT'; break; + case 60: $function = 'RATE'; break; + case 62: $function = 'IRR'; break; + case 64: $function = 'MATCH'; break; + case 70: $function = 'WEEKDAY'; break; + case 78: $function = 'OFFSET'; break; + case 82: $function = 'SEARCH'; break; + case 100: $function = 'CHOOSE'; break; + case 101: $function = 'HLOOKUP'; break; + case 102: $function = 'VLOOKUP'; break; + case 109: $function = 'LOG'; break; + case 115: $function = 'LEFT'; break; + case 116: $function = 'RIGHT'; break; + case 120: $function = 'SUBSTITUTE'; break; + case 124: $function = 'FIND'; break; + case 125: $function = 'CELL'; break; + case 144: $function = 'DDB'; break; + case 148: $function = 'INDIRECT'; break; + case 167: $function = 'IPMT'; break; + case 168: $function = 'PPMT'; break; + case 169: $function = 'COUNTA'; break; + case 183: $function = 'PRODUCT'; break; + case 193: $function = 'STDEVP'; break; + case 194: $function = 'VARP'; break; + case 197: $function = 'TRUNC'; break; + case 204: $function = 'USDOLLAR'; break; + case 205: $function = 'FINDB'; break; + case 206: $function = 'SEARCHB'; break; + case 208: $function = 'LEFTB'; break; + case 209: $function = 'RIGHTB'; break; + case 216: $function = 'RANK'; break; + case 219: $function = 'ADDRESS'; break; + case 220: $function = 'DAYS360'; break; + case 222: $function = 'VDB'; break; + case 227: $function = 'MEDIAN'; break; + case 228: $function = 'SUMPRODUCT'; break; + case 247: $function = 'DB'; break; + case 255: $function = ''; break; + case 269: $function = 'AVEDEV'; break; + case 270: $function = 'BETADIST'; break; + case 272: $function = 'BETAINV'; break; + case 317: $function = 'PROB'; break; + case 318: $function = 'DEVSQ'; break; + case 319: $function = 'GEOMEAN'; break; + case 320: $function = 'HARMEAN'; break; + case 321: $function = 'SUMSQ'; break; + case 322: $function = 'KURT'; break; + case 323: $function = 'SKEW'; break; + case 324: $function = 'ZTEST'; break; + case 329: $function = 'PERCENTRANK'; break; + case 330: $function = 'MODE'; break; + case 336: $function = 'CONCATENATE'; break; + case 344: $function = 'SUBTOTAL'; break; + case 345: $function = 'SUMIF'; break; + case 354: $function = 'ROMAN'; break; + case 358: $function = 'GETPIVOTDATA'; break; + case 359: $function = 'HYPERLINK'; break; + case 361: $function = 'AVERAGEA'; break; + case 362: $function = 'MAXA'; break; + case 363: $function = 'MINA'; break; + case 364: $function = 'STDEVPA'; break; + case 365: $function = 'VARPA'; break; + case 366: $function = 'STDEVA'; break; + case 367: $function = 'VARA'; break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); + break; + } + $data = array('function' => $function, 'args' => $args); + break; + case 0x23: // index to defined name + case 0x43: + case 0x63: + $name = 'tName'; + $size = 5; + // offset: 1; size: 2; one-based index to definedname record + $definedNameIndex = self::_GetInt2d($formulaData, 1) - 1; + // offset: 2; size: 2; not used + $data = $this->_definedname[$definedNameIndex]['name']; + break; + case 0x24: // single cell reference e.g. A5 + case 0x44: + case 0x64: + $name = 'tRef'; + $size = 5; + $data = $this->_readBIFF8CellAddress(substr($formulaData, 1, 4)); + break; + case 0x25: // cell range reference to cells in the same sheet (2d) + case 0x45: + case 0x65: + $name = 'tArea'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddress(substr($formulaData, 1, 8)); + break; + case 0x26: // Constant reference sub-expression + case 0x46: + case 0x66: + $name = 'tMemArea'; + // offset: 1; size: 4; not used + // offset: 5; size: 2; size of the following subexpression + $subSize = self::_GetInt2d($formulaData, 5); + $size = 7 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); + break; + case 0x27: // Deleted constant reference sub-expression + case 0x47: + case 0x67: + $name = 'tMemErr'; + // offset: 1; size: 4; not used + // offset: 5; size: 2; size of the following subexpression + $subSize = self::_GetInt2d($formulaData, 5); + $size = 7 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); + break; + case 0x29: // Variable reference sub-expression + case 0x49: + case 0x69: + $name = 'tMemFunc'; + // offset: 1; size: 2; size of the following sub-expression + $subSize = self::_GetInt2d($formulaData, 1); + $size = 3 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); + break; + + case 0x2C: // Relative 2d cell reference reference, used in shared formulas and some other places + case 0x4C: + case 0x6C: + $name = 'tRefN'; + $size = 5; + $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); + break; + + case 0x2D: // Relative 2d range reference + case 0x4D: + case 0x6D: + $name = 'tAreaN'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); + break; + + case 0x39: // External name + case 0x59: + case 0x79: + $name = 'tNameX'; + $size = 7; + // offset: 1; size: 2; index to REF entry in EXTERNSHEET record + // offset: 3; size: 2; one-based index to DEFINEDNAME or EXTERNNAME record + $index = self::_GetInt2d($formulaData, 3); + // assume index is to EXTERNNAME record + $data = $this->_externalNames[$index - 1]['name']; + // offset: 5; size: 2; not used + break; + + case 0x3A: // 3d reference to cell + case 0x5A: + case 0x7A: + $name = 'tRef3d'; + $size = 7; + + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); + // offset: 3; size: 4; cell address + $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); + + $data = "$sheetRange!$cellAddress"; + } catch (PHPExcel_Exception $e) { + // deleted sheet reference + $data = '#REF!'; + } + + break; + case 0x3B: // 3d reference to cell range + case 0x5B: + case 0x7B: + $name = 'tArea3d'; + $size = 11; + + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); + // offset: 3; size: 8; cell address + $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); + + $data = "$sheetRange!$cellRangeAddress"; + } catch (PHPExcel_Exception $e) { + // deleted sheet reference + $data = '#REF!'; + } + + break; + // Unknown cases // don't know how to deal with + default: + throw new PHPExcel_Reader_Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); + break; + } + + return array( + 'id' => $id, + 'name' => $name, + 'size' => $size, + 'data' => $data, + ); + } + + + /** + * Reads a cell address in BIFF8 e.g. 'A2' or '$A$2' + * section 3.3.4 + * + * @param string $cellAddressStructure + * @return string + */ + private function _readBIFF8CellAddress($cellAddressStructure) + { + // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) + $row = self::_GetInt2d($cellAddressStructure, 0) + 1; + + // offset: 2; size: 2; index to column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $column = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($cellAddressStructure, 2)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { + $column = '$' . $column; + } + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { + $row = '$' . $row; + } + + return $column . $row; + } + + + /** + * Reads a cell address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $cellAddressStructure + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string + */ + private function _readBIFF8CellAddressB($cellAddressStructure, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) + $rowIndex = self::_GetInt2d($cellAddressStructure, 0); + $row = self::_GetInt2d($cellAddressStructure, 0) + 1; + + // offset: 2; size: 2; index to column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $colIndex = 0x00FF & self::_GetInt2d($cellAddressStructure, 2); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { + $column = PHPExcel_Cell::stringFromColumnIndex($colIndex); + $column = '$' . $column; + } else { + $colIndex = ($colIndex <= 127) ? $colIndex : $colIndex - 256; + $column = PHPExcel_Cell::stringFromColumnIndex($baseCol + $colIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { + $row = '$' . $row; + } else { + $rowIndex = ($rowIndex <= 32767) ? $rowIndex : $rowIndex - 65536; + $row = $baseRow + $rowIndex; + } + + return $column . $row; + } + + + /** + * Reads a cell range address in BIFF5 e.g. 'A2:B6' or 'A1' + * always fixed range + * section 2.5.14 + * + * @param string $subData + * @return string + * @throws PHPExcel_Reader_Exception + */ + private function _readBIFF5CellRangeAddressFixed($subData) + { + // offset: 0; size: 2; index to first row + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 1; index to first column + $fc = ord($subData{4}); + + // offset: 5; size: 1; index to last column + $lc = ord($subData{5}); + + // check values + if ($fr > $lr || $fc > $lc) { + throw new PHPExcel_Reader_Exception('Not a cell range address'); + } + + // column index to letter + $fc = PHPExcel_Cell::stringFromColumnIndex($fc); + $lc = PHPExcel_Cell::stringFromColumnIndex($lc); + + if ($fr == $lr and $fc == $lc) { + return "$fc$fr"; + } + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 e.g. 'A2:B6' or 'A1' + * always fixed range + * section 2.5.14 + * + * @param string $subData + * @return string + * @throws PHPExcel_Reader_Exception + */ + private function _readBIFF8CellRangeAddressFixed($subData) + { + // offset: 0; size: 2; index to first row + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 2; index to first column + $fc = self::_GetInt2d($subData, 4); + + // offset: 6; size: 2; index to last column + $lc = self::_GetInt2d($subData, 6); + + // check values + if ($fr > $lr || $fc > $lc) { + throw new PHPExcel_Reader_Exception('Not a cell range address'); + } + + // column index to letter + $fc = PHPExcel_Cell::stringFromColumnIndex($fc); + $lc = PHPExcel_Cell::stringFromColumnIndex($lc); + + if ($fr == $lr and $fc == $lc) { + return "$fc$fr"; + } + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 e.g. 'A2:B6' or '$A$2:$B$6' + * there are flags indicating whether column/row index is relative + * section 3.3.4 + * + * @param string $subData + * @return string + */ + private function _readBIFF8CellRangeAddress($subData) + { + // todo: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; index to first row (0... 65535) (or offset (-32768... 32767)) + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row (0... 65535) (or offset (-32768... 32767)) + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 2; index to first column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $fc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 4)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 4))) { + $fc = '$' . $fc; + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 4))) { + $fr = '$' . $fr; + } + + // offset: 6; size: 2; index to last column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $lc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 6)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 6))) { + $lc = '$' . $lc; + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 6))) { + $lr = '$' . $lr; + } + + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $subData + * @param string $baseCell Base cell + * @return string Cell range address + */ + private function _readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // TODO: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; first row + $frIndex = self::_GetInt2d($subData, 0); // adjust below + + // offset: 2; size: 2; relative index to first row (0... 65535) should be treated as offset (-32768... 32767) + $lrIndex = self::_GetInt2d($subData, 2); // adjust below + + // offset: 4; size: 2; first column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $fcIndex = 0x00FF & self::_GetInt2d($subData, 4); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 4))) { + // absolute column index + $fc = PHPExcel_Cell::stringFromColumnIndex($fcIndex); + $fc = '$' . $fc; + } else { + // column offset + $fcIndex = ($fcIndex <= 127) ? $fcIndex : $fcIndex - 256; + $fc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $fcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 4))) { + // absolute row index + $fr = $frIndex + 1; + $fr = '$' . $fr; + } else { + // row offset + $frIndex = ($frIndex <= 32767) ? $frIndex : $frIndex - 65536; + $fr = $baseRow + $frIndex; + } + + // offset: 6; size: 2; last column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $lcIndex = 0x00FF & self::_GetInt2d($subData, 6); + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 6))) { + // absolute column index + $lc = PHPExcel_Cell::stringFromColumnIndex($lcIndex); + $lc = '$' . $lc; + } else { + // column offset + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 6))) { + // absolute row index + $lr = $lrIndex + 1; + $lr = '$' . $lr; + } else { + // row offset + $lrIndex = ($lrIndex <= 32767) ? $lrIndex : $lrIndex - 65536; + $lr = $baseRow + $lrIndex; + } + + return "$fc$fr:$lc$lr"; + } + + + /** + * Read BIFF8 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF8CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = self::_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 8 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF8CellRangeAddressFixed(substr($subData, $offset, 8)); + $offset += 8; + } + + return array( + 'size' => 2 + 8 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + + + /** + * Read BIFF5 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF5CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = self::_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 6 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF5CellRangeAddressFixed(substr($subData, $offset, 6)); + $offset += 6; + } + + return array( + 'size' => 2 + 6 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + + + /** + * Get a sheet range like Sheet1:Sheet3 from REF index + * Note: If there is only one sheet in the range, one gets e.g Sheet1 + * It can also happen that the REF structure uses the -1 (FFFF) code to indicate deleted sheets, + * in which case an PHPExcel_Reader_Exception is thrown + * + * @param int $index + * @return string|false + * @throws PHPExcel_Reader_Exception + */ + private function _readSheetRangeByRefIndex($index) + { + if (isset($this->_ref[$index])) { + + $type = $this->_externalBooks[$this->_ref[$index]['externalBookIndex']]['type']; + + switch ($type) { + case 'internal': + // check if we have a deleted 3d reference + if ($this->_ref[$index]['firstSheetIndex'] == 0xFFFF or $this->_ref[$index]['lastSheetIndex'] == 0xFFFF) { + throw new PHPExcel_Reader_Exception('Deleted sheet reference'); + } + + // we have normal sheet range (collapsed or uncollapsed) + $firstSheetName = $this->_sheets[$this->_ref[$index]['firstSheetIndex']]['name']; + $lastSheetName = $this->_sheets[$this->_ref[$index]['lastSheetIndex']]['name']; + + if ($firstSheetName == $lastSheetName) { + // collapsed sheet range + $sheetRange = $firstSheetName; + } else { + $sheetRange = "$firstSheetName:$lastSheetName"; + } + + // escape the single-quotes + $sheetRange = str_replace("'", "''", $sheetRange); + + // if there are special characters, we need to enclose the range in single-quotes + // todo: check if we have identified the whole set of special characters + // it seems that the following characters are not accepted for sheet names + // and we may assume that they are not present: []*/:\? + if (preg_match("/[ !\"@#£$%&{()}<>=+'|^,;-]/", $sheetRange)) { + $sheetRange = "'$sheetRange'"; + } + + return $sheetRange; + break; + + default: + // TODO: external sheet support + throw new PHPExcel_Reader_Exception('Excel5 reader only supports internal sheets in fomulas'); + break; + } + } + return false; + } + + + /** + * read BIFF8 constant value array from array data + * returns e.g. array('value' => '{1,2;3,4}', 'size' => 40} + * section 2.5.8 + * + * @param string $arrayData + * @return array + */ + private static function _readBIFF8ConstantArray($arrayData) + { + // offset: 0; size: 1; number of columns decreased by 1 + $nc = ord($arrayData[0]); + + // offset: 1; size: 2; number of rows decreased by 1 + $nr = self::_GetInt2d($arrayData, 1); + $size = 3; // initialize + $arrayData = substr($arrayData, 3); + + // offset: 3; size: var; list of ($nc + 1) * ($nr + 1) constant values + $matrixChunks = array(); + for ($r = 1; $r <= $nr + 1; ++$r) { + $items = array(); + for ($c = 1; $c <= $nc + 1; ++$c) { + $constant = self::_readBIFF8Constant($arrayData); + $items[] = $constant['value']; + $arrayData = substr($arrayData, $constant['size']); + $size += $constant['size']; + } + $matrixChunks[] = implode(',', $items); // looks like e.g. '1,"hello"' + } + $matrix = '{' . implode(';', $matrixChunks) . '}'; + + return array( + 'value' => $matrix, + 'size' => $size, + ); + } + + + /** + * read BIFF8 constant value which may be 'Empty Value', 'Number', 'String Value', 'Boolean Value', 'Error Value' + * section 2.5.7 + * returns e.g. array('value' => '5', 'size' => 9) + * + * @param string $valueData + * @return array + */ + private static function _readBIFF8Constant($valueData) + { + // offset: 0; size: 1; identifier for type of constant + $identifier = ord($valueData[0]); + + switch ($identifier) { + case 0x00: // empty constant (what is this?) + $value = ''; + $size = 9; + break; + case 0x01: // number + // offset: 1; size: 8; IEEE 754 floating-point value + $value = self::_extractNumber(substr($valueData, 1, 8)); + $size = 9; + break; + case 0x02: // string value + // offset: 1; size: var; Unicode string, 16-bit string length + $string = self::_readUnicodeStringLong(substr($valueData, 1)); + $value = '"' . $string['value'] . '"'; + $size = 1 + $string['size']; + break; + case 0x04: // boolean + // offset: 1; size: 1; 0 = FALSE, 1 = TRUE + if (ord($valueData[1])) { + $value = 'TRUE'; + } else { + $value = 'FALSE'; + } + $size = 9; + break; + case 0x10: // error code + // offset: 1; size: 1; error code + $value = self::_mapErrorCode(ord($valueData[1])); + $size = 9; + break; + } + return array( + 'value' => $value, + 'size' => $size, + ); + } + + + /** + * Extract RGB color + * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.4 + * + * @param string $rgb Encoded RGB value (4 bytes) + * @return array + */ + private static function _readRGB($rgb) + { + // offset: 0; size 1; Red component + $r = ord($rgb{0}); + + // offset: 1; size: 1; Green component + $g = ord($rgb{1}); + + // offset: 2; size: 1; Blue component + $b = ord($rgb{2}); + + // HEX notation, e.g. 'FF00FC' + $rgb = sprintf('%02X%02X%02X', $r, $g, $b); + + return array('rgb' => $rgb); + } + + + /** + * Read byte string (8-bit string length) + * OpenOffice documentation: 2.5.2 + * + * @param string $subData + * @return array + */ + private function _readByteStringShort($subData) + { + // offset: 0; size: 1; length of the string (character count) + $ln = ord($subData[0]); + + // offset: 1: size: var; character array (8-bit characters) + $value = $this->_decodeCodepage(substr($subData, 1, $ln)); + + return array( + 'value' => $value, + 'size' => 1 + $ln, // size in bytes of data structure + ); + } + + + /** + * Read byte string (16-bit string length) + * OpenOffice documentation: 2.5.2 + * + * @param string $subData + * @return array + */ + private function _readByteStringLong($subData) + { + // offset: 0; size: 2; length of the string (character count) + $ln = self::_GetInt2d($subData, 0); + + // offset: 2: size: var; character array (8-bit characters) + $value = $this->_decodeCodepage(substr($subData, 2)); + + //return $string; + return array( + 'value' => $value, + 'size' => 2 + $ln, // size in bytes of data structure + ); + } + + + /** + * Extracts an Excel Unicode short string (8-bit string length) + * OpenOffice documentation: 2.5.3 + * function will automatically find out where the Unicode string ends. + * + * @param string $subData + * @return array + */ + private static function _readUnicodeStringShort($subData) + { + $value = ''; + + // offset: 0: size: 1; length of the string (character count) + $characterCount = ord($subData[0]); + + $string = self::_readUnicodeString(substr($subData, 1), $characterCount); + + // add 1 for the string length + $string['size'] += 1; + + return $string; + } + + + /** + * Extracts an Excel Unicode long string (16-bit string length) + * OpenOffice documentation: 2.5.3 + * this function is under construction, needs to support rich text, and Asian phonetic settings + * + * @param string $subData + * @return array + */ + private static function _readUnicodeStringLong($subData) + { + $value = ''; + + // offset: 0: size: 2; length of the string (character count) + $characterCount = self::_GetInt2d($subData, 0); + + $string = self::_readUnicodeString(substr($subData, 2), $characterCount); + + // add 2 for the string length + $string['size'] += 2; + + return $string; + } + + + /** + * Read Unicode string with no string length field, but with known character count + * this function is under construction, needs to support rich text, and Asian phonetic settings + * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.3 + * + * @param string $subData + * @param int $characterCount + * @return array + */ + private static function _readUnicodeString($subData, $characterCount) + { + $value = ''; + + // offset: 0: size: 1; option flags + + // bit: 0; mask: 0x01; character compression (0 = compressed 8-bit, 1 = uncompressed 16-bit) + $isCompressed = !((0x01 & ord($subData[0])) >> 0); + + // bit: 2; mask: 0x04; Asian phonetic settings + $hasAsian = (0x04) & ord($subData[0]) >> 2; + + // bit: 3; mask: 0x08; Rich-Text settings + $hasRichText = (0x08) & ord($subData[0]) >> 3; + + // offset: 1: size: var; character array + // this offset assumes richtext and Asian phonetic settings are off which is generally wrong + // needs to be fixed + $value = self::_encodeUTF16(substr($subData, 1, $isCompressed ? $characterCount : 2 * $characterCount), $isCompressed); + + return array( + 'value' => $value, + 'size' => $isCompressed ? 1 + $characterCount : 1 + 2 * $characterCount, // the size in bytes including the option flags + ); + } + + + /** + * Convert UTF-8 string to string surounded by double quotes. Used for explicit string tokens in formulas. + * Example: hello"world --> "hello""world" + * + * @param string $value UTF-8 encoded string + * @return string + */ + private static function _UTF8toExcelDoubleQuoted($value) + { + return '"' . str_replace('"', '""', $value) . '"'; + } + + + /** + * Reads first 8 bytes of a string and return IEEE 754 float + * + * @param string $data Binary string that is at least 8 bytes long + * @return float + */ + private static function _extractNumber($data) + { + $rknumhigh = self::_GetInt4d($data, 4); + $rknumlow = self::_GetInt4d($data, 0); + $sign = ($rknumhigh & 0x80000000) >> 31; + $exp = (($rknumhigh & 0x7ff00000) >> 20) - 1023; + $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); + $mantissalow1 = ($rknumlow & 0x80000000) >> 31; + $mantissalow2 = ($rknumlow & 0x7fffffff); + $value = $mantissa / pow( 2 , (20 - $exp)); + + if ($mantissalow1 != 0) { + $value += 1 / pow (2 , (21 - $exp)); + } + + $value += $mantissalow2 / pow (2 , (52 - $exp)); + if ($sign) { + $value *= -1; + } + + return $value; + } + + + private static function _GetIEEE754($rknum) + { + if (($rknum & 0x02) != 0) { + $value = $rknum >> 2; + } else { + // changes by mmp, info on IEEE754 encoding from + // 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; + } + + + /** + * Get UTF-8 string from (compressed or uncompressed) UTF-16 string + * + * @param string $string + * @param bool $compressed + * @return string + */ + private static function _encodeUTF16($string, $compressed = '') + { + if ($compressed) { + $string = self::_uncompressByteString($string); + } + + return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', 'UTF-16LE'); + } + + + /** + * Convert UTF-16 string in compressed notation to uncompressed form. Only used for BIFF8. + * + * @param string $string + * @return string + */ + private static function _uncompressByteString($string) + { + $uncompressedString = ''; + $strLen = strlen($string); + for ($i = 0; $i < $strLen; ++$i) { + $uncompressedString .= $string[$i] . "\0"; + } + + return $uncompressedString; + } + + + /** + * Convert string to UTF-8. Only used for BIFF5. + * + * @param string $string + * @return string + */ + private function _decodeCodepage($string) + { + return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $this->_codepage); + } + + + /** + * Read 16-bit unsigned integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function _GetInt2d($data, $pos) + { + return ord($data[$pos]) | (ord($data[$pos+1]) << 8); + } + + + /** + * Read 32-bit signed integer + * + * @param string $data + * @param int $pos + * @return int + */ + public 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 + $_or_24 = ord($data[$pos + 3]); + if ($_or_24 >= 128) { + // 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; + } + + + /** + * Read color + * + * @param int $color Indexed color + * @param array $palette Color palette + * @return array RGB color value, example: array('rgb' => 'FF0000') + */ + private static function _readColor($color,$palette,$version) + { + if ($color <= 0x07 || $color >= 0x40) { + // special built-in color + return self::_mapBuiltInColor($color); + } elseif (isset($palette) && isset($palette[$color - 8])) { + // palette color, color index 0x08 maps to pallete index 0 + return $palette[$color - 8]; + } else { + // default color table + if ($version == self::XLS_BIFF8) { + return self::_mapColor($color); + } else { + // BIFF5 + return self::_mapColorBIFF5($color); + } + } + + return $color; + } + + + /** + * Map border style + * OpenOffice documentation: 2.5.11 + * + * @param int $index + * @return string + */ + private static function _mapBorderStyle($index) + { + switch ($index) { + case 0x00: return PHPExcel_Style_Border::BORDER_NONE; + case 0x01: return PHPExcel_Style_Border::BORDER_THIN; + case 0x02: return PHPExcel_Style_Border::BORDER_MEDIUM; + case 0x03: return PHPExcel_Style_Border::BORDER_DASHED; + case 0x04: return PHPExcel_Style_Border::BORDER_DOTTED; + case 0x05: return PHPExcel_Style_Border::BORDER_THICK; + case 0x06: return PHPExcel_Style_Border::BORDER_DOUBLE; + case 0x07: return PHPExcel_Style_Border::BORDER_HAIR; + case 0x08: return PHPExcel_Style_Border::BORDER_MEDIUMDASHED; + case 0x09: return PHPExcel_Style_Border::BORDER_DASHDOT; + case 0x0A: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; + case 0x0B: return PHPExcel_Style_Border::BORDER_DASHDOTDOT; + case 0x0C: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + case 0x0D: return PHPExcel_Style_Border::BORDER_SLANTDASHDOT; + default: return PHPExcel_Style_Border::BORDER_NONE; + } + } + + + /** + * Get fill pattern from index + * OpenOffice documentation: 2.5.12 + * + * @param int $index + * @return string + */ + private static function _mapFillPattern($index) + { + switch ($index) { + case 0x00: return PHPExcel_Style_Fill::FILL_NONE; + case 0x01: return PHPExcel_Style_Fill::FILL_SOLID; + case 0x02: return PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; + case 0x03: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; + case 0x04: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; + case 0x05: return PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; + case 0x06: return PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; + case 0x07: return PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; + case 0x08: return PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; + case 0x09: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; + case 0x0A: return PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; + case 0x0B: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; + case 0x0C: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; + case 0x0D: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; + case 0x0E: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; + case 0x0F: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; + case 0x10: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; + case 0x11: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; + case 0x12: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; + default: return PHPExcel_Style_Fill::FILL_NONE; + } + } + + + /** + * Map error code, e.g. '#N/A' + * + * @param int $subData + * @return string + */ + private static function _mapErrorCode($subData) + { + switch ($subData) { + case 0x00: return '#NULL!'; break; + case 0x07: return '#DIV/0!'; break; + case 0x0F: return '#VALUE!'; break; + case 0x17: return '#REF!'; break; + case 0x1D: return '#NAME?'; break; + case 0x24: return '#NUM!'; break; + case 0x2A: return '#N/A'; break; + default: return false; + } + } + + + /** + * Map built-in color to RGB value + * + * @param int $color Indexed color + * @return array + */ + private static function _mapBuiltInColor($color) + { + switch ($color) { + case 0x00: return array('rgb' => '000000'); + case 0x01: return array('rgb' => 'FFFFFF'); + case 0x02: return array('rgb' => 'FF0000'); + case 0x03: return array('rgb' => '00FF00'); + case 0x04: return array('rgb' => '0000FF'); + case 0x05: return array('rgb' => 'FFFF00'); + case 0x06: return array('rgb' => 'FF00FF'); + case 0x07: return array('rgb' => '00FFFF'); + case 0x40: return array('rgb' => '000000'); // system window text color + case 0x41: return array('rgb' => 'FFFFFF'); // system window background color + default: return array('rgb' => '000000'); + } + } + + + /** + * Map color array from BIFF5 built-in color index + * + * @param int $subData + * @return array + */ + private static function _mapColorBIFF5($subData) + { + switch ($subData) { + case 0x08: return array('rgb' => '000000'); + case 0x09: return array('rgb' => 'FFFFFF'); + case 0x0A: return array('rgb' => 'FF0000'); + case 0x0B: return array('rgb' => '00FF00'); + case 0x0C: return array('rgb' => '0000FF'); + case 0x0D: return array('rgb' => 'FFFF00'); + case 0x0E: return array('rgb' => 'FF00FF'); + case 0x0F: return array('rgb' => '00FFFF'); + case 0x10: return array('rgb' => '800000'); + case 0x11: return array('rgb' => '008000'); + case 0x12: return array('rgb' => '000080'); + case 0x13: return array('rgb' => '808000'); + case 0x14: return array('rgb' => '800080'); + case 0x15: return array('rgb' => '008080'); + case 0x16: return array('rgb' => 'C0C0C0'); + case 0x17: return array('rgb' => '808080'); + case 0x18: return array('rgb' => '8080FF'); + case 0x19: return array('rgb' => '802060'); + case 0x1A: return array('rgb' => 'FFFFC0'); + case 0x1B: return array('rgb' => 'A0E0F0'); + case 0x1C: return array('rgb' => '600080'); + case 0x1D: return array('rgb' => 'FF8080'); + case 0x1E: return array('rgb' => '0080C0'); + case 0x1F: return array('rgb' => 'C0C0FF'); + case 0x20: return array('rgb' => '000080'); + case 0x21: return array('rgb' => 'FF00FF'); + case 0x22: return array('rgb' => 'FFFF00'); + case 0x23: return array('rgb' => '00FFFF'); + case 0x24: return array('rgb' => '800080'); + case 0x25: return array('rgb' => '800000'); + case 0x26: return array('rgb' => '008080'); + case 0x27: return array('rgb' => '0000FF'); + case 0x28: return array('rgb' => '00CFFF'); + case 0x29: return array('rgb' => '69FFFF'); + case 0x2A: return array('rgb' => 'E0FFE0'); + case 0x2B: return array('rgb' => 'FFFF80'); + case 0x2C: return array('rgb' => 'A6CAF0'); + case 0x2D: return array('rgb' => 'DD9CB3'); + case 0x2E: return array('rgb' => 'B38FEE'); + case 0x2F: return array('rgb' => 'E3E3E3'); + case 0x30: return array('rgb' => '2A6FF9'); + case 0x31: return array('rgb' => '3FB8CD'); + case 0x32: return array('rgb' => '488436'); + case 0x33: return array('rgb' => '958C41'); + case 0x34: return array('rgb' => '8E5E42'); + case 0x35: return array('rgb' => 'A0627A'); + case 0x36: return array('rgb' => '624FAC'); + case 0x37: return array('rgb' => '969696'); + case 0x38: return array('rgb' => '1D2FBE'); + case 0x39: return array('rgb' => '286676'); + case 0x3A: return array('rgb' => '004500'); + case 0x3B: return array('rgb' => '453E01'); + case 0x3C: return array('rgb' => '6A2813'); + case 0x3D: return array('rgb' => '85396A'); + case 0x3E: return array('rgb' => '4A3285'); + case 0x3F: return array('rgb' => '424242'); + default: return array('rgb' => '000000'); + } + } + + + /** + * Map color array from BIFF8 built-in color index + * + * @param int $subData + * @return array + */ + private static function _mapColor($subData) + { + switch ($subData) { + case 0x08: return array('rgb' => '000000'); + case 0x09: return array('rgb' => 'FFFFFF'); + case 0x0A: return array('rgb' => 'FF0000'); + case 0x0B: return array('rgb' => '00FF00'); + case 0x0C: return array('rgb' => '0000FF'); + case 0x0D: return array('rgb' => 'FFFF00'); + case 0x0E: return array('rgb' => 'FF00FF'); + case 0x0F: return array('rgb' => '00FFFF'); + case 0x10: return array('rgb' => '800000'); + case 0x11: return array('rgb' => '008000'); + case 0x12: return array('rgb' => '000080'); + case 0x13: return array('rgb' => '808000'); + case 0x14: return array('rgb' => '800080'); + case 0x15: return array('rgb' => '008080'); + case 0x16: return array('rgb' => 'C0C0C0'); + case 0x17: return array('rgb' => '808080'); + case 0x18: return array('rgb' => '9999FF'); + case 0x19: return array('rgb' => '993366'); + case 0x1A: return array('rgb' => 'FFFFCC'); + case 0x1B: return array('rgb' => 'CCFFFF'); + case 0x1C: return array('rgb' => '660066'); + case 0x1D: return array('rgb' => 'FF8080'); + case 0x1E: return array('rgb' => '0066CC'); + case 0x1F: return array('rgb' => 'CCCCFF'); + case 0x20: return array('rgb' => '000080'); + case 0x21: return array('rgb' => 'FF00FF'); + case 0x22: return array('rgb' => 'FFFF00'); + case 0x23: return array('rgb' => '00FFFF'); + case 0x24: return array('rgb' => '800080'); + case 0x25: return array('rgb' => '800000'); + case 0x26: return array('rgb' => '008080'); + case 0x27: return array('rgb' => '0000FF'); + case 0x28: return array('rgb' => '00CCFF'); + case 0x29: return array('rgb' => 'CCFFFF'); + case 0x2A: return array('rgb' => 'CCFFCC'); + case 0x2B: return array('rgb' => 'FFFF99'); + case 0x2C: return array('rgb' => '99CCFF'); + case 0x2D: return array('rgb' => 'FF99CC'); + case 0x2E: return array('rgb' => 'CC99FF'); + case 0x2F: return array('rgb' => 'FFCC99'); + case 0x30: return array('rgb' => '3366FF'); + case 0x31: return array('rgb' => '33CCCC'); + case 0x32: return array('rgb' => '99CC00'); + case 0x33: return array('rgb' => 'FFCC00'); + case 0x34: return array('rgb' => 'FF9900'); + case 0x35: return array('rgb' => 'FF6600'); + case 0x36: return array('rgb' => '666699'); + case 0x37: return array('rgb' => '969696'); + case 0x38: return array('rgb' => '003366'); + case 0x39: return array('rgb' => '339966'); + case 0x3A: return array('rgb' => '003300'); + case 0x3B: return array('rgb' => '333300'); + case 0x3C: return array('rgb' => '993300'); + case 0x3D: return array('rgb' => '993366'); + case 0x3E: return array('rgb' => '333399'); + case 0x3F: return array('rgb' => '333333'); + default: return array('rgb' => '000000'); + } + } + + + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); + + $value->createText($is); + + return $value; + } } diff --git a/Classes/PHPExcel/Reader/Exception.php b/Classes/PHPExcel/Reader/Exception.php index c712fe0e..158b2075 100644 --- a/Classes/PHPExcel/Reader/Exception.php +++ b/Classes/PHPExcel/Reader/Exception.php @@ -21,8 +21,8 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ @@ -33,20 +33,22 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_Exception extends PHPExcel_Exception { - /** - * Error handler callback - * - * @param mixed $code - * @param mixed $string - * @param mixed $file - * @param mixed $line - * @param mixed $context - */ - public static function errorHandlerCallback($code, $string, $file, $line, $context) { - $e = new self($string, $code); - $e->line = $line; - $e->file = $file; - throw $e; - } +class PHPExcel_Reader_Exception extends PHPExcel_Exception +{ + /** + * Error handler callback + * + * @param mixed $code + * @param mixed $string + * @param mixed $file + * @param mixed $line + * @param mixed $context + */ + public static function errorHandlerCallback($code, $string, $file, $line, $context) + { + $e = new self($string, $code); + $e->line = $line; + $e->file = $file; + throw $e; + } } diff --git a/Classes/PHPExcel/Reader/Gnumeric.php b/Classes/PHPExcel/Reader/Gnumeric.php index 534a2143..1f7072f7 100644 --- a/Classes/PHPExcel/Reader/Gnumeric.php +++ b/Classes/PHPExcel/Reader/Gnumeric.php @@ -21,853 +21,853 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** * PHPExcel_Reader_Gnumeric * - * @category PHPExcel - * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Formats - * - * @var array - */ - private $_styles = array(); + /** + * Formats + * + * @var array + */ + private $_styles = array(); - /** - * Shared Expressions - * - * @var array - */ - private $_expressions = array(); + /** + * Shared Expressions + * + * @var array + */ + private $_expressions = array(); - private $_referenceHelper = null; + private $_referenceHelper = null; - /** - * Create a new PHPExcel_Reader_Gnumeric - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); - } + /** + * Create a new PHPExcel_Reader_Gnumeric + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); + } - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - // Check if gzlib functions are available - if (!function_exists('gzread')) { - throw new PHPExcel_Reader_Exception("gzlib library is not enabled"); - } + // Check if gzlib functions are available + if (!function_exists('gzread')) { + throw new PHPExcel_Reader_Exception("gzlib library is not enabled"); + } - // Read signature data (first 3 bytes) - $fh = fopen($pFilename, 'r'); - $data = fread($fh, 2); - fclose($fh); + // Read signature data (first 3 bytes) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2); + fclose($fh); - if ($data != chr(0x1F).chr(0x8B)) { - return false; - } + if ($data != chr(0x1F).chr(0x8B)) { + return false; + } - return true; - } + return true; + } - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $xml = new XMLReader(); - $xml->xml( - $this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions() - ); - $xml->setParserProperty(2,true); + $xml = new XMLReader(); + $xml->xml( + $this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions() + ); + $xml->setParserProperty(2,true); - $worksheetNames = array(); - while ($xml->read()) { - if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) { - $xml->read(); // Move onto the value node - $worksheetNames[] = (string) $xml->value; - } elseif ($xml->name == 'gnm:Sheets') { - // break out of the loop once we've got our sheet names rather than parse the entire file - break; - } - } + $worksheetNames = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $worksheetNames[] = (string) $xml->value; + } elseif ($xml->name == 'gnm:Sheets') { + // break out of the loop once we've got our sheet names rather than parse the entire file + break; + } + } - return $worksheetNames; - } + return $worksheetNames; + } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $xml = new XMLReader(); - $xml->xml( - $this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions() - ); - $xml->setParserProperty(2,true); + $xml = new XMLReader(); + $xml->xml( + $this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions() + ); + $xml->setParserProperty(2,true); - $worksheetInfo = array(); - while ($xml->read()) { - if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) { - $tmpInfo = array( - 'worksheetName' => '', - 'lastColumnLetter' => 'A', - 'lastColumnIndex' => 0, - 'totalRows' => 0, - 'totalColumns' => 0, - ); + $worksheetInfo = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) { + $tmpInfo = array( + 'worksheetName' => '', + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); - while ($xml->read()) { - if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) { - $xml->read(); // Move onto the value node - $tmpInfo['worksheetName'] = (string) $xml->value; - } elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) { - $xml->read(); // Move onto the value node - $tmpInfo['lastColumnIndex'] = (int) $xml->value; - $tmpInfo['totalColumns'] = (int) $xml->value + 1; - } elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) { - $xml->read(); // Move onto the value node - $tmpInfo['totalRows'] = (int) $xml->value + 1; - break; - } - } - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $worksheetInfo[] = $tmpInfo; - } - } + while ($xml->read()) { + if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['worksheetName'] = (string) $xml->value; + } elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['lastColumnIndex'] = (int) $xml->value; + $tmpInfo['totalColumns'] = (int) $xml->value + 1; + } elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['totalRows'] = (int) $xml->value + 1; + break; + } + } + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; + } + } - return $worksheetInfo; - } + return $worksheetInfo; + } - private function _gzfileGetContents($filename) { - $file = @gzopen($filename, 'rb'); - if ($file !== false) { - $data = ''; - while (!gzeof($file)) { - $data .= gzread($file, 1024); - } - gzclose($file); - } - return $data; - } + private function _gzfileGetContents($filename) { + $file = @gzopen($filename, 'rb'); + if ($file !== false) { + $data = ''; + while (!gzeof($file)) { + $data .= gzread($file, 1024); + } + gzclose($file); + } + return $data; + } - /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Create new PHPExcel - $objPHPExcel = new PHPExcel(); + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); - // Load into this instance - return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } - /** - * Loads PHPExcel from file into PHPExcel instance - * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $timezoneObj = new DateTimeZone('Europe/London'); - $GMT = new DateTimeZone('UTC'); + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); - $gFileData = $this->_gzfileGetContents($pFilename); + $gFileData = $this->_gzfileGetContents($pFilename); -// echo '<pre>'; -// echo htmlentities($gFileData,ENT_QUOTES,'UTF-8'); -// echo '</pre><hr />'; +// echo '<pre>'; +// echo htmlentities($gFileData,ENT_QUOTES,'UTF-8'); +// echo '</pre><hr />'; // - $xml = simplexml_load_string($this->securityScan($gFileData), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespacesMeta = $xml->getNamespaces(true); + $xml = simplexml_load_string($this->securityScan($gFileData), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesMeta = $xml->getNamespaces(true); -// var_dump($namespacesMeta); +// var_dump($namespacesMeta); // - $gnmXML = $xml->children($namespacesMeta['gnm']); + $gnmXML = $xml->children($namespacesMeta['gnm']); - $docProps = $objPHPExcel->getProperties(); - // Document Properties are held differently, depending on the version of Gnumeric - if (isset($namespacesMeta['office'])) { - $officeXML = $xml->children($namespacesMeta['office']); - $officeDocXML = $officeXML->{'document-meta'}; - $officeDocMetaXML = $officeDocXML->meta; + $docProps = $objPHPExcel->getProperties(); + // Document Properties are held differently, depending on the version of Gnumeric + if (isset($namespacesMeta['office'])) { + $officeXML = $xml->children($namespacesMeta['office']); + $officeDocXML = $officeXML->{'document-meta'}; + $officeDocMetaXML = $officeDocXML->meta; - foreach($officeDocMetaXML as $officePropertyData) { + foreach($officeDocMetaXML as $officePropertyData) { - $officePropertyDC = array(); - if (isset($namespacesMeta['dc'])) { - $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); - } - foreach($officePropertyDC as $propertyName => $propertyValue) { - $propertyValue = (string) $propertyValue; - switch ($propertyName) { - case 'title' : - $docProps->setTitle(trim($propertyValue)); - break; - case 'subject' : - $docProps->setSubject(trim($propertyValue)); - break; - case 'creator' : - $docProps->setCreator(trim($propertyValue)); - $docProps->setLastModifiedBy(trim($propertyValue)); - break; - case 'date' : - $creationDate = strtotime(trim($propertyValue)); - $docProps->setCreated($creationDate); - $docProps->setModified($creationDate); - break; - case 'description' : - $docProps->setDescription(trim($propertyValue)); - break; - } - } - $officePropertyMeta = array(); - if (isset($namespacesMeta['meta'])) { - $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); - } - foreach($officePropertyMeta as $propertyName => $propertyValue) { - $attributes = $propertyValue->attributes($namespacesMeta['meta']); - $propertyValue = (string) $propertyValue; - switch ($propertyName) { - case 'keyword' : - $docProps->setKeywords(trim($propertyValue)); - break; - case 'initial-creator' : - $docProps->setCreator(trim($propertyValue)); - $docProps->setLastModifiedBy(trim($propertyValue)); - break; - case 'creation-date' : - $creationDate = strtotime(trim($propertyValue)); - $docProps->setCreated($creationDate); - $docProps->setModified($creationDate); - break; - case 'user-defined' : - list(,$attrName) = explode(':',$attributes['name']); - switch ($attrName) { - case 'publisher' : - $docProps->setCompany(trim($propertyValue)); - break; - case 'category' : - $docProps->setCategory(trim($propertyValue)); - break; - case 'manager' : - $docProps->setManager(trim($propertyValue)); - break; - } - break; - } - } - } - } elseif (isset($gnmXML->Summary)) { - foreach($gnmXML->Summary->Item as $summaryItem) { - $propertyName = $summaryItem->name; - $propertyValue = $summaryItem->{'val-string'}; - switch ($propertyName) { - case 'title' : - $docProps->setTitle(trim($propertyValue)); - break; - case 'comments' : - $docProps->setDescription(trim($propertyValue)); - break; - case 'keywords' : - $docProps->setKeywords(trim($propertyValue)); - break; - case 'category' : - $docProps->setCategory(trim($propertyValue)); - break; - case 'manager' : - $docProps->setManager(trim($propertyValue)); - break; - case 'author' : - $docProps->setCreator(trim($propertyValue)); - $docProps->setLastModifiedBy(trim($propertyValue)); - break; - case 'company' : - $docProps->setCompany(trim($propertyValue)); - break; - } - } - } + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'title' : + $docProps->setTitle(trim($propertyValue)); + break; + case 'subject' : + $docProps->setSubject(trim($propertyValue)); + break; + case 'creator' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'description' : + $docProps->setDescription(trim($propertyValue)); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['meta'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $attributes = $propertyValue->attributes($namespacesMeta['meta']); + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'keyword' : + $docProps->setKeywords(trim($propertyValue)); + break; + case 'initial-creator' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'creation-date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'user-defined' : + list(,$attrName) = explode(':',$attributes['name']); + switch ($attrName) { + case 'publisher' : + $docProps->setCompany(trim($propertyValue)); + break; + case 'category' : + $docProps->setCategory(trim($propertyValue)); + break; + case 'manager' : + $docProps->setManager(trim($propertyValue)); + break; + } + break; + } + } + } + } elseif (isset($gnmXML->Summary)) { + foreach($gnmXML->Summary->Item as $summaryItem) { + $propertyName = $summaryItem->name; + $propertyValue = $summaryItem->{'val-string'}; + switch ($propertyName) { + case 'title' : + $docProps->setTitle(trim($propertyValue)); + break; + case 'comments' : + $docProps->setDescription(trim($propertyValue)); + break; + case 'keywords' : + $docProps->setKeywords(trim($propertyValue)); + break; + case 'category' : + $docProps->setCategory(trim($propertyValue)); + break; + case 'manager' : + $docProps->setManager(trim($propertyValue)); + break; + case 'author' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'company' : + $docProps->setCompany(trim($propertyValue)); + break; + } + } + } - $worksheetID = 0; - foreach($gnmXML->Sheets->Sheet as $sheet) { - $worksheetName = (string) $sheet->Name; -// echo '<b>Worksheet: ',$worksheetName,'</b><br />'; - if ((isset($this->_loadSheetsOnly)) && (!in_array($worksheetName, $this->_loadSheetsOnly))) { - continue; - } + $worksheetID = 0; + foreach($gnmXML->Sheets->Sheet as $sheet) { + $worksheetName = (string) $sheet->Name; +// echo '<b>Worksheet: ',$worksheetName,'</b><br />'; + if ((isset($this->_loadSheetsOnly)) && (!in_array($worksheetName, $this->_loadSheetsOnly))) { + continue; + } - $maxRow = $maxCol = 0; + $maxRow = $maxCol = 0; - // Create new Worksheet - $objPHPExcel->createSheet(); - $objPHPExcel->setActiveSheetIndex($worksheetID); - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula - // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet - // name in line with the formula, not the reverse - $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula + // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet + // name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); - if ((!$this->_readDataOnly) && (isset($sheet->PrintInformation))) { - if (isset($sheet->PrintInformation->Margins)) { - foreach($sheet->PrintInformation->Margins->children('gnm',TRUE) as $key => $margin) { - $marginAttributes = $margin->attributes(); - $marginSize = 72 / 100; // Default - switch($marginAttributes['PrefUnit']) { - case 'mm' : - $marginSize = intval($marginAttributes['Points']) / 100; - break; - } - switch($key) { - case 'top' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setTop($marginSize); - break; - case 'bottom' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom($marginSize); - break; - case 'left' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft($marginSize); - break; - case 'right' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setRight($marginSize); - break; - case 'header' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader($marginSize); - break; - case 'footer' : - $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter($marginSize); - break; - } - } - } - } + if ((!$this->_readDataOnly) && (isset($sheet->PrintInformation))) { + if (isset($sheet->PrintInformation->Margins)) { + foreach($sheet->PrintInformation->Margins->children('gnm',TRUE) as $key => $margin) { + $marginAttributes = $margin->attributes(); + $marginSize = 72 / 100; // Default + switch($marginAttributes['PrefUnit']) { + case 'mm' : + $marginSize = intval($marginAttributes['Points']) / 100; + break; + } + switch($key) { + case 'top' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setTop($marginSize); + break; + case 'bottom' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom($marginSize); + break; + case 'left' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft($marginSize); + break; + case 'right' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setRight($marginSize); + break; + case 'header' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader($marginSize); + break; + case 'footer' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter($marginSize); + break; + } + } + } + } - foreach($sheet->Cells->Cell as $cell) { - $cellAttributes = $cell->attributes(); - $row = (int) $cellAttributes->Row + 1; - $column = (int) $cellAttributes->Col; + foreach($sheet->Cells->Cell as $cell) { + $cellAttributes = $cell->attributes(); + $row = (int) $cellAttributes->Row + 1; + $column = (int) $cellAttributes->Col; - if ($row > $maxRow) $maxRow = $row; - if ($column > $maxCol) $maxCol = $column; + if ($row > $maxRow) $maxRow = $row; + if ($column > $maxCol) $maxCol = $column; - $column = PHPExcel_Cell::stringFromColumnIndex($column); + $column = PHPExcel_Cell::stringFromColumnIndex($column); - // Read cell? - if ($this->getReadFilter() !== NULL) { - if (!$this->getReadFilter()->readCell($column, $row, $worksheetName)) { - continue; - } - } + // Read cell? + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($column, $row, $worksheetName)) { + continue; + } + } - $ValueType = $cellAttributes->ValueType; - $ExprID = (string) $cellAttributes->ExprID; -// echo 'Cell ',$column,$row,'<br />'; -// echo 'Type is ',$ValueType,'<br />'; -// echo 'Value is ',$cell,'<br />'; - $type = PHPExcel_Cell_DataType::TYPE_FORMULA; - if ($ExprID > '') { - if (((string) $cell) > '') { + $ValueType = $cellAttributes->ValueType; + $ExprID = (string) $cellAttributes->ExprID; +// echo 'Cell ',$column,$row,'<br />'; +// echo 'Type is ',$ValueType,'<br />'; +// echo 'Value is ',$cell,'<br />'; + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + if ($ExprID > '') { + if (((string) $cell) > '') { - $this->_expressions[$ExprID] = array( 'column' => $cellAttributes->Col, - 'row' => $cellAttributes->Row, - 'formula' => (string) $cell - ); -// echo 'NEW EXPRESSION ',$ExprID,'<br />'; - } else { - $expression = $this->_expressions[$ExprID]; + $this->_expressions[$ExprID] = array( 'column' => $cellAttributes->Col, + 'row' => $cellAttributes->Row, + 'formula' => (string) $cell + ); +// echo 'NEW EXPRESSION ',$ExprID,'<br />'; + } else { + $expression = $this->_expressions[$ExprID]; - $cell = $this->_referenceHelper->updateFormulaReferences( $expression['formula'], - 'A1', - $cellAttributes->Col - $expression['column'], - $cellAttributes->Row - $expression['row'], - $worksheetName - ); -// echo 'SHARED EXPRESSION ',$ExprID,'<br />'; -// echo 'New Value is ',$cell,'<br />'; - } - $type = PHPExcel_Cell_DataType::TYPE_FORMULA; - } else { - switch($ValueType) { - case '10' : // NULL - $type = PHPExcel_Cell_DataType::TYPE_NULL; - break; - case '20' : // Boolean - $type = PHPExcel_Cell_DataType::TYPE_BOOL; - $cell = ($cell == 'TRUE') ? True : False; - break; - case '30' : // Integer - $cell = intval($cell); - case '40' : // Float - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - break; - case '50' : // Error - $type = PHPExcel_Cell_DataType::TYPE_ERROR; - break; - case '60' : // String - $type = PHPExcel_Cell_DataType::TYPE_STRING; - break; - case '70' : // Cell Range - case '80' : // Array - } - } - $objPHPExcel->getActiveSheet()->getCell($column.$row)->setValueExplicit($cell,$type); - } + $cell = $this->_referenceHelper->updateFormulaReferences( $expression['formula'], + 'A1', + $cellAttributes->Col - $expression['column'], + $cellAttributes->Row - $expression['row'], + $worksheetName + ); +// echo 'SHARED EXPRESSION ',$ExprID,'<br />'; +// echo 'New Value is ',$cell,'<br />'; + } + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + } else { + switch($ValueType) { + case '10' : // NULL + $type = PHPExcel_Cell_DataType::TYPE_NULL; + break; + case '20' : // Boolean + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cell = ($cell == 'TRUE') ? True : False; + break; + case '30' : // Integer + $cell = intval($cell); + case '40' : // Float + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + break; + case '50' : // Error + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + case '60' : // String + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case '70' : // Cell Range + case '80' : // Array + } + } + $objPHPExcel->getActiveSheet()->getCell($column.$row)->setValueExplicit($cell,$type); + } - if ((!$this->_readDataOnly) && (isset($sheet->Objects))) { - foreach($sheet->Objects->children('gnm',TRUE) as $key => $comment) { - $commentAttributes = $comment->attributes(); - // Only comment objects are handled at the moment - if ($commentAttributes->Text) { - $objPHPExcel->getActiveSheet()->getComment( (string)$commentAttributes->ObjectBound ) - ->setAuthor( (string)$commentAttributes->Author ) - ->setText($this->_parseRichText((string)$commentAttributes->Text) ); - } - } - } -// echo '$maxCol=',$maxCol,'; $maxRow=',$maxRow,'<br />'; + if ((!$this->_readDataOnly) && (isset($sheet->Objects))) { + foreach($sheet->Objects->children('gnm',TRUE) as $key => $comment) { + $commentAttributes = $comment->attributes(); + // Only comment objects are handled at the moment + if ($commentAttributes->Text) { + $objPHPExcel->getActiveSheet()->getComment( (string)$commentAttributes->ObjectBound ) + ->setAuthor( (string)$commentAttributes->Author ) + ->setText($this->_parseRichText((string)$commentAttributes->Text) ); + } + } + } +// echo '$maxCol=',$maxCol,'; $maxRow=',$maxRow,'<br />'; // - foreach($sheet->Styles->StyleRegion as $styleRegion) { - $styleAttributes = $styleRegion->attributes(); - if (($styleAttributes['startRow'] <= $maxRow) && - ($styleAttributes['startCol'] <= $maxCol)) { + foreach($sheet->Styles->StyleRegion as $styleRegion) { + $styleAttributes = $styleRegion->attributes(); + if (($styleAttributes['startRow'] <= $maxRow) && + ($styleAttributes['startCol'] <= $maxCol)) { - $startColumn = PHPExcel_Cell::stringFromColumnIndex((int) $styleAttributes['startCol']); - $startRow = $styleAttributes['startRow'] + 1; + $startColumn = PHPExcel_Cell::stringFromColumnIndex((int) $styleAttributes['startCol']); + $startRow = $styleAttributes['startRow'] + 1; - $endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol']; - $endColumn = PHPExcel_Cell::stringFromColumnIndex($endColumn); - $endRow = ($styleAttributes['endRow'] > $maxRow) ? $maxRow : $styleAttributes['endRow']; - $endRow += 1; - $cellRange = $startColumn.$startRow.':'.$endColumn.$endRow; -// echo $cellRange,'<br />'; + $endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol']; + $endColumn = PHPExcel_Cell::stringFromColumnIndex($endColumn); + $endRow = ($styleAttributes['endRow'] > $maxRow) ? $maxRow : $styleAttributes['endRow']; + $endRow += 1; + $cellRange = $startColumn.$startRow.':'.$endColumn.$endRow; +// echo $cellRange,'<br />'; - $styleAttributes = $styleRegion->Style->attributes(); -// var_dump($styleAttributes); -// echo '<br />'; + $styleAttributes = $styleRegion->Style->attributes(); +// var_dump($styleAttributes); +// echo '<br />'; - // We still set the number format mask for date/time values, even if _readDataOnly is true - if ((!$this->_readDataOnly) || - (PHPExcel_Shared_Date::isDateTimeFormatCode((string) $styleAttributes['Format']))) { - $styleArray = array(); - $styleArray['numberformat']['code'] = (string) $styleAttributes['Format']; - // If _readDataOnly is false, we set all formatting information - if (!$this->_readDataOnly) { - switch($styleAttributes['HAlign']) { - case '1' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; - break; - case '2' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_LEFT; - break; - case '4' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_RIGHT; - break; - case '8' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER; - break; - case '16' : - case '64' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS; - break; - case '32' : - $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY; - break; - } + // We still set the number format mask for date/time values, even if _readDataOnly is true + if ((!$this->_readDataOnly) || + (PHPExcel_Shared_Date::isDateTimeFormatCode((string) $styleAttributes['Format']))) { + $styleArray = array(); + $styleArray['numberformat']['code'] = (string) $styleAttributes['Format']; + // If _readDataOnly is false, we set all formatting information + if (!$this->_readDataOnly) { + switch($styleAttributes['HAlign']) { + case '1' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + break; + case '2' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_LEFT; + break; + case '4' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_RIGHT; + break; + case '8' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER; + break; + case '16' : + case '64' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS; + break; + case '32' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY; + break; + } - switch($styleAttributes['VAlign']) { - case '1' : - $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_TOP; - break; - case '2' : - $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; - break; - case '4' : - $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_CENTER; - break; - case '8' : - $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_JUSTIFY; - break; - } + switch($styleAttributes['VAlign']) { + case '1' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_TOP; + break; + case '2' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; + break; + case '4' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_CENTER; + break; + case '8' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_JUSTIFY; + break; + } - $styleArray['alignment']['wrap'] = ($styleAttributes['WrapText'] == '1') ? True : False; - $styleArray['alignment']['shrinkToFit'] = ($styleAttributes['ShrinkToFit'] == '1') ? True : False; - $styleArray['alignment']['indent'] = (intval($styleAttributes["Indent"]) > 0) ? $styleAttributes["indent"] : 0; + $styleArray['alignment']['wrap'] = ($styleAttributes['WrapText'] == '1') ? True : False; + $styleArray['alignment']['shrinkToFit'] = ($styleAttributes['ShrinkToFit'] == '1') ? True : False; + $styleArray['alignment']['indent'] = (intval($styleAttributes["Indent"]) > 0) ? $styleAttributes["indent"] : 0; - $RGB = self::_parseGnumericColour($styleAttributes["Fore"]); - $styleArray['font']['color']['rgb'] = $RGB; - $RGB = self::_parseGnumericColour($styleAttributes["Back"]); - $shade = $styleAttributes["Shade"]; - if (($RGB != '000000') || ($shade != '0')) { - $styleArray['fill']['color']['rgb'] = $styleArray['fill']['startcolor']['rgb'] = $RGB; - $RGB2 = self::_parseGnumericColour($styleAttributes["PatternColor"]); - $styleArray['fill']['endcolor']['rgb'] = $RGB2; - switch($shade) { - case '1' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_SOLID; - break; - case '2' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR; - break; - case '3' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_PATH; - break; - case '4' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; - break; - case '5' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; - break; - case '6' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; - break; - case '7' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; - break; - case '8' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; - break; - case '9' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; - break; - case '10' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; - break; - case '11' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; - break; - case '12' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; - break; - case '13' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; - break; - case '14' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; - break; - case '15' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; - break; - case '16' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; - break; - case '17' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; - break; - case '18' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; - break; - case '19' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; - break; - case '20' : - $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; - break; - } - } + $RGB = self::_parseGnumericColour($styleAttributes["Fore"]); + $styleArray['font']['color']['rgb'] = $RGB; + $RGB = self::_parseGnumericColour($styleAttributes["Back"]); + $shade = $styleAttributes["Shade"]; + if (($RGB != '000000') || ($shade != '0')) { + $styleArray['fill']['color']['rgb'] = $styleArray['fill']['startcolor']['rgb'] = $RGB; + $RGB2 = self::_parseGnumericColour($styleAttributes["PatternColor"]); + $styleArray['fill']['endcolor']['rgb'] = $RGB2; + switch($shade) { + case '1' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_SOLID; + break; + case '2' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR; + break; + case '3' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_PATH; + break; + case '4' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; + break; + case '5' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; + break; + case '6' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; + break; + case '7' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; + break; + case '8' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; + break; + case '9' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; + break; + case '10' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; + break; + case '11' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; + break; + case '12' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; + break; + case '13' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; + break; + case '14' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; + break; + case '15' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; + break; + case '16' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; + break; + case '17' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; + break; + case '18' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; + break; + case '19' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; + break; + case '20' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; + break; + } + } - $fontAttributes = $styleRegion->Style->Font->attributes(); -// var_dump($fontAttributes); -// echo '<br />'; - $styleArray['font']['name'] = (string) $styleRegion->Style->Font; - $styleArray['font']['size'] = intval($fontAttributes['Unit']); - $styleArray['font']['bold'] = ($fontAttributes['Bold'] == '1') ? True : False; - $styleArray['font']['italic'] = ($fontAttributes['Italic'] == '1') ? True : False; - $styleArray['font']['strike'] = ($fontAttributes['StrikeThrough'] == '1') ? True : False; - switch($fontAttributes['Underline']) { - case '1' : - $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLE; - break; - case '2' : - $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLE; - break; - case '3' : - $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING; - break; - case '4' : - $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING; - break; - default : - $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_NONE; - break; - } - switch($fontAttributes['Script']) { - case '1' : - $styleArray['font']['superScript'] = True; - break; - case '-1' : - $styleArray['font']['subScript'] = True; - break; - } + $fontAttributes = $styleRegion->Style->Font->attributes(); +// var_dump($fontAttributes); +// echo '<br />'; + $styleArray['font']['name'] = (string) $styleRegion->Style->Font; + $styleArray['font']['size'] = intval($fontAttributes['Unit']); + $styleArray['font']['bold'] = ($fontAttributes['Bold'] == '1') ? True : False; + $styleArray['font']['italic'] = ($fontAttributes['Italic'] == '1') ? True : False; + $styleArray['font']['strike'] = ($fontAttributes['StrikeThrough'] == '1') ? True : False; + switch($fontAttributes['Underline']) { + case '1' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLE; + break; + case '2' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLE; + break; + case '3' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING; + break; + case '4' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING; + break; + default : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_NONE; + break; + } + switch($fontAttributes['Script']) { + case '1' : + $styleArray['font']['superScript'] = True; + break; + case '-1' : + $styleArray['font']['subScript'] = True; + break; + } - if (isset($styleRegion->Style->StyleBorder)) { - if (isset($styleRegion->Style->StyleBorder->Top)) { - $styleArray['borders']['top'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Top->attributes()); - } - if (isset($styleRegion->Style->StyleBorder->Bottom)) { - $styleArray['borders']['bottom'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Bottom->attributes()); - } - if (isset($styleRegion->Style->StyleBorder->Left)) { - $styleArray['borders']['left'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Left->attributes()); - } - if (isset($styleRegion->Style->StyleBorder->Right)) { - $styleArray['borders']['right'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Right->attributes()); - } - if ((isset($styleRegion->Style->StyleBorder->Diagonal)) && (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}))) { - $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); - $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_BOTH; - } elseif (isset($styleRegion->Style->StyleBorder->Diagonal)) { - $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); - $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_UP; - } elseif (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'})) { - $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}->attributes()); - $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_DOWN; - } - } - if (isset($styleRegion->Style->HyperLink)) { - // TO DO - $hyperlink = $styleRegion->Style->HyperLink->attributes(); - } - } -// var_dump($styleArray); -// echo '<br />'; - $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($styleArray); - } - } - } + if (isset($styleRegion->Style->StyleBorder)) { + if (isset($styleRegion->Style->StyleBorder->Top)) { + $styleArray['borders']['top'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Top->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Bottom)) { + $styleArray['borders']['bottom'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Bottom->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Left)) { + $styleArray['borders']['left'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Left->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Right)) { + $styleArray['borders']['right'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Right->attributes()); + } + if ((isset($styleRegion->Style->StyleBorder->Diagonal)) && (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}))) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_BOTH; + } elseif (isset($styleRegion->Style->StyleBorder->Diagonal)) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_UP; + } elseif (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'})) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_DOWN; + } + } + if (isset($styleRegion->Style->HyperLink)) { + // TO DO + $hyperlink = $styleRegion->Style->HyperLink->attributes(); + } + } +// var_dump($styleArray); +// echo '<br />'; + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($styleArray); + } + } + } - if ((!$this->_readDataOnly) && (isset($sheet->Cols))) { - // Column Widths - $columnAttributes = $sheet->Cols->attributes(); - $defaultWidth = $columnAttributes['DefaultSizePts'] / 5.4; - $c = 0; - foreach($sheet->Cols->ColInfo as $columnOverride) { - $columnAttributes = $columnOverride->attributes(); - $column = $columnAttributes['No']; - $columnWidth = $columnAttributes['Unit'] / 5.4; - $hidden = ((isset($columnAttributes['Hidden'])) && ($columnAttributes['Hidden'] == '1')) ? true : false; - $columnCount = (isset($columnAttributes['Count'])) ? $columnAttributes['Count'] : 1; - while ($c < $column) { - $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); - ++$c; - } - while (($c < ($column+$columnCount)) && ($c <= $maxCol)) { - $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($columnWidth); - if ($hidden) { - $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setVisible(false); - } - ++$c; - } - } - while ($c <= $maxCol) { - $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); - ++$c; - } - } + if ((!$this->_readDataOnly) && (isset($sheet->Cols))) { + // Column Widths + $columnAttributes = $sheet->Cols->attributes(); + $defaultWidth = $columnAttributes['DefaultSizePts'] / 5.4; + $c = 0; + foreach($sheet->Cols->ColInfo as $columnOverride) { + $columnAttributes = $columnOverride->attributes(); + $column = $columnAttributes['No']; + $columnWidth = $columnAttributes['Unit'] / 5.4; + $hidden = ((isset($columnAttributes['Hidden'])) && ($columnAttributes['Hidden'] == '1')) ? true : false; + $columnCount = (isset($columnAttributes['Count'])) ? $columnAttributes['Count'] : 1; + while ($c < $column) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); + ++$c; + } + while (($c < ($column+$columnCount)) && ($c <= $maxCol)) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($columnWidth); + if ($hidden) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setVisible(false); + } + ++$c; + } + } + while ($c <= $maxCol) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); + ++$c; + } + } - if ((!$this->_readDataOnly) && (isset($sheet->Rows))) { - // Row Heights - $rowAttributes = $sheet->Rows->attributes(); - $defaultHeight = $rowAttributes['DefaultSizePts']; - $r = 0; + if ((!$this->_readDataOnly) && (isset($sheet->Rows))) { + // Row Heights + $rowAttributes = $sheet->Rows->attributes(); + $defaultHeight = $rowAttributes['DefaultSizePts']; + $r = 0; - foreach($sheet->Rows->RowInfo as $rowOverride) { - $rowAttributes = $rowOverride->attributes(); - $row = $rowAttributes['No']; - $rowHeight = $rowAttributes['Unit']; - $hidden = ((isset($rowAttributes['Hidden'])) && ($rowAttributes['Hidden'] == '1')) ? true : false; - $rowCount = (isset($rowAttributes['Count'])) ? $rowAttributes['Count'] : 1; - while ($r < $row) { - ++$r; - $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); - } - while (($r < ($row+$rowCount)) && ($r < $maxRow)) { - ++$r; - $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($rowHeight); - if ($hidden) { - $objPHPExcel->getActiveSheet()->getRowDimension($r)->setVisible(false); - } - } - } - while ($r < $maxRow) { - ++$r; - $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); - } - } + foreach($sheet->Rows->RowInfo as $rowOverride) { + $rowAttributes = $rowOverride->attributes(); + $row = $rowAttributes['No']; + $rowHeight = $rowAttributes['Unit']; + $hidden = ((isset($rowAttributes['Hidden'])) && ($rowAttributes['Hidden'] == '1')) ? true : false; + $rowCount = (isset($rowAttributes['Count'])) ? $rowAttributes['Count'] : 1; + while ($r < $row) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); + } + while (($r < ($row+$rowCount)) && ($r < $maxRow)) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($rowHeight); + if ($hidden) { + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setVisible(false); + } + } + } + while ($r < $maxRow) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); + } + } - // Handle Merged Cells in this worksheet - if (isset($sheet->MergedRegions)) { - foreach($sheet->MergedRegions->Merge as $mergeCells) { - if (strpos($mergeCells,':') !== FALSE) { - $objPHPExcel->getActiveSheet()->mergeCells($mergeCells); - } - } - } + // Handle Merged Cells in this worksheet + if (isset($sheet->MergedRegions)) { + foreach($sheet->MergedRegions->Merge as $mergeCells) { + if (strpos($mergeCells,':') !== FALSE) { + $objPHPExcel->getActiveSheet()->mergeCells($mergeCells); + } + } + } - $worksheetID++; - } + $worksheetID++; + } - // Loop through definedNames (global named ranges) - if (isset($gnmXML->Names)) { - foreach($gnmXML->Names->Name as $namedRange) { - $name = (string) $namedRange->name; - $range = (string) $namedRange->value; - if (stripos($range, '#REF!') !== false) { - continue; - } + // Loop through definedNames (global named ranges) + if (isset($gnmXML->Names)) { + foreach($gnmXML->Names->Name as $namedRange) { + $name = (string) $namedRange->name; + $range = (string) $namedRange->value; + if (stripos($range, '#REF!') !== false) { + continue; + } - $range = explode('!',$range); - $range[0] = trim($range[0],"'");; - if ($worksheet = $objPHPExcel->getSheetByName($range[0])) { - $extractedRange = str_replace('$', '', $range[1]); - $objPHPExcel->addNamedRange( new PHPExcel_NamedRange($name, $worksheet, $extractedRange) ); - } - } - } + $range = explode('!',$range); + $range[0] = trim($range[0],"'");; + if ($worksheet = $objPHPExcel->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $objPHPExcel->addNamedRange( new PHPExcel_NamedRange($name, $worksheet, $extractedRange) ); + } + } + } - // Return - return $objPHPExcel; - } + // Return + return $objPHPExcel; + } - private static function _parseBorderAttributes($borderAttributes) - { - $styleArray = array(); + private static function _parseBorderAttributes($borderAttributes) + { + $styleArray = array(); - if (isset($borderAttributes["Color"])) { - $RGB = self::_parseGnumericColour($borderAttributes["Color"]); - $styleArray['color']['rgb'] = $RGB; - } + if (isset($borderAttributes["Color"])) { + $RGB = self::_parseGnumericColour($borderAttributes["Color"]); + $styleArray['color']['rgb'] = $RGB; + } - switch ($borderAttributes["Style"]) { - case '0' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_NONE; - break; - case '1' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case '2' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; - break; - case '4' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHED; - break; - case '5' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_THICK; - break; - case '6' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOUBLE; - break; - case '7' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOTTED; - break; - case '9' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOT; - break; - case '10' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; - break; - case '11' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOTDOT; - break; - case '12' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; - break; - case '13' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; - break; - case '3' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_SLANTDASHDOT; - break; - case '8' : - $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHED; - break; - } - return $styleArray; - } + switch ($borderAttributes["Style"]) { + case '0' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_NONE; + break; + case '1' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case '2' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; + break; + case '4' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHED; + break; + case '5' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_THICK; + break; + case '6' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOUBLE; + break; + case '7' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOTTED; + break; + case '9' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOT; + break; + case '10' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; + break; + case '11' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOTDOT; + break; + case '12' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + break; + case '13' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + break; + case '3' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_SLANTDASHDOT; + break; + case '8' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHED; + break; + } + return $styleArray; + } - private function _parseRichText($is = '') { - $value = new PHPExcel_RichText(); + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); - $value->createText($is); + $value->createText($is); - return $value; - } + return $value; + } - private static function _parseGnumericColour($gnmColour) { - list($gnmR,$gnmG,$gnmB) = explode(':',$gnmColour); - $gnmR = substr(str_pad($gnmR,4,'0',STR_PAD_RIGHT),0,2); - $gnmG = substr(str_pad($gnmG,4,'0',STR_PAD_RIGHT),0,2); - $gnmB = substr(str_pad($gnmB,4,'0',STR_PAD_RIGHT),0,2); - $RGB = $gnmR.$gnmG.$gnmB; -// echo 'Excel Colour: ',$RGB,'<br />'; - return $RGB; - } + private static function _parseGnumericColour($gnmColour) { + list($gnmR,$gnmG,$gnmB) = explode(':',$gnmColour); + $gnmR = substr(str_pad($gnmR,4,'0',STR_PAD_RIGHT),0,2); + $gnmG = substr(str_pad($gnmG,4,'0',STR_PAD_RIGHT),0,2); + $gnmB = substr(str_pad($gnmB,4,'0',STR_PAD_RIGHT),0,2); + $RGB = $gnmR.$gnmG.$gnmB; +// echo 'Excel Colour: ',$RGB,'<br />'; + return $RGB; + } } diff --git a/Classes/PHPExcel/Reader/HTML.php b/Classes/PHPExcel/Reader/HTML.php index 68fd30c8..6b60f3f0 100644 --- a/Classes/PHPExcel/Reader/HTML.php +++ b/Classes/PHPExcel/Reader/HTML.php @@ -22,7 +22,7 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ @@ -67,38 +67,38 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ 'h1' => array('font' => array('bold' => true, 'size' => 24, ), - ), // Bold, 24pt + ), // Bold, 24pt 'h2' => array('font' => array('bold' => true, 'size' => 18, ), - ), // Bold, 18pt + ), // Bold, 18pt 'h3' => array('font' => array('bold' => true, 'size' => 13.5, ), - ), // Bold, 13.5pt + ), // Bold, 13.5pt 'h4' => array('font' => array('bold' => true, 'size' => 12, ), - ), // Bold, 12pt + ), // Bold, 12pt 'h5' => array('font' => array('bold' => true, 'size' => 10, ), - ), // Bold, 10pt + ), // Bold, 10pt 'h6' => array('font' => array('bold' => true, 'size' => 7.5, ), - ), // Bold, 7.5pt + ), // Bold, 7.5pt 'a' => array('font' => array('underline' => true, 'color' => array('argb' => PHPExcel_Style_Color::COLOR_BLUE, ), ), - ), // Blue underlined + ), // Blue underlined 'hr' => array('borders' => array('bottom' => array('style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array(\PHPExcel_Style_Color::COLOR_BLACK, ), ), ), - ), // Bottom border + ), // Bottom border ); protected $rowspan = array(); @@ -118,7 +118,7 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ */ protected function _isValidFormat() { - // Reading 2048 bytes should be enough to validate that the format is HTML + // Reading 2048 bytes should be enough to validate that the format is HTML $data = fread($this->_fileHandle, 2048); if ((strpos($data, '<') !== FALSE) && (strlen($data) !== strlen(strip_tags($data)))) { @@ -166,7 +166,7 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ return $this->_inputEncoding; } - // Data Array used for testing only, should write to PHPExcel object on completion of tests + // Data Array used for testing only, should write to PHPExcel object on completion of tests protected $_dataArray = array(); protected $_tableLevel = 0; protected $_nestedColumn = array('A'); @@ -196,18 +196,18 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ protected function _flushCell($sheet, $column, $row, &$cellContent) { if (is_string($cellContent)) { - // Simple String content + // Simple String content if (trim($cellContent) > '') { - // Only actually write it if there's content in the string -// echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '<br />'; - // Write to worksheet to be done here... - // ... we return the cell so we can mess about with styles more easily + // Only actually write it if there's content in the string +// echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '<br />'; + // Write to worksheet to be done here... + // ... we return the cell so we can mess about with styles more easily $sheet->setCellValue($column . $row, $cellContent, true); $this->_dataArray[$row][$column] = $cellContent; } } else { - // We have a Rich Text run - // TODO + // We have a Rich Text run + // TODO $this->_dataArray[$row][$column] = 'RICH TEXT: ' . $cellContent; } $cellContent = (string) ''; @@ -219,18 +219,18 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ if ($child instanceof DOMText) { $domText = preg_replace('/\s+/u', ' ', trim($child->nodeValue)); if (is_string($cellContent)) { - // simply append the text if the cell content is a plain text string + // simply append the text if the cell content is a plain text string $cellContent .= $domText; } else { - // but if we have a rich text run instead, we need to append it correctly - // TODO + // but if we have a rich text run instead, we need to append it correctly + // TODO } } elseif ($child instanceof DOMElement) { -// echo '<b>DOM ELEMENT: </b>' , strtoupper($child->nodeName) , '<br />'; +// echo '<b>DOM ELEMENT: </b>' , strtoupper($child->nodeName) , '<br />'; $attributeArray = array(); foreach ($child->attributes as $attribute) { -// echo '<b>ATTRIBUTE: </b>' , $attribute->name , ' => ' , $attribute->value , '<br />'; +// echo '<b>ATTRIBUTE: </b>' , $attribute->name , ' => ' , $attribute->value , '<br />'; $attributeArray[$attribute->name] = $attribute->value; } @@ -239,8 +239,8 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ foreach ($attributeArray as $attributeName => $attributeValue) { switch ($attributeName) { case 'content': - // TODO - // Extract character set, so we can convert to UTF-8 if required + // TODO + // Extract character set, so we can convert to UTF-8 if required break; } } @@ -258,13 +258,13 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ case 'em' : case 'strong': case 'b' : -// echo 'STYLING, SPAN OR DIV<br />'; +// echo 'STYLING, SPAN OR DIV<br />'; if ($cellContent > '') $cellContent .= ' '; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); if ($cellContent > '') $cellContent .= ' '; -// echo 'END OF STYLING, SPAN OR DIV<br />'; +// echo 'END OF STYLING, SPAN OR DIV<br />'; break; case 'hr' : $this->_flushCell($sheet, $column, $row, $cellContent); @@ -278,21 +278,21 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ ++$row; case 'br' : if ($this->_tableLevel > 0) { - // If we're inside a table, replace with a \n + // If we're inside a table, replace with a \n $cellContent .= "\n"; } else { - // Otherwise flush our existing content and move the row cursor on + // Otherwise flush our existing content and move the row cursor on $this->_flushCell($sheet, $column, $row, $cellContent); ++$row; } -// echo 'HARD LINE BREAK: ' , '<br />'; +// echo 'HARD LINE BREAK: ' , '<br />'; break; case 'a' : -// echo 'START OF HYPERLINK: ' , '<br />'; +// echo 'START OF HYPERLINK: ' , '<br />'; foreach ($attributeArray as $attributeName => $attributeValue) { switch ($attributeName) { case 'href': -// echo 'Link to ' , $attributeValue , '<br />'; +// echo 'Link to ' , $attributeValue , '<br />'; $sheet->getCell($column . $row)->getHyperlink()->setUrl($attributeValue); if (isset($this->_formats[$child->nodeName])) { $sheet->getStyle($column . $row)->applyFromArray($this->_formats[$child->nodeName]); @@ -302,7 +302,7 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ } $cellContent .= ' '; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF HYPERLINK:' , '<br />'; +// echo 'END OF HYPERLINK:' , '<br />'; break; case 'h1' : case 'h2' : @@ -314,19 +314,19 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ case 'ul' : case 'p' : if ($this->_tableLevel > 0) { - // If we're inside a table, replace with a \n + // If we're inside a table, replace with a \n $cellContent .= "\n"; -// echo 'LIST ENTRY: ' , '<br />'; +// echo 'LIST ENTRY: ' , '<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF LIST ENTRY:' , '<br />'; +// echo 'END OF LIST ENTRY:' , '<br />'; } else { if ($cellContent > '') { $this->_flushCell($sheet, $column, $row, $cellContent); $row++; } -// echo 'START OF PARAGRAPH: ' , '<br />'; +// echo 'START OF PARAGRAPH: ' , '<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF PARAGRAPH:' , '<br />'; +// echo 'END OF PARAGRAPH:' , '<br />'; $this->_flushCell($sheet, $column, $row, $cellContent); if (isset($this->_formats[$child->nodeName])) { @@ -339,19 +339,19 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ break; case 'li' : if ($this->_tableLevel > 0) { - // If we're inside a table, replace with a \n + // If we're inside a table, replace with a \n $cellContent .= "\n"; -// echo 'LIST ENTRY: ' , '<br />'; +// echo 'LIST ENTRY: ' , '<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF LIST ENTRY:' , '<br />'; +// echo 'END OF LIST ENTRY:' , '<br />'; } else { if ($cellContent > '') { $this->_flushCell($sheet, $column, $row, $cellContent); } ++$row; -// echo 'LIST ENTRY: ' , '<br />'; +// echo 'LIST ENTRY: ' , '<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF LIST ENTRY:' , '<br />'; +// echo 'END OF LIST ENTRY:' , '<br />'; $this->_flushCell($sheet, $column, $row, $cellContent); $column = 'A'; } @@ -359,11 +359,11 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ case 'table' : $this->_flushCell($sheet, $column, $row, $cellContent); $column = $this->_setTableStartColumn($column); -// echo 'START OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; +// echo 'START OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; if ($this->_tableLevel > 1) --$row; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; +// echo 'END OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; $column = $this->_releaseTableStartColumn(); if ($this->_tableLevel > 1) { ++$column; @@ -378,16 +378,16 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ case 'tr' : $column = $this->_getTableStartColumn(); $cellContent = ''; -// echo 'START OF TABLE ' , $this->_tableLevel , ' ROW<br />'; +// echo 'START OF TABLE ' , $this->_tableLevel , ' ROW<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); ++$row; -// echo 'END OF TABLE ' , $this->_tableLevel , ' ROW<br />'; +// echo 'END OF TABLE ' , $this->_tableLevel , ' ROW<br />'; break; case 'th' : case 'td' : -// echo 'START OF TABLE ' , $this->_tableLevel , ' CELL<br />'; +// echo 'START OF TABLE ' , $this->_tableLevel , ' CELL<br />'; $this->_processDomElement($child, $sheet, $row, $column, $cellContent); -// echo 'END OF TABLE ' , $this->_tableLevel , ' CELL<br />'; +// echo 'END OF TABLE ' , $this->_tableLevel , ' CELL<br />'; while (isset($this->rowspan[$column . $row])) { ++$column; @@ -463,7 +463,7 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ fclose($this->_fileHandle); throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid HTML file."); } - // Close after validating + // Close after validating fclose($this->_fileHandle); // Create new PHPExcel @@ -472,15 +472,15 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ } $objPHPExcel->setActiveSheetIndex($this->_sheetIndex); - // Create a new DOM object + // Create a new DOM object $dom = new domDocument; - // Reload the HTML file into the DOM object + // Reload the HTML file into the DOM object $loaded = $dom->loadHTML($this->securityScanFile($pFilename)); if ($loaded === FALSE) { throw new PHPExcel_Reader_Exception('Failed to load ', $pFilename, ' as a DOM Document'); } - // Discard white space + // Discard white space $dom->preserveWhiteSpace = false; $row = 0; @@ -488,7 +488,7 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ $content = ''; $this->_processDomElement($dom, $objPHPExcel->getActiveSheet(), $row, $column, $content); - // Return + // Return return $objPHPExcel; } @@ -515,14 +515,14 @@ class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_ return $this; } - /** - * Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks - * - * @param string $xml - * @throws PHPExcel_Reader_Exception - */ - public function securityScan($xml) - { + /** + * Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks + * + * @param string $xml + * @throws PHPExcel_Reader_Exception + */ + public function securityScan($xml) + { $pattern = '/\\0?' . implode('\\0?', str_split('<!ENTITY')) . '\\0?/'; if (preg_match($pattern, $xml)) { throw new PHPExcel_Reader_Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'); diff --git a/Classes/PHPExcel/Reader/IReadFilter.php b/Classes/PHPExcel/Reader/IReadFilter.php index f20dd97a..0006cf3d 100644 --- a/Classes/PHPExcel/Reader/IReadFilter.php +++ b/Classes/PHPExcel/Reader/IReadFilter.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Reader_IReadFilter * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,27 +22,18 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Reader_IReadFilter - * - * @category PHPExcel - * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ interface PHPExcel_Reader_IReadFilter { - /** - * Should this cell be read? - * - * @param $column String column index - * @param $row Row index - * @param $worksheetName Optional worksheet name - * @return boolean - */ - public function readCell($column, $row, $worksheetName = ''); + /** + * Should this cell be read? + * + * @param $column String column index + * @param $row Row index + * @param $worksheetName Optional worksheet name + * @return boolean + */ + public function readCell($column, $row, $worksheetName = ''); } diff --git a/Classes/PHPExcel/Reader/IReader.php b/Classes/PHPExcel/Reader/IReader.php index bc3a4bd8..79d098f8 100644 --- a/Classes/PHPExcel/Reader/IReader.php +++ b/Classes/PHPExcel/Reader/IReader.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,20 +35,20 @@ */ interface PHPExcel_Reader_IReader { - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - */ - public function canRead($pFilename); + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + */ + public function canRead($pFilename); - /** - * Loads PHPExcel from file - * - * @param string $pFilename + /** + * Loads PHPExcel from file + * + * @param string $pFilename * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename); + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename); } diff --git a/Classes/PHPExcel/Reader/OOCalc.php b/Classes/PHPExcel/Reader/OOCalc.php index 888aefb6..663bc813 100644 --- a/Classes/PHPExcel/Reader/OOCalc.php +++ b/Classes/PHPExcel/Reader/OOCalc.php @@ -21,691 +21,691 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** * PHPExcel_Reader_OOCalc * - * @category PHPExcel - * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_OOCalc extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Formats - * - * @var array - */ - private $_styles = array(); + /** + * Formats + * + * @var array + */ + private $_styles = array(); - /** - * Create a new PHPExcel_Reader_OOCalc - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } + /** + * Create a new PHPExcel_Reader_OOCalc + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } - /** - * Can the current PHPExcel_Reader_IReader read the file? - * - * @param string $pFilename - * @return boolean - * @throws PHPExcel_Reader_Exception - */ - public function canRead($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } $zipClass = PHPExcel_Settings::getZipClass(); - // Check if zip class exists -// if (!class_exists($zipClass, FALSE)) { -// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); -// } + // Check if zip class exists +// if (!class_exists($zipClass, FALSE)) { +// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); +// } $mimeType = 'UNKNOWN'; - // Load file - $zip = new $zipClass; - if ($zip->open($pFilename) === true) { - // check if it is an OOXML archive - $stat = $zip->statName('mimetype'); - if ($stat && ($stat['size'] <= 255)) { - $mimeType = $zip->getFromName($stat['name']); - } elseif($stat = $zip->statName('META-INF/manifest.xml')) { - $xml = simplexml_load_string($this->securityScan($zip->getFromName('META-INF/manifest.xml')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespacesContent = $xml->getNamespaces(true); - if (isset($namespacesContent['manifest'])) { - $manifest = $xml->children($namespacesContent['manifest']); - foreach($manifest as $manifestDataSet) { - $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); - if ($manifestAttributes->{'full-path'} == '/') { - $mimeType = (string) $manifestAttributes->{'media-type'}; - break; - } - } - } - } + // Load file + $zip = new $zipClass; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $stat = $zip->statName('mimetype'); + if ($stat && ($stat['size'] <= 255)) { + $mimeType = $zip->getFromName($stat['name']); + } elseif($stat = $zip->statName('META-INF/manifest.xml')) { + $xml = simplexml_load_string($this->securityScan($zip->getFromName('META-INF/manifest.xml')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesContent = $xml->getNamespaces(true); + if (isset($namespacesContent['manifest'])) { + $manifest = $xml->children($namespacesContent['manifest']); + foreach($manifest as $manifestDataSet) { + $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); + if ($manifestAttributes->{'full-path'} == '/') { + $mimeType = (string) $manifestAttributes->{'media-type'}; + break; + } + } + } + } - $zip->close(); + $zip->close(); - return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet'); - } + return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet'); + } - return FALSE; - } + return FALSE; + } - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - if (!$zip->open($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); - } + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } - $worksheetNames = array(); + $worksheetNames = array(); - $xml = new XMLReader(); - $res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions()); - $xml->setParserProperty(2,true); + $xml = new XMLReader(); + $res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); - // Step into the first level of content of the XML - $xml->read(); - while ($xml->read()) { - // Quickly jump through to the office:body node - while ($xml->name !== 'office:body') { - if ($xml->isEmptyElement) - $xml->read(); - else - $xml->next(); - } - // Now read each node until we find our first table:table node - while ($xml->read()) { - if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { - // Loop through each table:table node reading the table:name attribute for each worksheet name - do { - $worksheetNames[] = $xml->getAttribute('table:name'); - $xml->next(); - } while ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT); - } - } - } + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + // Loop through each table:table node reading the table:name attribute for each worksheet name + do { + $worksheetNames[] = $xml->getAttribute('table:name'); + $xml->next(); + } while ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT); + } + } + } - return $worksheetNames; - } + return $worksheetNames; + } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $worksheetInfo = array(); + $worksheetInfo = array(); $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - if (!$zip->open($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); - } + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } - $xml = new XMLReader(); - $res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions()); - $xml->setParserProperty(2,true); + $xml = new XMLReader(); + $res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); - // Step into the first level of content of the XML - $xml->read(); - while ($xml->read()) { - // Quickly jump through to the office:body node - while ($xml->name !== 'office:body') { - if ($xml->isEmptyElement) - $xml->read(); - else - $xml->next(); - } - // Now read each node until we find our first table:table node - while ($xml->read()) { - if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { - $worksheetNames[] = $xml->getAttribute('table:name'); + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + $worksheetNames[] = $xml->getAttribute('table:name'); - $tmpInfo = array( - 'worksheetName' => $xml->getAttribute('table:name'), - 'lastColumnLetter' => 'A', - 'lastColumnIndex' => 0, - 'totalRows' => 0, - 'totalColumns' => 0, - ); + $tmpInfo = array( + 'worksheetName' => $xml->getAttribute('table:name'), + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); - // Loop through each child node of the table:table element reading - $currCells = 0; - do { - $xml->read(); - if ($xml->name == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) { - $rowspan = $xml->getAttribute('table:number-rows-repeated'); - $rowspan = empty($rowspan) ? 1 : $rowspan; - $tmpInfo['totalRows'] += $rowspan; - $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); - $currCells = 0; - // Step into the row - $xml->read(); - do { - if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) { - if (!$xml->isEmptyElement) { - $currCells++; - $xml->next(); - } else { - $xml->read(); - } - } elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) { - $mergeSize = $xml->getAttribute('table:number-columns-repeated'); - $currCells += $mergeSize; - $xml->read(); - } - } while ($xml->name != 'table:table-row'); - } - } while ($xml->name != 'table:table'); + // Loop through each child node of the table:table element reading + $currCells = 0; + do { + $xml->read(); + if ($xml->name == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) { + $rowspan = $xml->getAttribute('table:number-rows-repeated'); + $rowspan = empty($rowspan) ? 1 : $rowspan; + $tmpInfo['totalRows'] += $rowspan; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + // Step into the row + $xml->read(); + do { + if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + if (!$xml->isEmptyElement) { + $currCells++; + $xml->next(); + } else { + $xml->read(); + } + } elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + $mergeSize = $xml->getAttribute('table:number-columns-repeated'); + $currCells += $mergeSize; + $xml->read(); + } + } while ($xml->name != 'table:table-row'); + } + } while ($xml->name != 'table:table'); - $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); - $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $worksheetInfo[] = $tmpInfo; - } - } + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; + } + } -// foreach($workbookData->table as $worksheetDataSet) { -// $worksheetData = $worksheetDataSet->children($namespacesContent['table']); -// $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// foreach($workbookData->table as $worksheetDataSet) { +// $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); // -// $rowIndex = 0; -// foreach ($worksheetData as $key => $rowData) { -// switch ($key) { -// case 'table-row' : -// $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); -// $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? -// $rowDataTableAttributes['number-rows-repeated'] : 1; -// $columnIndex = 0; +// $rowIndex = 0; +// foreach ($worksheetData as $key => $rowData) { +// switch ($key) { +// case 'table-row' : +// $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); +// $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? +// $rowDataTableAttributes['number-rows-repeated'] : 1; +// $columnIndex = 0; // -// foreach ($rowData as $key => $cellData) { -// $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); -// $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? -// $cellDataTableAttributes['number-columns-repeated'] : 1; -// $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); -// if (isset($cellDataOfficeAttributes['value-type'])) { -// $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); -// $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); -// } -// $columnIndex += $colRepeats; -// } -// $rowIndex += $rowRepeats; -// break; -// } -// } +// foreach ($rowData as $key => $cellData) { +// $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); +// $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? +// $cellDataTableAttributes['number-columns-repeated'] : 1; +// $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); +// if (isset($cellDataOfficeAttributes['value-type'])) { +// $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); +// $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); +// } +// $columnIndex += $colRepeats; +// } +// $rowIndex += $rowRepeats; +// break; +// } +// } // -// $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); -// $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; +// $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); +// $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; // -// } -// } - } +// } +// } + } - return $worksheetInfo; - } + return $worksheetInfo; + } - /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Create new PHPExcel - $objPHPExcel = new PHPExcel(); + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); - // Load into this instance - return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } - private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { - $styleAttributeValue = strtolower($styleAttributeValue); - foreach($styleList as $style) { - if ($styleAttributeValue == strtolower($style)) { - $styleAttributeValue = $style; - return true; - } - } - return false; - } + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } - /** - * Loads PHPExcel from file into PHPExcel instance - * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } - $timezoneObj = new DateTimeZone('Europe/London'); - $GMT = new DateTimeZone('UTC'); + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); $zipClass = PHPExcel_Settings::getZipClass(); - $zip = new $zipClass; - if (!$zip->open($pFilename)) { - throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); - } + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } -// echo '<h1>Meta Information</h1>'; - $xml = simplexml_load_string($this->securityScan($zip->getFromName("meta.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespacesMeta = $xml->getNamespaces(true); -// echo '<pre>'; -// print_r($namespacesMeta); -// echo '</pre><hr />'; +// echo '<h1>Meta Information</h1>'; + $xml = simplexml_load_string($this->securityScan($zip->getFromName("meta.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesMeta = $xml->getNamespaces(true); +// echo '<pre>'; +// print_r($namespacesMeta); +// echo '</pre><hr />'; - $docProps = $objPHPExcel->getProperties(); - $officeProperty = $xml->children($namespacesMeta['office']); - foreach($officeProperty as $officePropertyData) { - $officePropertyDC = array(); - if (isset($namespacesMeta['dc'])) { - $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); - } - foreach($officePropertyDC as $propertyName => $propertyValue) { - $propertyValue = (string) $propertyValue; - switch ($propertyName) { - case 'title' : - $docProps->setTitle($propertyValue); - break; - case 'subject' : - $docProps->setSubject($propertyValue); - break; - case 'creator' : - $docProps->setCreator($propertyValue); - $docProps->setLastModifiedBy($propertyValue); - break; - case 'date' : - $creationDate = strtotime($propertyValue); - $docProps->setCreated($creationDate); - $docProps->setModified($creationDate); - break; - case 'description' : - $docProps->setDescription($propertyValue); - break; - } - } - $officePropertyMeta = array(); - if (isset($namespacesMeta['dc'])) { - $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); - } - foreach($officePropertyMeta as $propertyName => $propertyValue) { - $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); - $propertyValue = (string) $propertyValue; - switch ($propertyName) { - case 'initial-creator' : - $docProps->setCreator($propertyValue); - break; - case 'keyword' : - $docProps->setKeywords($propertyValue); - break; - case 'creation-date' : - $creationDate = strtotime($propertyValue); - $docProps->setCreated($creationDate); - break; - case 'user-defined' : - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; - foreach ($propertyValueAttributes as $key => $value) { - if ($key == 'name') { - $propertyValueName = (string) $value; - } elseif($key == 'value-type') { - switch ($value) { - case 'date' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; - break; - case 'boolean' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; - break; - case 'float' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; - break; - default : - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; - } - } - } - $docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType); - break; - } - } - } + $docProps = $objPHPExcel->getProperties(); + $officeProperty = $xml->children($namespacesMeta['office']); + foreach($officeProperty as $officePropertyData) { + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'title' : + $docProps->setTitle($propertyValue); + break; + case 'subject' : + $docProps->setSubject($propertyValue); + break; + case 'creator' : + $docProps->setCreator($propertyValue); + $docProps->setLastModifiedBy($propertyValue); + break; + case 'date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'description' : + $docProps->setDescription($propertyValue); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'initial-creator' : + $docProps->setCreator($propertyValue); + break; + case 'keyword' : + $docProps->setKeywords($propertyValue); + break; + case 'creation-date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'user-defined' : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + foreach ($propertyValueAttributes as $key => $value) { + if ($key == 'name') { + $propertyValueName = (string) $value; + } elseif($key == 'value-type') { + switch ($value) { + case 'date' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; + break; + case 'boolean' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; + break; + case 'float' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; + break; + default : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + } + } + } + $docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType); + break; + } + } + } -// echo '<h1>Workbook Content</h1>'; - $xml = simplexml_load_string($this->securityScan($zip->getFromName("content.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); - $namespacesContent = $xml->getNamespaces(true); -// echo '<pre>'; -// print_r($namespacesContent); -// echo '</pre><hr />'; +// echo '<h1>Workbook Content</h1>'; + $xml = simplexml_load_string($this->securityScan($zip->getFromName("content.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesContent = $xml->getNamespaces(true); +// echo '<pre>'; +// print_r($namespacesContent); +// echo '</pre><hr />'; - $workbook = $xml->children($namespacesContent['office']); - foreach($workbook->body->spreadsheet as $workbookData) { - $workbookData = $workbookData->children($namespacesContent['table']); - $worksheetID = 0; - foreach($workbookData->table as $worksheetDataSet) { - $worksheetData = $worksheetDataSet->children($namespacesContent['table']); -// print_r($worksheetData); -// echo '<br />'; - $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); -// print_r($worksheetDataAttributes); -// echo '<br />'; - if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && - (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { - continue; - } + $workbook = $xml->children($namespacesContent['office']); + foreach($workbook->body->spreadsheet as $workbookData) { + $workbookData = $workbookData->children($namespacesContent['table']); + $worksheetID = 0; + foreach($workbookData->table as $worksheetDataSet) { + $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// print_r($worksheetData); +// echo '<br />'; + $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// print_r($worksheetDataAttributes); +// echo '<br />'; + if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && + (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { + continue; + } -// echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>'; - // Create new Worksheet - $objPHPExcel->createSheet(); - $objPHPExcel->setActiveSheetIndex($worksheetID); - if (isset($worksheetDataAttributes['name'])) { - $worksheetName = (string) $worksheetDataAttributes['name']; - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in - // formula cells... during the load, all formulae should be correct, and we're simply - // bringing the worksheet name in line with the formula, not the reverse - $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); - } +// echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>'; + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheetDataAttributes['name'])) { + $worksheetName = (string) $worksheetDataAttributes['name']; + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in + // formula cells... during the load, all formulae should be correct, and we're simply + // bringing the worksheet name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + } - $rowID = 1; - foreach($worksheetData as $key => $rowData) { -// echo '<b>'.$key.'</b><br />'; - switch ($key) { - case 'table-header-rows': - foreach ($rowData as $key=>$cellData) { - $rowData = $cellData; - break; - } - case 'table-row' : - $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); - $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? - $rowDataTableAttributes['number-rows-repeated'] : 1; - $columnID = 'A'; - foreach($rowData as $key => $cellData) { - if ($this->getReadFilter() !== NULL) { - if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { - continue; - } - } + $rowID = 1; + foreach($worksheetData as $key => $rowData) { +// echo '<b>'.$key.'</b><br />'; + switch ($key) { + case 'table-header-rows': + foreach ($rowData as $key=>$cellData) { + $rowData = $cellData; + break; + } + case 'table-row' : + $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); + $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? + $rowDataTableAttributes['number-rows-repeated'] : 1; + $columnID = 'A'; + foreach($rowData as $key => $cellData) { + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { + continue; + } + } -// echo '<b>'.$columnID.$rowID.'</b><br />'; - $cellDataText = (isset($namespacesContent['text'])) ? - $cellData->children($namespacesContent['text']) : - ''; - $cellDataOffice = $cellData->children($namespacesContent['office']); - $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); - $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); +// echo '<b>'.$columnID.$rowID.'</b><br />'; + $cellDataText = (isset($namespacesContent['text'])) ? + $cellData->children($namespacesContent['text']) : + ''; + $cellDataOffice = $cellData->children($namespacesContent['office']); + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); -// echo 'Office Attributes: '; -// print_r($cellDataOfficeAttributes); -// echo '<br />Table Attributes: '; -// print_r($cellDataTableAttributes); -// echo '<br />Cell Data Text'; -// print_r($cellDataText); -// echo '<br />'; +// echo 'Office Attributes: '; +// print_r($cellDataOfficeAttributes); +// echo '<br />Table Attributes: '; +// print_r($cellDataTableAttributes); +// echo '<br />Cell Data Text'; +// print_r($cellDataText); +// echo '<br />'; // - $type = $formatting = $hyperlink = null; - $hasCalculatedValue = false; - $cellDataFormula = ''; - if (isset($cellDataTableAttributes['formula'])) { - $cellDataFormula = $cellDataTableAttributes['formula']; - $hasCalculatedValue = true; - } + $type = $formatting = $hyperlink = null; + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cellDataTableAttributes['formula'])) { + $cellDataFormula = $cellDataTableAttributes['formula']; + $hasCalculatedValue = true; + } - if (isset($cellDataOffice->annotation)) { -// echo 'Cell has comment<br />'; - $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']); - $textArray = array(); - foreach($annotationText as $t) { - if (isset($t->span)) { - foreach($t->span as $text) { - $textArray[] = (string)$text; - } - } else { - $textArray[] = (string) $t; - } - } - $text = implode("\n",$textArray); -// echo $text,'<br />'; - $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) -// ->setAuthor( $author ) - ->setText($this->_parseRichText($text) ); - } + if (isset($cellDataOffice->annotation)) { +// echo 'Cell has comment<br />'; + $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']); + $textArray = array(); + foreach($annotationText as $t) { + if (isset($t->span)) { + foreach($t->span as $text) { + $textArray[] = (string)$text; + } + } else { + $textArray[] = (string) $t; + } + } + $text = implode("\n",$textArray); +// echo $text,'<br />'; + $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) +// ->setAuthor( $author ) + ->setText($this->_parseRichText($text) ); + } - if (isset($cellDataText->p)) { - // Consolidate if there are multiple p records (maybe with spans as well) - $dataArray = array(); - // Text can have multiple text:p and within those, multiple text:span. - // text:p newlines, but text:span does not. - // Also, here we assume there is no text data is span fields are specified, since - // we have no way of knowing proper positioning anyway. - foreach ($cellDataText->p as $pData) { - if (isset($pData->span)) { - // span sections do not newline, so we just create one large string here - $spanSection = ""; - foreach ($pData->span as $spanData) { - $spanSection .= $spanData; - } - array_push($dataArray, $spanSection); - } else { - array_push($dataArray, $pData); - } - } - $allCellDataText = implode($dataArray, "\n"); + if (isset($cellDataText->p)) { + // Consolidate if there are multiple p records (maybe with spans as well) + $dataArray = array(); + // Text can have multiple text:p and within those, multiple text:span. + // text:p newlines, but text:span does not. + // Also, here we assume there is no text data is span fields are specified, since + // we have no way of knowing proper positioning anyway. + foreach ($cellDataText->p as $pData) { + if (isset($pData->span)) { + // span sections do not newline, so we just create one large string here + $spanSection = ""; + foreach ($pData->span as $spanData) { + $spanSection .= $spanData; + } + array_push($dataArray, $spanSection); + } else { + array_push($dataArray, $pData); + } + } + $allCellDataText = implode($dataArray, "\n"); -// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />'; - switch ($cellDataOfficeAttributes['value-type']) { - case 'string' : - $type = PHPExcel_Cell_DataType::TYPE_STRING; - $dataValue = $allCellDataText; - if (isset($dataValue->a)) { - $dataValue = $dataValue->a; - $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); - $hyperlink = $cellXLinkAttributes['href']; - } - break; - case 'boolean' : - $type = PHPExcel_Cell_DataType::TYPE_BOOL; - $dataValue = ($allCellDataText == 'TRUE') ? True : False; - break; - case 'percentage' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - $dataValue = (integer) $dataValue; - } - $formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00; - break; - case 'currency' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - $dataValue = (integer) $dataValue; - } - $formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; - break; - case 'float' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - if ($dataValue == (integer) $dataValue) - $dataValue = (integer) $dataValue; - else - $dataValue = (float) $dataValue; - } - break; - case 'date' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT); - $dateObj->setTimeZone($timezoneObj); - list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); - $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); - if ($dataValue != floor($dataValue)) { - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; - } else { - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; - } - break; - case 'time' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; - break; - } -// echo 'Data value is '.$dataValue.'<br />'; -// if ($hyperlink !== NULL) { -// echo 'Hyperlink is '.$hyperlink.'<br />'; -// } - } else { - $type = PHPExcel_Cell_DataType::TYPE_NULL; - $dataValue = NULL; - } +// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />'; + switch ($cellDataOfficeAttributes['value-type']) { + case 'string' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + $dataValue = $allCellDataText; + if (isset($dataValue->a)) { + $dataValue = $dataValue->a; + $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); + $hyperlink = $cellXLinkAttributes['href']; + } + break; + case 'boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $dataValue = ($allCellDataText == 'TRUE') ? True : False; + break; + case 'percentage' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00; + break; + case 'currency' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; + break; + case 'float' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + if ($dataValue == (integer) $dataValue) + $dataValue = (integer) $dataValue; + else + $dataValue = (float) $dataValue; + } + break; + case 'date' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT); + $dateObj->setTimeZone($timezoneObj); + list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); + $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); + if ($dataValue != floor($dataValue)) { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + } else { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; + } + break; + case 'time' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + break; + } +// echo 'Data value is '.$dataValue.'<br />'; +// if ($hyperlink !== NULL) { +// echo 'Hyperlink is '.$hyperlink.'<br />'; +// } + } else { + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $dataValue = NULL; + } - if ($hasCalculatedValue) { - $type = PHPExcel_Cell_DataType::TYPE_FORMULA; -// echo 'Formula: ', $cellDataFormula, PHP_EOL; - $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); - $temp = explode('"',$cellDataFormula); - $tKey = false; - foreach($temp as &$value) { - // Only replace in alternate array entries (i.e. non-quoted blocks) - if ($tKey = !$tKey) { - $value = preg_replace('/\[([^\.]+)\.([^\.]+):\.([^\.]+)\]/Ui','$1!$2:$3',$value); // Cell range reference in another sheet - $value = preg_replace('/\[([^\.]+)\.([^\.]+)\]/Ui','$1!$2',$value); // Cell reference in another sheet - $value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/Ui','$1:$2',$value); // Cell range reference - $value = preg_replace('/\[\.([^\.]+)\]/Ui','$1',$value); // Simple cell reference - $value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces); - } - } - unset($value); - // Then rebuild the formula string - $cellDataFormula = implode('"',$temp); -// echo 'Adjusted Formula: ', $cellDataFormula, PHP_EOL; - } + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; +// echo 'Formula: ', $cellDataFormula, PHP_EOL; + $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); + $temp = explode('"',$cellDataFormula); + $tKey = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($tKey = !$tKey) { + $value = preg_replace('/\[([^\.]+)\.([^\.]+):\.([^\.]+)\]/Ui','$1!$2:$3',$value); // Cell range reference in another sheet + $value = preg_replace('/\[([^\.]+)\.([^\.]+)\]/Ui','$1!$2',$value); // Cell reference in another sheet + $value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/Ui','$1:$2',$value); // Cell range reference + $value = preg_replace('/\[\.([^\.]+)\]/Ui','$1',$value); // Simple cell reference + $value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces); + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'Adjusted Formula: ', $cellDataFormula, PHP_EOL; + } - $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? - $cellDataTableAttributes['number-columns-repeated'] : 1; - if ($type !== NULL) { - for ($i = 0; $i < $colRepeats; ++$i) { - if ($i > 0) { - ++$columnID; - } - if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { - for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { - $rID = $rowID + $rowAdjust; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); - if ($hasCalculatedValue) { -// echo 'Forumla result is '.$dataValue.'<br />'; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); - } - if ($formatting !== NULL) { - $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); - } else { - $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); - } - if ($hyperlink !== NULL) { - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); - } - } - } - } - } + $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? + $cellDataTableAttributes['number-columns-repeated'] : 1; + if ($type !== NULL) { + for ($i = 0; $i < $colRepeats; ++$i) { + if ($i > 0) { + ++$columnID; + } + if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { + for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { + $rID = $rowID + $rowAdjust; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'<br />'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); + } + if ($formatting !== NULL) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); + } else { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); + } + if ($hyperlink !== NULL) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); + } + } + } + } + } - // Merged cells - if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { - if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { - $columnTo = $columnID; - if (isset($cellDataTableAttributes['number-columns-spanned'])) { - $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); - } - $rowTo = $rowID; - if (isset($cellDataTableAttributes['number-rows-spanned'])) { - $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; - } - $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; - $objPHPExcel->getActiveSheet()->mergeCells($cellRange); - } - } + // Merged cells + if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { + if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + } - ++$columnID; - } - $rowID += $rowRepeats; - break; - } - } - ++$worksheetID; - } - } + ++$columnID; + } + $rowID += $rowRepeats; + break; + } + } + ++$worksheetID; + } + } - // Return - return $objPHPExcel; - } + // Return + return $objPHPExcel; + } - private function _parseRichText($is = '') { - $value = new PHPExcel_RichText(); + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); - $value->createText($is); + $value->createText($is); - return $value; - } + return $value; + } } diff --git a/Classes/PHPExcel/Reader/SYLK.php b/Classes/PHPExcel/Reader/SYLK.php index 4048d4fc..1eee8666 100644 --- a/Classes/PHPExcel/Reader/SYLK.php +++ b/Classes/PHPExcel/Reader/SYLK.php @@ -21,18 +21,18 @@ * @category PHPExcel * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } /** @@ -44,407 +44,407 @@ if (!defined('PHPEXCEL_ROOT')) { */ class PHPExcel_Reader_SYLK extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Input encoding - * - * @var string - */ - private $_inputEncoding = 'ANSI'; + /** + * Input encoding + * + * @var string + */ + private $_inputEncoding = 'ANSI'; - /** - * Sheet index to read - * - * @var int - */ - private $_sheetIndex = 0; + /** + * Sheet index to read + * + * @var int + */ + private $_sheetIndex = 0; - /** - * Formats - * - * @var array - */ - private $_formats = array(); + /** + * Formats + * + * @var array + */ + private $_formats = array(); - /** - * Format Count - * - * @var int - */ - private $_format = 0; + /** + * Format Count + * + * @var int + */ + private $_format = 0; - /** - * Create a new PHPExcel_Reader_SYLK - */ - public function __construct() { - $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } + /** + * Create a new PHPExcel_Reader_SYLK + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } - /** - * Validate that the current file is a SYLK file - * - * @return boolean - */ - protected function _isValidFormat() - { - // Read sample data (first 2 KB will do) - $data = fread($this->_fileHandle, 2048); + /** + * Validate that the current file is a SYLK file + * + * @return boolean + */ + protected function _isValidFormat() + { + // Read sample data (first 2 KB will do) + $data = fread($this->_fileHandle, 2048); - // Count delimiters in file - $delimiterCount = substr_count($data, ';'); - if ($delimiterCount < 1) { - return FALSE; - } + // Count delimiters in file + $delimiterCount = substr_count($data, ';'); + if ($delimiterCount < 1) { + return FALSE; + } - // Analyze first line looking for ID; signature - $lines = explode("\n", $data); - if (substr($lines[0],0,4) != 'ID;P') { - return FALSE; - } + // Analyze first line looking for ID; signature + $lines = explode("\n", $data); + if (substr($lines[0],0,4) != 'ID;P') { + return FALSE; + } - return TRUE; - } + return TRUE; + } - /** - * Set input encoding - * - * @param string $pValue Input encoding - */ - public function setInputEncoding($pValue = 'ANSI') - { - $this->_inputEncoding = $pValue; - return $this; - } + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'ANSI') + { + $this->_inputEncoding = $pValue; + return $this; + } - /** - * Get input encoding - * - * @return string - */ - public function getInputEncoding() - { - return $this->_inputEncoding; - } + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws PHPExcel_Reader_Exception - */ - public function listWorksheetInfo($pFilename) - { - // Open file - $this->_openFile($pFilename); - if (!$this->_isValidFormat()) { - fclose ($this->_fileHandle); - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } - $fileHandle = $this->_fileHandle; - rewind($fileHandle); + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); - $worksheetInfo = array(); - $worksheetInfo[0]['worksheetName'] = 'Worksheet'; - $worksheetInfo[0]['lastColumnLetter'] = 'A'; - $worksheetInfo[0]['lastColumnIndex'] = 0; - $worksheetInfo[0]['totalRows'] = 0; - $worksheetInfo[0]['totalColumns'] = 0; + $worksheetInfo = array(); + $worksheetInfo[0]['worksheetName'] = 'Worksheet'; + $worksheetInfo[0]['lastColumnLetter'] = 'A'; + $worksheetInfo[0]['lastColumnIndex'] = 0; + $worksheetInfo[0]['totalRows'] = 0; + $worksheetInfo[0]['totalColumns'] = 0; - // Loop through file - $rowData = array(); + // Loop through file + $rowData = array(); - // loop through one row (line) at a time in the file - $rowIndex = 0; - while (($rowData = fgets($fileHandle)) !== FALSE) { - $columnIndex = 0; + // loop through one row (line) at a time in the file + $rowIndex = 0; + while (($rowData = fgets($fileHandle)) !== FALSE) { + $columnIndex = 0; - // convert SYLK encoded $rowData to UTF-8 - $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); + // convert SYLK encoded $rowData to UTF-8 + $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); - // explode each row at semicolons while taking into account that literal semicolon (;) - // is escaped like this (;;) - $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + // explode each row at semicolons while taking into account that literal semicolon (;) + // is escaped like this (;;) + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); - $dataType = array_shift($rowData); - if ($dataType == 'C') { - // Read cell value data - foreach($rowData as $rowDatum) { - switch($rowDatum{0}) { - case 'C' : - case 'X' : - $columnIndex = substr($rowDatum,1) - 1; - break; - case 'R' : - case 'Y' : - $rowIndex = substr($rowDatum,1); - break; - } + $dataType = array_shift($rowData); + if ($dataType == 'C') { + // Read cell value data + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : + $columnIndex = substr($rowDatum,1) - 1; + break; + case 'R' : + case 'Y' : + $rowIndex = substr($rowDatum,1); + break; + } - $worksheetInfo[0]['totalRows'] = max($worksheetInfo[0]['totalRows'], $rowIndex); - $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], $columnIndex); - } - } - } + $worksheetInfo[0]['totalRows'] = max($worksheetInfo[0]['totalRows'], $rowIndex); + $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], $columnIndex); + } + } + } - $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); - $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; + $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); + $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; - // Close file - fclose($fileHandle); + // Close file + fclose($fileHandle); - return $worksheetInfo; - } + return $worksheetInfo; + } - /** - * Loads PHPExcel from file - * - * @param string $pFilename - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function load($pFilename) - { - // Create new PHPExcel - $objPHPExcel = new PHPExcel(); + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); - // Load into this instance - return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } - /** - * Loads PHPExcel from file into PHPExcel instance - * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @return PHPExcel - * @throws PHPExcel_Reader_Exception - */ - public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) - { - // Open file - $this->_openFile($pFilename); - if (!$this->_isValidFormat()) { - fclose ($this->_fileHandle); - throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); - } - $fileHandle = $this->_fileHandle; - rewind($fileHandle); + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); - // Create new PHPExcel - while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { - $objPHPExcel->createSheet(); - } - $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); + // Create new PHPExcel + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); - $fromFormats = array('\-', '\ '); - $toFormats = array('-', ' '); + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); - // Loop through file - $rowData = array(); - $column = $row = ''; + // Loop through file + $rowData = array(); + $column = $row = ''; - // loop through one row (line) at a time in the file - while (($rowData = fgets($fileHandle)) !== FALSE) { + // loop through one row (line) at a time in the file + while (($rowData = fgets($fileHandle)) !== FALSE) { - // convert SYLK encoded $rowData to UTF-8 - $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); + // convert SYLK encoded $rowData to UTF-8 + $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); - // explode each row at semicolons while taking into account that literal semicolon (;) - // is escaped like this (;;) - $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + // explode each row at semicolons while taking into account that literal semicolon (;) + // is escaped like this (;;) + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); - $dataType = array_shift($rowData); - // Read shared styles - if ($dataType == 'P') { - $formatArray = array(); - foreach($rowData as $rowDatum) { - switch($rowDatum{0}) { - case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1)); - break; - case 'E' : - case 'F' : $formatArray['font']['name'] = substr($rowDatum,1); - break; - case 'L' : $formatArray['font']['size'] = substr($rowDatum,1); - break; - case 'S' : $styleSettings = substr($rowDatum,1); - for ($i=0;$i<strlen($styleSettings);++$i) { - switch ($styleSettings{$i}) { - case 'I' : $formatArray['font']['italic'] = true; - break; - case 'D' : $formatArray['font']['bold'] = true; - break; - case 'T' : $formatArray['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'B' : $formatArray['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'L' : $formatArray['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'R' : $formatArray['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - } - } - break; - } - } - $this->_formats['P'.$this->_format++] = $formatArray; - // Read cell value data - } elseif ($dataType == 'C') { - $hasCalculatedValue = false; - $cellData = $cellDataFormula = ''; - foreach($rowData as $rowDatum) { - switch($rowDatum{0}) { - case 'C' : - case 'X' : $column = substr($rowDatum,1); - break; - case 'R' : - case 'Y' : $row = substr($rowDatum,1); - break; - case 'K' : $cellData = substr($rowDatum,1); - break; - case 'E' : $cellDataFormula = '='.substr($rowDatum,1); - // Convert R1C1 style references to A1 style references (but only when not quoted) - $temp = explode('"',$cellDataFormula); - $key = false; - foreach($temp as &$value) { - // Only count/replace in alternate array entries - if ($key = !$key) { - preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); - // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way - // through the formula from left to right. Reversing means that we work right to left.through - // the formula - $cellReferences = array_reverse($cellReferences); - // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, - // then modify the formula to use that new reference - foreach($cellReferences as $cellReference) { - $rowReference = $cellReference[2][0]; - // Empty R reference is the current row - if ($rowReference == '') $rowReference = $row; - // Bracketed R references are relative to the current row - if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]'); - $columnReference = $cellReference[4][0]; - // Empty C reference is the current column - if ($columnReference == '') $columnReference = $column; - // Bracketed C references are relative to the current column - if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]'); - $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + $dataType = array_shift($rowData); + // Read shared styles + if ($dataType == 'P') { + $formatArray = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1)); + break; + case 'E' : + case 'F' : $formatArray['font']['name'] = substr($rowDatum,1); + break; + case 'L' : $formatArray['font']['size'] = substr($rowDatum,1); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i<strlen($styleSettings);++$i) { + switch ($styleSettings{$i}) { + case 'I' : $formatArray['font']['italic'] = true; + break; + case 'D' : $formatArray['font']['bold'] = true; + break; + case 'T' : $formatArray['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'B' : $formatArray['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'L' : $formatArray['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'R' : $formatArray['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + } + } + break; + } + } + $this->_formats['P'.$this->_format++] = $formatArray; + // Read cell value data + } elseif ($dataType == 'C') { + $hasCalculatedValue = false; + $cellData = $cellDataFormula = ''; + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'K' : $cellData = substr($rowDatum,1); + break; + case 'E' : $cellDataFormula = '='.substr($rowDatum,1); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only count/replace in alternate array entries + if ($key = !$key) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $row; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $column; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; - $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); - } - } - } - unset($value); - // Then rebuild the formula string - $cellDataFormula = implode('"',$temp); - $hasCalculatedValue = true; - break; - } - } - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); - $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + $hasCalculatedValue = true; + break; + } + } + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); - // Set cell value - $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData); - if ($hasCalculatedValue) { - $cellData = PHPExcel_Calculation::_unwrapResult($cellData); - $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); - } - // Read cell formatting - } elseif ($dataType == 'F') { - $formatStyle = $columnWidth = $styleSettings = ''; - $styleData = array(); - foreach($rowData as $rowDatum) { - switch($rowDatum{0}) { - case 'C' : - case 'X' : $column = substr($rowDatum,1); - break; - case 'R' : - case 'Y' : $row = substr($rowDatum,1); - break; - case 'P' : $formatStyle = $rowDatum; - break; - case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1)); - break; - case 'S' : $styleSettings = substr($rowDatum,1); - for ($i=0;$i<strlen($styleSettings);++$i) { - switch ($styleSettings{$i}) { - case 'I' : $styleData['font']['italic'] = true; - break; - case 'D' : $styleData['font']['bold'] = true; - break; - case 'T' : $styleData['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'B' : $styleData['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'L' : $styleData['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - case 'R' : $styleData['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; - break; - } - } - break; - } - } - if (($formatStyle > '') && ($column > '') && ($row > '')) { - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); - if (isset($this->_formats[$formatStyle])) { - $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); - } - } - if ((!empty($styleData)) && ($column > '') && ($row > '')) { - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); - $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData); - } - if ($columnWidth > '') { - if ($startCol == $endCol) { - $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); - $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); - } else { - $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); - $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1); - $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); - do { - $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth); - } while ($startCol != $endCol); - } - } - } else { - foreach($rowData as $rowDatum) { - switch($rowDatum{0}) { - case 'C' : - case 'X' : $column = substr($rowDatum,1); - break; - case 'R' : - case 'Y' : $row = substr($rowDatum,1); - break; - } - } - } - } + // Set cell value + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData); + if ($hasCalculatedValue) { + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); + } + // Read cell formatting + } elseif ($dataType == 'F') { + $formatStyle = $columnWidth = $styleSettings = ''; + $styleData = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'P' : $formatStyle = $rowDatum; + break; + case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1)); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i<strlen($styleSettings);++$i) { + switch ($styleSettings{$i}) { + case 'I' : $styleData['font']['italic'] = true; + break; + case 'D' : $styleData['font']['bold'] = true; + break; + case 'T' : $styleData['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'B' : $styleData['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'L' : $styleData['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'R' : $styleData['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + } + } + break; + } + } + if (($formatStyle > '') && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + if (isset($this->_formats[$formatStyle])) { + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + } + } + if ((!empty($styleData)) && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData); + } + if ($columnWidth > '') { + if ($startCol == $endCol) { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + } else { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + do { + $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth); + } while ($startCol != $endCol); + } + } + } else { + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + } + } + } + } - // Close file - fclose($fileHandle); + // Close file + fclose($fileHandle); - // Return - return $objPHPExcel; - } + // Return + return $objPHPExcel; + } - /** - * Get sheet index - * - * @return int - */ - public function getSheetIndex() { - return $this->_sheetIndex; - } + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } - /** - * Set sheet index - * - * @param int $pValue Sheet index - * @return PHPExcel_Reader_SYLK - */ - public function setSheetIndex($pValue = 0) { - $this->_sheetIndex = $pValue; - return $this; - } + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_SYLK + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } } diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index dfd5b4c8..9144c01d 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_ReferenceHelper (Singleton) * * Copyright (c) 2006 - 2015 PHPExcel * @@ -19,749 +20,740 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## - */ - - -/** - * PHPExcel_ReferenceHelper (Singleton) - * - * @category PHPExcel - * @package PHPExcel + * @package PHPExcel * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ class PHPExcel_ReferenceHelper { - /** Constants */ - /** Regular Expressions */ - const REFHELPER_REGEXP_CELLREF = '((\w*|\'[^!]*\')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d\'])'; - const REFHELPER_REGEXP_CELLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+)'; - const REFHELPER_REGEXP_ROWRANGE = '((\w*|\'[^!]*\')!)?(\$?\d+):(\$?\d+)'; - const REFHELPER_REGEXP_COLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3})'; + /** Constants */ + /** Regular Expressions */ + const REFHELPER_REGEXP_CELLREF = '((\w*|\'[^!]*\')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d\'])'; + const REFHELPER_REGEXP_CELLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+)'; + const REFHELPER_REGEXP_ROWRANGE = '((\w*|\'[^!]*\')!)?(\$?\d+):(\$?\d+)'; + const REFHELPER_REGEXP_COLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3})'; - /** - * Instance of this class - * - * @var PHPExcel_ReferenceHelper - */ - private static $_instance; + /** + * Instance of this class + * + * @var PHPExcel_ReferenceHelper + */ + private static $_instance; - /** - * Get an instance of this class - * - * @return PHPExcel_ReferenceHelper - */ - public static function getInstance() { - if (!isset(self::$_instance) || (self::$_instance === NULL)) { - self::$_instance = new PHPExcel_ReferenceHelper(); - } + /** + * Get an instance of this class + * + * @return PHPExcel_ReferenceHelper + */ + public static function getInstance() { + if (!isset(self::$_instance) || (self::$_instance === NULL)) { + self::$_instance = new PHPExcel_ReferenceHelper(); + } - return self::$_instance; - } + return self::$_instance; + } - /** - * Create a new PHPExcel_ReferenceHelper - */ - protected function __construct() { - } + /** + * Create a new PHPExcel_ReferenceHelper + */ + protected function __construct() { + } - /** - * Compare two column addresses - * Intended for use as a Callback function for sorting column addresses by column - * - * @param string $a First column to test (e.g. 'AA') - * @param string $b Second column to test (e.g. 'Z') - * @return integer - */ - public static function columnSort($a, $b) { - return strcasecmp(strlen($a) . $a, strlen($b) . $b); - } + /** + * Compare two column addresses + * Intended for use as a Callback function for sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ + public static function columnSort($a, $b) { + return strcasecmp(strlen($a) . $a, strlen($b) . $b); + } - /** - * Compare two column addresses - * Intended for use as a Callback function for reverse sorting column addresses by column - * - * @param string $a First column to test (e.g. 'AA') - * @param string $b Second column to test (e.g. 'Z') - * @return integer - */ - public static function columnReverseSort($a, $b) { - return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); - } + /** + * Compare two column addresses + * Intended for use as a Callback function for reverse sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ + public static function columnReverseSort($a, $b) { + return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); + } - /** - * Compare two cell addresses - * Intended for use as a Callback function for sorting cell addresses by column and row - * - * @param string $a First cell to test (e.g. 'AA1') - * @param string $b Second cell to test (e.g. 'Z1') - * @return integer - */ - public static function cellSort($a, $b) { - sscanf($a,'%[A-Z]%d', $ac, $ar); - sscanf($b,'%[A-Z]%d', $bc, $br); + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); - if ($ar == $br) { - return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); - } - return ($ar < $br) ? -1 : 1; - } + if ($ar == $br) { + return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? -1 : 1; + } - /** - * Compare two cell addresses - * Intended for use as a Callback function for sorting cell addresses by column and row - * - * @param string $a First cell to test (e.g. 'AA1') - * @param string $b Second cell to test (e.g. 'Z1') - * @return integer - */ - public static function cellReverseSort($a, $b) { - sscanf($a,'%[A-Z]%d', $ac, $ar); - sscanf($b,'%[A-Z]%d', $bc, $br); + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellReverseSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); - if ($ar == $br) { - return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); - } - return ($ar < $br) ? 1 : -1; - } + if ($ar == $br) { + return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? 1 : -1; + } - /** - * Test whether a cell address falls within a defined range of cells - * - * @param string $cellAddress Address of the cell we're testing - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @return boolean - */ - private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { - list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); - $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); - // Is cell within the range of rows/columns if we're deleting - if ($pNumRows < 0 && - ($cellRow >= ($beforeRow + $pNumRows)) && - ($cellRow < $beforeRow)) { - return TRUE; - } elseif ($pNumCols < 0 && - ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && - ($cellColumnIndex < $beforeColumnIndex)) { - return TRUE; - } - return FALSE; - } + /** + * Test whether a cell address falls within a defined range of cells + * + * @param string $cellAddress Address of the cell we're testing + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @return boolean + */ + private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { + list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); + $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); + // Is cell within the range of rows/columns if we're deleting + if ($pNumRows < 0 && + ($cellRow >= ($beforeRow + $pNumRows)) && + ($cellRow < $beforeRow)) { + return TRUE; + } elseif ($pNumCols < 0 && + ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && + ($cellColumnIndex < $beforeColumnIndex)) { + return TRUE; + } + return FALSE; + } - /** - * Update page breaks when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aBreaks = $pSheet->getBreaks(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + /** + * Update page breaks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aBreaks as $key => $value) { - if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { - // If we're deleting, then clear any defined breaks that are within the range - // of rows/columns that we're deleting - $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); - } else { - // Otherwise update any affected breaks by inserting a new break at the appropriate point - // and removing the old affected break - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setBreak($newReference, $value) - ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); - } - } - } - } + foreach ($aBreaks as $key => $value) { + if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // If we're deleting, then clear any defined breaks that are within the range + // of rows/columns that we're deleting + $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } else { + // Otherwise update any affected breaks by inserting a new break at the appropriate point + // and removing the old affected break + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } + } + } + } - /** - * Update cell comments when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aComments = $pSheet->getComments(); - $aNewComments = array(); // the new array of all comments + /** + * Update cell comments when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aComments = $pSheet->getComments(); + $aNewComments = array(); // the new array of all comments - foreach ($aComments as $key => &$value) { - // Any comments inside a deleted range will be ignored - if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { - // Otherwise build a new array of comments indexed by the adjusted cell reference - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewComments[$newReference] = $value; - } - } - // Replace the comments array with the new set of comments - $pSheet->setComments($aNewComments); - } + foreach ($aComments as $key => &$value) { + // Any comments inside a deleted range will be ignored + if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // Otherwise build a new array of comments indexed by the adjusted cell reference + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewComments[$newReference] = $value; + } + } + // Replace the comments array with the new set of comments + $pSheet->setComments($aNewComments); + } - /** - * Update hyperlinks when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + /** + * Update hyperlinks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aHyperlinkCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setHyperlink( $newReference, $value ); - $pSheet->setHyperlink( $key, null ); - } - } - } + foreach ($aHyperlinkCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setHyperlink( $newReference, $value ); + $pSheet->setHyperlink( $key, null ); + } + } + } - /** - * Update data validations when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aDataValidationCollection = $pSheet->getDataValidationCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aDataValidationCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setDataValidation( $newReference, $value ); - $pSheet->setDataValidation( $key, null ); - } - } - } + /** + * Update data validations when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aDataValidationCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setDataValidation( $newReference, $value ); + $pSheet->setDataValidation( $key, null ); + } + } + } - /** - * Update merged cells when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aMergeCells = $pSheet->getMergeCells(); - $aNewMergeCells = array(); // the new array of all merge cells - foreach ($aMergeCells as $key => &$value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewMergeCells[$newReference] = $newReference; - } - $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array - } + /** + * Update merged cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewMergeCells[$newReference] = $newReference; + } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + } - /** - * Update protected cells when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aProtectedCells = $pSheet->getProtectedCells(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aProtectedCells as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->protectCells( $newReference, $value, true ); - $pSheet->unprotectCells( $key ); - } - } - } + /** + * Update protected cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aProtectedCells as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->protectCells( $newReference, $value, true ); + $pSheet->unprotectCells( $key ); + } + } + } - /** - * Update column dimensions when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); - if (!empty($aColumnDimensions)) { - foreach ($aColumnDimensions as $objColumnDimension) { - $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); - list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objColumnDimension->getColumnIndex() != $newReference) { - $objColumnDimension->setColumnIndex($newReference); - } - } - $pSheet->refreshColumnDimensions(); - } - } + /** + * Update column dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); + if (!empty($aColumnDimensions)) { + foreach ($aColumnDimensions as $objColumnDimension) { + $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); + list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objColumnDimension->getColumnIndex() != $newReference) { + $objColumnDimension->setColumnIndex($newReference); + } + } + $pSheet->refreshColumnDimensions(); + } + } - /** - * Update row dimensions when inserting/deleting rows/columns - * - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') - * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $beforeRow Number of the row we're inserting/deleting before - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - */ - protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) - { - $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); - if (!empty($aRowDimensions)) { - foreach ($aRowDimensions as $objRowDimension) { - $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); - list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objRowDimension->getRowIndex() != $newReference) { - $objRowDimension->setRowIndex($newReference); - } - } - $pSheet->refreshRowDimensions(); + /** + * Update row dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); + if (!empty($aRowDimensions)) { + foreach ($aRowDimensions as $objRowDimension) { + $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); + list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objRowDimension->getRowIndex() != $newReference) { + $objRowDimension->setRowIndex($newReference); + } + } + $pSheet->refreshRowDimensions(); - $copyDimension = $pSheet->getRowDimension($beforeRow - 1); - for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { - $newDimension = $pSheet->getRowDimension($i); - $newDimension->setRowHeight($copyDimension->getRowHeight()); - $newDimension->setVisible($copyDimension->getVisible()); - $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); - $newDimension->setCollapsed($copyDimension->getCollapsed()); - } - } - } + $copyDimension = $pSheet->getRowDimension($beforeRow - 1); + for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { + $newDimension = $pSheet->getRowDimension($i); + $newDimension->setRowHeight($copyDimension->getRowHeight()); + $newDimension->setVisible($copyDimension->getVisible()); + $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); + $newDimension->setCollapsed($copyDimension->getCollapsed()); + } + } + } - /** - * Insert a new column or row, updating all possible related data - * - * @param string $pBefore Insert before this cell address (e.g. 'A1') - * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) - * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) - * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing - * @throws PHPExcel_Exception - */ - public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) - { - $remove = ($pNumCols < 0 || $pNumRows < 0); - $aCellCollection = $pSheet->getCellCollection(); + /** + * Insert a new column or row, updating all possible related data + * + * @param string $pBefore Insert before this cell address (e.g. 'A1') + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @throws PHPExcel_Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) + { + $remove = ($pNumCols < 0 || $pNumRows < 0); + $aCellCollection = $pSheet->getCellCollection(); - // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); - $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); + $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); - // Clear cells if we are removing columns or rows - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + // Clear cells if we are removing columns or rows + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); - // 1. Clear column strips if we are removing columns - if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { - for ($i = 1; $i <= $highestRow - 1; ++$i) { - for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { - $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; - $pSheet->removeConditionalStyles($coordinate); - if ($pSheet->cellExists($coordinate)) { - $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); - $pSheet->getCell($coordinate)->setXfIndex(0); - } - } - } - } + // 1. Clear column strips if we are removing columns + if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { + for ($i = 1; $i <= $highestRow - 1; ++$i) { + for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } - // 2. Clear row strips if we are removing rows - if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { - for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { - for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { - $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; - $pSheet->removeConditionalStyles($coordinate); - if ($pSheet->cellExists($coordinate)) { - $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); - $pSheet->getCell($coordinate)->setXfIndex(0); - } - } - } - } + // 2. Clear row strips if we are removing rows + if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } - // Loop through cells, bottom-up, and change cell coordinates + // Loop through cells, bottom-up, and change cell coordinates if($remove) { // It's faster to reverse and pop than to use unshift, especially with large cell collections $aCellCollection = array_reverse($aCellCollection); } - while ($cellID = array_pop($aCellCollection)) { - $cell = $pSheet->getCell($cellID); - $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + while ($cellID = array_pop($aCellCollection)) { + $cell = $pSheet->getCell($cellID); + $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); - if ($cellIndex-1 + $pNumCols < 0) { - continue; - } + if ($cellIndex-1 + $pNumCols < 0) { + continue; + } - // New coordinates - $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows); + // New coordinates + $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows); - // Should the cell be updated? Move value and cellXf index from one cell to another. - if (($cellIndex >= $beforeColumnIndex) && - ($cell->getRow() >= $beforeRow)) { + // Should the cell be updated? Move value and cellXf index from one cell to another. + if (($cellIndex >= $beforeColumnIndex) && + ($cell->getRow() >= $beforeRow)) { - // Update cell styles - $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); + // Update cell styles + $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); - // Insert this cell at its new location - if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { - // Formula should be adjusted - $pSheet->getCell($newCoordinates) - ->setValue($this->updateFormulaReferences($cell->getValue(), - $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); - } else { - // Formula should not be adjusted - $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); - } + // Insert this cell at its new location + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $pSheet->getCell($newCoordinates) + ->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } else { + // Formula should not be adjusted + $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); + } - // Clear the original cell - $pSheet->getCellCacheController()->deleteCacheData($cellID); + // Clear the original cell + $pSheet->getCellCacheController()->deleteCacheData($cellID); - } else { - /* We don't need to update styles for rows/columns before our insertion position, - but we do still need to adjust any formulae in those cells */ - if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { - // Formula should be adjusted - $cell->setValue($this->updateFormulaReferences($cell->getValue(), - $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); - } + } else { + /* We don't need to update styles for rows/columns before our insertion position, + but we do still need to adjust any formulae in those cells */ + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $cell->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } - } - } + } + } - // Duplicate styles for the newly inserted cells - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + // Duplicate styles for the newly inserted cells + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); - if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { - for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { + if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { + for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { - // Style - $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i; - if ($pSheet->cellExists($coordinate)) { - $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); - $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? - $pSheet->getConditionalStyles($coordinate) : false; - for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { - $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); - if ($conditionalStyles) { - $cloned = array(); - foreach ($conditionalStyles as $conditionalStyle) { - $cloned[] = clone $conditionalStyle; - } - $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); - } - } - } + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i; + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { + $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); + } + } + } - } - } + } + } - if ($pNumRows > 0 && $beforeRow - 1 > 0) { - for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + if ($pNumRows > 0 && $beforeRow - 1 > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { - // Style - $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); - if ($pSheet->cellExists($coordinate)) { - $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); - $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? - $pSheet->getConditionalStyles($coordinate) : false; - for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { - $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); - if ($conditionalStyles) { - $cloned = array(); - foreach ($conditionalStyles as $conditionalStyle) { - $cloned[] = clone $conditionalStyle; - } - $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); - } - } - } - } - } + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { + $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); + } + } + } + } + } - // Update worksheet: column dimensions - $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: column dimensions + $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: row dimensions - $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: row dimensions + $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: page breaks - $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: page breaks + $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: comments - $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: comments + $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: hyperlinks - $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: hyperlinks + $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: data validations - $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: data validations + $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: merge cells - $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: merge cells + $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: protected cells - $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + // Update worksheet: protected cells + $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: autofilter - $autoFilter = $pSheet->getAutoFilter(); - $autoFilterRange = $autoFilter->getRange(); - if (!empty($autoFilterRange)) { - if ($pNumCols != 0) { - $autoFilterColumns = array_keys($autoFilter->getColumns()); - if (count($autoFilterColumns) > 0) { - sscanf($pBefore,'%[A-Z]%d', $column, $row); - $columnIndex = PHPExcel_Cell::columnIndexFromString($column); - list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); - if ($columnIndex <= $rangeEnd[0]) { - if ($pNumCols < 0) { - // If we're actually deleting any columns that fall within the autofilter range, - // then we delete any rules for those columns - $deleteColumn = $columnIndex + $pNumCols - 1; - $deleteCount = abs($pNumCols); - for ($i = 1; $i <= $deleteCount; ++$i) { - if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) { - $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); - } - ++$deleteColumn; - } - } - $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0]; + // Update worksheet: autofilter + $autoFilter = $pSheet->getAutoFilter(); + $autoFilterRange = $autoFilter->getRange(); + if (!empty($autoFilterRange)) { + if ($pNumCols != 0) { + $autoFilterColumns = array_keys($autoFilter->getColumns()); + if (count($autoFilterColumns) > 0) { + sscanf($pBefore,'%[A-Z]%d', $column, $row); + $columnIndex = PHPExcel_Cell::columnIndexFromString($column); + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + if ($columnIndex <= $rangeEnd[0]) { + if ($pNumCols < 0) { + // If we're actually deleting any columns that fall within the autofilter range, + // then we delete any rules for those columns + $deleteColumn = $columnIndex + $pNumCols - 1; + $deleteCount = abs($pNumCols); + for ($i = 1; $i <= $deleteCount; ++$i) { + if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) { + $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); + } + ++$deleteColumn; + } + } + $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0]; - // Shuffle columns in autofilter range - if ($pNumCols > 0) { - // For insert, we shuffle from end to beginning to avoid overwriting - $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); - $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); - $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + // Shuffle columns in autofilter range + if ($pNumCols > 0) { + // For insert, we shuffle from end to beginning to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); - $startColRef = $startCol; - $endColRef = $rangeEnd[0]; - $toColRef = $rangeEnd[0]+$pNumCols; + $startColRef = $startCol; + $endColRef = $rangeEnd[0]; + $toColRef = $rangeEnd[0]+$pNumCols; - do { - $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1)); - --$endColRef; - --$toColRef; - } while ($startColRef <= $endColRef); - } else { - // For delete, we shuffle from beginning to end to avoid overwriting - $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); - $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); - $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); - do { - $autoFilter->shiftColumn($startColID,$toColID); - ++$startColID; - ++$toColID; - } while ($startColID != $endColID); - } - } - } - } - $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); - } + do { + $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1)); + --$endColRef; + --$toColRef; + } while ($startColRef <= $endColRef); + } else { + // For delete, we shuffle from beginning to end to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + do { + $autoFilter->shiftColumn($startColID,$toColID); + ++$startColID; + ++$toColID; + } while ($startColID != $endColID); + } + } + } + } + $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); + } - // Update worksheet: freeze pane - if ($pSheet->getFreezePane() != '') { - $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); - } + // Update worksheet: freeze pane + if ($pSheet->getFreezePane() != '') { + $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); + } - // Page setup - if ($pSheet->getPageSetup()->isPrintAreaSet()) { - $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); - } + // Page setup + if ($pSheet->getPageSetup()->isPrintAreaSet()) { + $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); + } - // Update worksheet: drawings - $aDrawings = $pSheet->getDrawingCollection(); - foreach ($aDrawings as $objDrawing) { - $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); - if ($objDrawing->getCoordinates() != $newReference) { - $objDrawing->setCoordinates($newReference); - } - } + // Update worksheet: drawings + $aDrawings = $pSheet->getDrawingCollection(); + foreach ($aDrawings as $objDrawing) { + $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); + if ($objDrawing->getCoordinates() != $newReference) { + $objDrawing->setCoordinates($newReference); + } + } - // Update workbook: named ranges - if (count($pSheet->getParent()->getNamedRanges()) > 0) { - foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { - if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { - $namedRange->setRange( - $this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows) - ); - } - } - } + // Update workbook: named ranges + if (count($pSheet->getParent()->getNamedRanges()) > 0) { + foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { + if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { + $namedRange->setRange( + $this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows) + ); + } + } + } - // Garbage collect - $pSheet->garbageCollect(); - } + // Garbage collect + $pSheet->garbageCollect(); + } - /** - * Update references within formulas - * - * @param string $pFormula Formula to update - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @param string $sheetName Worksheet name/title - * @return string Updated formula - * @throws PHPExcel_Exception - */ - public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') { - // Update cell references in the formula - $formulaBlocks = explode('"',$pFormula); - $i = false; - foreach($formulaBlocks as &$formulaBlock) { - // Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode) - if ($i = !$i) { - $adjustCount = 0; - $newCellTokens = $cellTokens = array(); - // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5) - $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); - if ($matchCount > 0) { - foreach($matches as $match) { - $fromString = ($match[2] > '') ? $match[2].'!' : ''; - $fromString .= $match[3].':'.$match[4]; - $modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2); - $modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2); + /** + * Update references within formulas + * + * @param string $pFormula Formula to update + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @param string $sheetName Worksheet name/title + * @return string Updated formula + * @throws PHPExcel_Exception + */ + public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') { + // Update cell references in the formula + $formulaBlocks = explode('"',$pFormula); + $i = false; + foreach($formulaBlocks as &$formulaBlock) { + // Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode) + if ($i = !$i) { + $adjustCount = 0; + $newCellTokens = $cellTokens = array(); + // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2); + $modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2); - if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { - if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { - $toString = ($match[2] > '') ? $match[2].'!' : ''; - $toString .= $modified3.':'.$modified4; - // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more - $column = 100000; - $row = 10000000+trim($match[3],'$'); - $cellIndex = $column.$row; + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = 100000; + $row = 10000000+trim($match[3],'$'); + $cellIndex = $column.$row; - $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(?<!\d\$\!)'.preg_quote($fromString).'(?!\d)/i'; - ++$adjustCount; - } - } - } - } - // Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E) - $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_COLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); - if ($matchCount > 0) { - foreach($matches as $match) { - $fromString = ($match[2] > '') ? $match[2].'!' : ''; - $fromString .= $match[3].':'.$match[4]; - $modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); - $modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<!\d\$\!)'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + // Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_COLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + $modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); - if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { - if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { - $toString = ($match[2] > '') ? $match[2].'!' : ''; - $toString .= $modified3.':'.$modified4; - // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more - $column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000; - $row = 10000000; - $cellIndex = $column.$row; + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000; + $row = 10000000; + $cellIndex = $column.$row; - $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(?<![A-Z\$\!])'.preg_quote($fromString).'(?![A-Z])/i'; - ++$adjustCount; - } - } - } - } - // Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5) - $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); - if ($matchCount > 0) { - foreach($matches as $match) { - $fromString = ($match[2] > '') ? $match[2].'!' : ''; - $fromString .= $match[3].':'.$match[4]; - $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); - $modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows); + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z\$\!])'.preg_quote($fromString).'(?![A-Z])/i'; + ++$adjustCount; + } + } + } + } + // Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + $modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows); - if ($match[3].$match[4] !== $modified3.$modified4) { - if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { - $toString = ($match[2] > '') ? $match[2].'!' : ''; - $toString .= $modified3.':'.$modified4; - list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); - // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more - $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; - $row = trim($row,'$') + 10000000; - $cellIndex = $column.$row; + if ($match[3].$match[4] !== $modified3.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $column.$row; - $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(?<![A-Z]\$\!)'.preg_quote($fromString).'(?!\d)/i'; - ++$adjustCount; - } - } - } - } - // Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5) - $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLREF.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z]\$\!)'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + // Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLREF.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); - if ($matchCount > 0) { - foreach($matches as $match) { - $fromString = ($match[2] > '') ? $match[2].'!' : ''; - $fromString .= $match[3]; + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3]; - $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); - if ($match[3] !== $modified3) { - if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { - $toString = ($match[2] > '') ? $match[2].'!' : ''; - $toString .= $modified3; - list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); - // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more - $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; - $row = trim($row,'$') + 10000000; - $cellIndex = $row . $column; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + if ($match[3] !== $modified3) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $row . $column; - $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(?<![A-Z\$\!])'.preg_quote($fromString).'(?!\d)/i'; - ++$adjustCount; - } - } - } - } - if ($adjustCount > 0) { + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z\$\!])'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + if ($adjustCount > 0) { if ($pNumCols > 0 || $pNumRows > 0) { krsort($cellTokens); krsort($newCellTokens); @@ -769,154 +761,154 @@ class PHPExcel_ReferenceHelper ksort($cellTokens); ksort($newCellTokens); } // Update cell references in the formula - $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock)); - } - } - } - unset($formulaBlock); + $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock)); + } + } + } + unset($formulaBlock); - // Then rebuild the formula string - return implode('"',$formulaBlocks); - } + // Then rebuild the formula string + return implode('"',$formulaBlocks); + } - /** - * Update cell reference - * - * @param string $pCellRange Cell range - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws PHPExcel_Exception - */ - public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - // Is it in another worksheet? Will not have to update anything. - if (strpos($pCellRange, "!") !== false) { - return $pCellRange; - // Is it a range or a single cell? - } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { - // Single cell - return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); - } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { - // Range - return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); - } else { - // Return original - return $pCellRange; - } - } + /** + * Update cell reference + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + // Is it in another worksheet? Will not have to update anything. + if (strpos($pCellRange, "!") !== false) { + return $pCellRange; + // Is it a range or a single cell? + } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { + // Single cell + return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); + } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { + // Range + return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); + } else { + // Return original + return $pCellRange; + } + } - /** - * Update named formulas (i.e. containing worksheet references / named ranges) - * - * @param PHPExcel $pPhpExcel Object to update - * @param string $oldName Old name (name to replace) - * @param string $newName New name - */ - public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { - if ($oldName == '') { - return; - } + /** + * Update named formulas (i.e. containing worksheet references / named ranges) + * + * @param PHPExcel $pPhpExcel Object to update + * @param string $oldName Old name (name to replace) + * @param string $newName New name + */ + public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { + if ($oldName == '') { + return; + } - foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { - foreach ($sheet->getCellCollection(false) as $cellID) { - $cell = $sheet->getCell($cellID); - if (($cell !== NULL) && ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA)) { - $formula = $cell->getValue(); - if (strpos($formula, $oldName) !== false) { - $formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula); - $formula = str_replace($oldName . "!", $newName . "!", $formula); - $cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA); - } - } - } - } - } + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + if (($cell !== NULL) && ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA)) { + $formula = $cell->getValue(); + if (strpos($formula, $oldName) !== false) { + $formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula); + $formula = str_replace($oldName . "!", $newName . "!", $formula); + $cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + } + } + } + } + } - /** - * Update cell range - * - * @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3') - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws PHPExcel_Exception - */ - private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { - // Update range - $range = PHPExcel_Cell::splitRange($pCellRange); - $ic = count($range); - for ($i = 0; $i < $ic; ++$i) { - $jc = count($range[$i]); - for ($j = 0; $j < $jc; ++$j) { - if (ctype_alpha($range[$i][$j])) { - $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1', $pBefore, $pNumCols, $pNumRows)); - $range[$i][$j] = $r[0]; - } elseif(ctype_digit($range[$i][$j])) { - $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j], $pBefore, $pNumCols, $pNumRows)); - $range[$i][$j] = $r[1]; - } else { - $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); - } - } - } + /** + * Update cell range + * + * @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3') + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { + // Update range + $range = PHPExcel_Cell::splitRange($pCellRange); + $ic = count($range); + for ($i = 0; $i < $ic; ++$i) { + $jc = count($range[$i]); + for ($j = 0; $j < $jc; ++$j) { + if (ctype_alpha($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1', $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[0]; + } elseif(ctype_digit($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j], $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[1]; + } else { + $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); + } + } + } - // Recreate range string - return PHPExcel_Cell::buildRange($range); - } else { - throw new PHPExcel_Exception("Only cell ranges may be passed to this method."); - } - } + // Recreate range string + return PHPExcel_Cell::buildRange($range); + } else { + throw new PHPExcel_Exception("Only cell ranges may be passed to this method."); + } + } - /** - * Update single cell reference - * - * @param string $pCellReference Single cell reference - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell reference - * @throws PHPExcel_Exception - */ - private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { - // Get coordinates of $pBefore - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + /** + * Update single cell reference + * + * @param string $pCellReference Single cell reference + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell reference + * @throws PHPExcel_Exception + */ + private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { + // Get coordinates of $pBefore + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); - // Get coordinates of $pCellReference - list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); + // Get coordinates of $pCellReference + list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); - // Verify which parts should be updated - $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && - PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); - $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && - $newRow >= $beforeRow); + // Verify which parts should be updated + $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && + PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); + $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && + $newRow >= $beforeRow); - // Create new column reference - if ($updateColumn) { - $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); - } + // Create new column reference + if ($updateColumn) { + $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); + } - // Create new row reference - if ($updateRow) { - $newRow = $newRow + $pNumRows; - } + // Create new row reference + if ($updateRow) { + $newRow = $newRow + $pNumRows; + } - // Return new reference - return $newColumn . $newRow; - } else { - throw new PHPExcel_Exception("Only single cell references may be passed to this method."); - } - } + // Return new reference + return $newColumn . $newRow; + } else { + throw new PHPExcel_Exception("Only single cell references may be passed to this method."); + } + } - /** - * __clone implementation. Cloning should not be allowed in a Singleton! - * - * @throws PHPExcel_Exception - */ - public final function __clone() { - throw new PHPExcel_Exception("Cloning a Singleton is not allowed!"); - } + /** + * __clone implementation. Cloning should not be allowed in a Singleton! + * + * @throws PHPExcel_Exception + */ + public final function __clone() { + throw new PHPExcel_Exception("Cloning a Singleton is not allowed!"); + } } diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index f3f89d52..8d380848 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Worksheet * * Copyright (c) 2006 - 2015 PHPExcel * @@ -24,15 +25,6 @@ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Worksheet - * - * @category PHPExcel - * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ class PHPExcel_Worksheet implements PHPExcel_IComparable { /* Break types */ @@ -332,7 +324,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ private $_codeName = null; - /** + /** * Create a new worksheet * * @param PHPExcel $pParent @@ -344,7 +336,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_parent = $pParent; $this->setTitle($pTitle, FALSE); // setTitle can change $pTitle - $this->setCodeName($this->getTitle()); + $this->setCodeName($this->getTitle()); $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); @@ -385,11 +377,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * typically so that the worksheet object can be unset * */ - public function disconnectCells() { - if ( $this->_cellCollection !== NULL){ + public function disconnectCells() { + if ( $this->_cellCollection !== NULL){ $this->_cellCollection->unsetWorksheetCells(); $this->_cellCollection = NULL; - } + } // detach ourself from the workbook, so that it can then delete this worksheet successfully $this->_parent = null; } @@ -398,19 +390,19 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * Code to execute when this worksheet is unset() * */ - function __destruct() { - PHPExcel_Calculation::getInstance($this->_parent) - ->clearCalculationCacheForWorksheet($this->_title); + function __destruct() { + PHPExcel_Calculation::getInstance($this->_parent) + ->clearCalculationCacheForWorksheet($this->_title); - $this->disconnectCells(); - } + $this->disconnectCells(); + } /** * Return the cache controller for the cell collection * * @return PHPExcel_CachedObjectStorage_xxx */ - public function getCellCacheController() { + public function getCellCacheController() { return $this->_cellCollection; } // function getCellCacheController() @@ -745,22 +737,22 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // loop through all cells in the worksheet foreach ($this->getCellCollection(false) as $cellID) { $cell = $this->getCell($cellID); - if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) { + if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) { // Determine width if cell does not participate in a merge - if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) { + if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) { // Calculated value // To formatted string - $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( - $cell->getCalculatedValue(), - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode() - ); + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode() + ); - $autoSizes[$this->_cellCollection->getCurrentColumn()] = max( - (float) $autoSizes[$this->_cellCollection->getCurrentColumn()], + $autoSizes[$this->_cellCollection->getCurrentColumn()] = max( + (float) $autoSizes[$this->_cellCollection->getCurrentColumn()], (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), $this->getDefaultStyle()->getFont() ) ); @@ -783,7 +775,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return PHPExcel */ - public function getParent() { + public function getParent() { return $this->_parent; } @@ -793,7 +785,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @param PHPExcel $parent * @return PHPExcel_Worksheet */ - public function rebindParent(PHPExcel $parent) { + public function rebindParent(PHPExcel $parent) { if ($this->_parent !== null) { $namedRanges = $this->_parent->getNamedRanges(); foreach ($namedRanges as $namedRange) { @@ -824,7 +816,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @param string $pValue String containing the dimension of this worksheet * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should - * be updated to reflect the new sheet name. + * be updated to reflect the new sheet name. * This should be left as the default true, unless you are * certain that no formula cells on any worksheet contain * references to this worksheet @@ -845,14 +837,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($this->_parent) { // Is there already such sheet name? - if ($this->_parent->sheetNameExists($pValue)) { + if ($this->_parent->sheetNameExists($pValue)) { // Use name, but append with lowest possible integer if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); } $i = 1; - while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) { + while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) { ++$i; if ($i == 10) { if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { @@ -877,10 +869,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($this->_parent) { // New title $newTitle = $this->getTitle(); - PHPExcel_Calculation::getInstance($this->_parent) - ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); + PHPExcel_Calculation::getInstance($this->_parent) + ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); if ($updateFormulaCellReferences) - PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle); + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle); } return $this; @@ -891,7 +883,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return string Sheet state (visible, hidden, veryHidden) */ - public function getSheetState() { + public function getSheetState() { return $this->_sheetState; } @@ -901,7 +893,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @param string $value Sheet state (visible, hidden, veryHidden) * @return PHPExcel_Worksheet */ - public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { + public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { $this->_sheetState = $value; return $this; } @@ -1160,7 +1152,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Worksheet reference? if (strpos($pCoordinate, '!') !== false) { $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); - return $this->_parent->getSheetByName($worksheetReference[0])->getCell(strtoupper($worksheetReference[1])); + return $this->_parent->getSheetByName($worksheetReference[0])->getCell(strtoupper($worksheetReference[1])); } // Named range? @@ -1202,7 +1194,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_cellCollection->getCacheData($coordinate); } - return $this->_createNewCell($coordinate); + return $this->_createNewCell($coordinate); } /** @@ -1211,16 +1203,16 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @param string $pCoordinate Coordinate of the cell * @return PHPExcel_Cell Cell that was created */ - private function _createNewCell($pCoordinate) - { - $cell = $this->_cellCollection->addCacheData( - $pCoordinate, - new PHPExcel_Cell( - NULL, - PHPExcel_Cell_DataType::TYPE_NULL, - $this - ) - ); + private function _createNewCell($pCoordinate) + { + $cell = $this->_cellCollection->addCacheData( + $pCoordinate, + new PHPExcel_Cell( + NULL, + PHPExcel_Cell_DataType::TYPE_NULL, + $this + ) + ); $this->_cellCollectionIsSorted = false; // Coordinates @@ -1230,7 +1222,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_cachedHighestRow = max($this->_cachedHighestRow, $aCoordinates[1]); // Cell needs appropriate xfIndex from dimensions records - // but don't create dimension records if they don't already exist + // but don't create dimension records if they don't already exist $rowDimension = $this->getRowDimension($aCoordinates[1], FALSE); $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE); @@ -1243,8 +1235,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } return $cell; - } - + } + /** * Does the cell at a specific coordinate exist? * @@ -1257,7 +1249,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Worksheet reference? if (strpos($pCoordinate, '!') !== false) { $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); - return $this->_parent->getSheetByName($worksheetReference[0])->cellExists(strtoupper($worksheetReference[1])); + return $this->_parent->getSheetByName($worksheetReference[0])->cellExists(strtoupper($worksheetReference[1])); } // Named range? @@ -1318,8 +1310,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Get row dimension if (!isset($this->_rowDimensions[$pRow])) { - if (!$create) - return NULL; + if (!$create) + return NULL; $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); @@ -1340,8 +1332,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Fetch dimensions if (!isset($this->_columnDimensions[$pColumn])) { - if (!$create) - return NULL; + if (!$create) + return NULL; $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) @@ -1496,10 +1488,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1, $pColumn2 = null, $pRow2 = null) { if (!is_null($pColumn2) && !is_null($pRow2)) { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow . ':' . + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->getStyle($cellRange); - } + return $this->getStyle($cellRange); + } return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); } @@ -1538,7 +1530,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Add the style to the workbook if necessary $workbook = $this->_parent; - if ($existingStyle = $this->_parent->getCellXfByHashCode($pCellStyle->getHashCode())) { + if ($existingStyle = $this->_parent->getCellXfByHashCode($pCellStyle->getHashCode())) { // there is already such cell Xf in our collection $xfIndex = $existingStyle->getIndex(); } else { @@ -1572,7 +1564,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * Please note that this will overwrite existing cell styles for cells in range! * - * @param array of PHPExcel_Style_Conditional $pCellStyle Cell style to duplicate + * @param array of PHPExcel_Style_Conditional $pCellStyle Cell style to duplicate * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") * @throws PHPExcel_Exception * @return PHPExcel_Worksheet @@ -1639,13 +1631,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $pCell = strtoupper($pCell); if ($pCell != '') { - if ($pBreak == PHPExcel_Worksheet::BREAK_NONE) { - if (isset($this->_breaks[$pCell])) { - unset($this->_breaks[$pCell]); - } - } else { - $this->_breaks[$pCell] = $pBreak; - } + if ($pBreak == PHPExcel_Worksheet::BREAK_NONE) { + if (isset($this->_breaks[$pCell])) { + unset($this->_breaks[$pCell]); + } + } else { + $this->_breaks[$pCell] = $pBreak; + } } else { throw new PHPExcel_Exception('No cell coordinate specified.'); } @@ -2229,7 +2221,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable /** * Set comments array for the entire sheet. * - * @param array of PHPExcel_Comment + * @param array of PHPExcel_Comment * @return PHPExcel_Worksheet */ public function setComments($pValue = array()) @@ -2447,7 +2439,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * True - Return rows and columns indexed by their actual row and column IDs * @return array */ - public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { // Returnvalue $returnValue = array(); // Identify the range that we need to extract from the worksheet @@ -2485,10 +2477,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($formatData) { $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( - $returnValue[$rRef][$cRef], - ($style && $style->getNumberFormat()) ? - $style->getNumberFormat()->getFormatCode() : - PHPExcel_Style_NumberFormat::FORMAT_GENERAL + $returnValue[$rRef][$cRef], + ($style && $style->getNumberFormat()) ? + $style->getNumberFormat()->getFormatCode() : + PHPExcel_Style_NumberFormat::FORMAT_GENERAL ); } } else { @@ -2519,14 +2511,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @return array * @throws PHPExcel_Exception */ - public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); if ($namedRange !== NULL) { $pWorkSheet = $namedRange->getWorksheet(); $pCellRange = $namedRange->getRange(); - return $pWorkSheet->rangeToArray( $pCellRange, - $nullValue, $calculateFormulas, $formatData, $returnCellRef); + return $pWorkSheet->rangeToArray( $pCellRange, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); } throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.'); @@ -2543,7 +2535,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * True - Return rows and columns indexed by their actual row and column IDs * @return array */ - public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { // Garbage collect... $this->garbageCollect(); @@ -2551,8 +2543,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $maxCol = $this->getHighestColumn(); $maxRow = $this->getHighestRow(); // Return - return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, - $nullValue, $calculateFormulas, $formatData, $returnCellRef); + return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); } /** @@ -2563,7 +2555,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return PHPExcel_Worksheet_RowIterator */ - public function getRowIterator($startRow = 1, $endRow = null) { + public function getRowIterator($startRow = 1, $endRow = null) { return new PHPExcel_Worksheet_RowIterator($this, $startRow, $endRow); } @@ -2575,7 +2567,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return PHPExcel_Worksheet_ColumnIterator */ - public function getColumnIterator($startColumn = 'A', $endColumn = null) { + public function getColumnIterator($startColumn = 'A', $endColumn = null) { return new PHPExcel_Worksheet_ColumnIterator($this, $startColumn, $endColumn); } @@ -2584,7 +2576,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return PHPExcel_Worksheet */ - public function garbageCollect() { + public function garbageCollect() { // Flush cache $this->_cellCollection->getCacheData('A1'); // Build a reference table from images @@ -2628,7 +2620,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return string Hash code */ - public function getHashCode() { + public function getHashCode() { if ($this->_dirty) { $this->_hash = md5( $this->_title . $this->_autoFilter . @@ -2650,7 +2642,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @param bool $returnRange Return range? (see example) * @return mixed */ - public static function extractSheetTitle($pRange, $returnRange = false) { + public static function extractSheetTitle($pRange, $returnRange = false) { // Sheet title included? if (($sep = strpos($pRange, '!')) === false) { return ''; @@ -2782,7 +2774,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @param string $range * @return string Adjusted range value */ - public function shrinkRangeToFit($range) { + public function shrinkRangeToFit($range) { $maxCol = $this->getHighestColumn(); $maxRow = $this->getHighestRow(); $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); @@ -2844,7 +2836,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * * @return PHPExcel_Worksheet */ - public function copy() { + public function copy() { $copied = clone $this; return $copied; @@ -2853,7 +2845,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ - public function __clone() { + public function __clone() { foreach ($this as $key => $val) { if ($key == '_parent') { continue; @@ -2878,68 +2870,68 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } } /** - * Define the code name of the sheet - * - * @param null|string Same rule as Title minus space not allowed (but, like Excel, change silently space to underscore) - * @return objWorksheet - * @throws PHPExcel_Exception - */ - public function setCodeName($pValue=null){ - // Is this a 'rename' or not? - if ($this->getCodeName() == $pValue) { - return $this; - } - $pValue = str_replace(' ', '_', $pValue);//Excel does this automatically without flinching, we are doing the same - // Syntax check + * Define the code name of the sheet + * + * @param null|string Same rule as Title minus space not allowed (but, like Excel, change silently space to underscore) + * @return objWorksheet + * @throws PHPExcel_Exception + */ + public function setCodeName($pValue=null){ + // Is this a 'rename' or not? + if ($this->getCodeName() == $pValue) { + return $this; + } + $pValue = str_replace(' ', '_', $pValue);//Excel does this automatically without flinching, we are doing the same + // Syntax check // throw an exception if not valid - self::_checkSheetCodeName($pValue); + self::_checkSheetCodeName($pValue); - // We use the same code that setTitle to find a valid codeName else not using a space (Excel don't like) but a '_' - + // We use the same code that setTitle to find a valid codeName else not using a space (Excel don't like) but a '_' + if ($this->getParent()) { - // Is there already such sheet name? - if ($this->getParent()->sheetCodeNameExists($pValue)) { - // Use name, but append with lowest possible integer + // Is there already such sheet name? + if ($this->getParent()->sheetCodeNameExists($pValue)) { + // Use name, but append with lowest possible integer - if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { - $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); - } - $i = 1; - while ($this->getParent()->sheetCodeNameExists($pValue . '_' . $i)) { - ++$i; - if ($i == 10) { - if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { - $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); - } - } elseif ($i == 100) { - if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { - $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); - } - } - } + if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); + } + $i = 1; + while ($this->getParent()->sheetCodeNameExists($pValue . '_' . $i)) { + ++$i; + if ($i == 10) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); + } + } elseif ($i == 100) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); + } + } + } - $pValue = $pValue . '_' . $i;// ok, we have a valid name - //codeName is'nt used in formula : no need to call for an update - //return $this->setTitle($altTitle,$updateFormulaCellReferences); - } - } + $pValue = $pValue . '_' . $i;// ok, we have a valid name + //codeName is'nt used in formula : no need to call for an update + //return $this->setTitle($altTitle,$updateFormulaCellReferences); + } + } - $this->_codeName=$pValue; - return $this; - } - /** - * Return the code name of the sheet - * - * @return null|string - */ - public function getCodeName(){ - return $this->_codeName; - } - /** - * Sheet has a code name ? - * @return boolean - */ - public function hasCodeName(){ - return !(is_null($this->_codeName)); - } + $this->_codeName=$pValue; + return $this; + } + /** + * Return the code name of the sheet + * + * @return null|string + */ + public function getCodeName(){ + return $this->_codeName; + } + /** + * Sheet has a code name ? + * @return boolean + */ + public function hasCodeName(){ + return !(is_null($this->_codeName)); + } } diff --git a/Classes/PHPExcel/Writer/Abstract.php b/Classes/PHPExcel/Writer/Abstract.php index c064722c..911dc5dd 100644 --- a/Classes/PHPExcel/Writer/Abstract.php +++ b/Classes/PHPExcel/Writer/Abstract.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_Abstract * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,138 +22,130 @@ * @category PHPExcel * @package PHPExcel_Writer * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_Abstract - * - * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ abstract class PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * Write charts that are defined in the workbook? - * Identifies whether the Writer should write definitions for any charts that exist in the PHPExcel object; - * - * @var boolean - */ - protected $_includeCharts = FALSE; + /** + * Write charts that are defined in the workbook? + * Identifies whether the Writer should write definitions for any charts that exist in the PHPExcel object; + * + * @var boolean + */ + protected $_includeCharts = false; - /** - * Pre-calculate formulas - * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are - * immediately available to MS Excel or other office spreadsheet viewer when opening the file - * - * @var boolean - */ - protected $_preCalculateFormulas = TRUE; + /** + * Pre-calculate formulas + * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are + * immediately available to MS Excel or other office spreadsheet viewer when opening the file + * + * @var boolean + */ + protected $_preCalculateFormulas = true; - /** - * Use disk caching where possible? - * - * @var boolean - */ - protected $_useDiskCaching = FALSE; + /** + * Use disk caching where possible? + * + * @var boolean + */ + protected $_useDiskCaching = false; - /** - * Disk caching directory - * - * @var string - */ - protected $_diskCachingDirectory = './'; + /** + * Disk caching directory + * + * @var string + */ + protected $_diskCachingDirectory = './'; - /** - * Write charts in workbook? - * If this is true, then the Writer will write definitions for any charts that exist in the PHPExcel object. - * If false (the default) it will ignore any charts defined in the PHPExcel object. - * - * @return boolean - */ - public function getIncludeCharts() { - return $this->_includeCharts; - } + /** + * Write charts in workbook? + * If this is true, then the Writer will write definitions for any charts that exist in the PHPExcel object. + * If false (the default) it will ignore any charts defined in the PHPExcel object. + * + * @return boolean + */ + public function getIncludeCharts() { + return $this->_includeCharts; + } - /** - * Set write charts in workbook - * Set to true, to advise the Writer to include any charts that exist in the PHPExcel object. - * Set to false (the default) to ignore charts. - * - * @param boolean $pValue - * @return PHPExcel_Writer_IWriter - */ - public function setIncludeCharts($pValue = FALSE) { - $this->_includeCharts = (boolean) $pValue; - return $this; - } + /** + * Set write charts in workbook + * Set to true, to advise the Writer to include any charts that exist in the PHPExcel object. + * Set to false (the default) to ignore charts. + * + * @param boolean $pValue + * @return PHPExcel_Writer_IWriter + */ + public function setIncludeCharts($pValue = false) + { + $this->_includeCharts = (boolean) $pValue; + return $this; + } /** * Get Pre-Calculate Formulas flag - * If this is true (the default), then the writer will recalculate all formulae in a workbook when saving, - * so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet - * viewer when opening the file - * If false, then formulae are not calculated on save. This is faster for saving in PHPExcel, but slower - * when opening the resulting file in MS Excel, because Excel has to recalculate the formulae itself + * If this is true (the default), then the writer will recalculate all formulae in a workbook when saving, + * so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet + * viewer when opening the file + * If false, then formulae are not calculated on save. This is faster for saving in PHPExcel, but slower + * when opening the resulting file in MS Excel, because Excel has to recalculate the formulae itself * * @return boolean */ public function getPreCalculateFormulas() { - return $this->_preCalculateFormulas; + return $this->_preCalculateFormulas; } /** * Set Pre-Calculate Formulas - * Set to true (the default) to advise the Writer to calculate all formulae on save - * Set to false to prevent precalculation of formulae on save. + * Set to true (the default) to advise the Writer to calculate all formulae on save + * Set to false to prevent precalculation of formulae on save. * - * @param boolean $pValue Pre-Calculate Formulas? - * @return PHPExcel_Writer_IWriter + * @param boolean $pValue Pre-Calculate Formulas? + * @return PHPExcel_Writer_IWriter */ public function setPreCalculateFormulas($pValue = TRUE) { - $this->_preCalculateFormulas = (boolean) $pValue; - return $this; + $this->_preCalculateFormulas = (boolean) $pValue; + return $this; } - /** - * Get use disk caching where possible? - * - * @return boolean - */ - public function getUseDiskCaching() { - return $this->_useDiskCaching; - } + /** + * Get use disk caching where possible? + * + * @return boolean + */ + public function getUseDiskCaching() { + return $this->_useDiskCaching; + } - /** - * Set use disk caching where possible? - * - * @param boolean $pValue - * @param string $pDirectory Disk caching directory - * @throws PHPExcel_Writer_Exception when directory does not exist - * @return PHPExcel_Writer_Excel2007 - */ - public function setUseDiskCaching($pValue = FALSE, $pDirectory = NULL) { - $this->_useDiskCaching = $pValue; + /** + * Set use disk caching where possible? + * + * @param boolean $pValue + * @param string $pDirectory Disk caching directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel2007 + */ + public function setUseDiskCaching($pValue = FALSE, $pDirectory = NULL) { + $this->_useDiskCaching = $pValue; - if ($pDirectory !== NULL) { - if (is_dir($pDirectory)) { - $this->_diskCachingDirectory = $pDirectory; - } else { - throw new PHPExcel_Writer_Exception("Directory does not exist: $pDirectory"); - } - } - return $this; - } + if ($pDirectory !== NULL) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new PHPExcel_Writer_Exception("Directory does not exist: $pDirectory"); + } + } + return $this; + } - /** - * Get disk caching directory - * - * @return string - */ - public function getDiskCachingDirectory() { - return $this->_diskCachingDirectory; - } + /** + * Get disk caching directory + * + * @return string + */ + public function getDiskCachingDirectory() { + return $this->_diskCachingDirectory; + } } diff --git a/Classes/PHPExcel/Writer/CSV.php b/Classes/PHPExcel/Writer/CSV.php index b81270d6..74cbc1a1 100644 --- a/Classes/PHPExcel/Writer/CSV.php +++ b/Classes/PHPExcel/Writer/CSV.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_CSV * * Copyright (c) 2006 - 2015 PHPExcel * @@ -19,292 +20,286 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Writer_CSV + * @package PHPExcel_Writer_CSV * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ +class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter +{ + /** + * PHPExcel object + * + * @var PHPExcel + */ + private $_phpExcel; + /** + * Delimiter + * + * @var string + */ + private $_delimiter = ','; -/** - * PHPExcel_Writer_CSV - * - * @category PHPExcel - * @package PHPExcel_Writer_CSV - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ -class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * PHPExcel object - * - * @var PHPExcel - */ - private $_phpExcel; + /** + * Enclosure + * + * @var string + */ + private $_enclosure = '"'; - /** - * Delimiter - * - * @var string - */ - private $_delimiter = ','; + /** + * Line ending + * + * @var string + */ + private $_lineEnding = PHP_EOL; - /** - * Enclosure - * - * @var string - */ - private $_enclosure = '"'; + /** + * Sheet index to write + * + * @var int + */ + private $_sheetIndex = 0; - /** - * Line ending - * - * @var string - */ - private $_lineEnding = PHP_EOL; + /** + * Whether to write a BOM (for UTF8). + * + * @var boolean + */ + private $_useBOM = false; - /** - * Sheet index to write - * - * @var int - */ - private $_sheetIndex = 0; + /** + * Whether to write a fully Excel compatible CSV file. + * + * @var boolean + */ + private $_excelCompatibility = false; - /** - * Whether to write a BOM (for UTF8). - * - * @var boolean - */ - private $_useBOM = false; + /** + * Create a new PHPExcel_Writer_CSV + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + $this->_phpExcel = $phpExcel; + } - /** - * Whether to write a fully Excel compatible CSV file. - * - * @var boolean - */ - private $_excelCompatibility = false; + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) + { + // Fetch sheet + $sheet = $this->_phpExcel->getSheet($this->_sheetIndex); - /** - * Create a new PHPExcel_Writer_CSV - * - * @param PHPExcel $phpExcel PHPExcel object - */ - public function __construct(PHPExcel $phpExcel) { - $this->_phpExcel = $phpExcel; - } + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); - /** - * Save PHPExcel to file - * - * @param string $pFilename - * @throws PHPExcel_Writer_Exception - */ - public function save($pFilename = null) { - // Fetch sheet - $sheet = $this->_phpExcel->getSheet($this->_sheetIndex); + // Open file + $fileHandle = fopen($pFilename, 'wb+'); + if ($fileHandle === false) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } - $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); - $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); - PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); - - // Open file - $fileHandle = fopen($pFilename, 'wb+'); - if ($fileHandle === false) { - throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); - } - - if ($this->_excelCompatibility) { - fwrite($fileHandle, "\xEF\xBB\xBF"); // Enforce UTF-8 BOM Header - $this->setEnclosure('"'); // Set enclosure to " - $this->setDelimiter(";"); // Set delimiter to a semi-colon + if ($this->_excelCompatibility) { + fwrite($fileHandle, "\xEF\xBB\xBF"); // Enforce UTF-8 BOM Header + $this->setEnclosure('"'); // Set enclosure to " + $this->setDelimiter(";"); // Set delimiter to a semi-colon $this->setLineEnding("\r\n"); - fwrite($fileHandle, 'sep=' . $this->getDelimiter() . $this->_lineEnding); - } elseif ($this->_useBOM) { - // Write the UTF-8 BOM code if required - fwrite($fileHandle, "\xEF\xBB\xBF"); - } + fwrite($fileHandle, 'sep=' . $this->getDelimiter() . $this->_lineEnding); + } elseif ($this->_useBOM) { + // Write the UTF-8 BOM code if required + fwrite($fileHandle, "\xEF\xBB\xBF"); + } - // Identify the range that we need to extract from the worksheet - $maxCol = $sheet->getHighestDataColumn(); - $maxRow = $sheet->getHighestDataRow(); + // Identify the range that we need to extract from the worksheet + $maxCol = $sheet->getHighestDataColumn(); + $maxRow = $sheet->getHighestDataRow(); - // Write rows to file - for($row = 1; $row <= $maxRow; ++$row) { - // Convert the row to an array... - $cellsArray = $sheet->rangeToArray('A'.$row.':'.$maxCol.$row,'', $this->_preCalculateFormulas); - // ... and write to the file - $this->_writeLine($fileHandle, $cellsArray[0]); - } + // Write rows to file + for($row = 1; $row <= $maxRow; ++$row) { + // Convert the row to an array... + $cellsArray = $sheet->rangeToArray('A'.$row.':'.$maxCol.$row,'', $this->_preCalculateFormulas); + // ... and write to the file + $this->_writeLine($fileHandle, $cellsArray[0]); + } - // Close file - fclose($fileHandle); + // Close file + fclose($fileHandle); - PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); - } + PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } - /** - * Get delimiter - * - * @return string - */ - public function getDelimiter() { - return $this->_delimiter; - } + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } - /** - * Set delimiter - * - * @param string $pValue Delimiter, defaults to , - * @return PHPExcel_Writer_CSV - */ - public function setDelimiter($pValue = ',') { - $this->_delimiter = $pValue; - return $this; - } + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Writer_CSV + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } - /** - * Get enclosure - * - * @return string - */ - public function getEnclosure() { - return $this->_enclosure; - } + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } - /** - * Set enclosure - * - * @param string $pValue Enclosure, defaults to " - * @return PHPExcel_Writer_CSV - */ - public function setEnclosure($pValue = '"') { - if ($pValue == '') { - $pValue = null; - } - $this->_enclosure = $pValue; - return $this; - } + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Writer_CSV + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = null; + } + $this->_enclosure = $pValue; + return $this; + } - /** - * Get line ending - * - * @return string - */ - public function getLineEnding() { - return $this->_lineEnding; - } + /** + * Get line ending + * + * @return string + */ + public function getLineEnding() { + return $this->_lineEnding; + } - /** - * Set line ending - * - * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) - * @return PHPExcel_Writer_CSV - */ - public function setLineEnding($pValue = PHP_EOL) { - $this->_lineEnding = $pValue; - return $this; - } + /** + * Set line ending + * + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Writer_CSV + */ + public function setLineEnding($pValue = PHP_EOL) { + $this->_lineEnding = $pValue; + return $this; + } - /** - * Get whether BOM should be used - * - * @return boolean - */ - public function getUseBOM() { - return $this->_useBOM; - } + /** + * Get whether BOM should be used + * + * @return boolean + */ + public function getUseBOM() { + return $this->_useBOM; + } - /** - * Set whether BOM should be used - * - * @param boolean $pValue Use UTF-8 byte-order mark? Defaults to false - * @return PHPExcel_Writer_CSV - */ - public function setUseBOM($pValue = false) { - $this->_useBOM = $pValue; - return $this; - } + /** + * Set whether BOM should be used + * + * @param boolean $pValue Use UTF-8 byte-order mark? Defaults to false + * @return PHPExcel_Writer_CSV + */ + public function setUseBOM($pValue = false) { + $this->_useBOM = $pValue; + return $this; + } - /** - * Get whether the file should be saved with full Excel Compatibility - * - * @return boolean - */ - public function getExcelCompatibility() { - return $this->_excelCompatibility; - } + /** + * Get whether the file should be saved with full Excel Compatibility + * + * @return boolean + */ + public function getExcelCompatibility() { + return $this->_excelCompatibility; + } - /** - * Set whether the file should be saved with full Excel Compatibility - * - * @param boolean $pValue Set the file to be written as a fully Excel compatible csv file - * Note that this overrides other settings such as useBOM, enclosure and delimiter - * @return PHPExcel_Writer_CSV - */ - public function setExcelCompatibility($pValue = false) { - $this->_excelCompatibility = $pValue; - return $this; - } + /** + * Set whether the file should be saved with full Excel Compatibility + * + * @param boolean $pValue Set the file to be written as a fully Excel compatible csv file + * Note that this overrides other settings such as useBOM, enclosure and delimiter + * @return PHPExcel_Writer_CSV + */ + public function setExcelCompatibility($pValue = false) { + $this->_excelCompatibility = $pValue; + return $this; + } - /** - * Get sheet index - * - * @return int - */ - public function getSheetIndex() { - return $this->_sheetIndex; - } + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } - /** - * Set sheet index - * - * @param int $pValue Sheet index - * @return PHPExcel_Writer_CSV - */ - public function setSheetIndex($pValue = 0) { - $this->_sheetIndex = $pValue; - return $this; - } + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Writer_CSV + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } - /** - * Write line to CSV file - * - * @param mixed $pFileHandle PHP filehandle - * @param array $pValues Array containing values in a row - * @throws PHPExcel_Writer_Exception - */ - private function _writeLine($pFileHandle = null, $pValues = null) { - if (is_array($pValues)) { - // No leading delimiter - $writeDelimiter = false; + /** + * Write line to CSV file + * + * @param mixed $pFileHandle PHP filehandle + * @param array $pValues Array containing values in a row + * @throws PHPExcel_Writer_Exception + */ + private function _writeLine($pFileHandle = null, $pValues = null) { + if (is_array($pValues)) { + // No leading delimiter + $writeDelimiter = false; - // Build the line - $line = ''; + // Build the line + $line = ''; - foreach ($pValues as $element) { - // Escape enclosures - $element = str_replace($this->_enclosure, $this->_enclosure . $this->_enclosure, $element); + foreach ($pValues as $element) { + // Escape enclosures + $element = str_replace($this->_enclosure, $this->_enclosure . $this->_enclosure, $element); - // Add delimiter - if ($writeDelimiter) { - $line .= $this->_delimiter; - } else { - $writeDelimiter = true; - } + // Add delimiter + if ($writeDelimiter) { + $line .= $this->_delimiter; + } else { + $writeDelimiter = true; + } - // Add enclosed string - $line .= $this->_enclosure . $element . $this->_enclosure; - } + // Add enclosed string + $line .= $this->_enclosure . $element . $this->_enclosure; + } - // Add line ending - $line .= $this->_lineEnding; + // Add line ending + $line .= $this->_lineEnding; - // Write to file + // Write to file fwrite($pFileHandle, $line); - } else { - throw new PHPExcel_Writer_Exception("Invalid data row passed to CSV writer."); - } - } + } else { + throw new PHPExcel_Writer_Exception("Invalid data row passed to CSV writer."); + } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007.php b/Classes/PHPExcel/Writer/Excel2007.php index a3abe16a..6a2be44c 100644 --- a/Classes/PHPExcel/Writer/Excel2007.php +++ b/Classes/PHPExcel/Writer/Excel2007.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_Excel2007 * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,421 +22,412 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_Excel2007 - * - * @category PHPExcel - * @package PHPExcel_Writer_2007 - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * Pre-calculate formulas - * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are - * immediately available to MS Excel or other office spreadsheet viewer when opening the file - * + /** + * Pre-calculate formulas + * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are + * immediately available to MS Excel or other office spreadsheet viewer when opening the file + * * Overrides the default TRUE for this specific writer for performance reasons * - * @var boolean - */ - protected $_preCalculateFormulas = FALSE; + * @var boolean + */ + protected $_preCalculateFormulas = false; - /** - * Office2003 compatibility - * - * @var boolean - */ - private $_office2003compatibility = false; + /** + * Office2003 compatibility + * + * @var boolean + */ + private $_office2003compatibility = false; - /** - * Private writer parts - * - * @var PHPExcel_Writer_Excel2007_WriterPart[] - */ - private $_writerParts = array(); + /** + * Private writer parts + * + * @var PHPExcel_Writer_Excel2007_WriterPart[] + */ + private $_writerParts = array(); - /** - * Private PHPExcel - * - * @var PHPExcel - */ - private $_spreadSheet; + /** + * Private PHPExcel + * + * @var PHPExcel + */ + private $_spreadSheet; - /** - * Private string table - * - * @var string[] - */ - private $_stringTable = array(); + /** + * Private string table + * + * @var string[] + */ + private $_stringTable = array(); - /** - * Private unique PHPExcel_Style_Conditional HashTable - * - * @var PHPExcel_HashTable - */ - private $_stylesConditionalHashTable; + /** + * Private unique PHPExcel_Style_Conditional HashTable + * + * @var PHPExcel_HashTable + */ + private $_stylesConditionalHashTable; - /** - * Private unique PHPExcel_Style HashTable - * - * @var PHPExcel_HashTable - */ - private $_styleHashTable; + /** + * Private unique PHPExcel_Style HashTable + * + * @var PHPExcel_HashTable + */ + private $_styleHashTable; - /** - * Private unique PHPExcel_Style_Fill HashTable - * - * @var PHPExcel_HashTable - */ - private $_fillHashTable; + /** + * Private unique PHPExcel_Style_Fill HashTable + * + * @var PHPExcel_HashTable + */ + private $_fillHashTable; - /** - * Private unique PHPExcel_Style_Font HashTable - * - * @var PHPExcel_HashTable - */ - private $_fontHashTable; + /** + * Private unique PHPExcel_Style_Font HashTable + * + * @var PHPExcel_HashTable + */ + private $_fontHashTable; - /** - * Private unique PHPExcel_Style_Borders HashTable - * - * @var PHPExcel_HashTable - */ - private $_bordersHashTable ; + /** + * Private unique PHPExcel_Style_Borders HashTable + * + * @var PHPExcel_HashTable + */ + private $_bordersHashTable ; - /** - * Private unique PHPExcel_Style_NumberFormat HashTable - * - * @var PHPExcel_HashTable - */ - private $_numFmtHashTable; + /** + * Private unique PHPExcel_Style_NumberFormat HashTable + * + * @var PHPExcel_HashTable + */ + private $_numFmtHashTable; - /** - * Private unique PHPExcel_Worksheet_BaseDrawing HashTable - * - * @var PHPExcel_HashTable - */ - private $_drawingHashTable; + /** + * Private unique PHPExcel_Worksheet_BaseDrawing HashTable + * + * @var PHPExcel_HashTable + */ + private $_drawingHashTable; /** * Create a new PHPExcel_Writer_Excel2007 * - * @param PHPExcel $pPHPExcel + * @param PHPExcel $pPHPExcel */ public function __construct(PHPExcel $pPHPExcel = null) { - // Assign PHPExcel - $this->setPHPExcel($pPHPExcel); + // Assign PHPExcel + $this->setPHPExcel($pPHPExcel); - $writerPartsArray = array( 'stringtable' => 'PHPExcel_Writer_Excel2007_StringTable', - 'contenttypes' => 'PHPExcel_Writer_Excel2007_ContentTypes', - 'docprops' => 'PHPExcel_Writer_Excel2007_DocProps', - 'rels' => 'PHPExcel_Writer_Excel2007_Rels', - 'theme' => 'PHPExcel_Writer_Excel2007_Theme', - 'style' => 'PHPExcel_Writer_Excel2007_Style', - 'workbook' => 'PHPExcel_Writer_Excel2007_Workbook', - 'worksheet' => 'PHPExcel_Writer_Excel2007_Worksheet', - 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', - 'comments' => 'PHPExcel_Writer_Excel2007_Comments', - 'chart' => 'PHPExcel_Writer_Excel2007_Chart', - 'relsvba' => 'PHPExcel_Writer_Excel2007_RelsVBA', - 'relsribbonobjects' => 'PHPExcel_Writer_Excel2007_RelsRibbon' - ); + $writerPartsArray = array( 'stringtable' => 'PHPExcel_Writer_Excel2007_StringTable', + 'contenttypes' => 'PHPExcel_Writer_Excel2007_ContentTypes', + 'docprops' => 'PHPExcel_Writer_Excel2007_DocProps', + 'rels' => 'PHPExcel_Writer_Excel2007_Rels', + 'theme' => 'PHPExcel_Writer_Excel2007_Theme', + 'style' => 'PHPExcel_Writer_Excel2007_Style', + 'workbook' => 'PHPExcel_Writer_Excel2007_Workbook', + 'worksheet' => 'PHPExcel_Writer_Excel2007_Worksheet', + 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', + 'comments' => 'PHPExcel_Writer_Excel2007_Comments', + 'chart' => 'PHPExcel_Writer_Excel2007_Chart', + 'relsvba' => 'PHPExcel_Writer_Excel2007_RelsVBA', + 'relsribbonobjects' => 'PHPExcel_Writer_Excel2007_RelsRibbon' + ); - // Initialise writer parts - // and Assign their parent IWriters - foreach ($writerPartsArray as $writer => $class) { - $this->_writerParts[$writer] = new $class($this); - } + // Initialise writer parts + // and Assign their parent IWriters + foreach ($writerPartsArray as $writer => $class) { + $this->_writerParts[$writer] = new $class($this); + } - $hashTablesArray = array( '_stylesConditionalHashTable', '_fillHashTable', '_fontHashTable', - '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable', + $hashTablesArray = array( '_stylesConditionalHashTable', '_fillHashTable', '_fontHashTable', + '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable', '_styleHashTable' - ); + ); - // Set HashTable variables - foreach ($hashTablesArray as $tableName) { - $this->$tableName = new PHPExcel_HashTable(); - } + // Set HashTable variables + foreach ($hashTablesArray as $tableName) { + $this->$tableName = new PHPExcel_HashTable(); + } } - /** - * Get writer part - * - * @param string $pPartName Writer part name - * @return PHPExcel_Writer_Excel2007_WriterPart - */ - public function getWriterPart($pPartName = '') { - if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { - return $this->_writerParts[strtolower($pPartName)]; - } else { - return null; - } - } + /** + * Get writer part + * + * @param string $pPartName Writer part name + * @return PHPExcel_Writer_Excel2007_WriterPart + */ + public function getWriterPart($pPartName = '') { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } - /** - * Save PHPExcel to file - * - * @param string $pFilename - * @throws PHPExcel_Writer_Exception - */ - public function save($pFilename = null) - { - if ($this->_spreadSheet !== NULL) { - // garbage collect - $this->_spreadSheet->garbageCollect(); + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) + { + if ($this->_spreadSheet !== NULL) { + // garbage collect + $this->_spreadSheet->garbageCollect(); - // If $pFilename is php://output or php://stdout, make it a temporary file... - $originalFilename = $pFilename; - if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { - $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp'); - if ($pFilename == '') { - $pFilename = $originalFilename; - } - } + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } - $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog(); - PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE); - $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); - PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); - // Create string lookup table - $this->_stringTable = array(); - for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { - $this->_stringTable = $this->getWriterPart('StringTable')->createStringTable($this->_spreadSheet->getSheet($i), $this->_stringTable); - } + // Create string lookup table + $this->_stringTable = array(); + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $this->_stringTable = $this->getWriterPart('StringTable')->createStringTable($this->_spreadSheet->getSheet($i), $this->_stringTable); + } - // Create styles dictionaries - $this->_styleHashTable->addFromSource( $this->getWriterPart('Style')->allStyles($this->_spreadSheet) ); - $this->_stylesConditionalHashTable->addFromSource( $this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) ); - $this->_fillHashTable->addFromSource( $this->getWriterPart('Style')->allFills($this->_spreadSheet) ); - $this->_fontHashTable->addFromSource( $this->getWriterPart('Style')->allFonts($this->_spreadSheet) ); - $this->_bordersHashTable->addFromSource( $this->getWriterPart('Style')->allBorders($this->_spreadSheet) ); - $this->_numFmtHashTable->addFromSource( $this->getWriterPart('Style')->allNumberFormats($this->_spreadSheet) ); + // Create styles dictionaries + $this->_styleHashTable->addFromSource( $this->getWriterPart('Style')->allStyles($this->_spreadSheet) ); + $this->_stylesConditionalHashTable->addFromSource( $this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) ); + $this->_fillHashTable->addFromSource( $this->getWriterPart('Style')->allFills($this->_spreadSheet) ); + $this->_fontHashTable->addFromSource( $this->getWriterPart('Style')->allFonts($this->_spreadSheet) ); + $this->_bordersHashTable->addFromSource( $this->getWriterPart('Style')->allBorders($this->_spreadSheet) ); + $this->_numFmtHashTable->addFromSource( $this->getWriterPart('Style')->allNumberFormats($this->_spreadSheet) ); - // Create drawing dictionary - $this->_drawingHashTable->addFromSource( $this->getWriterPart('Drawing')->allDrawings($this->_spreadSheet) ); + // Create drawing dictionary + $this->_drawingHashTable->addFromSource( $this->getWriterPart('Drawing')->allDrawings($this->_spreadSheet) ); - // Create new ZIP file and open it for writing - $zipClass = PHPExcel_Settings::getZipClass(); - $objZip = new $zipClass(); + // Create new ZIP file and open it for writing + $zipClass = PHPExcel_Settings::getZipClass(); + $objZip = new $zipClass(); - // Retrieve OVERWRITE and CREATE constants from the instantiated zip class - // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP - $ro = new ReflectionObject($objZip); - $zipOverWrite = $ro->getConstant('OVERWRITE'); - $zipCreate = $ro->getConstant('CREATE'); + // Retrieve OVERWRITE and CREATE constants from the instantiated zip class + // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP + $ro = new ReflectionObject($objZip); + $zipOverWrite = $ro->getConstant('OVERWRITE'); + $zipCreate = $ro->getConstant('CREATE'); - if (file_exists($pFilename)) { - unlink($pFilename); - } - // Try opening the ZIP file - if ($objZip->open($pFilename, $zipOverWrite) !== true) { - if ($objZip->open($pFilename, $zipCreate) !== true) { - throw new PHPExcel_Writer_Exception("Could not open " . $pFilename . " for writing."); - } - } + if (file_exists($pFilename)) { + unlink($pFilename); + } + // Try opening the ZIP file + if ($objZip->open($pFilename, $zipOverWrite) !== true) { + if ($objZip->open($pFilename, $zipCreate) !== true) { + throw new PHPExcel_Writer_Exception("Could not open " . $pFilename . " for writing."); + } + } - // Add [Content_Types].xml to ZIP file - $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); + // Add [Content_Types].xml to ZIP file + $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); - //if hasMacros, add the vbaProject.bin file, Certificate file(if exists) - if($this->_spreadSheet->hasMacros()){ - $macrosCode=$this->_spreadSheet->getMacrosCode(); - if(!is_null($macrosCode)){// we have the code ? - $objZip->addFromString('xl/vbaProject.bin', $macrosCode);//allways in 'xl', allways named vbaProject.bin - if($this->_spreadSheet->hasMacrosCertificate()){//signed macros ? - // Yes : add the certificate file and the related rels file - $objZip->addFromString('xl/vbaProjectSignature.bin', $this->_spreadSheet->getMacrosCertificate()); - $objZip->addFromString('xl/_rels/vbaProject.bin.rels', - $this->getWriterPart('RelsVBA')->writeVBARelationships($this->_spreadSheet)); - } - } - } - //a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels) - if($this->_spreadSheet->hasRibbon()){ - $tmpRibbonTarget=$this->_spreadSheet->getRibbonXMLData('target'); - $objZip->addFromString($tmpRibbonTarget, $this->_spreadSheet->getRibbonXMLData('data')); - if($this->_spreadSheet->hasRibbonBinObjects()){ - $tmpRootPath=dirname($tmpRibbonTarget).'/'; - $ribbonBinObjects=$this->_spreadSheet->getRibbonBinObjects('data');//the files to write - foreach($ribbonBinObjects as $aPath=>$aContent){ - $objZip->addFromString($tmpRootPath.$aPath, $aContent); - } - //the rels for files - $objZip->addFromString($tmpRootPath.'_rels/'.basename($tmpRibbonTarget).'.rels', - $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->_spreadSheet)); - } - } - - // Add relationships to ZIP file - $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); - $objZip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet)); + //if hasMacros, add the vbaProject.bin file, Certificate file(if exists) + if($this->_spreadSheet->hasMacros()){ + $macrosCode=$this->_spreadSheet->getMacrosCode(); + if(!is_null($macrosCode)){// we have the code ? + $objZip->addFromString('xl/vbaProject.bin', $macrosCode);//allways in 'xl', allways named vbaProject.bin + if($this->_spreadSheet->hasMacrosCertificate()){//signed macros ? + // Yes : add the certificate file and the related rels file + $objZip->addFromString('xl/vbaProjectSignature.bin', $this->_spreadSheet->getMacrosCertificate()); + $objZip->addFromString('xl/_rels/vbaProject.bin.rels', + $this->getWriterPart('RelsVBA')->writeVBARelationships($this->_spreadSheet)); + } + } + } + //a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels) + if($this->_spreadSheet->hasRibbon()){ + $tmpRibbonTarget=$this->_spreadSheet->getRibbonXMLData('target'); + $objZip->addFromString($tmpRibbonTarget, $this->_spreadSheet->getRibbonXMLData('data')); + if($this->_spreadSheet->hasRibbonBinObjects()){ + $tmpRootPath=dirname($tmpRibbonTarget).'/'; + $ribbonBinObjects=$this->_spreadSheet->getRibbonBinObjects('data');//the files to write + foreach($ribbonBinObjects as $aPath=>$aContent){ + $objZip->addFromString($tmpRootPath.$aPath, $aContent); + } + //the rels for files + $objZip->addFromString($tmpRootPath.'_rels/'.basename($tmpRibbonTarget).'.rels', + $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->_spreadSheet)); + } + } + + // Add relationships to ZIP file + $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); + $objZip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet)); - // Add document properties to ZIP file - $objZip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->_spreadSheet)); - $objZip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->_spreadSheet)); - $customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->_spreadSheet); - if ($customPropertiesPart !== NULL) { - $objZip->addFromString('docProps/custom.xml', $customPropertiesPart); - } + // Add document properties to ZIP file + $objZip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->_spreadSheet)); + $objZip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->_spreadSheet)); + $customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->_spreadSheet); + if ($customPropertiesPart !== NULL) { + $objZip->addFromString('docProps/custom.xml', $customPropertiesPart); + } - // Add theme to ZIP file - $objZip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->_spreadSheet)); + // Add theme to ZIP file + $objZip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->_spreadSheet)); - // Add string table to ZIP file - $objZip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->_stringTable)); + // Add string table to ZIP file + $objZip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->_stringTable)); - // Add styles to ZIP file - $objZip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->_spreadSheet)); + // Add styles to ZIP file + $objZip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->_spreadSheet)); - // Add workbook to ZIP file - $objZip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->_spreadSheet, $this->_preCalculateFormulas)); + // Add workbook to ZIP file + $objZip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->_spreadSheet, $this->_preCalculateFormulas)); - $chartCount = 0; - // Add worksheets - for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { - $objZip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->_spreadSheet->getSheet($i), $this->_stringTable, $this->_includeCharts)); - if ($this->_includeCharts) { - $charts = $this->_spreadSheet->getSheet($i)->getChartCollection(); - if (count($charts) > 0) { - foreach($charts as $chart) { - $objZip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart)); - $chartCount++; - } - } - } - } + $chartCount = 0; + // Add worksheets + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $objZip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->_spreadSheet->getSheet($i), $this->_stringTable, $this->_includeCharts)); + if ($this->_includeCharts) { + $charts = $this->_spreadSheet->getSheet($i)->getChartCollection(); + if (count($charts) > 0) { + foreach($charts as $chart) { + $objZip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart)); + $chartCount++; + } + } + } + } - $chartRef1 = $chartRef2 = 0; - // Add worksheet relationships (drawings, ...) - for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $chartRef1 = $chartRef2 = 0; + // Add worksheet relationships (drawings, ...) + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { - // Add relationships - $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts)); + // Add relationships + $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts)); - $drawings = $this->_spreadSheet->getSheet($i)->getDrawingCollection(); - $drawingCount = count($drawings); - if ($this->_includeCharts) { - $chartCount = $this->_spreadSheet->getSheet($i)->getChartCount(); - } + $drawings = $this->_spreadSheet->getSheet($i)->getDrawingCollection(); + $drawingCount = count($drawings); + if ($this->_includeCharts) { + $chartCount = $this->_spreadSheet->getSheet($i)->getChartCount(); + } - // Add drawing and image relationship parts - if (($drawingCount > 0) || ($chartCount > 0)) { - // Drawing relationships - $objZip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->_spreadSheet->getSheet($i),$chartRef1, $this->_includeCharts)); + // Add drawing and image relationship parts + if (($drawingCount > 0) || ($chartCount > 0)) { + // Drawing relationships + $objZip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->_spreadSheet->getSheet($i),$chartRef1, $this->_includeCharts)); - // Drawings - $objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts)); - } + // Drawings + $objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts)); + } - // Add comment relationship parts - if (count($this->_spreadSheet->getSheet($i)->getComments()) > 0) { - // VML Comments - $objZip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->_spreadSheet->getSheet($i))); + // Add comment relationship parts + if (count($this->_spreadSheet->getSheet($i)->getComments()) > 0) { + // VML Comments + $objZip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->_spreadSheet->getSheet($i))); - // Comments - $objZip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->_spreadSheet->getSheet($i))); - } + // Comments + $objZip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->_spreadSheet->getSheet($i))); + } - // Add header/footer relationship parts - if (count($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) { - // VML Drawings - $objZip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->_spreadSheet->getSheet($i))); + // Add header/footer relationship parts + if (count($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) { + // VML Drawings + $objZip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->_spreadSheet->getSheet($i))); - // VML Drawing relationships - $objZip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->_spreadSheet->getSheet($i))); + // VML Drawing relationships + $objZip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->_spreadSheet->getSheet($i))); - // Media - foreach ($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) { - $objZip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath())); - } - } - } + // Media + foreach ($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) { + $objZip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath())); + } + } + } - // Add media - for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { - if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { - $imageContents = null; - $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); - if (strpos($imagePath, 'zip://') !== false) { - $imagePath = substr($imagePath, 6); - $imagePathSplitted = explode('#', $imagePath); + // Add media + for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { + if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { + $imageContents = null; + $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); + if (strpos($imagePath, 'zip://') !== false) { + $imagePath = substr($imagePath, 6); + $imagePathSplitted = explode('#', $imagePath); - $imageZip = new ZipArchive(); - $imageZip->open($imagePathSplitted[0]); - $imageContents = $imageZip->getFromName($imagePathSplitted[1]); - $imageZip->close(); - unset($imageZip); - } else { - $imageContents = file_get_contents($imagePath); - } + $imageZip = new ZipArchive(); + $imageZip->open($imagePathSplitted[0]); + $imageContents = $imageZip->getFromName($imagePathSplitted[1]); + $imageZip->close(); + unset($imageZip); + } else { + $imageContents = file_get_contents($imagePath); + } - $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); - } else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { - ob_start(); - call_user_func( - $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), - $this->getDrawingHashTable()->getByIndex($i)->getImageResource() - ); - $imageContents = ob_get_contents(); - ob_end_clean(); + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { + ob_start(); + call_user_func( + $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), + $this->getDrawingHashTable()->getByIndex($i)->getImageResource() + ); + $imageContents = ob_get_contents(); + ob_end_clean(); - $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); - } - } + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } + } - PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); - PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); - // Close file - if ($objZip->close() === false) { - throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); - } + // Close file + if ($objZip->close() === false) { + throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); + } - // If a temporary file was used, copy it to the correct file stream - if ($originalFilename != $pFilename) { - if (copy($pFilename, $originalFilename) === false) { - throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); - } - @unlink($pFilename); - } - } else { - throw new PHPExcel_Writer_Exception("PHPExcel object unassigned."); - } - } + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + } else { + throw new PHPExcel_Writer_Exception("PHPExcel object unassigned."); + } + } - /** - * Get PHPExcel object - * - * @return PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function getPHPExcel() { - if ($this->_spreadSheet !== null) { - return $this->_spreadSheet; - } else { - throw new PHPExcel_Writer_Exception("No PHPExcel assigned."); - } - } + /** + * Get PHPExcel object + * + * @return PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function getPHPExcel() { + if ($this->_spreadSheet !== null) { + return $this->_spreadSheet; + } else { + throw new PHPExcel_Writer_Exception("No PHPExcel assigned."); + } + } - /** - * Set PHPExcel object - * - * @param PHPExcel $pPHPExcel PHPExcel object - * @throws PHPExcel_Writer_Exception - * @return PHPExcel_Writer_Excel2007 - */ - public function setPHPExcel(PHPExcel $pPHPExcel = null) { - $this->_spreadSheet = $pPHPExcel; - return $this; - } + /** + * Set PHPExcel object + * + * @param PHPExcel $pPHPExcel PHPExcel object + * @throws PHPExcel_Writer_Exception + * @return PHPExcel_Writer_Excel2007 + */ + public function setPHPExcel(PHPExcel $pPHPExcel = null) { + $this->_spreadSheet = $pPHPExcel; + return $this; + } /** * Get string table @@ -443,7 +435,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return string[] */ public function getStringTable() { - return $this->_stringTable; + return $this->_stringTable; } /** @@ -452,7 +444,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getStyleHashTable() { - return $this->_styleHashTable; + return $this->_styleHashTable; } /** @@ -461,7 +453,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getStylesConditionalHashTable() { - return $this->_stylesConditionalHashTable; + return $this->_stylesConditionalHashTable; } /** @@ -470,7 +462,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getFillHashTable() { - return $this->_fillHashTable; + return $this->_fillHashTable; } /** @@ -479,7 +471,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getFontHashTable() { - return $this->_fontHashTable; + return $this->_fontHashTable; } /** @@ -488,7 +480,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getBordersHashTable() { - return $this->_bordersHashTable; + return $this->_bordersHashTable; } /** @@ -497,7 +489,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getNumFmtHashTable() { - return $this->_numFmtHashTable; + return $this->_numFmtHashTable; } /** @@ -506,7 +498,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return PHPExcel_HashTable */ public function getDrawingHashTable() { - return $this->_drawingHashTable; + return $this->_drawingHashTable; } /** @@ -515,18 +507,18 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE * @return boolean */ public function getOffice2003Compatibility() { - return $this->_office2003compatibility; + return $this->_office2003compatibility; } /** * Set Office2003 compatibility * - * @param boolean $pValue Office2003 compatibility? + * @param boolean $pValue Office2003 compatibility? * @return PHPExcel_Writer_Excel2007 */ public function setOffice2003Compatibility($pValue = false) { - $this->_office2003compatibility = $pValue; - return $this; + $this->_office2003compatibility = $pValue; + return $this; } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Chart.php b/Classes/PHPExcel/Writer/Excel2007/Chart.php index 91c12bbb..a610a13e 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Chart.php +++ b/Classes/PHPExcel/Writer/Excel2007/Chart.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -54,7 +54,7 @@ class PHPExcel_Writer_Excel2007_Chart extends } else { $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); } - // Ensure that data series values are up-to-date before we save + // Ensure that data series values are up-to-date before we save $pChart->refresh(); // XML header @@ -284,7 +284,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $this->_writeDataLbls($objWriter, $layout); if ($chartType === PHPExcel_Chart_DataSeries::TYPE_LINECHART) { - // Line only, Line3D can't be smoothed + // Line only, Line3D can't be smoothed $objWriter->startElement('c:smooth'); $objWriter->writeAttribute('val', (integer) $plotGroup->getSmoothLine()); @@ -334,11 +334,11 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Generate 2 unique numbers to use for axId values - // $id1 = $id2 = rand(10000000,99999999); - // do { - // $id2 = rand(10000000,99999999); - // } while ($id1 == $id2); + // Generate 2 unique numbers to use for axId values + // $id1 = $id2 = rand(10000000,99999999); + // do { + // $id2 = rand(10000000,99999999); + // } while ($id1 == $id2); $id1 = '75091328'; $id2 = '75089408'; @@ -490,7 +490,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $caption = $caption[0]; } $objWriter->startElement('a:t'); - // $objWriter->writeAttribute('xml:space', 'preserve'); + // $objWriter->writeAttribute('xml:space', 'preserve'); $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML($caption)); $objWriter->endElement(); @@ -840,7 +840,7 @@ class PHPExcel_Writer_Excel2007_Chart extends } $objWriter->startElement('a:t'); - // $objWriter->writeAttribute('xml:space', 'preserve'); + // $objWriter->writeAttribute('xml:space', 'preserve'); $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML($caption)); $objWriter->endElement(); @@ -1117,7 +1117,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Get these details before the loop, because we can use the count to check for varyColors + // Get these details before the loop, because we can use the count to check for varyColors $plotSeriesOrder = $plotGroup->getPlotOrder(); $plotSeriesCount = count($plotSeriesOrder); @@ -1177,7 +1177,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Labels + // Labels $plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesRef); if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) { $objWriter->startElement('c:tx'); @@ -1187,7 +1187,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Formatting for the points + // Formatting for the points if (($groupType == PHPExcel_Chart_DataSeries::TYPE_LINECHART) || ($groupType == PHPExcel_Chart_DataSeries::TYPE_STOCKCHART) ) { @@ -1231,7 +1231,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Category Labels + // Category Labels $plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesRef); if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) { $catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries(); @@ -1263,7 +1263,7 @@ class PHPExcel_Writer_Excel2007_Chart extends $objWriter->endElement(); } - // Values + // Values if ($plotSeriesValues) { $valIsMultiLevelSeries = $valIsMultiLevelSeries || $plotSeriesValues->isMultiLevelSeries(); diff --git a/Classes/PHPExcel/Writer/Excel2007/Comments.php b/Classes/PHPExcel/Writer/Excel2007/Comments.php index a6faaaa9..177e0fae 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Comments.php +++ b/Classes/PHPExcel/Writer/Excel2007/Comments.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,234 +35,234 @@ */ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write comments to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeComments(PHPExcel_Worksheet $pWorksheet = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write comments to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeComments(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Comments cache - $comments = $pWorksheet->getComments(); + // Comments cache + $comments = $pWorksheet->getComments(); - // Authors cache - $authors = array(); - $authorId = 0; - foreach ($comments as $comment) { - if (!isset($authors[$comment->getAuthor()])) { - $authors[$comment->getAuthor()] = $authorId++; - } - } + // Authors cache + $authors = array(); + $authorId = 0; + foreach ($comments as $comment) { + if (!isset($authors[$comment->getAuthor()])) { + $authors[$comment->getAuthor()] = $authorId++; + } + } - // comments - $objWriter->startElement('comments'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + // comments + $objWriter->startElement('comments'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - // Loop through authors - $objWriter->startElement('authors'); - foreach ($authors as $author => $index) { - $objWriter->writeElement('author', $author); - } - $objWriter->endElement(); + // Loop through authors + $objWriter->startElement('authors'); + foreach ($authors as $author => $index) { + $objWriter->writeElement('author', $author); + } + $objWriter->endElement(); - // Loop through comments - $objWriter->startElement('commentList'); - foreach ($comments as $key => $value) { - $this->_writeComment($objWriter, $key, $value, $authors); - } - $objWriter->endElement(); + // Loop through comments + $objWriter->startElement('commentList'); + foreach ($comments as $key => $value) { + $this->_writeComment($objWriter, $key, $value, $authors); + } + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write comment to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pCellReference Cell reference - * @param PHPExcel_Comment $pComment Comment - * @param array $pAuthors Array of authors - * @throws PHPExcel_Writer_Exception - */ - public function _writeComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null, $pAuthors = null) - { - // comment - $objWriter->startElement('comment'); - $objWriter->writeAttribute('ref', $pCellReference); - $objWriter->writeAttribute('authorId', $pAuthors[$pComment->getAuthor()]); + /** + * Write comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pCellReference Cell reference + * @param PHPExcel_Comment $pComment Comment + * @param array $pAuthors Array of authors + * @throws PHPExcel_Writer_Exception + */ + public function _writeComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null, $pAuthors = null) + { + // comment + $objWriter->startElement('comment'); + $objWriter->writeAttribute('ref', $pCellReference); + $objWriter->writeAttribute('authorId', $pAuthors[$pComment->getAuthor()]); - // text - $objWriter->startElement('text'); - $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText()); - $objWriter->endElement(); + // text + $objWriter->startElement('text'); + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText()); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write VML comments to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeVMLComments(PHPExcel_Worksheet $pWorksheet = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write VML comments to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVMLComments(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Comments cache - $comments = $pWorksheet->getComments(); + // Comments cache + $comments = $pWorksheet->getComments(); - // xml - $objWriter->startElement('xml'); - $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); - $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); - $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); + // xml + $objWriter->startElement('xml'); + $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); - // o:shapelayout - $objWriter->startElement('o:shapelayout'); - $objWriter->writeAttribute('v:ext', 'edit'); + // o:shapelayout + $objWriter->startElement('o:shapelayout'); + $objWriter->writeAttribute('v:ext', 'edit'); - // o:idmap - $objWriter->startElement('o:idmap'); - $objWriter->writeAttribute('v:ext', 'edit'); - $objWriter->writeAttribute('data', '1'); - $objWriter->endElement(); + // o:idmap + $objWriter->startElement('o:idmap'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('data', '1'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // v:shapetype - $objWriter->startElement('v:shapetype'); - $objWriter->writeAttribute('id', '_x0000_t202'); - $objWriter->writeAttribute('coordsize', '21600,21600'); - $objWriter->writeAttribute('o:spt', '202'); - $objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe'); + // v:shapetype + $objWriter->startElement('v:shapetype'); + $objWriter->writeAttribute('id', '_x0000_t202'); + $objWriter->writeAttribute('coordsize', '21600,21600'); + $objWriter->writeAttribute('o:spt', '202'); + $objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe'); - // v:stroke - $objWriter->startElement('v:stroke'); - $objWriter->writeAttribute('joinstyle', 'miter'); - $objWriter->endElement(); + // v:stroke + $objWriter->startElement('v:stroke'); + $objWriter->writeAttribute('joinstyle', 'miter'); + $objWriter->endElement(); - // v:path - $objWriter->startElement('v:path'); - $objWriter->writeAttribute('gradientshapeok', 't'); - $objWriter->writeAttribute('o:connecttype', 'rect'); - $objWriter->endElement(); + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('gradientshapeok', 't'); + $objWriter->writeAttribute('o:connecttype', 'rect'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // Loop through comments - foreach ($comments as $key => $value) { - $this->_writeVMLComment($objWriter, $key, $value); - } + // Loop through comments + foreach ($comments as $key => $value) { + $this->_writeVMLComment($objWriter, $key, $value); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write VML comment to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pCellReference Cell reference - * @param PHPExcel_Comment $pComment Comment - * @throws PHPExcel_Writer_Exception - */ - public function _writeVMLComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null) - { - // Metadata - list($column, $row) = PHPExcel_Cell::coordinateFromString($pCellReference); - $column = PHPExcel_Cell::columnIndexFromString($column); - $id = 1024 + $column + $row; - $id = substr($id, 0, 4); + /** + * Write VML comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pCellReference Cell reference + * @param PHPExcel_Comment $pComment Comment + * @throws PHPExcel_Writer_Exception + */ + public function _writeVMLComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null) + { + // Metadata + list($column, $row) = PHPExcel_Cell::coordinateFromString($pCellReference); + $column = PHPExcel_Cell::columnIndexFromString($column); + $id = 1024 + $column + $row; + $id = substr($id, 0, 4); - // v:shape - $objWriter->startElement('v:shape'); - $objWriter->writeAttribute('id', '_x0000_s' . $id); - $objWriter->writeAttribute('type', '#_x0000_t202'); - $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $pComment->getMarginLeft() . ';margin-top:' . $pComment->getMarginTop() . ';width:' . $pComment->getWidth() . ';height:' . $pComment->getHeight() . ';z-index:1;visibility:' . ($pComment->getVisible() ? 'visible' : 'hidden')); - $objWriter->writeAttribute('fillcolor', '#' . $pComment->getFillColor()->getRGB()); - $objWriter->writeAttribute('o:insetmode', 'auto'); + // v:shape + $objWriter->startElement('v:shape'); + $objWriter->writeAttribute('id', '_x0000_s' . $id); + $objWriter->writeAttribute('type', '#_x0000_t202'); + $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $pComment->getMarginLeft() . ';margin-top:' . $pComment->getMarginTop() . ';width:' . $pComment->getWidth() . ';height:' . $pComment->getHeight() . ';z-index:1;visibility:' . ($pComment->getVisible() ? 'visible' : 'hidden')); + $objWriter->writeAttribute('fillcolor', '#' . $pComment->getFillColor()->getRGB()); + $objWriter->writeAttribute('o:insetmode', 'auto'); - // v:fill - $objWriter->startElement('v:fill'); - $objWriter->writeAttribute('color2', '#' . $pComment->getFillColor()->getRGB()); - $objWriter->endElement(); + // v:fill + $objWriter->startElement('v:fill'); + $objWriter->writeAttribute('color2', '#' . $pComment->getFillColor()->getRGB()); + $objWriter->endElement(); - // v:shadow - $objWriter->startElement('v:shadow'); - $objWriter->writeAttribute('on', 't'); - $objWriter->writeAttribute('color', 'black'); - $objWriter->writeAttribute('obscured', 't'); - $objWriter->endElement(); + // v:shadow + $objWriter->startElement('v:shadow'); + $objWriter->writeAttribute('on', 't'); + $objWriter->writeAttribute('color', 'black'); + $objWriter->writeAttribute('obscured', 't'); + $objWriter->endElement(); - // v:path - $objWriter->startElement('v:path'); - $objWriter->writeAttribute('o:connecttype', 'none'); - $objWriter->endElement(); + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('o:connecttype', 'none'); + $objWriter->endElement(); - // v:textbox - $objWriter->startElement('v:textbox'); - $objWriter->writeAttribute('style', 'mso-direction-alt:auto'); + // v:textbox + $objWriter->startElement('v:textbox'); + $objWriter->writeAttribute('style', 'mso-direction-alt:auto'); - // div - $objWriter->startElement('div'); - $objWriter->writeAttribute('style', 'text-align:left'); - $objWriter->endElement(); + // div + $objWriter->startElement('div'); + $objWriter->writeAttribute('style', 'text-align:left'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // x:ClientData - $objWriter->startElement('x:ClientData'); - $objWriter->writeAttribute('ObjectType', 'Note'); + // x:ClientData + $objWriter->startElement('x:ClientData'); + $objWriter->writeAttribute('ObjectType', 'Note'); - // x:MoveWithCells - $objWriter->writeElement('x:MoveWithCells', ''); + // x:MoveWithCells + $objWriter->writeElement('x:MoveWithCells', ''); - // x:SizeWithCells - $objWriter->writeElement('x:SizeWithCells', ''); + // x:SizeWithCells + $objWriter->writeElement('x:SizeWithCells', ''); - // x:Anchor - //$objWriter->writeElement('x:Anchor', $column . ', 15, ' . ($row - 2) . ', 10, ' . ($column + 4) . ', 15, ' . ($row + 5) . ', 18'); + // x:Anchor + //$objWriter->writeElement('x:Anchor', $column . ', 15, ' . ($row - 2) . ', 10, ' . ($column + 4) . ', 15, ' . ($row + 5) . ', 18'); - // x:AutoFill - $objWriter->writeElement('x:AutoFill', 'False'); + // x:AutoFill + $objWriter->writeElement('x:AutoFill', 'False'); - // x:Row - $objWriter->writeElement('x:Row', ($row - 1)); + // x:Row + $objWriter->writeElement('x:Row', ($row - 1)); - // x:Column - $objWriter->writeElement('x:Column', ($column - 1)); + // x:Column + $objWriter->writeElement('x:Column', ($column - 1)); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php b/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php index a410b854..56ebf0bb 100644 --- a/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,253 +35,253 @@ */ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write content types to XML format - * - * @param PHPExcel $pPHPExcel - * @param boolean $includeCharts Flag indicating if we should include drawing details for charts - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeContentTypes(PHPExcel $pPHPExcel = null, $includeCharts = FALSE) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write content types to XML format + * + * @param PHPExcel $pPHPExcel + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeContentTypes(PHPExcel $pPHPExcel = null, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Types - $objWriter->startElement('Types'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types'); + // Types + $objWriter->startElement('Types'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types'); - // Theme - $this->_writeOverrideContentType( - $objWriter, '/xl/theme/theme1.xml', 'application/vnd.openxmlformats-officedocument.theme+xml' - ); + // Theme + $this->_writeOverrideContentType( + $objWriter, '/xl/theme/theme1.xml', 'application/vnd.openxmlformats-officedocument.theme+xml' + ); - // Styles - $this->_writeOverrideContentType( - $objWriter, '/xl/styles.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml' - ); + // Styles + $this->_writeOverrideContentType( + $objWriter, '/xl/styles.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml' + ); - // Rels - $this->_writeDefaultContentType( - $objWriter, 'rels', 'application/vnd.openxmlformats-package.relationships+xml' - ); + // Rels + $this->_writeDefaultContentType( + $objWriter, 'rels', 'application/vnd.openxmlformats-package.relationships+xml' + ); - // XML - $this->_writeDefaultContentType( - $objWriter, 'xml', 'application/xml' - ); + // XML + $this->_writeDefaultContentType( + $objWriter, 'xml', 'application/xml' + ); - // VML - $this->_writeDefaultContentType( - $objWriter, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing' - ); + // VML + $this->_writeDefaultContentType( + $objWriter, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing' + ); - // Workbook - if($pPHPExcel->hasMacros()){ //Macros in workbook ? - // Yes : not standard content but "macroEnabled" - $this->_writeOverrideContentType( - $objWriter, '/xl/workbook.xml', 'application/vnd.ms-excel.sheet.macroEnabled.main+xml' - ); - //... and define a new type for the VBA project - $this->_writeDefaultContentType( - $objWriter, 'bin', 'application/vnd.ms-office.vbaProject' - ); - if($pPHPExcel->hasMacrosCertificate()){// signed macros ? - // Yes : add needed information - $this->_writeOverrideContentType( - $objWriter, '/xl/vbaProjectSignature.bin', 'application/vnd.ms-office.vbaProjectSignature' - ); - } - }else{// no macros in workbook, so standard type - $this->_writeOverrideContentType( - $objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' - ); - } + // Workbook + if($pPHPExcel->hasMacros()){ //Macros in workbook ? + // Yes : not standard content but "macroEnabled" + $this->_writeOverrideContentType( + $objWriter, '/xl/workbook.xml', 'application/vnd.ms-excel.sheet.macroEnabled.main+xml' + ); + //... and define a new type for the VBA project + $this->_writeDefaultContentType( + $objWriter, 'bin', 'application/vnd.ms-office.vbaProject' + ); + if($pPHPExcel->hasMacrosCertificate()){// signed macros ? + // Yes : add needed information + $this->_writeOverrideContentType( + $objWriter, '/xl/vbaProjectSignature.bin', 'application/vnd.ms-office.vbaProjectSignature' + ); + } + }else{// no macros in workbook, so standard type + $this->_writeOverrideContentType( + $objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' + ); + } - // DocProps - $this->_writeOverrideContentType( - $objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml' - ); + // DocProps + $this->_writeOverrideContentType( + $objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml' + ); - $this->_writeOverrideContentType( - $objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml' - ); + $this->_writeOverrideContentType( + $objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml' + ); - $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); - if (!empty($customPropertyList)) { - $this->_writeOverrideContentType( - $objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml' - ); - } + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (!empty($customPropertyList)) { + $this->_writeOverrideContentType( + $objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml' + ); + } - // Worksheets - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - $this->_writeOverrideContentType( - $objWriter, '/xl/worksheets/sheet' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml' - ); - } + // Worksheets + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $this->_writeOverrideContentType( + $objWriter, '/xl/worksheets/sheet' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml' + ); + } - // Shared strings - $this->_writeOverrideContentType( - $objWriter, '/xl/sharedStrings.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml' - ); + // Shared strings + $this->_writeOverrideContentType( + $objWriter, '/xl/sharedStrings.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml' + ); - // Add worksheet relationship content types - $chart = 1; - for ($i = 0; $i < $sheetCount; ++$i) { - $drawings = $pPHPExcel->getSheet($i)->getDrawingCollection(); - $drawingCount = count($drawings); - $chartCount = ($includeCharts) ? $pPHPExcel->getSheet($i)->getChartCount() : 0; + // Add worksheet relationship content types + $chart = 1; + for ($i = 0; $i < $sheetCount; ++$i) { + $drawings = $pPHPExcel->getSheet($i)->getDrawingCollection(); + $drawingCount = count($drawings); + $chartCount = ($includeCharts) ? $pPHPExcel->getSheet($i)->getChartCount() : 0; - // We need a drawing relationship for the worksheet if we have either drawings or charts - if (($drawingCount > 0) || ($chartCount > 0)) { - $this->_writeOverrideContentType( - $objWriter, '/xl/drawings/drawing' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.drawing+xml' - ); - } + // We need a drawing relationship for the worksheet if we have either drawings or charts + if (($drawingCount > 0) || ($chartCount > 0)) { + $this->_writeOverrideContentType( + $objWriter, '/xl/drawings/drawing' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.drawing+xml' + ); + } - // If we have charts, then we need a chart relationship for every individual chart - if ($chartCount > 0) { - for ($c = 0; $c < $chartCount; ++$c) { - $this->_writeOverrideContentType( - $objWriter, '/xl/charts/chart' . $chart++ . '.xml', 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml' - ); - } - } - } + // If we have charts, then we need a chart relationship for every individual chart + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeOverrideContentType( + $objWriter, '/xl/charts/chart' . $chart++ . '.xml', 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml' + ); + } + } + } - // Comments - for ($i = 0; $i < $sheetCount; ++$i) { - if (count($pPHPExcel->getSheet($i)->getComments()) > 0) { - $this->_writeOverrideContentType( - $objWriter, '/xl/comments' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml' - ); - } - } + // Comments + for ($i = 0; $i < $sheetCount; ++$i) { + if (count($pPHPExcel->getSheet($i)->getComments()) > 0) { + $this->_writeOverrideContentType( + $objWriter, '/xl/comments' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml' + ); + } + } - // Add media content-types - $aMediaContentTypes = array(); - $mediaCount = $this->getParentWriter()->getDrawingHashTable()->count(); - for ($i = 0; $i < $mediaCount; ++$i) { - $extension = ''; - $mimeType = ''; + // Add media content-types + $aMediaContentTypes = array(); + $mediaCount = $this->getParentWriter()->getDrawingHashTable()->count(); + for ($i = 0; $i < $mediaCount; ++$i) { + $extension = ''; + $mimeType = ''; - if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { - $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); - $mimeType = $this->_getImageMimeType( $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath() ); - } else if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { - $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); - $extension = explode('/', $extension); - $extension = $extension[1]; + if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); + $mimeType = $this->_getImageMimeType( $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath() ); + } else if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); + $extension = explode('/', $extension); + $extension = $extension[1]; - $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); - } + $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); + } - if (!isset( $aMediaContentTypes[$extension]) ) { - $aMediaContentTypes[$extension] = $mimeType; + if (!isset( $aMediaContentTypes[$extension]) ) { + $aMediaContentTypes[$extension] = $mimeType; - $this->_writeDefaultContentType( - $objWriter, $extension, $mimeType - ); - } - } - if($pPHPExcel->hasRibbonBinObjects()){//Some additional objects in the ribbon ? - //we need to write "Extension" but not already write for media content - $tabRibbonTypes=array_diff($pPHPExcel->getRibbonBinObjects('types'), array_keys($aMediaContentTypes)); - foreach($tabRibbonTypes as $aRibbonType){ - $mimeType='image/.'.$aRibbonType;//we wrote $mimeType like customUI Editor - $this->_writeDefaultContentType( - $objWriter, $aRibbonType, $mimeType - ); - } - } - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - if (count($pPHPExcel->getSheet()->getHeaderFooter()->getImages()) > 0) { - foreach ($pPHPExcel->getSheet()->getHeaderFooter()->getImages() as $image) { - if (!isset( $aMediaContentTypes[strtolower($image->getExtension())]) ) { - $aMediaContentTypes[strtolower($image->getExtension())] = $this->_getImageMimeType( $image->getPath() ); + $this->_writeDefaultContentType( + $objWriter, $extension, $mimeType + ); + } + } + if($pPHPExcel->hasRibbonBinObjects()){//Some additional objects in the ribbon ? + //we need to write "Extension" but not already write for media content + $tabRibbonTypes=array_diff($pPHPExcel->getRibbonBinObjects('types'), array_keys($aMediaContentTypes)); + foreach($tabRibbonTypes as $aRibbonType){ + $mimeType='image/.'.$aRibbonType;//we wrote $mimeType like customUI Editor + $this->_writeDefaultContentType( + $objWriter, $aRibbonType, $mimeType + ); + } + } + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + if (count($pPHPExcel->getSheet()->getHeaderFooter()->getImages()) > 0) { + foreach ($pPHPExcel->getSheet()->getHeaderFooter()->getImages() as $image) { + if (!isset( $aMediaContentTypes[strtolower($image->getExtension())]) ) { + $aMediaContentTypes[strtolower($image->getExtension())] = $this->_getImageMimeType( $image->getPath() ); - $this->_writeDefaultContentType( - $objWriter, strtolower($image->getExtension()), $aMediaContentTypes[strtolower($image->getExtension())] - ); - } - } - } - } + $this->_writeDefaultContentType( + $objWriter, strtolower($image->getExtension()), $aMediaContentTypes[strtolower($image->getExtension())] + ); + } + } + } + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Get image mime type - * - * @param string $pFile Filename - * @return string Mime Type - * @throws PHPExcel_Writer_Exception - */ - private function _getImageMimeType($pFile = '') - { - if (PHPExcel_Shared_File::file_exists($pFile)) { - $image = getimagesize($pFile); - return image_type_to_mime_type($image[2]); - } else { - throw new PHPExcel_Writer_Exception("File $pFile does not exist"); - } - } + /** + * Get image mime type + * + * @param string $pFile Filename + * @return string Mime Type + * @throws PHPExcel_Writer_Exception + */ + private function _getImageMimeType($pFile = '') + { + if (PHPExcel_Shared_File::file_exists($pFile)) { + $image = getimagesize($pFile); + return image_type_to_mime_type($image[2]); + } else { + throw new PHPExcel_Writer_Exception("File $pFile does not exist"); + } + } - /** - * Write Default content type - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pPartname Part name - * @param string $pContentType Content type - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefaultContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') - { - if ($pPartname != '' && $pContentType != '') { - // Write content type - $objWriter->startElement('Default'); - $objWriter->writeAttribute('Extension', $pPartname); - $objWriter->writeAttribute('ContentType', $pContentType); - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + /** + * Write Default content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefaultContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $objWriter->startElement('Default'); + $objWriter->writeAttribute('Extension', $pPartname); + $objWriter->writeAttribute('ContentType', $pContentType); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } - /** - * Write Override content type - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pPartname Part name - * @param string $pContentType Content type - * @throws PHPExcel_Writer_Exception - */ - private function _writeOverrideContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') - { - if ($pPartname != '' && $pContentType != '') { - // Write content type - $objWriter->startElement('Override'); - $objWriter->writeAttribute('PartName', $pPartname); - $objWriter->writeAttribute('ContentType', $pContentType); - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + /** + * Write Override content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws PHPExcel_Writer_Exception + */ + private function _writeOverrideContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $objWriter->startElement('Override'); + $objWriter->writeAttribute('PartName', $pPartname); + $objWriter->writeAttribute('ContentType', $pContentType); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/DocProps.php b/Classes/PHPExcel/Writer/Excel2007/DocProps.php index c4a4b2d4..a65d39ac 100644 --- a/Classes/PHPExcel/Writer/Excel2007/DocProps.php +++ b/Classes/PHPExcel/Writer/Excel2007/DocProps.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -36,237 +36,237 @@ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_WriterPart { /** - * Write docProps/app.xml to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeDocPropsApp(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + * Write docProps/app.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsApp(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Properties - $objWriter->startElement('Properties'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'); - $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + // Properties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); - // Application - $objWriter->writeElement('Application', 'Microsoft Excel'); + // Application + $objWriter->writeElement('Application', 'Microsoft Excel'); - // DocSecurity - $objWriter->writeElement('DocSecurity', '0'); + // DocSecurity + $objWriter->writeElement('DocSecurity', '0'); - // ScaleCrop - $objWriter->writeElement('ScaleCrop', 'false'); + // ScaleCrop + $objWriter->writeElement('ScaleCrop', 'false'); - // HeadingPairs - $objWriter->startElement('HeadingPairs'); + // HeadingPairs + $objWriter->startElement('HeadingPairs'); - // Vector - $objWriter->startElement('vt:vector'); - $objWriter->writeAttribute('size', '2'); - $objWriter->writeAttribute('baseType', 'variant'); + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', '2'); + $objWriter->writeAttribute('baseType', 'variant'); - // Variant - $objWriter->startElement('vt:variant'); - $objWriter->writeElement('vt:lpstr', 'Worksheets'); - $objWriter->endElement(); + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:lpstr', 'Worksheets'); + $objWriter->endElement(); - // Variant - $objWriter->startElement('vt:variant'); - $objWriter->writeElement('vt:i4', $pPHPExcel->getSheetCount()); - $objWriter->endElement(); + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:i4', $pPHPExcel->getSheetCount()); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // TitlesOfParts - $objWriter->startElement('TitlesOfParts'); + // TitlesOfParts + $objWriter->startElement('TitlesOfParts'); - // Vector - $objWriter->startElement('vt:vector'); - $objWriter->writeAttribute('size', $pPHPExcel->getSheetCount()); - $objWriter->writeAttribute('baseType', 'lpstr'); + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', $pPHPExcel->getSheetCount()); + $objWriter->writeAttribute('baseType', 'lpstr'); - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - $objWriter->writeElement('vt:lpstr', $pPHPExcel->getSheet($i)->getTitle()); - } + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $objWriter->writeElement('vt:lpstr', $pPHPExcel->getSheet($i)->getTitle()); + } - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // Company - $objWriter->writeElement('Company', $pPHPExcel->getProperties()->getCompany()); + // Company + $objWriter->writeElement('Company', $pPHPExcel->getProperties()->getCompany()); - // Company - $objWriter->writeElement('Manager', $pPHPExcel->getProperties()->getManager()); + // Company + $objWriter->writeElement('Manager', $pPHPExcel->getProperties()->getManager()); - // LinksUpToDate - $objWriter->writeElement('LinksUpToDate', 'false'); + // LinksUpToDate + $objWriter->writeElement('LinksUpToDate', 'false'); - // SharedDoc - $objWriter->writeElement('SharedDoc', 'false'); + // SharedDoc + $objWriter->writeElement('SharedDoc', 'false'); - // HyperlinksChanged - $objWriter->writeElement('HyperlinksChanged', 'false'); + // HyperlinksChanged + $objWriter->writeElement('HyperlinksChanged', 'false'); - // AppVersion - $objWriter->writeElement('AppVersion', '12.0000'); + // AppVersion + $objWriter->writeElement('AppVersion', '12.0000'); - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write docProps/core.xml to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeDocPropsCore(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write docProps/core.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCore(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // cp:coreProperties - $objWriter->startElement('cp:coreProperties'); - $objWriter->writeAttribute('xmlns:cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'); - $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); - $objWriter->writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/'); - $objWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); - $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + // cp:coreProperties + $objWriter->startElement('cp:coreProperties'); + $objWriter->writeAttribute('xmlns:cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/'); + $objWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); + $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - // dc:creator - $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); + // dc:creator + $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); - // cp:lastModifiedBy - $objWriter->writeElement('cp:lastModifiedBy', $pPHPExcel->getProperties()->getLastModifiedBy()); + // cp:lastModifiedBy + $objWriter->writeElement('cp:lastModifiedBy', $pPHPExcel->getProperties()->getLastModifiedBy()); - // dcterms:created - $objWriter->startElement('dcterms:created'); - $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); - $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); - $objWriter->endElement(); + // dcterms:created + $objWriter->startElement('dcterms:created'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); + $objWriter->endElement(); - // dcterms:modified - $objWriter->startElement('dcterms:modified'); - $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); - $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getModified())); - $objWriter->endElement(); + // dcterms:modified + $objWriter->startElement('dcterms:modified'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getModified())); + $objWriter->endElement(); - // dc:title - $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); + // dc:title + $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); - // dc:description - $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); + // dc:description + $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); - // dc:subject - $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); + // dc:subject + $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); - // cp:keywords - $objWriter->writeElement('cp:keywords', $pPHPExcel->getProperties()->getKeywords()); + // cp:keywords + $objWriter->writeElement('cp:keywords', $pPHPExcel->getProperties()->getKeywords()); - // cp:category - $objWriter->writeElement('cp:category', $pPHPExcel->getProperties()->getCategory()); + // cp:category + $objWriter->writeElement('cp:category', $pPHPExcel->getProperties()->getCategory()); - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write docProps/custom.xml to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeDocPropsCustom(PHPExcel $pPHPExcel = null) - { - $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); - if (empty($customPropertyList)) { - return; - } + /** + * Write docProps/custom.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCustom(PHPExcel $pPHPExcel = null) + { + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (empty($customPropertyList)) { + return; + } - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // cp:coreProperties - $objWriter->startElement('Properties'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); - $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + // cp:coreProperties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); - foreach($customPropertyList as $key => $customProperty) { - $propertyValue = $pPHPExcel->getProperties()->getCustomPropertyValue($customProperty); - $propertyType = $pPHPExcel->getProperties()->getCustomPropertyType($customProperty); + foreach($customPropertyList as $key => $customProperty) { + $propertyValue = $pPHPExcel->getProperties()->getCustomPropertyValue($customProperty); + $propertyType = $pPHPExcel->getProperties()->getCustomPropertyType($customProperty); - $objWriter->startElement('property'); - $objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'); - $objWriter->writeAttribute('pid', $key+2); - $objWriter->writeAttribute('name', $customProperty); + $objWriter->startElement('property'); + $objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'); + $objWriter->writeAttribute('pid', $key+2); + $objWriter->writeAttribute('name', $customProperty); - switch($propertyType) { - case 'i' : - $objWriter->writeElement('vt:i4', $propertyValue); - break; - case 'f' : - $objWriter->writeElement('vt:r8', $propertyValue); - break; - case 'b' : - $objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false'); - break; - case 'd' : - $objWriter->startElement('vt:filetime'); - $objWriter->writeRawData(date(DATE_W3C, $propertyValue)); - $objWriter->endElement(); - break; - default : - $objWriter->writeElement('vt:lpwstr', $propertyValue); - break; - } + switch($propertyType) { + case 'i' : + $objWriter->writeElement('vt:i4', $propertyValue); + break; + case 'f' : + $objWriter->writeElement('vt:r8', $propertyValue); + break; + case 'b' : + $objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false'); + break; + case 'd' : + $objWriter->startElement('vt:filetime'); + $objWriter->writeRawData(date(DATE_W3C, $propertyValue)); + $objWriter->endElement(); + break; + default : + $objWriter->writeElement('vt:lpwstr', $propertyValue); + break; + } - $objWriter->endElement(); - } + $objWriter->endElement(); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Drawing.php b/Classes/PHPExcel/Writer/Excel2007/Drawing.php index 2cda6035..4810542d 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Drawing.php +++ b/Classes/PHPExcel/Writer/Excel2007/Drawing.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,564 +35,564 @@ */ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write drawings to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @param int &$chartRef Chart ID - * @param boolean $includeCharts Flag indicating if we should include drawing details for charts - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write drawings to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int &$chartRef Chart ID + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // xdr:wsDr - $objWriter->startElement('xdr:wsDr'); - $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); - $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + // xdr:wsDr + $objWriter->startElement('xdr:wsDr'); + $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); - // Loop through images and write drawings - $i = 1; - $iterator = $pWorksheet->getDrawingCollection()->getIterator(); - while ($iterator->valid()) { - $this->_writeDrawing($objWriter, $iterator->current(), $i); + // Loop through images and write drawings + $i = 1; + $iterator = $pWorksheet->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $this->_writeDrawing($objWriter, $iterator->current(), $i); - $iterator->next(); - ++$i; - } + $iterator->next(); + ++$i; + } - if ($includeCharts) { - $chartCount = $pWorksheet->getChartCount(); - // Loop through charts and write the chart position - if ($chartCount > 0) { - for ($c = 0; $c < $chartCount; ++$c) { - $this->_writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c+$i); - } - } - } + if ($includeCharts) { + $chartCount = $pWorksheet->getChartCount(); + // Loop through charts and write the chart position + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c+$i); + } + } + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write drawings to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Chart $pChart - * @param int $pRelationId - * @throws PHPExcel_Writer_Exception - */ - public function _writeChart(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Chart $pChart = null, $pRelationId = -1) - { - $tl = $pChart->getTopLeftPosition(); - $tl['colRow'] = PHPExcel_Cell::coordinateFromString($tl['cell']); - $br = $pChart->getBottomRightPosition(); - $br['colRow'] = PHPExcel_Cell::coordinateFromString($br['cell']); + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart $pChart + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeChart(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Chart $pChart = null, $pRelationId = -1) + { + $tl = $pChart->getTopLeftPosition(); + $tl['colRow'] = PHPExcel_Cell::coordinateFromString($tl['cell']); + $br = $pChart->getBottomRightPosition(); + $br['colRow'] = PHPExcel_Cell::coordinateFromString($br['cell']); - $objWriter->startElement('xdr:twoCellAnchor'); + $objWriter->startElement('xdr:twoCellAnchor'); - $objWriter->startElement('xdr:from'); - $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($tl['colRow'][0]) - 1); - $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['xOffset'])); - $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1); - $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['yOffset'])); - $objWriter->endElement(); - $objWriter->startElement('xdr:to'); - $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($br['colRow'][0]) - 1); - $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['xOffset'])); - $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1); - $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['yOffset'])); - $objWriter->endElement(); + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($tl['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['xOffset'])); + $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['yOffset'])); + $objWriter->endElement(); + $objWriter->startElement('xdr:to'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($br['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['xOffset'])); + $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['yOffset'])); + $objWriter->endElement(); - $objWriter->startElement('xdr:graphicFrame'); - $objWriter->writeAttribute('macro', ''); - $objWriter->startElement('xdr:nvGraphicFramePr'); - $objWriter->startElement('xdr:cNvPr'); - $objWriter->writeAttribute('name', 'Chart '.$pRelationId); - $objWriter->writeAttribute('id', 1025 * $pRelationId); - $objWriter->endElement(); - $objWriter->startElement('xdr:cNvGraphicFramePr'); - $objWriter->startElement('a:graphicFrameLocks'); - $objWriter->endElement(); - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->startElement('xdr:graphicFrame'); + $objWriter->writeAttribute('macro', ''); + $objWriter->startElement('xdr:nvGraphicFramePr'); + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('name', 'Chart '.$pRelationId); + $objWriter->writeAttribute('id', 1025 * $pRelationId); + $objWriter->endElement(); + $objWriter->startElement('xdr:cNvGraphicFramePr'); + $objWriter->startElement('a:graphicFrameLocks'); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->startElement('xdr:xfrm'); - $objWriter->startElement('a:off'); - $objWriter->writeAttribute('x', '0'); - $objWriter->writeAttribute('y', '0'); - $objWriter->endElement(); - $objWriter->startElement('a:ext'); - $objWriter->writeAttribute('cx', '0'); - $objWriter->writeAttribute('cy', '0'); - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->startElement('xdr:xfrm'); + $objWriter->startElement('a:off'); + $objWriter->writeAttribute('x', '0'); + $objWriter->writeAttribute('y', '0'); + $objWriter->endElement(); + $objWriter->startElement('a:ext'); + $objWriter->writeAttribute('cx', '0'); + $objWriter->writeAttribute('cy', '0'); + $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->startElement('a:graphic'); - $objWriter->startElement('a:graphicData'); - $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); - $objWriter->startElement('c:chart'); - $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); - $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - $objWriter->writeAttribute('r:id', 'rId'.$pRelationId); - $objWriter->endElement(); - $objWriter->endElement(); - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->startElement('a:graphic'); + $objWriter->startElement('a:graphicData'); + $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->startElement('c:chart'); + $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:id', 'rId'.$pRelationId); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->startElement('xdr:clientData'); - $objWriter->endElement(); + $objWriter->startElement('xdr:clientData'); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write drawings to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet_BaseDrawing $pDrawing - * @param int $pRelationId - * @throws PHPExcel_Writer_Exception - */ - public function _writeDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet_BaseDrawing $pDrawing = null, $pRelationId = -1) - { - if ($pRelationId >= 0) { - // xdr:oneCellAnchor - $objWriter->startElement('xdr:oneCellAnchor'); - // Image location - $aCoordinates = PHPExcel_Cell::coordinateFromString($pDrawing->getCoordinates()); - $aCoordinates[0] = PHPExcel_Cell::columnIndexFromString($aCoordinates[0]); + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet_BaseDrawing $pDrawing + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet_BaseDrawing $pDrawing = null, $pRelationId = -1) + { + if ($pRelationId >= 0) { + // xdr:oneCellAnchor + $objWriter->startElement('xdr:oneCellAnchor'); + // Image location + $aCoordinates = PHPExcel_Cell::coordinateFromString($pDrawing->getCoordinates()); + $aCoordinates[0] = PHPExcel_Cell::columnIndexFromString($aCoordinates[0]); - // xdr:from - $objWriter->startElement('xdr:from'); - $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1); - $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetX())); - $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1); - $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetY())); - $objWriter->endElement(); + // xdr:from + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetX())); + $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetY())); + $objWriter->endElement(); - // xdr:ext - $objWriter->startElement('xdr:ext'); - $objWriter->writeAttribute('cx', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getWidth())); - $objWriter->writeAttribute('cy', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getHeight())); - $objWriter->endElement(); + // xdr:ext + $objWriter->startElement('xdr:ext'); + $objWriter->writeAttribute('cx', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getWidth())); + $objWriter->writeAttribute('cy', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getHeight())); + $objWriter->endElement(); - // xdr:pic - $objWriter->startElement('xdr:pic'); + // xdr:pic + $objWriter->startElement('xdr:pic'); - // xdr:nvPicPr - $objWriter->startElement('xdr:nvPicPr'); + // xdr:nvPicPr + $objWriter->startElement('xdr:nvPicPr'); - // xdr:cNvPr - $objWriter->startElement('xdr:cNvPr'); - $objWriter->writeAttribute('id', $pRelationId); - $objWriter->writeAttribute('name', $pDrawing->getName()); - $objWriter->writeAttribute('descr', $pDrawing->getDescription()); - $objWriter->endElement(); + // xdr:cNvPr + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('id', $pRelationId); + $objWriter->writeAttribute('name', $pDrawing->getName()); + $objWriter->writeAttribute('descr', $pDrawing->getDescription()); + $objWriter->endElement(); - // xdr:cNvPicPr - $objWriter->startElement('xdr:cNvPicPr'); + // xdr:cNvPicPr + $objWriter->startElement('xdr:cNvPicPr'); - // a:picLocks - $objWriter->startElement('a:picLocks'); - $objWriter->writeAttribute('noChangeAspect', '1'); - $objWriter->endElement(); + // a:picLocks + $objWriter->startElement('a:picLocks'); + $objWriter->writeAttribute('noChangeAspect', '1'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // xdr:blipFill - $objWriter->startElement('xdr:blipFill'); + // xdr:blipFill + $objWriter->startElement('xdr:blipFill'); - // a:blip - $objWriter->startElement('a:blip'); - $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId); - $objWriter->endElement(); + // a:blip + $objWriter->startElement('a:blip'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId); + $objWriter->endElement(); - // a:stretch - $objWriter->startElement('a:stretch'); - $objWriter->writeElement('a:fillRect', null); - $objWriter->endElement(); + // a:stretch + $objWriter->startElement('a:stretch'); + $objWriter->writeElement('a:fillRect', null); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // xdr:spPr - $objWriter->startElement('xdr:spPr'); + // xdr:spPr + $objWriter->startElement('xdr:spPr'); - // a:xfrm - $objWriter->startElement('a:xfrm'); - $objWriter->writeAttribute('rot', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getRotation())); - $objWriter->endElement(); + // a:xfrm + $objWriter->startElement('a:xfrm'); + $objWriter->writeAttribute('rot', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getRotation())); + $objWriter->endElement(); - // a:prstGeom - $objWriter->startElement('a:prstGeom'); - $objWriter->writeAttribute('prst', 'rect'); + // a:prstGeom + $objWriter->startElement('a:prstGeom'); + $objWriter->writeAttribute('prst', 'rect'); - // a:avLst - $objWriter->writeElement('a:avLst', null); + // a:avLst + $objWriter->writeElement('a:avLst', null); - $objWriter->endElement(); + $objWriter->endElement(); -// // a:solidFill -// $objWriter->startElement('a:solidFill'); +// // a:solidFill +// $objWriter->startElement('a:solidFill'); -// // a:srgbClr -// $objWriter->startElement('a:srgbClr'); -// $objWriter->writeAttribute('val', 'FFFFFF'); +// // a:srgbClr +// $objWriter->startElement('a:srgbClr'); +// $objWriter->writeAttribute('val', 'FFFFFF'); ///* SHADE -// // a:shade -// $objWriter->startElement('a:shade'); -// $objWriter->writeAttribute('val', '85000'); -// $objWriter->endElement(); +// // a:shade +// $objWriter->startElement('a:shade'); +// $objWriter->writeAttribute('val', '85000'); +// $objWriter->endElement(); //*/ -// $objWriter->endElement(); +// $objWriter->endElement(); -// $objWriter->endElement(); +// $objWriter->endElement(); /* - // a:ln - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', '88900'); - $objWriter->writeAttribute('cap', 'sq'); + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '88900'); + $objWriter->writeAttribute('cap', 'sq'); - // a:solidFill - $objWriter->startElement('a:solidFill'); + // a:solidFill + $objWriter->startElement('a:solidFill'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', 'FFFFFF'); - $objWriter->endElement(); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:miter - $objWriter->startElement('a:miter'); - $objWriter->writeAttribute('lim', '800000'); - $objWriter->endElement(); + // a:miter + $objWriter->startElement('a:miter'); + $objWriter->writeAttribute('lim', '800000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); */ - if ($pDrawing->getShadow()->getVisible()) { - // a:effectLst - $objWriter->startElement('a:effectLst'); + if ($pDrawing->getShadow()->getVisible()) { + // a:effectLst + $objWriter->startElement('a:effectLst'); - // a:outerShdw - $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius())); - $objWriter->writeAttribute('dist', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance())); - $objWriter->writeAttribute('dir', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getShadow()->getDirection())); - $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment()); - $objWriter->writeAttribute('rotWithShape', '0'); + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius())); + $objWriter->writeAttribute('dist', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance())); + $objWriter->writeAttribute('dir', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getShadow()->getDirection())); + $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment()); + $objWriter->writeAttribute('rotWithShape', '0'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB()); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB()); - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000); - $objWriter->endElement(); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } /* - // a:scene3d - $objWriter->startElement('a:scene3d'); + // a:scene3d + $objWriter->startElement('a:scene3d'); - // a:camera - $objWriter->startElement('a:camera'); - $objWriter->writeAttribute('prst', 'orthographicFront'); - $objWriter->endElement(); + // a:camera + $objWriter->startElement('a:camera'); + $objWriter->writeAttribute('prst', 'orthographicFront'); + $objWriter->endElement(); - // a:lightRig - $objWriter->startElement('a:lightRig'); - $objWriter->writeAttribute('rig', 'twoPt'); - $objWriter->writeAttribute('dir', 't'); + // a:lightRig + $objWriter->startElement('a:lightRig'); + $objWriter->writeAttribute('rig', 'twoPt'); + $objWriter->writeAttribute('dir', 't'); - // a:rot - $objWriter->startElement('a:rot'); - $objWriter->writeAttribute('lat', '0'); - $objWriter->writeAttribute('lon', '0'); - $objWriter->writeAttribute('rev', '0'); - $objWriter->endElement(); + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '0'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); */ /* - // a:sp3d - $objWriter->startElement('a:sp3d'); + // a:sp3d + $objWriter->startElement('a:sp3d'); - // a:bevelT - $objWriter->startElement('a:bevelT'); - $objWriter->writeAttribute('w', '25400'); - $objWriter->writeAttribute('h', '19050'); - $objWriter->endElement(); + // a:bevelT + $objWriter->startElement('a:bevelT'); + $objWriter->writeAttribute('w', '25400'); + $objWriter->writeAttribute('h', '19050'); + $objWriter->endElement(); - // a:contourClr - $objWriter->startElement('a:contourClr'); + // a:contourClr + $objWriter->startElement('a:contourClr'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', 'FFFFFF'); - $objWriter->endElement(); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); */ - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // xdr:clientData - $objWriter->writeElement('xdr:clientData', null); + // xdr:clientData + $objWriter->writeElement('xdr:clientData', null); - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } - /** - * Write VML header/footer images to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeVMLHeaderFooterImages(PHPExcel_Worksheet $pWorksheet = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write VML header/footer images to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVMLHeaderFooterImages(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Header/footer images - $images = $pWorksheet->getHeaderFooter()->getImages(); + // Header/footer images + $images = $pWorksheet->getHeaderFooter()->getImages(); - // xml - $objWriter->startElement('xml'); - $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); - $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); - $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); + // xml + $objWriter->startElement('xml'); + $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); - // o:shapelayout - $objWriter->startElement('o:shapelayout'); - $objWriter->writeAttribute('v:ext', 'edit'); + // o:shapelayout + $objWriter->startElement('o:shapelayout'); + $objWriter->writeAttribute('v:ext', 'edit'); - // o:idmap - $objWriter->startElement('o:idmap'); - $objWriter->writeAttribute('v:ext', 'edit'); - $objWriter->writeAttribute('data', '1'); - $objWriter->endElement(); + // o:idmap + $objWriter->startElement('o:idmap'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('data', '1'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // v:shapetype - $objWriter->startElement('v:shapetype'); - $objWriter->writeAttribute('id', '_x0000_t75'); - $objWriter->writeAttribute('coordsize', '21600,21600'); - $objWriter->writeAttribute('o:spt', '75'); - $objWriter->writeAttribute('o:preferrelative', 't'); - $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe'); - $objWriter->writeAttribute('filled', 'f'); - $objWriter->writeAttribute('stroked', 'f'); + // v:shapetype + $objWriter->startElement('v:shapetype'); + $objWriter->writeAttribute('id', '_x0000_t75'); + $objWriter->writeAttribute('coordsize', '21600,21600'); + $objWriter->writeAttribute('o:spt', '75'); + $objWriter->writeAttribute('o:preferrelative', 't'); + $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe'); + $objWriter->writeAttribute('filled', 'f'); + $objWriter->writeAttribute('stroked', 'f'); - // v:stroke - $objWriter->startElement('v:stroke'); - $objWriter->writeAttribute('joinstyle', 'miter'); - $objWriter->endElement(); + // v:stroke + $objWriter->startElement('v:stroke'); + $objWriter->writeAttribute('joinstyle', 'miter'); + $objWriter->endElement(); - // v:formulas - $objWriter->startElement('v:formulas'); + // v:formulas + $objWriter->startElement('v:formulas'); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'sum @0 1 0'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 1 0'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'sum 0 0 @1'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum 0 0 @1'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @2 1 2'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @2 1 2'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'sum @0 0 1'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 0 1'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @6 1 2'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @6 1 2'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'sum @8 21600 0'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @8 21600 0'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight'); + $objWriter->endElement(); - // v:f - $objWriter->startElement('v:f'); - $objWriter->writeAttribute('eqn', 'sum @10 21600 0'); - $objWriter->endElement(); + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @10 21600 0'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // v:path - $objWriter->startElement('v:path'); - $objWriter->writeAttribute('o:extrusionok', 'f'); - $objWriter->writeAttribute('gradientshapeok', 't'); - $objWriter->writeAttribute('o:connecttype', 'rect'); - $objWriter->endElement(); + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('o:extrusionok', 'f'); + $objWriter->writeAttribute('gradientshapeok', 't'); + $objWriter->writeAttribute('o:connecttype', 'rect'); + $objWriter->endElement(); - // o:lock - $objWriter->startElement('o:lock'); - $objWriter->writeAttribute('v:ext', 'edit'); - $objWriter->writeAttribute('aspectratio', 't'); - $objWriter->endElement(); + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('aspectratio', 't'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // Loop through images - foreach ($images as $key => $value) { - $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); - } + // Loop through images + foreach ($images as $key => $value) { + $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write VML comment to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pReference Reference - * @param PHPExcel_Worksheet_HeaderFooterDrawing $pImage Image - * @throws PHPExcel_Writer_Exception - */ - public function _writeVMLHeaderFooterImage(PHPExcel_Shared_XMLWriter $objWriter = null, $pReference = '', PHPExcel_Worksheet_HeaderFooterDrawing $pImage = null) - { - // Calculate object id - preg_match('{(\d+)}', md5($pReference), $m); - $id = 1500 + (substr($m[1], 0, 2) * 1); + /** + * Write VML comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pReference Reference + * @param PHPExcel_Worksheet_HeaderFooterDrawing $pImage Image + * @throws PHPExcel_Writer_Exception + */ + public function _writeVMLHeaderFooterImage(PHPExcel_Shared_XMLWriter $objWriter = null, $pReference = '', PHPExcel_Worksheet_HeaderFooterDrawing $pImage = null) + { + // Calculate object id + preg_match('{(\d+)}', md5($pReference), $m); + $id = 1500 + (substr($m[1], 0, 2) * 1); - // Calculate offset - $width = $pImage->getWidth(); - $height = $pImage->getHeight(); - $marginLeft = $pImage->getOffsetX(); - $marginTop = $pImage->getOffsetY(); + // Calculate offset + $width = $pImage->getWidth(); + $height = $pImage->getHeight(); + $marginLeft = $pImage->getOffsetX(); + $marginTop = $pImage->getOffsetY(); - // v:shape - $objWriter->startElement('v:shape'); - $objWriter->writeAttribute('id', $pReference); - $objWriter->writeAttribute('o:spid', '_x0000_s' . $id); - $objWriter->writeAttribute('type', '#_x0000_t75'); - $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1"); + // v:shape + $objWriter->startElement('v:shape'); + $objWriter->writeAttribute('id', $pReference); + $objWriter->writeAttribute('o:spid', '_x0000_s' . $id); + $objWriter->writeAttribute('type', '#_x0000_t75'); + $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1"); - // v:imagedata - $objWriter->startElement('v:imagedata'); - $objWriter->writeAttribute('o:relid', 'rId' . $pReference); - $objWriter->writeAttribute('o:title', $pImage->getName()); - $objWriter->endElement(); + // v:imagedata + $objWriter->startElement('v:imagedata'); + $objWriter->writeAttribute('o:relid', 'rId' . $pReference); + $objWriter->writeAttribute('o:title', $pImage->getName()); + $objWriter->endElement(); - // o:lock - $objWriter->startElement('o:lock'); - $objWriter->writeAttribute('v:ext', 'edit'); - $objWriter->writeAttribute('rotation', 't'); - $objWriter->endElement(); + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('rotation', 't'); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Get an array of all drawings - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Worksheet_Drawing[] All drawings in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allDrawings(PHPExcel $pPHPExcel = null) - { - // Get an array of all drawings - $aDrawings = array(); + /** + * Get an array of all drawings + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Worksheet_Drawing[] All drawings in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allDrawings(PHPExcel $pPHPExcel = null) + { + // Get an array of all drawings + $aDrawings = array(); - // Loop through PHPExcel - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - // Loop through images and add to array - $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); - while ($iterator->valid()) { - $aDrawings[] = $iterator->current(); + // Loop through PHPExcel + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // Loop through images and add to array + $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $aDrawings[] = $iterator->current(); - $iterator->next(); - } - } + $iterator->next(); + } + } - return $aDrawings; - } + return $aDrawings; + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Rels.php b/Classes/PHPExcel/Writer/Excel2007/Rels.php index cf9b6bed..912d23f2 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Rels.php +++ b/Classes/PHPExcel/Writer/Excel2007/Rels.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,403 +35,403 @@ */ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write relationships to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeRelationships(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write relationships to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeRelationships(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); - if (!empty($customPropertyList)) { - // Relationship docProps/app.xml - $this->_writeRelationship( - $objWriter, - 4, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties', - 'docProps/custom.xml' - ); + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (!empty($customPropertyList)) { + // Relationship docProps/app.xml + $this->_writeRelationship( + $objWriter, + 4, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties', + 'docProps/custom.xml' + ); - } + } - // Relationship docProps/app.xml - $this->_writeRelationship( - $objWriter, - 3, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', - 'docProps/app.xml' - ); + // Relationship docProps/app.xml + $this->_writeRelationship( + $objWriter, + 3, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', + 'docProps/app.xml' + ); - // Relationship docProps/core.xml - $this->_writeRelationship( - $objWriter, - 2, - 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', - 'docProps/core.xml' - ); + // Relationship docProps/core.xml + $this->_writeRelationship( + $objWriter, + 2, + 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + 'docProps/core.xml' + ); - // Relationship xl/workbook.xml - $this->_writeRelationship( - $objWriter, - 1, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', - 'xl/workbook.xml' - ); - // a custom UI in workbook ? - if($pPHPExcel->hasRibbon()){ - $this->_writeRelationShip( - $objWriter, - 5, - 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility', - $pPHPExcel->getRibbonXMLData('target') - ); - } + // Relationship xl/workbook.xml + $this->_writeRelationship( + $objWriter, + 1, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', + 'xl/workbook.xml' + ); + // a custom UI in workbook ? + if($pPHPExcel->hasRibbon()){ + $this->_writeRelationShip( + $objWriter, + 5, + 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility', + $pPHPExcel->getRibbonXMLData('target') + ); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write workbook relationships to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeWorkbookRelationships(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write workbook relationships to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorkbookRelationships(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Relationship styles.xml - $this->_writeRelationship( - $objWriter, - 1, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', - 'styles.xml' - ); + // Relationship styles.xml + $this->_writeRelationship( + $objWriter, + 1, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + 'styles.xml' + ); - // Relationship theme/theme1.xml - $this->_writeRelationship( - $objWriter, - 2, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', - 'theme/theme1.xml' - ); + // Relationship theme/theme1.xml + $this->_writeRelationship( + $objWriter, + 2, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', + 'theme/theme1.xml' + ); - // Relationship sharedStrings.xml - $this->_writeRelationship( - $objWriter, - 3, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', - 'sharedStrings.xml' - ); + // Relationship sharedStrings.xml + $this->_writeRelationship( + $objWriter, + 3, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + 'sharedStrings.xml' + ); - // Relationships with sheets - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - $this->_writeRelationship( - $objWriter, - ($i + 1 + 3), - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', - 'worksheets/sheet' . ($i + 1) . '.xml' - ); - } - // Relationships for vbaProject if needed - // id : just after the last sheet - if($pPHPExcel->hasMacros()){ - $this->_writeRelationShip( - $objWriter, - ($i + 1 + 3), - 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', - 'vbaProject.bin' - ); - ++$i;//increment i if needed for an another relation - } + // Relationships with sheets + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $this->_writeRelationship( + $objWriter, + ($i + 1 + 3), + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + 'worksheets/sheet' . ($i + 1) . '.xml' + ); + } + // Relationships for vbaProject if needed + // id : just after the last sheet + if($pPHPExcel->hasMacros()){ + $this->_writeRelationShip( + $objWriter, + ($i + 1 + 3), + 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', + 'vbaProject.bin' + ); + ++$i;//increment i if needed for an another relation + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write worksheet relationships to XML format - * - * Numbering is as follows: - * rId1 - Drawings - * rId_hyperlink_x - Hyperlinks - * - * @param PHPExcel_Worksheet $pWorksheet - * @param int $pWorksheetId - * @param boolean $includeCharts Flag indicating if we should write charts - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = FALSE) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write worksheet relationships to XML format + * + * Numbering is as follows: + * rId1 - Drawings + * rId_hyperlink_x - Hyperlinks + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int $pWorksheetId + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Write drawing relationships? - $d = 0; - if ($includeCharts) { - $charts = $pWorksheet->getChartCollection(); - } else { - $charts = array(); - } - if (($pWorksheet->getDrawingCollection()->count() > 0) || - (count($charts) > 0)) { - $this->_writeRelationship( - $objWriter, - ++$d, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', - '../drawings/drawing' . $pWorksheetId . '.xml' - ); - } + // Write drawing relationships? + $d = 0; + if ($includeCharts) { + $charts = $pWorksheet->getChartCollection(); + } else { + $charts = array(); + } + if (($pWorksheet->getDrawingCollection()->count() > 0) || + (count($charts) > 0)) { + $this->_writeRelationship( + $objWriter, + ++$d, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + '../drawings/drawing' . $pWorksheetId . '.xml' + ); + } - // Write chart relationships? -// $chartCount = 0; -// $charts = $pWorksheet->getChartCollection(); -// echo 'Chart Rels: ' , count($charts) , '<br />'; -// if (count($charts) > 0) { -// foreach($charts as $chart) { -// $this->_writeRelationship( -// $objWriter, -// ++$d, -// 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', -// '../charts/chart' . ++$chartCount . '.xml' -// ); -// } -// } + // Write chart relationships? +// $chartCount = 0; +// $charts = $pWorksheet->getChartCollection(); +// echo 'Chart Rels: ' , count($charts) , '<br />'; +// if (count($charts) > 0) { +// foreach($charts as $chart) { +// $this->_writeRelationship( +// $objWriter, +// ++$d, +// 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', +// '../charts/chart' . ++$chartCount . '.xml' +// ); +// } +// } // - // Write hyperlink relationships? - $i = 1; - foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) { - if (!$hyperlink->isInternal()) { - $this->_writeRelationship( - $objWriter, - '_hyperlink_' . $i, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', - $hyperlink->getUrl(), - 'External' - ); + // Write hyperlink relationships? + $i = 1; + foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) { + if (!$hyperlink->isInternal()) { + $this->_writeRelationship( + $objWriter, + '_hyperlink_' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', + $hyperlink->getUrl(), + 'External' + ); - ++$i; - } - } + ++$i; + } + } - // Write comments relationship? - $i = 1; - if (count($pWorksheet->getComments()) > 0) { - $this->_writeRelationship( - $objWriter, - '_comments_vml' . $i, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', - '../drawings/vmlDrawing' . $pWorksheetId . '.vml' - ); + // Write comments relationship? + $i = 1; + if (count($pWorksheet->getComments()) > 0) { + $this->_writeRelationship( + $objWriter, + '_comments_vml' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', + '../drawings/vmlDrawing' . $pWorksheetId . '.vml' + ); - $this->_writeRelationship( - $objWriter, - '_comments' . $i, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', - '../comments' . $pWorksheetId . '.xml' - ); - } + $this->_writeRelationship( + $objWriter, + '_comments' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', + '../comments' . $pWorksheetId . '.xml' + ); + } - // Write header/footer relationship? - $i = 1; - if (count($pWorksheet->getHeaderFooter()->getImages()) > 0) { - $this->_writeRelationship( - $objWriter, - '_headerfooter_vml' . $i, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', - '../drawings/vmlDrawingHF' . $pWorksheetId . '.vml' - ); - } + // Write header/footer relationship? + $i = 1; + if (count($pWorksheet->getHeaderFooter()->getImages()) > 0) { + $this->_writeRelationship( + $objWriter, + '_headerfooter_vml' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', + '../drawings/vmlDrawingHF' . $pWorksheetId . '.vml' + ); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write drawing relationships to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @param int &$chartRef Chart ID - * @param boolean $includeCharts Flag indicating if we should write charts - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write drawing relationships to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int &$chartRef Chart ID + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop through images and write relationships - $i = 1; - $iterator = $pWorksheet->getDrawingCollection()->getIterator(); - while ($iterator->valid()) { - if ($iterator->current() instanceof PHPExcel_Worksheet_Drawing - || $iterator->current() instanceof PHPExcel_Worksheet_MemoryDrawing) { - // Write relationship for image drawing - $this->_writeRelationship( - $objWriter, - $i, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', - '../media/' . str_replace(' ', '', $iterator->current()->getIndexedFilename()) - ); - } + // Loop through images and write relationships + $i = 1; + $iterator = $pWorksheet->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + if ($iterator->current() instanceof PHPExcel_Worksheet_Drawing + || $iterator->current() instanceof PHPExcel_Worksheet_MemoryDrawing) { + // Write relationship for image drawing + $this->_writeRelationship( + $objWriter, + $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + '../media/' . str_replace(' ', '', $iterator->current()->getIndexedFilename()) + ); + } - $iterator->next(); - ++$i; - } + $iterator->next(); + ++$i; + } - if ($includeCharts) { - // Loop through charts and write relationships - $chartCount = $pWorksheet->getChartCount(); - if ($chartCount > 0) { - for ($c = 0; $c < $chartCount; ++$c) { - $this->_writeRelationship( - $objWriter, - $i++, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', - '../charts/chart' . ++$chartRef . '.xml' - ); - } - } - } + if ($includeCharts) { + // Loop through charts and write relationships + $chartCount = $pWorksheet->getChartCount(); + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeRelationship( + $objWriter, + $i++, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + '../charts/chart' . ++$chartRef . '.xml' + ); + } + } + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write header/footer drawing relationships to XML format - * - * @param PHPExcel_Worksheet $pWorksheet - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeHeaderFooterDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write header/footer drawing relationships to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeHeaderFooterDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop through images and write relationships - foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) { - // Write relationship for image drawing - $this->_writeRelationship( - $objWriter, - $key, - 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', - '../media/' . $value->getIndexedFilename() - ); - } + // Loop through images and write relationships + foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) { + // Write relationship for image drawing + $this->_writeRelationship( + $objWriter, + $key, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + '../media/' . $value->getIndexedFilename() + ); + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write Override content type - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param int $pId Relationship ID. rId will be prepended! - * @param string $pType Relationship type - * @param string $pTarget Relationship target - * @param string $pTargetMode Relationship target mode - * @throws PHPExcel_Writer_Exception - */ - private function _writeRelationship(PHPExcel_Shared_XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') - { - if ($pType != '' && $pTarget != '') { - // Write relationship - $objWriter->startElement('Relationship'); - $objWriter->writeAttribute('Id', 'rId' . $pId); - $objWriter->writeAttribute('Type', $pType); - $objWriter->writeAttribute('Target', $pTarget); + /** + * Write Override content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param int $pId Relationship ID. rId will be prepended! + * @param string $pType Relationship type + * @param string $pTarget Relationship target + * @param string $pTargetMode Relationship target mode + * @throws PHPExcel_Writer_Exception + */ + private function _writeRelationship(PHPExcel_Shared_XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') + { + if ($pType != '' && $pTarget != '') { + // Write relationship + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', 'rId' . $pId); + $objWriter->writeAttribute('Type', $pType); + $objWriter->writeAttribute('Target', $pTarget); - if ($pTargetMode != '') { - $objWriter->writeAttribute('TargetMode', $pTargetMode); - } + if ($pTargetMode != '') { + $objWriter->writeAttribute('TargetMode', $pTargetMode); + } - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/RelsRibbon.php b/Classes/PHPExcel/Writer/Excel2007/RelsRibbon.php index 3cb81804..555a8fc2 100644 --- a/Classes/PHPExcel/Writer/Excel2007/RelsRibbon.php +++ b/Classes/PHPExcel/Writer/Excel2007/RelsRibbon.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,43 +35,43 @@ */ class PHPExcel_Writer_Excel2007_RelsRibbon extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write relationships for additional objects of custom UI (ribbon) - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeRibbonRelationships(PHPExcel $pPHPExcel = null){ - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write relationships for additional objects of custom UI (ribbon) + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeRibbonRelationships(PHPExcel $pPHPExcel = null){ + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - $localRels=$pPHPExcel->getRibbonBinObjects('names'); - if(is_array($localRels)){ - foreach($localRels as $aId=>$aTarget){ - $objWriter->startElement('Relationship'); - $objWriter->writeAttribute('Id', $aId); - $objWriter->writeAttribute('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'); - $objWriter->writeAttribute('Target', $aTarget); - $objWriter->endElement();//Relationship - } - } - $objWriter->endElement();//Relationships + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + $localRels=$pPHPExcel->getRibbonBinObjects('names'); + if(is_array($localRels)){ + foreach($localRels as $aId=>$aTarget){ + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', $aId); + $objWriter->writeAttribute('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'); + $objWriter->writeAttribute('Target', $aTarget); + $objWriter->endElement();//Relationship + } + } + $objWriter->endElement();//Relationships - // Return - return $objWriter->getData(); + // Return + return $objWriter->getData(); - } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/RelsVBA.php b/Classes/PHPExcel/Writer/Excel2007/RelsVBA.php index bd2bbb66..992d0e42 100644 --- a/Classes/PHPExcel/Writer/Excel2007/RelsVBA.php +++ b/Classes/PHPExcel/Writer/Excel2007/RelsVBA.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,38 +35,38 @@ */ class PHPExcel_Writer_Excel2007_RelsVBA extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write relationships for a signed VBA Project - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeVBARelationships(PHPExcel $pPHPExcel = null){ - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write relationships for a signed VBA Project + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVBARelationships(PHPExcel $pPHPExcel = null){ + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // Relationships - $objWriter->startElement('Relationships'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - $objWriter->startElement('Relationship'); - $objWriter->writeAttribute('Id', 'rId1'); - $objWriter->writeAttribute('Type', 'http://schemas.microsoft.com/office/2006/relationships/vbaProjectSignature'); - $objWriter->writeAttribute('Target', 'vbaProjectSignature.bin'); - $objWriter->endElement();//Relationship - $objWriter->endElement();//Relationships + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', 'rId1'); + $objWriter->writeAttribute('Type', 'http://schemas.microsoft.com/office/2006/relationships/vbaProjectSignature'); + $objWriter->writeAttribute('Target', 'vbaProjectSignature.bin'); + $objWriter->endElement();//Relationship + $objWriter->endElement();//Relationships - // Return - return $objWriter->getData(); + // Return + return $objWriter->getData(); - } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/StringTable.php b/Classes/PHPExcel/Writer/Excel2007/StringTable.php index 1d7bbfde..dbadb88b 100644 --- a/Classes/PHPExcel/Writer/Excel2007/StringTable.php +++ b/Classes/PHPExcel/Writer/Excel2007/StringTable.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,285 +35,285 @@ */ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Create worksheet stringtable - * - * @param PHPExcel_Worksheet $pSheet Worksheet - * @param string[] $pExistingTable Existing table to eventually merge with - * @return string[] String table for worksheet - * @throws PHPExcel_Writer_Exception - */ - public function createStringTable($pSheet = null, $pExistingTable = null) - { - if ($pSheet !== NULL) { - // Create string lookup table - $aStringTable = array(); - $cellCollection = null; - $aFlippedStringTable = null; // For faster lookup + /** + * Create worksheet stringtable + * + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param string[] $pExistingTable Existing table to eventually merge with + * @return string[] String table for worksheet + * @throws PHPExcel_Writer_Exception + */ + public function createStringTable($pSheet = null, $pExistingTable = null) + { + if ($pSheet !== NULL) { + // Create string lookup table + $aStringTable = array(); + $cellCollection = null; + $aFlippedStringTable = null; // For faster lookup - // Is an existing table given? - if (($pExistingTable !== NULL) && is_array($pExistingTable)) { - $aStringTable = $pExistingTable; - } + // Is an existing table given? + if (($pExistingTable !== NULL) && is_array($pExistingTable)) { + $aStringTable = $pExistingTable; + } - // Fill index array - $aFlippedStringTable = $this->flipStringTable($aStringTable); + // Fill index array + $aFlippedStringTable = $this->flipStringTable($aStringTable); - // Loop through cells - foreach ($pSheet->getCellCollection() as $cellID) { - $cell = $pSheet->getCell($cellID); - $cellValue = $cell->getValue(); - if (!is_object($cellValue) && - ($cellValue !== NULL) && - $cellValue !== '' && - !isset($aFlippedStringTable[$cellValue]) && - ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING2 || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_NULL)) { - $aStringTable[] = $cellValue; - $aFlippedStringTable[$cellValue] = true; - } elseif ($cellValue instanceof PHPExcel_RichText && - ($cellValue !== NULL) && - !isset($aFlippedStringTable[$cellValue->getHashCode()])) { - $aStringTable[] = $cellValue; - $aFlippedStringTable[$cellValue->getHashCode()] = true; - } - } + // Loop through cells + foreach ($pSheet->getCellCollection() as $cellID) { + $cell = $pSheet->getCell($cellID); + $cellValue = $cell->getValue(); + if (!is_object($cellValue) && + ($cellValue !== NULL) && + $cellValue !== '' && + !isset($aFlippedStringTable[$cellValue]) && + ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING2 || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_NULL)) { + $aStringTable[] = $cellValue; + $aFlippedStringTable[$cellValue] = true; + } elseif ($cellValue instanceof PHPExcel_RichText && + ($cellValue !== NULL) && + !isset($aFlippedStringTable[$cellValue->getHashCode()])) { + $aStringTable[] = $cellValue; + $aFlippedStringTable[$cellValue->getHashCode()] = true; + } + } - // Return - return $aStringTable; - } else { - throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); - } - } + // Return + return $aStringTable; + } else { + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); + } + } - /** - * Write string table to XML format - * - * @param string[] $pStringTable - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeStringTable($pStringTable = null) - { - if ($pStringTable !== NULL) { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write string table to XML format + * + * @param string[] $pStringTable + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeStringTable($pStringTable = null) + { + if ($pStringTable !== NULL) { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // String table - $objWriter->startElement('sst'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - $objWriter->writeAttribute('uniqueCount', count($pStringTable)); + // String table + $objWriter->startElement('sst'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('uniqueCount', count($pStringTable)); - // Loop through string table - foreach ($pStringTable as $textElement) { - $objWriter->startElement('si'); + // Loop through string table + foreach ($pStringTable as $textElement) { + $objWriter->startElement('si'); - if (! $textElement instanceof PHPExcel_RichText) { - $textToWrite = PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $textElement ); - $objWriter->startElement('t'); - if ($textToWrite !== trim($textToWrite)) { - $objWriter->writeAttribute('xml:space', 'preserve'); - } - $objWriter->writeRawData($textToWrite); - $objWriter->endElement(); - } else if ($textElement instanceof PHPExcel_RichText) { - $this->writeRichText($objWriter, $textElement); - } + if (! $textElement instanceof PHPExcel_RichText) { + $textToWrite = PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $textElement ); + $objWriter->startElement('t'); + if ($textToWrite !== trim($textToWrite)) { + $objWriter->writeAttribute('xml:space', 'preserve'); + } + $objWriter->writeRawData($textToWrite); + $objWriter->endElement(); + } else if ($textElement instanceof PHPExcel_RichText) { + $this->writeRichText($objWriter, $textElement); + } $objWriter->endElement(); - } + } - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } else { - throw new PHPExcel_Writer_Exception("Invalid string table array passed."); - } - } + // Return + return $objWriter->getData(); + } else { + throw new PHPExcel_Writer_Exception("Invalid string table array passed."); + } + } - /** - * Write Rich Text - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_RichText $pRichText Rich text - * @param string $prefix Optional Namespace prefix - * @throws PHPExcel_Writer_Exception - */ - public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null, $prefix=NULL) - { - if ($prefix !== NULL) - $prefix .= ':'; - // Loop through rich text elements - $elements = $pRichText->getRichTextElements(); - foreach ($elements as $element) { - // r - $objWriter->startElement($prefix.'r'); + /** + * Write Rich Text + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_RichText $pRichText Rich text + * @param string $prefix Optional Namespace prefix + * @throws PHPExcel_Writer_Exception + */ + public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null, $prefix=NULL) + { + if ($prefix !== NULL) + $prefix .= ':'; + // Loop through rich text elements + $elements = $pRichText->getRichTextElements(); + foreach ($elements as $element) { + // r + $objWriter->startElement($prefix.'r'); - // rPr - if ($element instanceof PHPExcel_RichText_Run) { - // rPr - $objWriter->startElement($prefix.'rPr'); + // rPr + if ($element instanceof PHPExcel_RichText_Run) { + // rPr + $objWriter->startElement($prefix.'rPr'); - // rFont - $objWriter->startElement($prefix.'rFont'); - $objWriter->writeAttribute('val', $element->getFont()->getName()); - $objWriter->endElement(); + // rFont + $objWriter->startElement($prefix.'rFont'); + $objWriter->writeAttribute('val', $element->getFont()->getName()); + $objWriter->endElement(); - // Bold - $objWriter->startElement($prefix.'b'); - $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false')); - $objWriter->endElement(); + // Bold + $objWriter->startElement($prefix.'b'); + $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false')); + $objWriter->endElement(); - // Italic - $objWriter->startElement($prefix.'i'); - $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false')); - $objWriter->endElement(); + // Italic + $objWriter->startElement($prefix.'i'); + $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false')); + $objWriter->endElement(); - // Superscript / subscript - if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { - $objWriter->startElement($prefix.'vertAlign'); - if ($element->getFont()->getSuperScript()) { - $objWriter->writeAttribute('val', 'superscript'); - } else if ($element->getFont()->getSubScript()) { - $objWriter->writeAttribute('val', 'subscript'); - } - $objWriter->endElement(); - } + // Superscript / subscript + if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { + $objWriter->startElement($prefix.'vertAlign'); + if ($element->getFont()->getSuperScript()) { + $objWriter->writeAttribute('val', 'superscript'); + } else if ($element->getFont()->getSubScript()) { + $objWriter->writeAttribute('val', 'subscript'); + } + $objWriter->endElement(); + } - // Strikethrough - $objWriter->startElement($prefix.'strike'); - $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false')); - $objWriter->endElement(); + // Strikethrough + $objWriter->startElement($prefix.'strike'); + $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false')); + $objWriter->endElement(); - // Color - $objWriter->startElement($prefix.'color'); - $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB()); - $objWriter->endElement(); + // Color + $objWriter->startElement($prefix.'color'); + $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB()); + $objWriter->endElement(); - // Size - $objWriter->startElement($prefix.'sz'); - $objWriter->writeAttribute('val', $element->getFont()->getSize()); - $objWriter->endElement(); + // Size + $objWriter->startElement($prefix.'sz'); + $objWriter->writeAttribute('val', $element->getFont()->getSize()); + $objWriter->endElement(); - // Underline - $objWriter->startElement($prefix.'u'); - $objWriter->writeAttribute('val', $element->getFont()->getUnderline()); - $objWriter->endElement(); + // Underline + $objWriter->startElement($prefix.'u'); + $objWriter->writeAttribute('val', $element->getFont()->getUnderline()); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - // t - $objWriter->startElement($prefix.'t'); - $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); - $objWriter->endElement(); + // t + $objWriter->startElement($prefix.'t'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); + $objWriter->endElement(); - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } - /** - * Write Rich Text - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string|PHPExcel_RichText $pRichText text string or Rich text - * @param string $prefix Optional Namespace prefix - * @throws PHPExcel_Writer_Exception - */ - public function writeRichTextForCharts(PHPExcel_Shared_XMLWriter $objWriter = null, $pRichText = null, $prefix=NULL) - { - if (!$pRichText instanceof PHPExcel_RichText) { - $textRun = $pRichText; - $pRichText = new PHPExcel_RichText(); - $pRichText->createTextRun($textRun); - } + /** + * Write Rich Text + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string|PHPExcel_RichText $pRichText text string or Rich text + * @param string $prefix Optional Namespace prefix + * @throws PHPExcel_Writer_Exception + */ + public function writeRichTextForCharts(PHPExcel_Shared_XMLWriter $objWriter = null, $pRichText = null, $prefix=NULL) + { + if (!$pRichText instanceof PHPExcel_RichText) { + $textRun = $pRichText; + $pRichText = new PHPExcel_RichText(); + $pRichText->createTextRun($textRun); + } - if ($prefix !== NULL) - $prefix .= ':'; - // Loop through rich text elements - $elements = $pRichText->getRichTextElements(); - foreach ($elements as $element) { - // r - $objWriter->startElement($prefix.'r'); + if ($prefix !== NULL) + $prefix .= ':'; + // Loop through rich text elements + $elements = $pRichText->getRichTextElements(); + foreach ($elements as $element) { + // r + $objWriter->startElement($prefix.'r'); - // rPr - $objWriter->startElement($prefix.'rPr'); + // rPr + $objWriter->startElement($prefix.'rPr'); - // Bold - $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0)); - // Italic - $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? 1 : 0)); - // Underline - $underlineType = $element->getFont()->getUnderline(); - switch($underlineType) { - case 'single' : - $underlineType = 'sng'; - break; - case 'double' : - $underlineType = 'dbl'; - break; - } - $objWriter->writeAttribute('u', $underlineType); - // Strikethrough - $objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike')); + // Bold + $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0)); + // Italic + $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? 1 : 0)); + // Underline + $underlineType = $element->getFont()->getUnderline(); + switch($underlineType) { + case 'single' : + $underlineType = 'sng'; + break; + case 'double' : + $underlineType = 'dbl'; + break; + } + $objWriter->writeAttribute('u', $underlineType); + // Strikethrough + $objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike')); - // rFont - $objWriter->startElement($prefix.'latin'); - $objWriter->writeAttribute('typeface', $element->getFont()->getName()); - $objWriter->endElement(); + // rFont + $objWriter->startElement($prefix.'latin'); + $objWriter->writeAttribute('typeface', $element->getFont()->getName()); + $objWriter->endElement(); - // Superscript / subscript -// if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { -// $objWriter->startElement($prefix.'vertAlign'); -// if ($element->getFont()->getSuperScript()) { -// $objWriter->writeAttribute('val', 'superscript'); -// } else if ($element->getFont()->getSubScript()) { -// $objWriter->writeAttribute('val', 'subscript'); -// } -// $objWriter->endElement(); -// } + // Superscript / subscript +// if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { +// $objWriter->startElement($prefix.'vertAlign'); +// if ($element->getFont()->getSuperScript()) { +// $objWriter->writeAttribute('val', 'superscript'); +// } else if ($element->getFont()->getSubScript()) { +// $objWriter->writeAttribute('val', 'subscript'); +// } +// $objWriter->endElement(); +// } // - $objWriter->endElement(); + $objWriter->endElement(); - // t - $objWriter->startElement($prefix.'t'); -// $objWriter->writeAttribute('xml:space', 'preserve'); // Excel2010 accepts, Excel2007 complains - $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); - $objWriter->endElement(); + // t + $objWriter->startElement($prefix.'t'); +// $objWriter->writeAttribute('xml:space', 'preserve'); // Excel2010 accepts, Excel2007 complains + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); + $objWriter->endElement(); - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } - /** - * Flip string table (for index searching) - * - * @param array $stringTable Stringtable - * @return array - */ - public function flipStringTable($stringTable = array()) { - // Return value - $returnValue = array(); + /** + * Flip string table (for index searching) + * + * @param array $stringTable Stringtable + * @return array + */ + public function flipStringTable($stringTable = array()) { + // Return value + $returnValue = array(); - // Loop through stringtable and add flipped items to $returnValue - foreach ($stringTable as $key => $value) { - if (! $value instanceof PHPExcel_RichText) { - $returnValue[$value] = $key; - } else if ($value instanceof PHPExcel_RichText) { - $returnValue[$value->getHashCode()] = $key; - } - } + // Loop through stringtable and add flipped items to $returnValue + foreach ($stringTable as $key => $value) { + if (! $value instanceof PHPExcel_RichText) { + $returnValue[$value] = $key; + } else if ($value instanceof PHPExcel_RichText) { + $returnValue[$value->getHashCode()] = $key; + } + } - // Return - return $returnValue; - } + // Return + return $returnValue; + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Style.php b/Classes/PHPExcel/Writer/Excel2007/Style.php index d0a7ce9f..527984b9 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Style.php +++ b/Classes/PHPExcel/Writer/Excel2007/Style.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,673 +35,673 @@ */ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write styles to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeStyles(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write styles to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeStyles(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // styleSheet - $objWriter->startElement('styleSheet'); - $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + // styleSheet + $objWriter->startElement('styleSheet'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - // numFmts - $objWriter->startElement('numFmts'); - $objWriter->writeAttribute('count', $this->getParentWriter()->getNumFmtHashTable()->count()); + // numFmts + $objWriter->startElement('numFmts'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getNumFmtHashTable()->count()); - // numFmt - for ($i = 0; $i < $this->getParentWriter()->getNumFmtHashTable()->count(); ++$i) { - $this->_writeNumFmt($objWriter, $this->getParentWriter()->getNumFmtHashTable()->getByIndex($i), $i); - } + // numFmt + for ($i = 0; $i < $this->getParentWriter()->getNumFmtHashTable()->count(); ++$i) { + $this->_writeNumFmt($objWriter, $this->getParentWriter()->getNumFmtHashTable()->getByIndex($i), $i); + } - $objWriter->endElement(); + $objWriter->endElement(); - // fonts - $objWriter->startElement('fonts'); - $objWriter->writeAttribute('count', $this->getParentWriter()->getFontHashTable()->count()); + // fonts + $objWriter->startElement('fonts'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getFontHashTable()->count()); - // font - for ($i = 0; $i < $this->getParentWriter()->getFontHashTable()->count(); ++$i) { - $this->_writeFont($objWriter, $this->getParentWriter()->getFontHashTable()->getByIndex($i)); - } + // font + for ($i = 0; $i < $this->getParentWriter()->getFontHashTable()->count(); ++$i) { + $this->_writeFont($objWriter, $this->getParentWriter()->getFontHashTable()->getByIndex($i)); + } - $objWriter->endElement(); + $objWriter->endElement(); - // fills - $objWriter->startElement('fills'); - $objWriter->writeAttribute('count', $this->getParentWriter()->getFillHashTable()->count()); + // fills + $objWriter->startElement('fills'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getFillHashTable()->count()); - // fill - for ($i = 0; $i < $this->getParentWriter()->getFillHashTable()->count(); ++$i) { - $this->_writeFill($objWriter, $this->getParentWriter()->getFillHashTable()->getByIndex($i)); - } + // fill + for ($i = 0; $i < $this->getParentWriter()->getFillHashTable()->count(); ++$i) { + $this->_writeFill($objWriter, $this->getParentWriter()->getFillHashTable()->getByIndex($i)); + } - $objWriter->endElement(); + $objWriter->endElement(); - // borders - $objWriter->startElement('borders'); - $objWriter->writeAttribute('count', $this->getParentWriter()->getBordersHashTable()->count()); + // borders + $objWriter->startElement('borders'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getBordersHashTable()->count()); - // border - for ($i = 0; $i < $this->getParentWriter()->getBordersHashTable()->count(); ++$i) { - $this->_writeBorder($objWriter, $this->getParentWriter()->getBordersHashTable()->getByIndex($i)); - } + // border + for ($i = 0; $i < $this->getParentWriter()->getBordersHashTable()->count(); ++$i) { + $this->_writeBorder($objWriter, $this->getParentWriter()->getBordersHashTable()->getByIndex($i)); + } - $objWriter->endElement(); + $objWriter->endElement(); - // cellStyleXfs - $objWriter->startElement('cellStyleXfs'); - $objWriter->writeAttribute('count', 1); + // cellStyleXfs + $objWriter->startElement('cellStyleXfs'); + $objWriter->writeAttribute('count', 1); - // xf - $objWriter->startElement('xf'); - $objWriter->writeAttribute('numFmtId', 0); - $objWriter->writeAttribute('fontId', 0); - $objWriter->writeAttribute('fillId', 0); - $objWriter->writeAttribute('borderId', 0); - $objWriter->endElement(); + // xf + $objWriter->startElement('xf'); + $objWriter->writeAttribute('numFmtId', 0); + $objWriter->writeAttribute('fontId', 0); + $objWriter->writeAttribute('fillId', 0); + $objWriter->writeAttribute('borderId', 0); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // cellXfs - $objWriter->startElement('cellXfs'); - $objWriter->writeAttribute('count', count($pPHPExcel->getCellXfCollection())); + // cellXfs + $objWriter->startElement('cellXfs'); + $objWriter->writeAttribute('count', count($pPHPExcel->getCellXfCollection())); - // xf - foreach ($pPHPExcel->getCellXfCollection() as $cellXf) { - $this->_writeCellStyleXf($objWriter, $cellXf, $pPHPExcel); - } + // xf + foreach ($pPHPExcel->getCellXfCollection() as $cellXf) { + $this->_writeCellStyleXf($objWriter, $cellXf, $pPHPExcel); + } - $objWriter->endElement(); + $objWriter->endElement(); - // cellStyles - $objWriter->startElement('cellStyles'); - $objWriter->writeAttribute('count', 1); + // cellStyles + $objWriter->startElement('cellStyles'); + $objWriter->writeAttribute('count', 1); - // cellStyle - $objWriter->startElement('cellStyle'); - $objWriter->writeAttribute('name', 'Normal'); - $objWriter->writeAttribute('xfId', 0); - $objWriter->writeAttribute('builtinId', 0); - $objWriter->endElement(); + // cellStyle + $objWriter->startElement('cellStyle'); + $objWriter->writeAttribute('name', 'Normal'); + $objWriter->writeAttribute('xfId', 0); + $objWriter->writeAttribute('builtinId', 0); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // dxfs - $objWriter->startElement('dxfs'); - $objWriter->writeAttribute('count', $this->getParentWriter()->getStylesConditionalHashTable()->count()); + // dxfs + $objWriter->startElement('dxfs'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getStylesConditionalHashTable()->count()); - // dxf - for ($i = 0; $i < $this->getParentWriter()->getStylesConditionalHashTable()->count(); ++$i) { - $this->_writeCellStyleDxf($objWriter, $this->getParentWriter()->getStylesConditionalHashTable()->getByIndex($i)->getStyle()); - } + // dxf + for ($i = 0; $i < $this->getParentWriter()->getStylesConditionalHashTable()->count(); ++$i) { + $this->_writeCellStyleDxf($objWriter, $this->getParentWriter()->getStylesConditionalHashTable()->getByIndex($i)->getStyle()); + } - $objWriter->endElement(); + $objWriter->endElement(); - // tableStyles - $objWriter->startElement('tableStyles'); - $objWriter->writeAttribute('defaultTableStyle', 'TableStyleMedium9'); - $objWriter->writeAttribute('defaultPivotStyle', 'PivotTableStyle1'); - $objWriter->endElement(); + // tableStyles + $objWriter->startElement('tableStyles'); + $objWriter->writeAttribute('defaultTableStyle', 'TableStyleMedium9'); + $objWriter->writeAttribute('defaultPivotStyle', 'PivotTableStyle1'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write Fill - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_Fill $pFill Fill style - * @throws PHPExcel_Writer_Exception - */ - private function _writeFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) - { - // Check if this is a pattern type or gradient type - if ($pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR || - $pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_PATH) { - // Gradient fill - $this->_writeGradientFill($objWriter, $pFill); - } elseif($pFill->getFillType() !== NULL) { - // Pattern fill - $this->_writePatternFill($objWriter, $pFill); - } - } + /** + * Write Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writeFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // Check if this is a pattern type or gradient type + if ($pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR || + $pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_PATH) { + // Gradient fill + $this->_writeGradientFill($objWriter, $pFill); + } elseif($pFill->getFillType() !== NULL) { + // Pattern fill + $this->_writePatternFill($objWriter, $pFill); + } + } - /** - * Write Gradient Fill - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_Fill $pFill Fill style - * @throws PHPExcel_Writer_Exception - */ - private function _writeGradientFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) - { - // fill - $objWriter->startElement('fill'); + /** + * Write Gradient Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writeGradientFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // fill + $objWriter->startElement('fill'); - // gradientFill - $objWriter->startElement('gradientFill'); - $objWriter->writeAttribute('type', $pFill->getFillType()); - $objWriter->writeAttribute('degree', $pFill->getRotation()); + // gradientFill + $objWriter->startElement('gradientFill'); + $objWriter->writeAttribute('type', $pFill->getFillType()); + $objWriter->writeAttribute('degree', $pFill->getRotation()); - // stop - $objWriter->startElement('stop'); - $objWriter->writeAttribute('position', '0'); + // stop + $objWriter->startElement('stop'); + $objWriter->writeAttribute('position', '0'); - // color - $objWriter->startElement('color'); - $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); - $objWriter->endElement(); + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // stop - $objWriter->startElement('stop'); - $objWriter->writeAttribute('position', '1'); + // stop + $objWriter->startElement('stop'); + $objWriter->writeAttribute('position', '1'); - // color - $objWriter->startElement('color'); - $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); - $objWriter->endElement(); + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write Pattern Fill - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_Fill $pFill Fill style - * @throws PHPExcel_Writer_Exception - */ - private function _writePatternFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) - { - // fill - $objWriter->startElement('fill'); + /** + * Write Pattern Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writePatternFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // fill + $objWriter->startElement('fill'); - // patternFill - $objWriter->startElement('patternFill'); - $objWriter->writeAttribute('patternType', $pFill->getFillType()); + // patternFill + $objWriter->startElement('patternFill'); + $objWriter->writeAttribute('patternType', $pFill->getFillType()); - if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { - // fgColor - if ($pFill->getStartColor()->getARGB()) { - $objWriter->startElement('fgColor'); - $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); - $objWriter->endElement(); - } - } - if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { - // bgColor - if ($pFill->getEndColor()->getARGB()) { - $objWriter->startElement('bgColor'); - $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); - $objWriter->endElement(); - } - } + if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { + // fgColor + if ($pFill->getStartColor()->getARGB()) { + $objWriter->startElement('fgColor'); + $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); + $objWriter->endElement(); + } + } + if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { + // bgColor + if ($pFill->getEndColor()->getARGB()) { + $objWriter->startElement('bgColor'); + $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); + $objWriter->endElement(); + } + } - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write Font - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_Font $pFont Font style - * @throws PHPExcel_Writer_Exception - */ - private function _writeFont(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Font $pFont = null) - { - // font - $objWriter->startElement('font'); - // Weird! The order of these elements actually makes a difference when opening Excel2007 - // files in Excel2003 with the compatibility pack. It's not documented behaviour, - // and makes for a real WTF! + /** + * Write Font + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Font $pFont Font style + * @throws PHPExcel_Writer_Exception + */ + private function _writeFont(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Font $pFont = null) + { + // font + $objWriter->startElement('font'); + // Weird! The order of these elements actually makes a difference when opening Excel2007 + // files in Excel2003 with the compatibility pack. It's not documented behaviour, + // and makes for a real WTF! - // Bold. We explicitly write this element also when false (like MS Office Excel 2007 does - // for conditional formatting). Otherwise it will apparently not be picked up in conditional - // formatting style dialog - if ($pFont->getBold() !== NULL) { - $objWriter->startElement('b'); - $objWriter->writeAttribute('val', $pFont->getBold() ? '1' : '0'); - $objWriter->endElement(); - } - - // Italic - if ($pFont->getItalic() !== NULL) { - $objWriter->startElement('i'); - $objWriter->writeAttribute('val', $pFont->getItalic() ? '1' : '0'); - $objWriter->endElement(); - } - - // Strikethrough - if ($pFont->getStrikethrough() !== NULL) { - $objWriter->startElement('strike'); - $objWriter->writeAttribute('val', $pFont->getStrikethrough() ? '1' : '0'); - $objWriter->endElement(); - } - - // Underline - if ($pFont->getUnderline() !== NULL) { - $objWriter->startElement('u'); - $objWriter->writeAttribute('val', $pFont->getUnderline()); - $objWriter->endElement(); - } - - // Superscript / subscript - if ($pFont->getSuperScript() === TRUE || $pFont->getSubScript() === TRUE) { - $objWriter->startElement('vertAlign'); - if ($pFont->getSuperScript() === TRUE) { - $objWriter->writeAttribute('val', 'superscript'); - } else if ($pFont->getSubScript() === TRUE) { - $objWriter->writeAttribute('val', 'subscript'); - } - $objWriter->endElement(); - } - - // Size - if ($pFont->getSize() !== NULL) { - $objWriter->startElement('sz'); - $objWriter->writeAttribute('val', $pFont->getSize()); - $objWriter->endElement(); - } - - // Foreground color - if ($pFont->getColor()->getARGB() !== NULL) { - $objWriter->startElement('color'); - $objWriter->writeAttribute('rgb', $pFont->getColor()->getARGB()); - $objWriter->endElement(); - } - - // Name - if ($pFont->getName() !== NULL) { - $objWriter->startElement('name'); - $objWriter->writeAttribute('val', $pFont->getName()); - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - - /** - * Write Border - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_Borders $pBorders Borders style - * @throws PHPExcel_Writer_Exception - */ - private function _writeBorder(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Borders $pBorders = null) - { - // Write border - $objWriter->startElement('border'); - // Diagonal? - switch ($pBorders->getDiagonalDirection()) { - case PHPExcel_Style_Borders::DIAGONAL_UP: - $objWriter->writeAttribute('diagonalUp', 'true'); - $objWriter->writeAttribute('diagonalDown', 'false'); - break; - case PHPExcel_Style_Borders::DIAGONAL_DOWN: - $objWriter->writeAttribute('diagonalUp', 'false'); - $objWriter->writeAttribute('diagonalDown', 'true'); - break; - case PHPExcel_Style_Borders::DIAGONAL_BOTH: - $objWriter->writeAttribute('diagonalUp', 'true'); - $objWriter->writeAttribute('diagonalDown', 'true'); - break; - } - - // BorderPr - $this->_writeBorderPr($objWriter, 'left', $pBorders->getLeft()); - $this->_writeBorderPr($objWriter, 'right', $pBorders->getRight()); - $this->_writeBorderPr($objWriter, 'top', $pBorders->getTop()); - $this->_writeBorderPr($objWriter, 'bottom', $pBorders->getBottom()); - $this->_writeBorderPr($objWriter, 'diagonal', $pBorders->getDiagonal()); - $objWriter->endElement(); - } - - /** - * Write Cell Style Xf - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style $pStyle Style - * @param PHPExcel $pPHPExcel Workbook - * @throws PHPExcel_Writer_Exception - */ - private function _writeCellStyleXf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null, PHPExcel $pPHPExcel = null) - { - // xf - $objWriter->startElement('xf'); - $objWriter->writeAttribute('xfId', 0); - $objWriter->writeAttribute('fontId', (int)$this->getParentWriter()->getFontHashTable()->getIndexForHashCode($pStyle->getFont()->getHashCode())); - if ($pStyle->getQuotePrefix()) { - $objWriter->writeAttribute('quotePrefix', 1); + // Bold. We explicitly write this element also when false (like MS Office Excel 2007 does + // for conditional formatting). Otherwise it will apparently not be picked up in conditional + // formatting style dialog + if ($pFont->getBold() !== NULL) { + $objWriter->startElement('b'); + $objWriter->writeAttribute('val', $pFont->getBold() ? '1' : '0'); + $objWriter->endElement(); } - if ($pStyle->getNumberFormat()->getBuiltInFormatCode() === false) { - $objWriter->writeAttribute('numFmtId', (int)($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($pStyle->getNumberFormat()->getHashCode()) + 164) ); - } else { - $objWriter->writeAttribute('numFmtId', (int)$pStyle->getNumberFormat()->getBuiltInFormatCode()); - } + // Italic + if ($pFont->getItalic() !== NULL) { + $objWriter->startElement('i'); + $objWriter->writeAttribute('val', $pFont->getItalic() ? '1' : '0'); + $objWriter->endElement(); + } - $objWriter->writeAttribute('fillId', (int)$this->getParentWriter()->getFillHashTable()->getIndexForHashCode($pStyle->getFill()->getHashCode())); - $objWriter->writeAttribute('borderId', (int)$this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($pStyle->getBorders()->getHashCode())); + // Strikethrough + if ($pFont->getStrikethrough() !== NULL) { + $objWriter->startElement('strike'); + $objWriter->writeAttribute('val', $pFont->getStrikethrough() ? '1' : '0'); + $objWriter->endElement(); + } - // Apply styles? - $objWriter->writeAttribute('applyFont', ($pPHPExcel->getDefaultStyle()->getFont()->getHashCode() != $pStyle->getFont()->getHashCode()) ? '1' : '0'); - $objWriter->writeAttribute('applyNumberFormat', ($pPHPExcel->getDefaultStyle()->getNumberFormat()->getHashCode() != $pStyle->getNumberFormat()->getHashCode()) ? '1' : '0'); - $objWriter->writeAttribute('applyFill', ($pPHPExcel->getDefaultStyle()->getFill()->getHashCode() != $pStyle->getFill()->getHashCode()) ? '1' : '0'); - $objWriter->writeAttribute('applyBorder', ($pPHPExcel->getDefaultStyle()->getBorders()->getHashCode() != $pStyle->getBorders()->getHashCode()) ? '1' : '0'); - $objWriter->writeAttribute('applyAlignment', ($pPHPExcel->getDefaultStyle()->getAlignment()->getHashCode() != $pStyle->getAlignment()->getHashCode()) ? '1' : '0'); - if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { - $objWriter->writeAttribute('applyProtection', 'true'); - } + // Underline + if ($pFont->getUnderline() !== NULL) { + $objWriter->startElement('u'); + $objWriter->writeAttribute('val', $pFont->getUnderline()); + $objWriter->endElement(); + } - // alignment - $objWriter->startElement('alignment'); - $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); - $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); + // Superscript / subscript + if ($pFont->getSuperScript() === TRUE || $pFont->getSubScript() === TRUE) { + $objWriter->startElement('vertAlign'); + if ($pFont->getSuperScript() === TRUE) { + $objWriter->writeAttribute('val', 'superscript'); + } else if ($pFont->getSubScript() === TRUE) { + $objWriter->writeAttribute('val', 'subscript'); + } + $objWriter->endElement(); + } - $textRotation = 0; - if ($pStyle->getAlignment()->getTextRotation() >= 0) { - $textRotation = $pStyle->getAlignment()->getTextRotation(); - } else if ($pStyle->getAlignment()->getTextRotation() < 0) { - $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); - } - $objWriter->writeAttribute('textRotation', $textRotation); + // Size + if ($pFont->getSize() !== NULL) { + $objWriter->startElement('sz'); + $objWriter->writeAttribute('val', $pFont->getSize()); + $objWriter->endElement(); + } - $objWriter->writeAttribute('wrapText', ($pStyle->getAlignment()->getWrapText() ? 'true' : 'false')); - $objWriter->writeAttribute('shrinkToFit', ($pStyle->getAlignment()->getShrinkToFit() ? 'true' : 'false')); + // Foreground color + if ($pFont->getColor()->getARGB() !== NULL) { + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFont->getColor()->getARGB()); + $objWriter->endElement(); + } - if ($pStyle->getAlignment()->getIndent() > 0) { - $objWriter->writeAttribute('indent', $pStyle->getAlignment()->getIndent()); - } - if ($pStyle->getAlignment()->getReadorder() > 0) { - $objWriter->writeAttribute('readingOrder', $pStyle->getAlignment()->getReadorder()); - } - $objWriter->endElement(); + // Name + if ($pFont->getName() !== NULL) { + $objWriter->startElement('name'); + $objWriter->writeAttribute('val', $pFont->getName()); + $objWriter->endElement(); + } - // protection - if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { - $objWriter->startElement('protection'); - if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { - $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); - } - if ($pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { - $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); - } - $objWriter->endElement(); - } + $objWriter->endElement(); + } - $objWriter->endElement(); - } + /** + * Write Border + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Borders $pBorders Borders style + * @throws PHPExcel_Writer_Exception + */ + private function _writeBorder(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Borders $pBorders = null) + { + // Write border + $objWriter->startElement('border'); + // Diagonal? + switch ($pBorders->getDiagonalDirection()) { + case PHPExcel_Style_Borders::DIAGONAL_UP: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'false'); + break; + case PHPExcel_Style_Borders::DIAGONAL_DOWN: + $objWriter->writeAttribute('diagonalUp', 'false'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; + case PHPExcel_Style_Borders::DIAGONAL_BOTH: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; + } - /** - * Write Cell Style Dxf - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style $pStyle Style - * @throws PHPExcel_Writer_Exception - */ - private function _writeCellStyleDxf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null) - { - // dxf - $objWriter->startElement('dxf'); + // BorderPr + $this->_writeBorderPr($objWriter, 'left', $pBorders->getLeft()); + $this->_writeBorderPr($objWriter, 'right', $pBorders->getRight()); + $this->_writeBorderPr($objWriter, 'top', $pBorders->getTop()); + $this->_writeBorderPr($objWriter, 'bottom', $pBorders->getBottom()); + $this->_writeBorderPr($objWriter, 'diagonal', $pBorders->getDiagonal()); + $objWriter->endElement(); + } - // font - $this->_writeFont($objWriter, $pStyle->getFont()); + /** + * Write Cell Style Xf + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style $pStyle Style + * @param PHPExcel $pPHPExcel Workbook + * @throws PHPExcel_Writer_Exception + */ + private function _writeCellStyleXf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null, PHPExcel $pPHPExcel = null) + { + // xf + $objWriter->startElement('xf'); + $objWriter->writeAttribute('xfId', 0); + $objWriter->writeAttribute('fontId', (int)$this->getParentWriter()->getFontHashTable()->getIndexForHashCode($pStyle->getFont()->getHashCode())); + if ($pStyle->getQuotePrefix()) { + $objWriter->writeAttribute('quotePrefix', 1); + } - // numFmt - $this->_writeNumFmt($objWriter, $pStyle->getNumberFormat()); + if ($pStyle->getNumberFormat()->getBuiltInFormatCode() === false) { + $objWriter->writeAttribute('numFmtId', (int)($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($pStyle->getNumberFormat()->getHashCode()) + 164) ); + } else { + $objWriter->writeAttribute('numFmtId', (int)$pStyle->getNumberFormat()->getBuiltInFormatCode()); + } - // fill - $this->_writeFill($objWriter, $pStyle->getFill()); + $objWriter->writeAttribute('fillId', (int)$this->getParentWriter()->getFillHashTable()->getIndexForHashCode($pStyle->getFill()->getHashCode())); + $objWriter->writeAttribute('borderId', (int)$this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($pStyle->getBorders()->getHashCode())); - // alignment - $objWriter->startElement('alignment'); - if ($pStyle->getAlignment()->getHorizontal() !== NULL) { - $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); - } - if ($pStyle->getAlignment()->getVertical() !== NULL) { - $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); - } + // Apply styles? + $objWriter->writeAttribute('applyFont', ($pPHPExcel->getDefaultStyle()->getFont()->getHashCode() != $pStyle->getFont()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyNumberFormat', ($pPHPExcel->getDefaultStyle()->getNumberFormat()->getHashCode() != $pStyle->getNumberFormat()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyFill', ($pPHPExcel->getDefaultStyle()->getFill()->getHashCode() != $pStyle->getFill()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyBorder', ($pPHPExcel->getDefaultStyle()->getBorders()->getHashCode() != $pStyle->getBorders()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyAlignment', ($pPHPExcel->getDefaultStyle()->getAlignment()->getHashCode() != $pStyle->getAlignment()->getHashCode()) ? '1' : '0'); + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('applyProtection', 'true'); + } - if ($pStyle->getAlignment()->getTextRotation() !== NULL) { - $textRotation = 0; - if ($pStyle->getAlignment()->getTextRotation() >= 0) { - $textRotation = $pStyle->getAlignment()->getTextRotation(); - } else if ($pStyle->getAlignment()->getTextRotation() < 0) { - $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); - } - $objWriter->writeAttribute('textRotation', $textRotation); - } - $objWriter->endElement(); + // alignment + $objWriter->startElement('alignment'); + $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); + $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); - // border - $this->_writeBorder($objWriter, $pStyle->getBorders()); + $textRotation = 0; + if ($pStyle->getAlignment()->getTextRotation() >= 0) { + $textRotation = $pStyle->getAlignment()->getTextRotation(); + } else if ($pStyle->getAlignment()->getTextRotation() < 0) { + $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); + } + $objWriter->writeAttribute('textRotation', $textRotation); - // protection - if (($pStyle->getProtection()->getLocked() !== NULL) || - ($pStyle->getProtection()->getHidden() !== NULL)) { - if ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT || - $pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT) { - $objWriter->startElement('protection'); - if (($pStyle->getProtection()->getLocked() !== NULL) && - ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { - $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); - } - if (($pStyle->getProtection()->getHidden() !== NULL) && - ($pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { - $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); - } - $objWriter->endElement(); - } - } + $objWriter->writeAttribute('wrapText', ($pStyle->getAlignment()->getWrapText() ? 'true' : 'false')); + $objWriter->writeAttribute('shrinkToFit', ($pStyle->getAlignment()->getShrinkToFit() ? 'true' : 'false')); - $objWriter->endElement(); - } + if ($pStyle->getAlignment()->getIndent() > 0) { + $objWriter->writeAttribute('indent', $pStyle->getAlignment()->getIndent()); + } + if ($pStyle->getAlignment()->getReadorder() > 0) { + $objWriter->writeAttribute('readingOrder', $pStyle->getAlignment()->getReadorder()); + } + $objWriter->endElement(); - /** - * Write BorderPr - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pName Element name - * @param PHPExcel_Style_Border $pBorder Border style - * @throws PHPExcel_Writer_Exception - */ - private function _writeBorderPr(PHPExcel_Shared_XMLWriter $objWriter = null, $pName = 'left', PHPExcel_Style_Border $pBorder = null) - { - // Write BorderPr - if ($pBorder->getBorderStyle() != PHPExcel_Style_Border::BORDER_NONE) { - $objWriter->startElement($pName); - $objWriter->writeAttribute('style', $pBorder->getBorderStyle()); + // protection + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->startElement('protection'); + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + if ($pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + $objWriter->endElement(); + } - // color - $objWriter->startElement('color'); - $objWriter->writeAttribute('rgb', $pBorder->getColor()->getARGB()); - $objWriter->endElement(); + $objWriter->endElement(); + } - $objWriter->endElement(); - } - } + /** + * Write Cell Style Dxf + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style $pStyle Style + * @throws PHPExcel_Writer_Exception + */ + private function _writeCellStyleDxf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null) + { + // dxf + $objWriter->startElement('dxf'); - /** - * Write NumberFormat - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Style_NumberFormat $pNumberFormat Number Format - * @param int $pId Number Format identifier - * @throws PHPExcel_Writer_Exception - */ - private function _writeNumFmt(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_NumberFormat $pNumberFormat = null, $pId = 0) - { - // Translate formatcode - $formatCode = $pNumberFormat->getFormatCode(); + // font + $this->_writeFont($objWriter, $pStyle->getFont()); - // numFmt - if ($formatCode !== NULL) { - $objWriter->startElement('numFmt'); - $objWriter->writeAttribute('numFmtId', ($pId + 164)); - $objWriter->writeAttribute('formatCode', $formatCode); - $objWriter->endElement(); - } - } + // numFmt + $this->_writeNumFmt($objWriter, $pStyle->getNumberFormat()); - /** - * Get an array of all styles - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style[] All styles in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allStyles(PHPExcel $pPHPExcel = null) - { - $aStyles = $pPHPExcel->getCellXfCollection(); + // fill + $this->_writeFill($objWriter, $pStyle->getFill()); - return $aStyles; - } + // alignment + $objWriter->startElement('alignment'); + if ($pStyle->getAlignment()->getHorizontal() !== NULL) { + $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); + } + if ($pStyle->getAlignment()->getVertical() !== NULL) { + $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); + } - /** - * Get an array of all conditional styles - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style_Conditional[] All conditional styles in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allConditionalStyles(PHPExcel $pPHPExcel = null) - { - // Get an array of all styles - $aStyles = array(); + if ($pStyle->getAlignment()->getTextRotation() !== NULL) { + $textRotation = 0; + if ($pStyle->getAlignment()->getTextRotation() >= 0) { + $textRotation = $pStyle->getAlignment()->getTextRotation(); + } else if ($pStyle->getAlignment()->getTextRotation() < 0) { + $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); + } + $objWriter->writeAttribute('textRotation', $textRotation); + } + $objWriter->endElement(); - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - foreach ($pPHPExcel->getSheet($i)->getConditionalStylesCollection() as $conditionalStyles) { - foreach ($conditionalStyles as $conditionalStyle) { - $aStyles[] = $conditionalStyle; - } - } - } + // border + $this->_writeBorder($objWriter, $pStyle->getBorders()); - return $aStyles; - } + // protection + if (($pStyle->getProtection()->getLocked() !== NULL) || + ($pStyle->getProtection()->getHidden() !== NULL)) { + if ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT || + $pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->startElement('protection'); + if (($pStyle->getProtection()->getLocked() !== NULL) && + ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { + $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + if (($pStyle->getProtection()->getHidden() !== NULL) && + ($pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { + $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + $objWriter->endElement(); + } + } - /** - * Get an array of all fills - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style_Fill[] All fills in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allFills(PHPExcel $pPHPExcel = null) - { - // Get an array of unique fills - $aFills = array(); + $objWriter->endElement(); + } - // Two first fills are predefined - $fill0 = new PHPExcel_Style_Fill(); - $fill0->setFillType(PHPExcel_Style_Fill::FILL_NONE); - $aFills[] = $fill0; + /** + * Write BorderPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pName Element name + * @param PHPExcel_Style_Border $pBorder Border style + * @throws PHPExcel_Writer_Exception + */ + private function _writeBorderPr(PHPExcel_Shared_XMLWriter $objWriter = null, $pName = 'left', PHPExcel_Style_Border $pBorder = null) + { + // Write BorderPr + if ($pBorder->getBorderStyle() != PHPExcel_Style_Border::BORDER_NONE) { + $objWriter->startElement($pName); + $objWriter->writeAttribute('style', $pBorder->getBorderStyle()); - $fill1 = new PHPExcel_Style_Fill(); - $fill1->setFillType(PHPExcel_Style_Fill::FILL_PATTERN_GRAY125); - $aFills[] = $fill1; - // The remaining fills - $aStyles = $this->allStyles($pPHPExcel); - foreach ($aStyles as $style) { - if (!array_key_exists($style->getFill()->getHashCode(), $aFills)) { - $aFills[ $style->getFill()->getHashCode() ] = $style->getFill(); - } - } + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pBorder->getColor()->getARGB()); + $objWriter->endElement(); - return $aFills; - } + $objWriter->endElement(); + } + } - /** - * Get an array of all fonts - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style_Font[] All fonts in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allFonts(PHPExcel $pPHPExcel = null) - { - // Get an array of unique fonts - $aFonts = array(); - $aStyles = $this->allStyles($pPHPExcel); + /** + * Write NumberFormat + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_NumberFormat $pNumberFormat Number Format + * @param int $pId Number Format identifier + * @throws PHPExcel_Writer_Exception + */ + private function _writeNumFmt(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_NumberFormat $pNumberFormat = null, $pId = 0) + { + // Translate formatcode + $formatCode = $pNumberFormat->getFormatCode(); - foreach ($aStyles as $style) { - if (!array_key_exists($style->getFont()->getHashCode(), $aFonts)) { - $aFonts[ $style->getFont()->getHashCode() ] = $style->getFont(); - } - } + // numFmt + if ($formatCode !== NULL) { + $objWriter->startElement('numFmt'); + $objWriter->writeAttribute('numFmtId', ($pId + 164)); + $objWriter->writeAttribute('formatCode', $formatCode); + $objWriter->endElement(); + } + } - return $aFonts; - } + /** + * Get an array of all styles + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style[] All styles in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allStyles(PHPExcel $pPHPExcel = null) + { + $aStyles = $pPHPExcel->getCellXfCollection(); - /** - * Get an array of all borders - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style_Borders[] All borders in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allBorders(PHPExcel $pPHPExcel = null) - { - // Get an array of unique borders - $aBorders = array(); - $aStyles = $this->allStyles($pPHPExcel); + return $aStyles; + } - foreach ($aStyles as $style) { - if (!array_key_exists($style->getBorders()->getHashCode(), $aBorders)) { - $aBorders[ $style->getBorders()->getHashCode() ] = $style->getBorders(); - } - } + /** + * Get an array of all conditional styles + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Conditional[] All conditional styles in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allConditionalStyles(PHPExcel $pPHPExcel = null) + { + // Get an array of all styles + $aStyles = array(); - return $aBorders; - } + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + foreach ($pPHPExcel->getSheet($i)->getConditionalStylesCollection() as $conditionalStyles) { + foreach ($conditionalStyles as $conditionalStyle) { + $aStyles[] = $conditionalStyle; + } + } + } - /** - * Get an array of all number formats - * - * @param PHPExcel $pPHPExcel - * @return PHPExcel_Style_NumberFormat[] All number formats in PHPExcel - * @throws PHPExcel_Writer_Exception - */ - public function allNumberFormats(PHPExcel $pPHPExcel = null) - { - // Get an array of unique number formats - $aNumFmts = array(); - $aStyles = $this->allStyles($pPHPExcel); + return $aStyles; + } - foreach ($aStyles as $style) { - if ($style->getNumberFormat()->getBuiltInFormatCode() === false && !array_key_exists($style->getNumberFormat()->getHashCode(), $aNumFmts)) { - $aNumFmts[ $style->getNumberFormat()->getHashCode() ] = $style->getNumberFormat(); - } - } + /** + * Get an array of all fills + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Fill[] All fills in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allFills(PHPExcel $pPHPExcel = null) + { + // Get an array of unique fills + $aFills = array(); - return $aNumFmts; - } + // Two first fills are predefined + $fill0 = new PHPExcel_Style_Fill(); + $fill0->setFillType(PHPExcel_Style_Fill::FILL_NONE); + $aFills[] = $fill0; + + $fill1 = new PHPExcel_Style_Fill(); + $fill1->setFillType(PHPExcel_Style_Fill::FILL_PATTERN_GRAY125); + $aFills[] = $fill1; + // The remaining fills + $aStyles = $this->allStyles($pPHPExcel); + foreach ($aStyles as $style) { + if (!array_key_exists($style->getFill()->getHashCode(), $aFills)) { + $aFills[ $style->getFill()->getHashCode() ] = $style->getFill(); + } + } + + return $aFills; + } + + /** + * Get an array of all fonts + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Font[] All fonts in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allFonts(PHPExcel $pPHPExcel = null) + { + // Get an array of unique fonts + $aFonts = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if (!array_key_exists($style->getFont()->getHashCode(), $aFonts)) { + $aFonts[ $style->getFont()->getHashCode() ] = $style->getFont(); + } + } + + return $aFonts; + } + + /** + * Get an array of all borders + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Borders[] All borders in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allBorders(PHPExcel $pPHPExcel = null) + { + // Get an array of unique borders + $aBorders = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if (!array_key_exists($style->getBorders()->getHashCode(), $aBorders)) { + $aBorders[ $style->getBorders()->getHashCode() ] = $style->getBorders(); + } + } + + return $aBorders; + } + + /** + * Get an array of all number formats + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_NumberFormat[] All number formats in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allNumberFormats(PHPExcel $pPHPExcel = null) + { + // Get an array of unique number formats + $aNumFmts = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if ($style->getNumberFormat()->getBuiltInFormatCode() === false && !array_key_exists($style->getNumberFormat()->getHashCode(), $aNumFmts)) { + $aNumFmts[ $style->getNumberFormat()->getHashCode() ] = $style->getNumberFormat(); + } + } + + return $aNumFmts; + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Theme.php b/Classes/PHPExcel/Writer/Excel2007/Theme.php index f9c2fd1d..281cd5fe 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Theme.php +++ b/Classes/PHPExcel/Writer/Excel2007/Theme.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,837 +35,837 @@ */ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Map of Major fonts to write - * @static array of string - * - */ - private static $_majorFonts = array( - 'Jpan' => 'MS Pゴシック', - 'Hang' => '맑은 고딕', - 'Hans' => '宋体', - 'Hant' => '新細明體', - 'Arab' => 'Times New Roman', - 'Hebr' => 'Times New Roman', - 'Thai' => 'Tahoma', - 'Ethi' => 'Nyala', - 'Beng' => 'Vrinda', - 'Gujr' => 'Shruti', - 'Khmr' => 'MoolBoran', - 'Knda' => 'Tunga', - 'Guru' => 'Raavi', - 'Cans' => 'Euphemia', - 'Cher' => 'Plantagenet Cherokee', - 'Yiii' => 'Microsoft Yi Baiti', - 'Tibt' => 'Microsoft Himalaya', - 'Thaa' => 'MV Boli', - 'Deva' => 'Mangal', - 'Telu' => 'Gautami', - 'Taml' => 'Latha', - 'Syrc' => 'Estrangelo Edessa', - 'Orya' => 'Kalinga', - 'Mlym' => 'Kartika', - 'Laoo' => 'DokChampa', - 'Sinh' => 'Iskoola Pota', - 'Mong' => 'Mongolian Baiti', - 'Viet' => 'Times New Roman', - 'Uigh' => 'Microsoft Uighur', - 'Geor' => 'Sylfaen', - ); - - /** - * Map of Minor fonts to write - * @static array of string - * - */ - private static $_minorFonts = array( - 'Jpan' => 'MS Pゴシック', - 'Hang' => '맑은 고딕', - 'Hans' => '宋体', - 'Hant' => '新細明體', - 'Arab' => 'Arial', - 'Hebr' => 'Arial', - 'Thai' => 'Tahoma', - 'Ethi' => 'Nyala', - 'Beng' => 'Vrinda', - 'Gujr' => 'Shruti', - 'Khmr' => 'DaunPenh', - 'Knda' => 'Tunga', - 'Guru' => 'Raavi', - 'Cans' => 'Euphemia', - 'Cher' => 'Plantagenet Cherokee', - 'Yiii' => 'Microsoft Yi Baiti', - 'Tibt' => 'Microsoft Himalaya', - 'Thaa' => 'MV Boli', - 'Deva' => 'Mangal', - 'Telu' => 'Gautami', - 'Taml' => 'Latha', - 'Syrc' => 'Estrangelo Edessa', - 'Orya' => 'Kalinga', - 'Mlym' => 'Kartika', - 'Laoo' => 'DokChampa', - 'Sinh' => 'Iskoola Pota', - 'Mong' => 'Mongolian Baiti', - 'Viet' => 'Arial', - 'Uigh' => 'Microsoft Uighur', - 'Geor' => 'Sylfaen', - ); - - /** - * Map of core colours - * @static array of string - * - */ - private static $_colourScheme = array( - 'dk2' => '1F497D', - 'lt2' => 'EEECE1', - 'accent1' => '4F81BD', - 'accent2' => 'C0504D', - 'accent3' => '9BBB59', - 'accent4' => '8064A2', - 'accent5' => '4BACC6', - 'accent6' => 'F79646', - 'hlink' => '0000FF', - 'folHlink' => '800080', - ); - - /** - * Write theme to XML format - * - * @param PHPExcel $pPHPExcel - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeTheme(PHPExcel $pPHPExcel = null) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } - - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); - - // a:theme - $objWriter->startElement('a:theme'); - $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); - $objWriter->writeAttribute('name', 'Office Theme'); - - // a:themeElements - $objWriter->startElement('a:themeElements'); - - // a:clrScheme - $objWriter->startElement('a:clrScheme'); - $objWriter->writeAttribute('name', 'Office'); - - // a:dk1 - $objWriter->startElement('a:dk1'); - - // a:sysClr - $objWriter->startElement('a:sysClr'); - $objWriter->writeAttribute('val', 'windowText'); - $objWriter->writeAttribute('lastClr', '000000'); - $objWriter->endElement(); - - $objWriter->endElement(); - - // a:lt1 - $objWriter->startElement('a:lt1'); - - // a:sysClr - $objWriter->startElement('a:sysClr'); - $objWriter->writeAttribute('val', 'window'); - $objWriter->writeAttribute('lastClr', 'FFFFFF'); - $objWriter->endElement(); - - $objWriter->endElement(); - - // a:dk2 - $this->_writeColourScheme($objWriter); - - $objWriter->endElement(); - - // a:fontScheme - $objWriter->startElement('a:fontScheme'); - $objWriter->writeAttribute('name', 'Office'); - - // a:majorFont - $objWriter->startElement('a:majorFont'); - $this->_writeFonts($objWriter, 'Cambria', self::$_majorFonts); - $objWriter->endElement(); - - // a:minorFont - $objWriter->startElement('a:minorFont'); - $this->_writeFonts($objWriter, 'Calibri', self::$_minorFonts); - $objWriter->endElement(); - - $objWriter->endElement(); - - // a:fmtScheme - $objWriter->startElement('a:fmtScheme'); - $objWriter->writeAttribute('name', 'Office'); - - // a:fillStyleLst - $objWriter->startElement('a:fillStyleLst'); - - // a:solidFill - $objWriter->startElement('a:solidFill'); - - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); - $objWriter->endElement(); - - $objWriter->endElement(); - - // a:gradFill - $objWriter->startElement('a:gradFill'); - $objWriter->writeAttribute('rotWithShape', '1'); + /** + * Map of Major fonts to write + * @static array of string + * + */ + private static $_majorFonts = array( + 'Jpan' => 'MS Pゴシック', + 'Hang' => '맑은 고딕', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Times New Roman', + 'Hebr' => 'Times New Roman', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'MoolBoran', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Times New Roman', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ); + + /** + * Map of Minor fonts to write + * @static array of string + * + */ + private static $_minorFonts = array( + 'Jpan' => 'MS Pゴシック', + 'Hang' => '맑은 고딕', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Arial', + 'Hebr' => 'Arial', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'DaunPenh', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Arial', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ); + + /** + * Map of core colours + * @static array of string + * + */ + private static $_colourScheme = array( + 'dk2' => '1F497D', + 'lt2' => 'EEECE1', + 'accent1' => '4F81BD', + 'accent2' => 'C0504D', + 'accent3' => '9BBB59', + 'accent4' => '8064A2', + 'accent5' => '4BACC6', + 'accent6' => 'F79646', + 'hlink' => '0000FF', + 'folHlink' => '800080', + ); + + /** + * Write theme to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeTheme(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // a:theme + $objWriter->startElement('a:theme'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $objWriter->writeAttribute('name', 'Office Theme'); + + // a:themeElements + $objWriter->startElement('a:themeElements'); + + // a:clrScheme + $objWriter->startElement('a:clrScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:dk1 + $objWriter->startElement('a:dk1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'windowText'); + $objWriter->writeAttribute('lastClr', '000000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lt1 + $objWriter->startElement('a:lt1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'window'); + $objWriter->writeAttribute('lastClr', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:dk2 + $this->_writeColourScheme($objWriter); + + $objWriter->endElement(); + + // a:fontScheme + $objWriter->startElement('a:fontScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:majorFont + $objWriter->startElement('a:majorFont'); + $this->_writeFonts($objWriter, 'Cambria', self::$_majorFonts); + $objWriter->endElement(); + + // a:minorFont + $objWriter->startElement('a:minorFont'); + $this->_writeFonts($objWriter, 'Calibri', self::$_minorFonts); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:fmtScheme + $objWriter->startElement('a:fmtScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:fillStyleLst + $objWriter->startElement('a:fillStyleLst'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); - // a:gsLst - $objWriter->startElement('a:gsLst'); + // a:gsLst + $objWriter->startElement('a:gsLst'); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '0'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '50000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '50000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '300000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '35000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '35000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '37000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '37000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '300000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '100000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '15000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '15000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '350000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:lin - $objWriter->startElement('a:lin'); - $objWriter->writeAttribute('ang', '16200000'); - $objWriter->writeAttribute('scaled', '1'); - $objWriter->endElement(); + // a:lin + $objWriter->startElement('a:lin'); + $objWriter->writeAttribute('ang', '16200000'); + $objWriter->writeAttribute('scaled', '1'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gradFill - $objWriter->startElement('a:gradFill'); - $objWriter->writeAttribute('rotWithShape', '1'); + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); - // a:gsLst - $objWriter->startElement('a:gsLst'); + // a:gsLst + $objWriter->startElement('a:gsLst'); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '0'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '51000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '51000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '130000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '130000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '80000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '80000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '93000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '93000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '130000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '130000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '100000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '94000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '94000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '135000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '135000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:lin - $objWriter->startElement('a:lin'); - $objWriter->writeAttribute('ang', '16200000'); - $objWriter->writeAttribute('scaled', '0'); - $objWriter->endElement(); + // a:lin + $objWriter->startElement('a:lin'); + $objWriter->writeAttribute('ang', '16200000'); + $objWriter->writeAttribute('scaled', '0'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:lnStyleLst - $objWriter->startElement('a:lnStyleLst'); + // a:lnStyleLst + $objWriter->startElement('a:lnStyleLst'); - // a:ln - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', '9525'); - $objWriter->writeAttribute('cap', 'flat'); - $objWriter->writeAttribute('cmpd', 'sng'); - $objWriter->writeAttribute('algn', 'ctr'); + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '9525'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); - // a:solidFill - $objWriter->startElement('a:solidFill'); + // a:solidFill + $objWriter->startElement('a:solidFill'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '95000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '95000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '105000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '105000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:prstDash - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', 'solid'); - $objWriter->endElement(); + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:ln - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', '25400'); - $objWriter->writeAttribute('cap', 'flat'); - $objWriter->writeAttribute('cmpd', 'sng'); - $objWriter->writeAttribute('algn', 'ctr'); + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '25400'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); - // a:solidFill - $objWriter->startElement('a:solidFill'); + // a:solidFill + $objWriter->startElement('a:solidFill'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); - $objWriter->endElement(); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:prstDash - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', 'solid'); - $objWriter->endElement(); + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:ln - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', '38100'); - $objWriter->writeAttribute('cap', 'flat'); - $objWriter->writeAttribute('cmpd', 'sng'); - $objWriter->writeAttribute('algn', 'ctr'); + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '38100'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); - // a:solidFill - $objWriter->startElement('a:solidFill'); + // a:solidFill + $objWriter->startElement('a:solidFill'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); - $objWriter->endElement(); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:prstDash - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', 'solid'); - $objWriter->endElement(); + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:effectStyleLst - $objWriter->startElement('a:effectStyleLst'); + // a:effectStyleLst + $objWriter->startElement('a:effectStyleLst'); - // a:effectStyle - $objWriter->startElement('a:effectStyle'); + // a:effectStyle + $objWriter->startElement('a:effectStyle'); - // a:effectLst - $objWriter->startElement('a:effectLst'); + // a:effectLst + $objWriter->startElement('a:effectLst'); - // a:outerShdw - $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '20000'); - $objWriter->writeAttribute('dir', '5400000'); - $objWriter->writeAttribute('rotWithShape', '0'); + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '20000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', '000000'); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '38000'); - $objWriter->endElement(); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '38000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:effectStyle - $objWriter->startElement('a:effectStyle'); + // a:effectStyle + $objWriter->startElement('a:effectStyle'); - // a:effectLst - $objWriter->startElement('a:effectLst'); + // a:effectLst + $objWriter->startElement('a:effectLst'); - // a:outerShdw - $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '23000'); - $objWriter->writeAttribute('dir', '5400000'); - $objWriter->writeAttribute('rotWithShape', '0'); + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', '000000'); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '35000'); - $objWriter->endElement(); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:effectStyle - $objWriter->startElement('a:effectStyle'); + // a:effectStyle + $objWriter->startElement('a:effectStyle'); - // a:effectLst - $objWriter->startElement('a:effectLst'); + // a:effectLst + $objWriter->startElement('a:effectLst'); - // a:outerShdw - $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '23000'); - $objWriter->writeAttribute('dir', '5400000'); - $objWriter->writeAttribute('rotWithShape', '0'); + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', '000000'); + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '35000'); - $objWriter->endElement(); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:scene3d - $objWriter->startElement('a:scene3d'); + // a:scene3d + $objWriter->startElement('a:scene3d'); - // a:camera - $objWriter->startElement('a:camera'); - $objWriter->writeAttribute('prst', 'orthographicFront'); + // a:camera + $objWriter->startElement('a:camera'); + $objWriter->writeAttribute('prst', 'orthographicFront'); - // a:rot - $objWriter->startElement('a:rot'); - $objWriter->writeAttribute('lat', '0'); - $objWriter->writeAttribute('lon', '0'); - $objWriter->writeAttribute('rev', '0'); - $objWriter->endElement(); + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '0'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:lightRig - $objWriter->startElement('a:lightRig'); - $objWriter->writeAttribute('rig', 'threePt'); - $objWriter->writeAttribute('dir', 't'); + // a:lightRig + $objWriter->startElement('a:lightRig'); + $objWriter->writeAttribute('rig', 'threePt'); + $objWriter->writeAttribute('dir', 't'); - // a:rot - $objWriter->startElement('a:rot'); - $objWriter->writeAttribute('lat', '0'); - $objWriter->writeAttribute('lon', '0'); - $objWriter->writeAttribute('rev', '1200000'); - $objWriter->endElement(); + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '1200000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:sp3d - $objWriter->startElement('a:sp3d'); + // a:sp3d + $objWriter->startElement('a:sp3d'); - // a:bevelT - $objWriter->startElement('a:bevelT'); - $objWriter->writeAttribute('w', '63500'); - $objWriter->writeAttribute('h', '25400'); - $objWriter->endElement(); + // a:bevelT + $objWriter->startElement('a:bevelT'); + $objWriter->writeAttribute('w', '63500'); + $objWriter->writeAttribute('h', '25400'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:bgFillStyleLst - $objWriter->startElement('a:bgFillStyleLst'); + // a:bgFillStyleLst + $objWriter->startElement('a:bgFillStyleLst'); - // a:solidFill - $objWriter->startElement('a:solidFill'); + // a:solidFill + $objWriter->startElement('a:solidFill'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); - $objWriter->endElement(); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gradFill - $objWriter->startElement('a:gradFill'); - $objWriter->writeAttribute('rotWithShape', '1'); + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); - // a:gsLst - $objWriter->startElement('a:gsLst'); + // a:gsLst + $objWriter->startElement('a:gsLst'); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '0'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '40000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '40000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '350000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '40000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '40000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '45000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '45000'); + $objWriter->endElement(); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '99000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '99000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '350000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '100000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '20000'); - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '20000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '255000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '255000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:path - $objWriter->startElement('a:path'); - $objWriter->writeAttribute('path', 'circle'); + // a:path + $objWriter->startElement('a:path'); + $objWriter->writeAttribute('path', 'circle'); - // a:fillToRect - $objWriter->startElement('a:fillToRect'); - $objWriter->writeAttribute('l', '50000'); - $objWriter->writeAttribute('t', '-80000'); - $objWriter->writeAttribute('r', '50000'); - $objWriter->writeAttribute('b', '180000'); - $objWriter->endElement(); + // a:fillToRect + $objWriter->startElement('a:fillToRect'); + $objWriter->writeAttribute('l', '50000'); + $objWriter->writeAttribute('t', '-80000'); + $objWriter->writeAttribute('r', '50000'); + $objWriter->writeAttribute('b', '180000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gradFill - $objWriter->startElement('a:gradFill'); - $objWriter->writeAttribute('rotWithShape', '1'); + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); - // a:gsLst - $objWriter->startElement('a:gsLst'); + // a:gsLst + $objWriter->startElement('a:gsLst'); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '0'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:tint - $objWriter->startElement('a:tint'); - $objWriter->writeAttribute('val', '80000'); - $objWriter->endElement(); + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '80000'); + $objWriter->endElement(); - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '300000'); - $objWriter->endElement(); + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:gs - $objWriter->startElement('a:gs'); - $objWriter->writeAttribute('pos', '100000'); + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); - // a:schemeClr - $objWriter->startElement('a:schemeClr'); - $objWriter->writeAttribute('val', 'phClr'); + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '30000'); - $objWriter->endElement(); - - // a:satMod - $objWriter->startElement('a:satMod'); - $objWriter->writeAttribute('val', '200000'); - $objWriter->endElement(); - - $objWriter->endElement(); + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '30000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '200000'); + $objWriter->endElement(); + + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); - // a:path - $objWriter->startElement('a:path'); - $objWriter->writeAttribute('path', 'circle'); + // a:path + $objWriter->startElement('a:path'); + $objWriter->writeAttribute('path', 'circle'); - // a:fillToRect - $objWriter->startElement('a:fillToRect'); - $objWriter->writeAttribute('l', '50000'); - $objWriter->writeAttribute('t', '50000'); - $objWriter->writeAttribute('r', '50000'); - $objWriter->writeAttribute('b', '50000'); - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); + // a:fillToRect + $objWriter->startElement('a:fillToRect'); + $objWriter->writeAttribute('l', '50000'); + $objWriter->writeAttribute('t', '50000'); + $objWriter->writeAttribute('r', '50000'); + $objWriter->writeAttribute('b', '50000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); - $objWriter->endElement(); - - // a:objectDefaults - $objWriter->writeElement('a:objectDefaults', null); + $objWriter->endElement(); + + // a:objectDefaults + $objWriter->writeElement('a:objectDefaults', null); - // a:extraClrSchemeLst - $objWriter->writeElement('a:extraClrSchemeLst', null); - - $objWriter->endElement(); - - // Return - return $objWriter->getData(); - } - - /** - * Write fonts to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter - * @param string $latinFont - * @param array of string $fontSet - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - private function _writeFonts($objWriter, $latinFont, $fontSet) - { - // a:latin - $objWriter->startElement('a:latin'); - $objWriter->writeAttribute('typeface', $latinFont); - $objWriter->endElement(); - - // a:ea - $objWriter->startElement('a:ea'); - $objWriter->writeAttribute('typeface', ''); - $objWriter->endElement(); - - // a:cs - $objWriter->startElement('a:cs'); - $objWriter->writeAttribute('typeface', ''); - $objWriter->endElement(); - - foreach($fontSet as $fontScript => $typeface) { - $objWriter->startElement('a:font'); - $objWriter->writeAttribute('script', $fontScript); - $objWriter->writeAttribute('typeface', $typeface); - $objWriter->endElement(); - } - - } - - /** - * Write colour scheme to XML format - * - * @param PHPExcel_Shared_XMLWriter $objWriter - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - private function _writeColourScheme($objWriter) - { - foreach(self::$_colourScheme as $colourName => $colourValue) { - $objWriter->startElement('a:'.$colourName); - - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', $colourValue); - $objWriter->endElement(); - - $objWriter->endElement(); - } - - } + // a:extraClrSchemeLst + $objWriter->writeElement('a:extraClrSchemeLst', null); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write fonts to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter + * @param string $latinFont + * @param array of string $fontSet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + private function _writeFonts($objWriter, $latinFont, $fontSet) + { + // a:latin + $objWriter->startElement('a:latin'); + $objWriter->writeAttribute('typeface', $latinFont); + $objWriter->endElement(); + + // a:ea + $objWriter->startElement('a:ea'); + $objWriter->writeAttribute('typeface', ''); + $objWriter->endElement(); + + // a:cs + $objWriter->startElement('a:cs'); + $objWriter->writeAttribute('typeface', ''); + $objWriter->endElement(); + + foreach($fontSet as $fontScript => $typeface) { + $objWriter->startElement('a:font'); + $objWriter->writeAttribute('script', $fontScript); + $objWriter->writeAttribute('typeface', $typeface); + $objWriter->endElement(); + } + + } + + /** + * Write colour scheme to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + private function _writeColourScheme($objWriter) + { + foreach(self::$_colourScheme as $colourName => $colourValue) { + $objWriter->startElement('a:'.$colourName); + + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $colourValue); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Workbook.php b/Classes/PHPExcel/Writer/Excel2007/Workbook.php index 56a3939b..4753d810 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel2007/Workbook.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,422 +35,422 @@ */ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write workbook to XML format - * - * @param PHPExcel $pPHPExcel - * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = FALSE) - { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } + /** + * Write workbook to XML format + * + * @param PHPExcel $pPHPExcel + * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); - // workbook - $objWriter->startElement('workbook'); - $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + // workbook + $objWriter->startElement('workbook'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - // fileVersion - $this->_writeFileVersion($objWriter); + // fileVersion + $this->_writeFileVersion($objWriter); - // workbookPr - $this->_writeWorkbookPr($objWriter); + // workbookPr + $this->_writeWorkbookPr($objWriter); - // workbookProtection - $this->_writeWorkbookProtection($objWriter, $pPHPExcel); + // workbookProtection + $this->_writeWorkbookProtection($objWriter, $pPHPExcel); - // bookViews - if ($this->getParentWriter()->getOffice2003Compatibility() === false) { - $this->_writeBookViews($objWriter, $pPHPExcel); - } + // bookViews + if ($this->getParentWriter()->getOffice2003Compatibility() === false) { + $this->_writeBookViews($objWriter, $pPHPExcel); + } - // sheets - $this->_writeSheets($objWriter, $pPHPExcel); + // sheets + $this->_writeSheets($objWriter, $pPHPExcel); - // definedNames - $this->_writeDefinedNames($objWriter, $pPHPExcel); + // definedNames + $this->_writeDefinedNames($objWriter, $pPHPExcel); - // calcPr - $this->_writeCalcPr($objWriter,$recalcRequired); + // calcPr + $this->_writeCalcPr($objWriter,$recalcRequired); - $objWriter->endElement(); + $objWriter->endElement(); - // Return - return $objWriter->getData(); - } + // Return + return $objWriter->getData(); + } - /** - * Write file version - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws PHPExcel_Writer_Exception - */ - private function _writeFileVersion(PHPExcel_Shared_XMLWriter $objWriter = null) - { - $objWriter->startElement('fileVersion'); - $objWriter->writeAttribute('appName', 'xl'); - $objWriter->writeAttribute('lastEdited', '4'); - $objWriter->writeAttribute('lowestEdited', '4'); - $objWriter->writeAttribute('rupBuild', '4505'); - $objWriter->endElement(); - } + /** + * Write file version + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeFileVersion(PHPExcel_Shared_XMLWriter $objWriter = null) + { + $objWriter->startElement('fileVersion'); + $objWriter->writeAttribute('appName', 'xl'); + $objWriter->writeAttribute('lastEdited', '4'); + $objWriter->writeAttribute('lowestEdited', '4'); + $objWriter->writeAttribute('rupBuild', '4505'); + $objWriter->endElement(); + } - /** - * Write WorkbookPr - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws PHPExcel_Writer_Exception - */ - private function _writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null) - { - $objWriter->startElement('workbookPr'); + /** + * Write WorkbookPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null) + { + $objWriter->startElement('workbookPr'); - if (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) { - $objWriter->writeAttribute('date1904', '1'); - } + if (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) { + $objWriter->writeAttribute('date1904', '1'); + } - $objWriter->writeAttribute('codeName', 'ThisWorkbook'); + $objWriter->writeAttribute('codeName', 'ThisWorkbook'); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write BookViews - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel $pPHPExcel - * @throws PHPExcel_Writer_Exception - */ - private function _writeBookViews(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) - { - // bookViews - $objWriter->startElement('bookViews'); + /** + * Write BookViews + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeBookViews(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // bookViews + $objWriter->startElement('bookViews'); - // workbookView - $objWriter->startElement('workbookView'); + // workbookView + $objWriter->startElement('workbookView'); - $objWriter->writeAttribute('activeTab', $pPHPExcel->getActiveSheetIndex()); - $objWriter->writeAttribute('autoFilterDateGrouping', '1'); - $objWriter->writeAttribute('firstSheet', '0'); - $objWriter->writeAttribute('minimized', '0'); - $objWriter->writeAttribute('showHorizontalScroll', '1'); - $objWriter->writeAttribute('showSheetTabs', '1'); - $objWriter->writeAttribute('showVerticalScroll', '1'); - $objWriter->writeAttribute('tabRatio', '600'); - $objWriter->writeAttribute('visibility', 'visible'); + $objWriter->writeAttribute('activeTab', $pPHPExcel->getActiveSheetIndex()); + $objWriter->writeAttribute('autoFilterDateGrouping', '1'); + $objWriter->writeAttribute('firstSheet', '0'); + $objWriter->writeAttribute('minimized', '0'); + $objWriter->writeAttribute('showHorizontalScroll', '1'); + $objWriter->writeAttribute('showSheetTabs', '1'); + $objWriter->writeAttribute('showVerticalScroll', '1'); + $objWriter->writeAttribute('tabRatio', '600'); + $objWriter->writeAttribute('visibility', 'visible'); - $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write WorkbookProtection - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel $pPHPExcel - * @throws PHPExcel_Writer_Exception - */ - private function _writeWorkbookProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) - { - if ($pPHPExcel->getSecurity()->isSecurityEnabled()) { - $objWriter->startElement('workbookProtection'); - $objWriter->writeAttribute('lockRevision', ($pPHPExcel->getSecurity()->getLockRevision() ? 'true' : 'false')); - $objWriter->writeAttribute('lockStructure', ($pPHPExcel->getSecurity()->getLockStructure() ? 'true' : 'false')); - $objWriter->writeAttribute('lockWindows', ($pPHPExcel->getSecurity()->getLockWindows() ? 'true' : 'false')); + /** + * Write WorkbookProtection + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeWorkbookProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + if ($pPHPExcel->getSecurity()->isSecurityEnabled()) { + $objWriter->startElement('workbookProtection'); + $objWriter->writeAttribute('lockRevision', ($pPHPExcel->getSecurity()->getLockRevision() ? 'true' : 'false')); + $objWriter->writeAttribute('lockStructure', ($pPHPExcel->getSecurity()->getLockStructure() ? 'true' : 'false')); + $objWriter->writeAttribute('lockWindows', ($pPHPExcel->getSecurity()->getLockWindows() ? 'true' : 'false')); - if ($pPHPExcel->getSecurity()->getRevisionsPassword() != '') { - $objWriter->writeAttribute('revisionsPassword', $pPHPExcel->getSecurity()->getRevisionsPassword()); - } + if ($pPHPExcel->getSecurity()->getRevisionsPassword() != '') { + $objWriter->writeAttribute('revisionsPassword', $pPHPExcel->getSecurity()->getRevisionsPassword()); + } - if ($pPHPExcel->getSecurity()->getWorkbookPassword() != '') { - $objWriter->writeAttribute('workbookPassword', $pPHPExcel->getSecurity()->getWorkbookPassword()); - } + if ($pPHPExcel->getSecurity()->getWorkbookPassword() != '') { + $objWriter->writeAttribute('workbookPassword', $pPHPExcel->getSecurity()->getWorkbookPassword()); + } - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } - /** - * Write calcPr - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing - * @throws PHPExcel_Writer_Exception - */ - private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = TRUE) - { - $objWriter->startElement('calcPr'); + /** + * Write calcPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing + * @throws PHPExcel_Writer_Exception + */ + private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = TRUE) + { + $objWriter->startElement('calcPr'); - // Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc + // Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc // If MS Excel does do a recalc, then users opening a file in MS Excel will be prompted to save on exit // because the file has changed - $objWriter->writeAttribute('calcId', '999999'); - $objWriter->writeAttribute('calcMode', 'auto'); - // fullCalcOnLoad isn't needed if we've recalculating for the save - $objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? 1 : 0); - $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? 0 : 1); + $objWriter->writeAttribute('calcId', '999999'); + $objWriter->writeAttribute('calcMode', 'auto'); + // fullCalcOnLoad isn't needed if we've recalculating for the save + $objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? 1 : 0); + $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? 0 : 1); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write sheets - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel $pPHPExcel - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheets(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) - { - // Write sheets - $objWriter->startElement('sheets'); - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - // sheet - $this->_writeSheet( - $objWriter, - $pPHPExcel->getSheet($i)->getTitle(), - ($i + 1), - ($i + 1 + 3), - $pPHPExcel->getSheet($i)->getSheetState() - ); - } + /** + * Write sheets + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheets(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // Write sheets + $objWriter->startElement('sheets'); + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // sheet + $this->_writeSheet( + $objWriter, + $pPHPExcel->getSheet($i)->getTitle(), + ($i + 1), + ($i + 1 + 3), + $pPHPExcel->getSheet($i)->getSheetState() + ); + } - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write sheet - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param string $pSheetname Sheet name - * @param int $pSheetId Sheet id - * @param int $pRelId Relationship ID - * @param string $sheetState Sheet state (visible, hidden, veryHidden) - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') - { - if ($pSheetname != '') { - // Write sheet - $objWriter->startElement('sheet'); - $objWriter->writeAttribute('name', $pSheetname); - $objWriter->writeAttribute('sheetId', $pSheetId); - if ($sheetState != 'visible' && $sheetState != '') { - $objWriter->writeAttribute('state', $sheetState); - } - $objWriter->writeAttribute('r:id', 'rId' . $pRelId); - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + /** + * Write sheet + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pSheetname Sheet name + * @param int $pSheetId Sheet id + * @param int $pRelId Relationship ID + * @param string $sheetState Sheet state (visible, hidden, veryHidden) + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') + { + if ($pSheetname != '') { + // Write sheet + $objWriter->startElement('sheet'); + $objWriter->writeAttribute('name', $pSheetname); + $objWriter->writeAttribute('sheetId', $pSheetId); + if ($sheetState != 'visible' && $sheetState != '') { + $objWriter->writeAttribute('state', $sheetState); + } + $objWriter->writeAttribute('r:id', 'rId' . $pRelId); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } - /** - * Write Defined Names - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel $pPHPExcel - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefinedNames(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) - { - // Write defined names - $objWriter->startElement('definedNames'); + /** + * Write Defined Names + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNames(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // Write defined names + $objWriter->startElement('definedNames'); - // Named ranges - if (count($pPHPExcel->getNamedRanges()) > 0) { - // Named ranges - $this->_writeNamedRanges($objWriter, $pPHPExcel); - } + // Named ranges + if (count($pPHPExcel->getNamedRanges()) > 0) { + // Named ranges + $this->_writeNamedRanges($objWriter, $pPHPExcel); + } - // Other defined names - $sheetCount = $pPHPExcel->getSheetCount(); - for ($i = 0; $i < $sheetCount; ++$i) { - // definedName for autoFilter - $this->_writeDefinedNameForAutofilter($objWriter, $pPHPExcel->getSheet($i), $i); + // Other defined names + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // definedName for autoFilter + $this->_writeDefinedNameForAutofilter($objWriter, $pPHPExcel->getSheet($i), $i); - // definedName for Print_Titles - $this->_writeDefinedNameForPrintTitles($objWriter, $pPHPExcel->getSheet($i), $i); + // definedName for Print_Titles + $this->_writeDefinedNameForPrintTitles($objWriter, $pPHPExcel->getSheet($i), $i); - // definedName for Print_Area - $this->_writeDefinedNameForPrintArea($objWriter, $pPHPExcel->getSheet($i), $i); - } + // definedName for Print_Area + $this->_writeDefinedNameForPrintArea($objWriter, $pPHPExcel->getSheet($i), $i); + } - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write named ranges - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel $pPHPExcel - * @throws PHPExcel_Writer_Exception - */ - private function _writeNamedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel) - { - // Loop named ranges - $namedRanges = $pPHPExcel->getNamedRanges(); - foreach ($namedRanges as $namedRange) { - $this->_writeDefinedNameForNamedRange($objWriter, $namedRange); - } - } + /** + * Write named ranges + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeNamedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel) + { + // Loop named ranges + $namedRanges = $pPHPExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + $this->_writeDefinedNameForNamedRange($objWriter, $namedRange); + } + } - /** - * Write Defined Name for named range - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_NamedRange $pNamedRange - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefinedNameForNamedRange(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_NamedRange $pNamedRange) - { - // definedName for named range - $objWriter->startElement('definedName'); - $objWriter->writeAttribute('name', $pNamedRange->getName()); - if ($pNamedRange->getLocalOnly()) { - $objWriter->writeAttribute('localSheetId', $pNamedRange->getScope()->getParent()->getIndex($pNamedRange->getScope())); - } + /** + * Write Defined Name for named range + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_NamedRange $pNamedRange + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForNamedRange(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_NamedRange $pNamedRange) + { + // definedName for named range + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', $pNamedRange->getName()); + if ($pNamedRange->getLocalOnly()) { + $objWriter->writeAttribute('localSheetId', $pNamedRange->getScope()->getParent()->getIndex($pNamedRange->getScope())); + } - // Create absolute coordinate and write as raw text - $range = PHPExcel_Cell::splitRange($pNamedRange->getRange()); - for ($i = 0; $i < count($range); $i++) { - $range[$i][0] = '\'' . str_replace("'", "''", $pNamedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteReference($range[$i][0]); - if (isset($range[$i][1])) { - $range[$i][1] = PHPExcel_Cell::absoluteReference($range[$i][1]); - } - } - $range = PHPExcel_Cell::buildRange($range); + // Create absolute coordinate and write as raw text + $range = PHPExcel_Cell::splitRange($pNamedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $pNamedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteReference($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteReference($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); - $objWriter->writeRawData($range); + $objWriter->writeRawData($range); - $objWriter->endElement(); - } + $objWriter->endElement(); + } - /** - * Write Defined Name for autoFilter - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet - * @param int $pSheetId - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) - { - // definedName for autoFilter - $autoFilterRange = $pSheet->getAutoFilter()->getRange(); - if (!empty($autoFilterRange)) { - $objWriter->startElement('definedName'); - $objWriter->writeAttribute('name', '_xlnm._FilterDatabase'); - $objWriter->writeAttribute('localSheetId', $pSheetId); - $objWriter->writeAttribute('hidden', '1'); + /** + * Write Defined Name for autoFilter + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for autoFilter + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm._FilterDatabase'); + $objWriter->writeAttribute('localSheetId', $pSheetId); + $objWriter->writeAttribute('hidden', '1'); - // Create absolute coordinate and write as raw text - $range = PHPExcel_Cell::splitRange($autoFilterRange); - $range = $range[0]; - // Strip any worksheet ref so we can make the cell ref absolute - if (strpos($range[0],'!') !== false) { - list($ws,$range[0]) = explode('!',$range[0]); - } + // Create absolute coordinate and write as raw text + $range = PHPExcel_Cell::splitRange($autoFilterRange); + $range = $range[0]; + // Strip any worksheet ref so we can make the cell ref absolute + if (strpos($range[0],'!') !== false) { + list($ws,$range[0]) = explode('!',$range[0]); + } - $range[0] = PHPExcel_Cell::absoluteCoordinate($range[0]); - $range[1] = PHPExcel_Cell::absoluteCoordinate($range[1]); - $range = implode(':', $range); + $range[0] = PHPExcel_Cell::absoluteCoordinate($range[0]); + $range[1] = PHPExcel_Cell::absoluteCoordinate($range[1]); + $range = implode(':', $range); - $objWriter->writeRawData('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . $range); + $objWriter->writeRawData('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . $range); - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } - /** - * Write Defined Name for PrintTitles - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet - * @param int $pSheetId - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefinedNameForPrintTitles(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) - { - // definedName for PrintTitles - if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { - $objWriter->startElement('definedName'); - $objWriter->writeAttribute('name', '_xlnm.Print_Titles'); - $objWriter->writeAttribute('localSheetId', $pSheetId); + /** + * Write Defined Name for PrintTitles + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForPrintTitles(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for PrintTitles + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm.Print_Titles'); + $objWriter->writeAttribute('localSheetId', $pSheetId); - // Setting string - $settingString = ''; + // Setting string + $settingString = ''; - // Columns to repeat - if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { - $repeat = $pSheet->getPageSetup()->getColumnsToRepeatAtLeft(); + // Columns to repeat + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { + $repeat = $pSheet->getPageSetup()->getColumnsToRepeatAtLeft(); - $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; - } + $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; + } - // Rows to repeat - if ($pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { - if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { - $settingString .= ','; - } + // Rows to repeat + if ($pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { + $settingString .= ','; + } - $repeat = $pSheet->getPageSetup()->getRowsToRepeatAtTop(); + $repeat = $pSheet->getPageSetup()->getRowsToRepeatAtTop(); - $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; - } + $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; + } - $objWriter->writeRawData($settingString); + $objWriter->writeRawData($settingString); - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } - /** - * Write Defined Name for PrintTitles - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet - * @param int $pSheetId - * @throws PHPExcel_Writer_Exception - */ - private function _writeDefinedNameForPrintArea(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) - { - // definedName for PrintArea - if ($pSheet->getPageSetup()->isPrintAreaSet()) { - $objWriter->startElement('definedName'); - $objWriter->writeAttribute('name', '_xlnm.Print_Area'); - $objWriter->writeAttribute('localSheetId', $pSheetId); + /** + * Write Defined Name for PrintTitles + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForPrintArea(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for PrintArea + if ($pSheet->getPageSetup()->isPrintAreaSet()) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm.Print_Area'); + $objWriter->writeAttribute('localSheetId', $pSheetId); - // Setting string - $settingString = ''; + // Setting string + $settingString = ''; - // Print area - $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea()); + // Print area + $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea()); - $chunks = array(); - foreach ($printArea as $printAreaRect) { - $printAreaRect[0] = PHPExcel_Cell::absoluteReference($printAreaRect[0]); - $printAreaRect[1] = PHPExcel_Cell::absoluteReference($printAreaRect[1]); - $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect); - } + $chunks = array(); + foreach ($printArea as $printAreaRect) { + $printAreaRect[0] = PHPExcel_Cell::absoluteReference($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::absoluteReference($printAreaRect[1]); + $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect); + } - $objWriter->writeRawData(implode(',', $chunks)); + $objWriter->writeRawData(implode(',', $chunks)); - $objWriter->endElement(); - } - } + $objWriter->endElement(); + } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php index 6ca93c03..e0ef6f53 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Writer_Excel2007 + * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ @@ -30,1191 +30,1191 @@ * PHPExcel_Writer_Excel2007_Worksheet * * @category PHPExcel - * @package PHPExcel_Writer_Excel2007 + * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_WriterPart { - /** - * Write worksheet to XML format - * - * @param PHPExcel_Worksheet $pSheet - * @param string[] $pStringTable - * @param boolean $includeCharts Flag indicating if we should write charts - * @return string XML Output - * @throws PHPExcel_Writer_Exception - */ - public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = FALSE) - { - if (!is_null($pSheet)) { - // Create XML writer - $objWriter = null; - if ($this->getParentWriter()->getUseDiskCaching()) { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); - } else { - $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); - } - - // XML header - $objWriter->startDocument('1.0','UTF-8','yes'); - - // Worksheet - $objWriter->startElement('worksheet'); - $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - - // sheetPr - $this->_writeSheetPr($objWriter, $pSheet); - - // Dimension - $this->_writeDimension($objWriter, $pSheet); - - // sheetViews - $this->_writeSheetViews($objWriter, $pSheet); - - // sheetFormatPr - $this->_writeSheetFormatPr($objWriter, $pSheet); - - // cols - $this->_writeCols($objWriter, $pSheet); - - // sheetData - $this->_writeSheetData($objWriter, $pSheet, $pStringTable); - - // sheetProtection - $this->_writeSheetProtection($objWriter, $pSheet); - - // protectedRanges - $this->_writeProtectedRanges($objWriter, $pSheet); - - // autoFilter - $this->_writeAutoFilter($objWriter, $pSheet); - - // mergeCells - $this->_writeMergeCells($objWriter, $pSheet); - - // conditionalFormatting - $this->_writeConditionalFormatting($objWriter, $pSheet); - - // dataValidations - $this->_writeDataValidations($objWriter, $pSheet); - - // hyperlinks - $this->_writeHyperlinks($objWriter, $pSheet); - - // Print options - $this->_writePrintOptions($objWriter, $pSheet); - - // Page margins - $this->_writePageMargins($objWriter, $pSheet); - - // Page setup - $this->_writePageSetup($objWriter, $pSheet); - - // Header / footer - $this->_writeHeaderFooter($objWriter, $pSheet); - - // Breaks - $this->_writeBreaks($objWriter, $pSheet); - - // Drawings and/or Charts - $this->_writeDrawings($objWriter, $pSheet, $includeCharts); - - // LegacyDrawing - $this->_writeLegacyDrawing($objWriter, $pSheet); - - // LegacyDrawingHF - $this->_writeLegacyDrawingHF($objWriter, $pSheet); - - $objWriter->endElement(); - - // Return - return $objWriter->getData(); - } else { - throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); - } - } - - /** - * Write SheetPr - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheetPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // sheetPr - $objWriter->startElement('sheetPr'); - //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); - if($pSheet->getParent()->hasMacros()){//if the workbook have macros, we need to have codeName for the sheet - if($pSheet->hasCodeName()==false){ - $pSheet->setCodeName($pSheet->getTitle()); - } - $objWriter->writeAttribute('codeName', $pSheet->getCodeName()); - } - $autoFilterRange = $pSheet->getAutoFilter()->getRange(); - if (!empty($autoFilterRange)) { - $objWriter->writeAttribute('filterMode', 1); - $pSheet->getAutoFilter()->showHideRows(); - } - - // tabColor - if ($pSheet->isTabColorSet()) { - $objWriter->startElement('tabColor'); - $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); - $objWriter->endElement(); - } - - // outlinePr - $objWriter->startElement('outlinePr'); - $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); - $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0')); - $objWriter->endElement(); - - // pageSetUpPr - if ($pSheet->getPageSetup()->getFitToPage()) { - $objWriter->startElement('pageSetUpPr'); - $objWriter->writeAttribute('fitToPage', '1'); - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - - /** - * Write Dimension - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeDimension(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // dimension - $objWriter->startElement('dimension'); - $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension()); - $objWriter->endElement(); - } - - /** - * Write SheetViews - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheetViews(PHPExcel_Shared_XMLWriter $objWriter = NULL, PHPExcel_Worksheet $pSheet = NULL) - { - // sheetViews - $objWriter->startElement('sheetViews'); - - // Sheet selected? - $sheetSelected = false; - if ($this->getParentWriter()->getPHPExcel()->getIndex($pSheet) == $this->getParentWriter()->getPHPExcel()->getActiveSheetIndex()) - $sheetSelected = true; - - - // sheetView - $objWriter->startElement('sheetView'); - $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0'); - $objWriter->writeAttribute('workbookViewId', '0'); - - // Zoom scales - if ($pSheet->getSheetView()->getZoomScale() != 100) { - $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale()); - } - if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) { - $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal()); - } - - // View Layout Type - if ($pSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL) { - $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView()); - } - - // Gridlines - if ($pSheet->getShowGridlines()) { - $objWriter->writeAttribute('showGridLines', 'true'); - } else { - $objWriter->writeAttribute('showGridLines', 'false'); - } - - // Row and column headers - if ($pSheet->getShowRowColHeaders()) { - $objWriter->writeAttribute('showRowColHeaders', '1'); - } else { - $objWriter->writeAttribute('showRowColHeaders', '0'); - } - - // Right-to-left - if ($pSheet->getRightToLeft()) { - $objWriter->writeAttribute('rightToLeft', 'true'); - } - - $activeCell = $pSheet->getActiveCell(); - - // Pane - $pane = ''; - $topLeftCell = $pSheet->getFreezePane(); - if (($topLeftCell != '') && ($topLeftCell != 'A1')) { - $activeCell = $topLeftCell; - // Calculate freeze coordinates - $xSplit = $ySplit = 0; - - list($xSplit, $ySplit) = PHPExcel_Cell::coordinateFromString($topLeftCell); - $xSplit = PHPExcel_Cell::columnIndexFromString($xSplit); - - // pane - $pane = 'topRight'; - $objWriter->startElement('pane'); - if ($xSplit > 1) - $objWriter->writeAttribute('xSplit', $xSplit - 1); - if ($ySplit > 1) { - $objWriter->writeAttribute('ySplit', $ySplit - 1); - $pane = ($xSplit > 1) ? 'bottomRight' : 'bottomLeft'; - } - $objWriter->writeAttribute('topLeftCell', $topLeftCell); - $objWriter->writeAttribute('activePane', $pane); - $objWriter->writeAttribute('state', 'frozen'); - $objWriter->endElement(); - - if (($xSplit > 1) && ($ySplit > 1)) { - // Write additional selections if more than two panes (ie both an X and a Y split) - $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'topRight'); $objWriter->endElement(); - $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'bottomLeft'); $objWriter->endElement(); - } - } - - // Selection -// if ($pane != '') { - // Only need to write selection element if we have a split pane - // We cheat a little by over-riding the active cell selection, setting it to the split cell - $objWriter->startElement('selection'); - if ($pane != '') { - $objWriter->writeAttribute('pane', $pane); - } - $objWriter->writeAttribute('activeCell', $activeCell); - $objWriter->writeAttribute('sqref', $activeCell); - $objWriter->endElement(); -// } - - $objWriter->endElement(); - - $objWriter->endElement(); - } - - /** - * Write SheetFormatPr - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheetFormatPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // sheetFormatPr - $objWriter->startElement('sheetFormatPr'); - - // Default row height - if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) { - $objWriter->writeAttribute('customHeight', 'true'); - $objWriter->writeAttribute('defaultRowHeight', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultRowDimension()->getRowHeight())); - } else { - $objWriter->writeAttribute('defaultRowHeight', '14.4'); - } - - // Set Zero Height row - if ((string)$pSheet->getDefaultRowDimension()->getZeroHeight() == '1' || - strtolower((string)$pSheet->getDefaultRowDimension()->getZeroHeight()) == 'true' ) { - $objWriter->writeAttribute('zeroHeight', '1'); - } - - // Default column width - if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) { - $objWriter->writeAttribute('defaultColWidth', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultColumnDimension()->getWidth())); - } - - // Outline level - row - $outlineLevelRow = 0; - foreach ($pSheet->getRowDimensions() as $dimension) { - if ($dimension->getOutlineLevel() > $outlineLevelRow) { - $outlineLevelRow = $dimension->getOutlineLevel(); - } - } - $objWriter->writeAttribute('outlineLevelRow', (int)$outlineLevelRow); - - // Outline level - column - $outlineLevelCol = 0; - foreach ($pSheet->getColumnDimensions() as $dimension) { - if ($dimension->getOutlineLevel() > $outlineLevelCol) { - $outlineLevelCol = $dimension->getOutlineLevel(); - } - } - $objWriter->writeAttribute('outlineLevelCol', (int)$outlineLevelCol); - - $objWriter->endElement(); - } - - /** - * Write Cols - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // cols - if (count($pSheet->getColumnDimensions()) > 0) { - $objWriter->startElement('cols'); - - $pSheet->calculateColumnWidths(); - - // Loop through column dimensions - foreach ($pSheet->getColumnDimensions() as $colDimension) { - // col - $objWriter->startElement('col'); - $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - - if ($colDimension->getWidth() < 0) { - // No width set, apply default of 10 - $objWriter->writeAttribute('width', '9.10'); - } else { - // Width set - $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); - } - - // Column visibility - if ($colDimension->getVisible() == false) { - $objWriter->writeAttribute('hidden', 'true'); - } - - // Auto size? - if ($colDimension->getAutoSize()) { - $objWriter->writeAttribute('bestFit', 'true'); - } - - // Custom width? - if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { - $objWriter->writeAttribute('customWidth', 'true'); - } - - // Collapsed - if ($colDimension->getCollapsed() == true) { - $objWriter->writeAttribute('collapsed', 'true'); - } - - // Outline level - if ($colDimension->getOutlineLevel() > 0) { - $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); - } - - // Style - $objWriter->writeAttribute('style', $colDimension->getXfIndex()); - - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write SheetProtection - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheetProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // sheetProtection - $objWriter->startElement('sheetProtection'); - - if ($pSheet->getProtection()->getPassword() != '') { - $objWriter->writeAttribute('password', $pSheet->getProtection()->getPassword()); - } - - $objWriter->writeAttribute('sheet', ($pSheet->getProtection()->getSheet() ? 'true' : 'false')); - $objWriter->writeAttribute('objects', ($pSheet->getProtection()->getObjects() ? 'true' : 'false')); - $objWriter->writeAttribute('scenarios', ($pSheet->getProtection()->getScenarios() ? 'true' : 'false')); - $objWriter->writeAttribute('formatCells', ($pSheet->getProtection()->getFormatCells() ? 'true' : 'false')); - $objWriter->writeAttribute('formatColumns', ($pSheet->getProtection()->getFormatColumns() ? 'true' : 'false')); - $objWriter->writeAttribute('formatRows', ($pSheet->getProtection()->getFormatRows() ? 'true' : 'false')); - $objWriter->writeAttribute('insertColumns', ($pSheet->getProtection()->getInsertColumns() ? 'true' : 'false')); - $objWriter->writeAttribute('insertRows', ($pSheet->getProtection()->getInsertRows() ? 'true' : 'false')); - $objWriter->writeAttribute('insertHyperlinks', ($pSheet->getProtection()->getInsertHyperlinks() ? 'true' : 'false')); - $objWriter->writeAttribute('deleteColumns', ($pSheet->getProtection()->getDeleteColumns() ? 'true' : 'false')); - $objWriter->writeAttribute('deleteRows', ($pSheet->getProtection()->getDeleteRows() ? 'true' : 'false')); - $objWriter->writeAttribute('selectLockedCells', ($pSheet->getProtection()->getSelectLockedCells() ? 'true' : 'false')); - $objWriter->writeAttribute('sort', ($pSheet->getProtection()->getSort() ? 'true' : 'false')); - $objWriter->writeAttribute('autoFilter', ($pSheet->getProtection()->getAutoFilter() ? 'true' : 'false')); - $objWriter->writeAttribute('pivotTables', ($pSheet->getProtection()->getPivotTables() ? 'true' : 'false')); - $objWriter->writeAttribute('selectUnlockedCells', ($pSheet->getProtection()->getSelectUnlockedCells() ? 'true' : 'false')); - $objWriter->endElement(); - } - - /** - * Write ConditionalFormatting - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeConditionalFormatting(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // Conditional id - $id = 1; - - // Loop through styles in the current worksheet - foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { - foreach ($conditionalStyles as $conditional) { - // WHY was this again? - // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() ) == '') { - // continue; - // } - if ($conditional->getConditionType() != PHPExcel_Style_Conditional::CONDITION_NONE) { - // conditionalFormatting - $objWriter->startElement('conditionalFormatting'); - $objWriter->writeAttribute('sqref', $cellCoordinate); - - // cfRule - $objWriter->startElement('cfRule'); - $objWriter->writeAttribute('type', $conditional->getConditionType()); - $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() )); - $objWriter->writeAttribute('priority', $id++); - - if (($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS - || - $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT) - && $conditional->getOperatorType() != PHPExcel_Style_Conditional::OPERATOR_NONE) { - $objWriter->writeAttribute('operator', $conditional->getOperatorType()); - } - - if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - && !is_null($conditional->getText())) { - $objWriter->writeAttribute('text', $conditional->getText()); - } - - if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_CONTAINSTEXT - && !is_null($conditional->getText())) { - $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))'); - } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BEGINSWITH - && !is_null($conditional->getText())) { - $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); - } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_ENDSWITH - && !is_null($conditional->getText())) { - $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); - } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_NOTCONTAINS - && !is_null($conditional->getText())) { - $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))'); - } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS - || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) { - foreach ($conditional->getConditions() as $formula) { - // Formula - $objWriter->writeElement('formula', $formula); - } - } - - $objWriter->endElement(); - - $objWriter->endElement(); - } - } - } - } - - /** - * Write DataValidations - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // Datavalidation collection - $dataValidationCollection = $pSheet->getDataValidationCollection(); - - // Write data validations? - if (!empty($dataValidationCollection)) { - $objWriter->startElement('dataValidations'); - $objWriter->writeAttribute('count', count($dataValidationCollection)); - - foreach ($dataValidationCollection as $coordinate => $dv) { - $objWriter->startElement('dataValidation'); - - if ($dv->getType() != '') { - $objWriter->writeAttribute('type', $dv->getType()); - } - - if ($dv->getErrorStyle() != '') { - $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle()); - } - - if ($dv->getOperator() != '') { - $objWriter->writeAttribute('operator', $dv->getOperator()); - } - - $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0')); - $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0')); - $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0')); - $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0')); - - if ($dv->getErrorTitle() !== '') { - $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle()); - } - if ($dv->getError() !== '') { - $objWriter->writeAttribute('error', $dv->getError()); - } - if ($dv->getPromptTitle() !== '') { - $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle()); - } - if ($dv->getPrompt() !== '') { - $objWriter->writeAttribute('prompt', $dv->getPrompt()); - } - - $objWriter->writeAttribute('sqref', $coordinate); - - if ($dv->getFormula1() !== '') { - $objWriter->writeElement('formula1', $dv->getFormula1()); - } - if ($dv->getFormula2() !== '') { - $objWriter->writeElement('formula2', $dv->getFormula2()); - } - - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write Hyperlinks - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // Hyperlink collection - $hyperlinkCollection = $pSheet->getHyperlinkCollection(); - - // Relation ID - $relationId = 1; - - // Write hyperlinks? - if (!empty($hyperlinkCollection)) { - $objWriter->startElement('hyperlinks'); - - foreach ($hyperlinkCollection as $coordinate => $hyperlink) { - $objWriter->startElement('hyperlink'); - - $objWriter->writeAttribute('ref', $coordinate); - if (!$hyperlink->isInternal()) { - $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId); - ++$relationId; - } else { - $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl())); - } - - if ($hyperlink->getTooltip() != '') { - $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip()); - } - - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write ProtectedRanges - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeProtectedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - if (count($pSheet->getProtectedCells()) > 0) { - // protectedRanges - $objWriter->startElement('protectedRanges'); - - // Loop protectedRanges - foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) { - // protectedRange - $objWriter->startElement('protectedRange'); - $objWriter->writeAttribute('name', 'p' . md5($protectedCell)); - $objWriter->writeAttribute('sqref', $protectedCell); - if (!empty($passwordHash)) { - $objWriter->writeAttribute('password', $passwordHash); - } - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write MergeCells - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeMergeCells(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - if (count($pSheet->getMergeCells()) > 0) { - // mergeCells - $objWriter->startElement('mergeCells'); - - // Loop mergeCells - foreach ($pSheet->getMergeCells() as $mergeCell) { - // mergeCell - $objWriter->startElement('mergeCell'); - $objWriter->writeAttribute('ref', $mergeCell); - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write PrintOptions - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writePrintOptions(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // printOptions - $objWriter->startElement('printOptions'); - - $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true': 'false')); - $objWriter->writeAttribute('gridLinesSet', 'true'); - - if ($pSheet->getPageSetup()->getHorizontalCentered()) { - $objWriter->writeAttribute('horizontalCentered', 'true'); - } - - if ($pSheet->getPageSetup()->getVerticalCentered()) { - $objWriter->writeAttribute('verticalCentered', 'true'); - } - - $objWriter->endElement(); - } - - /** - * Write PageMargins - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writePageMargins(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // pageMargins - $objWriter->startElement('pageMargins'); - $objWriter->writeAttribute('left', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft())); - $objWriter->writeAttribute('right', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight())); - $objWriter->writeAttribute('top', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop())); - $objWriter->writeAttribute('bottom', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom())); - $objWriter->writeAttribute('header', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getHeader())); - $objWriter->writeAttribute('footer', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getFooter())); - $objWriter->endElement(); - } - - /** - * Write AutoFilter - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeAutoFilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - $autoFilterRange = $pSheet->getAutoFilter()->getRange(); - if (!empty($autoFilterRange)) { - // autoFilter - $objWriter->startElement('autoFilter'); - - // Strip any worksheet reference from the filter coordinates - $range = PHPExcel_Cell::splitRange($autoFilterRange); - $range = $range[0]; - // Strip any worksheet ref - if (strpos($range[0],'!') !== false) { - list($ws,$range[0]) = explode('!',$range[0]); - } - $range = implode(':', $range); - - $objWriter->writeAttribute('ref', str_replace('$','',$range)); - - $columns = $pSheet->getAutoFilter()->getColumns(); - if (count($columns > 0)) { - foreach($columns as $columnID => $column) { - $rules = $column->getRules(); - if (count($rules > 0)) { - $objWriter->startElement('filterColumn'); - $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID)); - - $objWriter->startElement( $column->getFilterType()); - if ($column->getJoin() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND) { - $objWriter->writeAttribute('and', 1); - } - - foreach ($rules as $rule) { - if (($column->getFilterType() === PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER) && - ($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) && - ($rule->getValue() === '')) { - // Filter rule for Blanks - $objWriter->writeAttribute('blank', 1); - } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) { - // Dynamic Filter Rule - $objWriter->writeAttribute('type', $rule->getGrouping()); - $val = $column->getAttribute('val'); - if ($val !== NULL) { - $objWriter->writeAttribute('val', $val); - } - $maxVal = $column->getAttribute('maxVal'); - if ($maxVal !== NULL) { - $objWriter->writeAttribute('maxVal', $maxVal); - } - } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) { - // Top 10 Filter Rule - $objWriter->writeAttribute('val', $rule->getValue()); - $objWriter->writeAttribute('percent', (($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0')); - $objWriter->writeAttribute('top', (($rule->getGrouping() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1': '0')); - } else { - // Filter, DateGroupItem or CustomFilter - $objWriter->startElement($rule->getRuleType()); - - if ($rule->getOperator() !== PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) { - $objWriter->writeAttribute('operator', $rule->getOperator()); - } - if ($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP) { - // Date Group filters - foreach($rule->getValue() as $key => $value) { - if ($value > '') $objWriter->writeAttribute($key, $value); - } - $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping()); - } else { - $objWriter->writeAttribute('val', $rule->getValue()); - } - - $objWriter->endElement(); - } - } - - $objWriter->endElement(); - - $objWriter->endElement(); - } - } - } - - $objWriter->endElement(); - } - } - - /** - * Write PageSetup - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writePageSetup(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // pageSetup - $objWriter->startElement('pageSetup'); - $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize()); - $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation()); - - if (!is_null($pSheet->getPageSetup()->getScale())) { - $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); - } - if (!is_null($pSheet->getPageSetup()->getFitToHeight())) { - $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); - } else { - $objWriter->writeAttribute('fitToHeight', '0'); - } - if (!is_null($pSheet->getPageSetup()->getFitToWidth())) { - $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); - } else { - $objWriter->writeAttribute('fitToWidth', '0'); - } - if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) { - $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber()); - $objWriter->writeAttribute('useFirstPageNumber', '1'); - } - - $objWriter->endElement(); - } - - /** - * Write Header / Footer - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeHeaderFooter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // headerFooter - $objWriter->startElement('headerFooter'); - $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false')); - $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false')); - $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false')); - $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false')); - - $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader()); - $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter()); - $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader()); - $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter()); - $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader()); - $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter()); - $objWriter->endElement(); - } - - /** - * Write Breaks - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeBreaks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // Get row and column breaks - $aRowBreaks = array(); - $aColumnBreaks = array(); - foreach ($pSheet->getBreaks() as $cell => $breakType) { - if ($breakType == PHPExcel_Worksheet::BREAK_ROW) { - $aRowBreaks[] = $cell; - } else if ($breakType == PHPExcel_Worksheet::BREAK_COLUMN) { - $aColumnBreaks[] = $cell; - } - } - - // rowBreaks - if (!empty($aRowBreaks)) { - $objWriter->startElement('rowBreaks'); - $objWriter->writeAttribute('count', count($aRowBreaks)); - $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks)); - - foreach ($aRowBreaks as $cell) { - $coords = PHPExcel_Cell::coordinateFromString($cell); - - $objWriter->startElement('brk'); - $objWriter->writeAttribute('id', $coords[1]); - $objWriter->writeAttribute('man', '1'); - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - - // Second, write column breaks - if (!empty($aColumnBreaks)) { - $objWriter->startElement('colBreaks'); - $objWriter->writeAttribute('count', count($aColumnBreaks)); - $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks)); - - foreach ($aColumnBreaks as $cell) { - $coords = PHPExcel_Cell::coordinateFromString($cell); - - $objWriter->startElement('brk'); - $objWriter->writeAttribute('id', PHPExcel_Cell::columnIndexFromString($coords[0]) - 1); - $objWriter->writeAttribute('man', '1'); - $objWriter->endElement(); - } - - $objWriter->endElement(); - } - } - - /** - * Write SheetData - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @param string[] $pStringTable String table - * @throws PHPExcel_Writer_Exception - */ - private function _writeSheetData(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pStringTable = null) - { - if (is_array($pStringTable)) { - // Flipped stringtable, for faster index searching - $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable); - - // sheetData - $objWriter->startElement('sheetData'); - - // Get column count - $colCount = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()); - - // Highest row number - $highestRow = $pSheet->getHighestRow(); - - // Loop through cells - $cellsByRow = array(); - foreach ($pSheet->getCellCollection() as $cellID) { - $cellAddress = PHPExcel_Cell::coordinateFromString($cellID); - $cellsByRow[$cellAddress[1]][] = $cellID; - } - - $currentRow = 0; - while($currentRow++ < $highestRow) { - // Get row dimension - $rowDimension = $pSheet->getRowDimension($currentRow); - - // Write current row? - $writeCurrentRow = isset($cellsByRow[$currentRow]) || - $rowDimension->getRowHeight() >= 0 || - $rowDimension->getVisible() == false || - $rowDimension->getCollapsed() == true || - $rowDimension->getOutlineLevel() > 0 || - $rowDimension->getXfIndex() !== null; - - if ($writeCurrentRow) { - // Start a new row - $objWriter->startElement('row'); - $objWriter->writeAttribute('r', $currentRow); - $objWriter->writeAttribute('spans', '1:' . $colCount); - - // Row dimensions - if ($rowDimension->getRowHeight() >= 0) { - $objWriter->writeAttribute('customHeight', '1'); - $objWriter->writeAttribute('ht', PHPExcel_Shared_String::FormatNumber($rowDimension->getRowHeight())); - } - - // Row visibility - if ($rowDimension->getVisible() == false) { - $objWriter->writeAttribute('hidden', 'true'); - } - - // Collapsed - if ($rowDimension->getCollapsed() == true) { - $objWriter->writeAttribute('collapsed', 'true'); - } - - // Outline level - if ($rowDimension->getOutlineLevel() > 0) { - $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); - } - - // Style - if ($rowDimension->getXfIndex() !== null) { - $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); - $objWriter->writeAttribute('customFormat', '1'); - } - - // Write cells - if (isset($cellsByRow[$currentRow])) { - foreach($cellsByRow[$currentRow] as $cellAddress) { - // Write cell - $this->_writeCell($objWriter, $pSheet, $cellAddress, $pStringTable, $aFlippedStringTable); - } - } - - // End row - $objWriter->endElement(); - } - } - - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } - - /** - * Write Cell - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @param PHPExcel_Cell $pCellAddress Cell Address - * @param string[] $pStringTable String table - * @param string[] $pFlippedStringTable String table (flipped), for faster index searching - * @throws PHPExcel_Writer_Exception - */ - private function _writeCell(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pCellAddress = null, $pStringTable = null, $pFlippedStringTable = null) - { - if (is_array($pStringTable) && is_array($pFlippedStringTable)) { - // Cell - $pCell = $pSheet->getCell($pCellAddress); - $objWriter->startElement('c'); - $objWriter->writeAttribute('r', $pCellAddress); - - // Sheet styles - if ($pCell->getXfIndex() != '') { - $objWriter->writeAttribute('s', $pCell->getXfIndex()); - } - - // If cell value is supplied, write cell value - $cellValue = $pCell->getValue(); - if (is_object($cellValue) || $cellValue !== '') { - // Map type - $mappedType = $pCell->getDataType(); - - // Write data type depending on its type - switch (strtolower($mappedType)) { - case 'inlinestr': // Inline string - case 's': // String - case 'b': // Boolean - $objWriter->writeAttribute('t', $mappedType); - break; - case 'f': // Formula - $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ? - $pCell->getCalculatedValue() : - $cellValue; - if (is_string($calculatedValue)) { - $objWriter->writeAttribute('t', 'str'); - } - break; - case 'e': // Error - $objWriter->writeAttribute('t', $mappedType); - } - - // Write data depending on its type - switch (strtolower($mappedType)) { - case 'inlinestr': // Inline string - if (! $cellValue instanceof PHPExcel_RichText) { - $objWriter->writeElement('t', PHPExcel_Shared_String::ControlCharacterPHP2OOXML( htmlspecialchars($cellValue) ) ); - } else if ($cellValue instanceof PHPExcel_RichText) { - $objWriter->startElement('is'); - $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue); - $objWriter->endElement(); - } - - break; - case 's': // String - if (! $cellValue instanceof PHPExcel_RichText) { - if (isset($pFlippedStringTable[$cellValue])) { - $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]); - } - } else if ($cellValue instanceof PHPExcel_RichText) { - $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]); - } - - break; - case 'f': // Formula - $attributes = $pCell->getFormulaAttributes(); - if($attributes['t'] == 'array') { - $objWriter->startElement('f'); - $objWriter->writeAttribute('t', 'array'); - $objWriter->writeAttribute('ref', $pCellAddress); - $objWriter->writeAttribute('aca', '1'); - $objWriter->writeAttribute('ca', '1'); - $objWriter->text(substr($cellValue, 1)); - $objWriter->endElement(); - } else { - $objWriter->writeElement('f', substr($cellValue, 1)); - } - if ($this->getParentWriter()->getOffice2003Compatibility() === false) { - if ($this->getParentWriter()->getPreCalculateFormulas()) { -// $calculatedValue = $pCell->getCalculatedValue(); - if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') { - $objWriter->writeElement('v', PHPExcel_Shared_String::FormatNumber($calculatedValue)); - } else { - $objWriter->writeElement('v', '0'); - } - } else { - $objWriter->writeElement('v', '0'); - } - } - break; - case 'n': // Numeric - // force point as decimal separator in case current locale uses comma - $objWriter->writeElement('v', str_replace(',', '.', $cellValue)); - break; - case 'b': // Boolean - $objWriter->writeElement('v', ($cellValue ? '1' : '0')); - break; - case 'e': // Error - if (substr($cellValue, 0, 1) == '=') { - $objWriter->writeElement('f', substr($cellValue, 1)); - $objWriter->writeElement('v', substr($cellValue, 1)); - } else { - $objWriter->writeElement('v', $cellValue); - } - - break; - } - } - - $objWriter->endElement(); - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } - - /** - * Write Drawings - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @param boolean $includeCharts Flag indicating if we should include drawing details for charts - * @throws PHPExcel_Writer_Exception - */ - private function _writeDrawings(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $includeCharts = FALSE) - { - $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0; - // If sheet contains drawings, add the relationships - if (($pSheet->getDrawingCollection()->count() > 0) || - ($chartCount > 0)) { - $objWriter->startElement('drawing'); - $objWriter->writeAttribute('r:id', 'rId1'); - $objWriter->endElement(); - } - } - - /** - * Write LegacyDrawing - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeLegacyDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // If sheet contains comments, add the relationships - if (count($pSheet->getComments()) > 0) { - $objWriter->startElement('legacyDrawing'); - $objWriter->writeAttribute('r:id', 'rId_comments_vml1'); - $objWriter->endElement(); - } - } - - /** - * Write LegacyDrawingHF - * - * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws PHPExcel_Writer_Exception - */ - private function _writeLegacyDrawingHF(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) - { - // If sheet contains images, add the relationships - if (count($pSheet->getHeaderFooter()->getImages()) > 0) { - $objWriter->startElement('legacyDrawingHF'); - $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1'); - $objWriter->endElement(); - } - } + /** + * Write worksheet to XML format + * + * @param PHPExcel_Worksheet $pSheet + * @param string[] $pStringTable + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = FALSE) + { + if (!is_null($pSheet)) { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Worksheet + $objWriter->startElement('worksheet'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + // sheetPr + $this->_writeSheetPr($objWriter, $pSheet); + + // Dimension + $this->_writeDimension($objWriter, $pSheet); + + // sheetViews + $this->_writeSheetViews($objWriter, $pSheet); + + // sheetFormatPr + $this->_writeSheetFormatPr($objWriter, $pSheet); + + // cols + $this->_writeCols($objWriter, $pSheet); + + // sheetData + $this->_writeSheetData($objWriter, $pSheet, $pStringTable); + + // sheetProtection + $this->_writeSheetProtection($objWriter, $pSheet); + + // protectedRanges + $this->_writeProtectedRanges($objWriter, $pSheet); + + // autoFilter + $this->_writeAutoFilter($objWriter, $pSheet); + + // mergeCells + $this->_writeMergeCells($objWriter, $pSheet); + + // conditionalFormatting + $this->_writeConditionalFormatting($objWriter, $pSheet); + + // dataValidations + $this->_writeDataValidations($objWriter, $pSheet); + + // hyperlinks + $this->_writeHyperlinks($objWriter, $pSheet); + + // Print options + $this->_writePrintOptions($objWriter, $pSheet); + + // Page margins + $this->_writePageMargins($objWriter, $pSheet); + + // Page setup + $this->_writePageSetup($objWriter, $pSheet); + + // Header / footer + $this->_writeHeaderFooter($objWriter, $pSheet); + + // Breaks + $this->_writeBreaks($objWriter, $pSheet); + + // Drawings and/or Charts + $this->_writeDrawings($objWriter, $pSheet, $includeCharts); + + // LegacyDrawing + $this->_writeLegacyDrawing($objWriter, $pSheet); + + // LegacyDrawingHF + $this->_writeLegacyDrawingHF($objWriter, $pSheet); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } else { + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); + } + } + + /** + * Write SheetPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetPr + $objWriter->startElement('sheetPr'); + //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); + if($pSheet->getParent()->hasMacros()){//if the workbook have macros, we need to have codeName for the sheet + if($pSheet->hasCodeName()==false){ + $pSheet->setCodeName($pSheet->getTitle()); + } + $objWriter->writeAttribute('codeName', $pSheet->getCodeName()); + } + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + $objWriter->writeAttribute('filterMode', 1); + $pSheet->getAutoFilter()->showHideRows(); + } + + // tabColor + if ($pSheet->isTabColorSet()) { + $objWriter->startElement('tabColor'); + $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); + $objWriter->endElement(); + } + + // outlinePr + $objWriter->startElement('outlinePr'); + $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); + $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0')); + $objWriter->endElement(); + + // pageSetUpPr + if ($pSheet->getPageSetup()->getFitToPage()) { + $objWriter->startElement('pageSetUpPr'); + $objWriter->writeAttribute('fitToPage', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + /** + * Write Dimension + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeDimension(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // dimension + $objWriter->startElement('dimension'); + $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension()); + $objWriter->endElement(); + } + + /** + * Write SheetViews + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetViews(PHPExcel_Shared_XMLWriter $objWriter = NULL, PHPExcel_Worksheet $pSheet = NULL) + { + // sheetViews + $objWriter->startElement('sheetViews'); + + // Sheet selected? + $sheetSelected = false; + if ($this->getParentWriter()->getPHPExcel()->getIndex($pSheet) == $this->getParentWriter()->getPHPExcel()->getActiveSheetIndex()) + $sheetSelected = true; + + + // sheetView + $objWriter->startElement('sheetView'); + $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0'); + $objWriter->writeAttribute('workbookViewId', '0'); + + // Zoom scales + if ($pSheet->getSheetView()->getZoomScale() != 100) { + $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale()); + } + if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) { + $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal()); + } + + // View Layout Type + if ($pSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL) { + $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView()); + } + + // Gridlines + if ($pSheet->getShowGridlines()) { + $objWriter->writeAttribute('showGridLines', 'true'); + } else { + $objWriter->writeAttribute('showGridLines', 'false'); + } + + // Row and column headers + if ($pSheet->getShowRowColHeaders()) { + $objWriter->writeAttribute('showRowColHeaders', '1'); + } else { + $objWriter->writeAttribute('showRowColHeaders', '0'); + } + + // Right-to-left + if ($pSheet->getRightToLeft()) { + $objWriter->writeAttribute('rightToLeft', 'true'); + } + + $activeCell = $pSheet->getActiveCell(); + + // Pane + $pane = ''; + $topLeftCell = $pSheet->getFreezePane(); + if (($topLeftCell != '') && ($topLeftCell != 'A1')) { + $activeCell = $topLeftCell; + // Calculate freeze coordinates + $xSplit = $ySplit = 0; + + list($xSplit, $ySplit) = PHPExcel_Cell::coordinateFromString($topLeftCell); + $xSplit = PHPExcel_Cell::columnIndexFromString($xSplit); + + // pane + $pane = 'topRight'; + $objWriter->startElement('pane'); + if ($xSplit > 1) + $objWriter->writeAttribute('xSplit', $xSplit - 1); + if ($ySplit > 1) { + $objWriter->writeAttribute('ySplit', $ySplit - 1); + $pane = ($xSplit > 1) ? 'bottomRight' : 'bottomLeft'; + } + $objWriter->writeAttribute('topLeftCell', $topLeftCell); + $objWriter->writeAttribute('activePane', $pane); + $objWriter->writeAttribute('state', 'frozen'); + $objWriter->endElement(); + + if (($xSplit > 1) && ($ySplit > 1)) { + // Write additional selections if more than two panes (ie both an X and a Y split) + $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'topRight'); $objWriter->endElement(); + $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'bottomLeft'); $objWriter->endElement(); + } + } + + // Selection +// if ($pane != '') { + // Only need to write selection element if we have a split pane + // We cheat a little by over-riding the active cell selection, setting it to the split cell + $objWriter->startElement('selection'); + if ($pane != '') { + $objWriter->writeAttribute('pane', $pane); + } + $objWriter->writeAttribute('activeCell', $activeCell); + $objWriter->writeAttribute('sqref', $activeCell); + $objWriter->endElement(); +// } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write SheetFormatPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetFormatPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetFormatPr + $objWriter->startElement('sheetFormatPr'); + + // Default row height + if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) { + $objWriter->writeAttribute('customHeight', 'true'); + $objWriter->writeAttribute('defaultRowHeight', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultRowDimension()->getRowHeight())); + } else { + $objWriter->writeAttribute('defaultRowHeight', '14.4'); + } + + // Set Zero Height row + if ((string)$pSheet->getDefaultRowDimension()->getZeroHeight() == '1' || + strtolower((string)$pSheet->getDefaultRowDimension()->getZeroHeight()) == 'true' ) { + $objWriter->writeAttribute('zeroHeight', '1'); + } + + // Default column width + if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) { + $objWriter->writeAttribute('defaultColWidth', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultColumnDimension()->getWidth())); + } + + // Outline level - row + $outlineLevelRow = 0; + foreach ($pSheet->getRowDimensions() as $dimension) { + if ($dimension->getOutlineLevel() > $outlineLevelRow) { + $outlineLevelRow = $dimension->getOutlineLevel(); + } + } + $objWriter->writeAttribute('outlineLevelRow', (int)$outlineLevelRow); + + // Outline level - column + $outlineLevelCol = 0; + foreach ($pSheet->getColumnDimensions() as $dimension) { + if ($dimension->getOutlineLevel() > $outlineLevelCol) { + $outlineLevelCol = $dimension->getOutlineLevel(); + } + } + $objWriter->writeAttribute('outlineLevelCol', (int)$outlineLevelCol); + + $objWriter->endElement(); + } + + /** + * Write Cols + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // cols + if (count($pSheet->getColumnDimensions()) > 0) { + $objWriter->startElement('cols'); + + $pSheet->calculateColumnWidths(); + + // Loop through column dimensions + foreach ($pSheet->getColumnDimensions() as $colDimension) { + // col + $objWriter->startElement('col'); + $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + + if ($colDimension->getWidth() < 0) { + // No width set, apply default of 10 + $objWriter->writeAttribute('width', '9.10'); + } else { + // Width set + $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + } + + // Column visibility + if ($colDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Auto size? + if ($colDimension->getAutoSize()) { + $objWriter->writeAttribute('bestFit', 'true'); + } + + // Custom width? + if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { + $objWriter->writeAttribute('customWidth', 'true'); + } + + // Collapsed + if ($colDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($colDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); + } + + // Style + $objWriter->writeAttribute('style', $colDimension->getXfIndex()); + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write SheetProtection + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetProtection + $objWriter->startElement('sheetProtection'); + + if ($pSheet->getProtection()->getPassword() != '') { + $objWriter->writeAttribute('password', $pSheet->getProtection()->getPassword()); + } + + $objWriter->writeAttribute('sheet', ($pSheet->getProtection()->getSheet() ? 'true' : 'false')); + $objWriter->writeAttribute('objects', ($pSheet->getProtection()->getObjects() ? 'true' : 'false')); + $objWriter->writeAttribute('scenarios', ($pSheet->getProtection()->getScenarios() ? 'true' : 'false')); + $objWriter->writeAttribute('formatCells', ($pSheet->getProtection()->getFormatCells() ? 'true' : 'false')); + $objWriter->writeAttribute('formatColumns', ($pSheet->getProtection()->getFormatColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('formatRows', ($pSheet->getProtection()->getFormatRows() ? 'true' : 'false')); + $objWriter->writeAttribute('insertColumns', ($pSheet->getProtection()->getInsertColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('insertRows', ($pSheet->getProtection()->getInsertRows() ? 'true' : 'false')); + $objWriter->writeAttribute('insertHyperlinks', ($pSheet->getProtection()->getInsertHyperlinks() ? 'true' : 'false')); + $objWriter->writeAttribute('deleteColumns', ($pSheet->getProtection()->getDeleteColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('deleteRows', ($pSheet->getProtection()->getDeleteRows() ? 'true' : 'false')); + $objWriter->writeAttribute('selectLockedCells', ($pSheet->getProtection()->getSelectLockedCells() ? 'true' : 'false')); + $objWriter->writeAttribute('sort', ($pSheet->getProtection()->getSort() ? 'true' : 'false')); + $objWriter->writeAttribute('autoFilter', ($pSheet->getProtection()->getAutoFilter() ? 'true' : 'false')); + $objWriter->writeAttribute('pivotTables', ($pSheet->getProtection()->getPivotTables() ? 'true' : 'false')); + $objWriter->writeAttribute('selectUnlockedCells', ($pSheet->getProtection()->getSelectUnlockedCells() ? 'true' : 'false')); + $objWriter->endElement(); + } + + /** + * Write ConditionalFormatting + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeConditionalFormatting(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Conditional id + $id = 1; + + // Loop through styles in the current worksheet + foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + // WHY was this again? + // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() ) == '') { + // continue; + // } + if ($conditional->getConditionType() != PHPExcel_Style_Conditional::CONDITION_NONE) { + // conditionalFormatting + $objWriter->startElement('conditionalFormatting'); + $objWriter->writeAttribute('sqref', $cellCoordinate); + + // cfRule + $objWriter->startElement('cfRule'); + $objWriter->writeAttribute('type', $conditional->getConditionType()); + $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() )); + $objWriter->writeAttribute('priority', $id++); + + if (($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + || + $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT) + && $conditional->getOperatorType() != PHPExcel_Style_Conditional::OPERATOR_NONE) { + $objWriter->writeAttribute('operator', $conditional->getOperatorType()); + } + + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeAttribute('text', $conditional->getText()); + } + + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BEGINSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_ENDSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_NOTCONTAINS + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) { + foreach ($conditional->getConditions() as $formula) { + // Formula + $objWriter->writeElement('formula', $formula); + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + } + + /** + * Write DataValidations + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Datavalidation collection + $dataValidationCollection = $pSheet->getDataValidationCollection(); + + // Write data validations? + if (!empty($dataValidationCollection)) { + $objWriter->startElement('dataValidations'); + $objWriter->writeAttribute('count', count($dataValidationCollection)); + + foreach ($dataValidationCollection as $coordinate => $dv) { + $objWriter->startElement('dataValidation'); + + if ($dv->getType() != '') { + $objWriter->writeAttribute('type', $dv->getType()); + } + + if ($dv->getErrorStyle() != '') { + $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle()); + } + + if ($dv->getOperator() != '') { + $objWriter->writeAttribute('operator', $dv->getOperator()); + } + + $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0')); + $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0')); + $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0')); + $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0')); + + if ($dv->getErrorTitle() !== '') { + $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle()); + } + if ($dv->getError() !== '') { + $objWriter->writeAttribute('error', $dv->getError()); + } + if ($dv->getPromptTitle() !== '') { + $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle()); + } + if ($dv->getPrompt() !== '') { + $objWriter->writeAttribute('prompt', $dv->getPrompt()); + } + + $objWriter->writeAttribute('sqref', $coordinate); + + if ($dv->getFormula1() !== '') { + $objWriter->writeElement('formula1', $dv->getFormula1()); + } + if ($dv->getFormula2() !== '') { + $objWriter->writeElement('formula2', $dv->getFormula2()); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write Hyperlinks + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Hyperlink collection + $hyperlinkCollection = $pSheet->getHyperlinkCollection(); + + // Relation ID + $relationId = 1; + + // Write hyperlinks? + if (!empty($hyperlinkCollection)) { + $objWriter->startElement('hyperlinks'); + + foreach ($hyperlinkCollection as $coordinate => $hyperlink) { + $objWriter->startElement('hyperlink'); + + $objWriter->writeAttribute('ref', $coordinate); + if (!$hyperlink->isInternal()) { + $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId); + ++$relationId; + } else { + $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl())); + } + + if ($hyperlink->getTooltip() != '') { + $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip()); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write ProtectedRanges + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeProtectedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + if (count($pSheet->getProtectedCells()) > 0) { + // protectedRanges + $objWriter->startElement('protectedRanges'); + + // Loop protectedRanges + foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) { + // protectedRange + $objWriter->startElement('protectedRange'); + $objWriter->writeAttribute('name', 'p' . md5($protectedCell)); + $objWriter->writeAttribute('sqref', $protectedCell); + if (!empty($passwordHash)) { + $objWriter->writeAttribute('password', $passwordHash); + } + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write MergeCells + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeMergeCells(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + if (count($pSheet->getMergeCells()) > 0) { + // mergeCells + $objWriter->startElement('mergeCells'); + + // Loop mergeCells + foreach ($pSheet->getMergeCells() as $mergeCell) { + // mergeCell + $objWriter->startElement('mergeCell'); + $objWriter->writeAttribute('ref', $mergeCell); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write PrintOptions + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePrintOptions(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // printOptions + $objWriter->startElement('printOptions'); + + $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true': 'false')); + $objWriter->writeAttribute('gridLinesSet', 'true'); + + if ($pSheet->getPageSetup()->getHorizontalCentered()) { + $objWriter->writeAttribute('horizontalCentered', 'true'); + } + + if ($pSheet->getPageSetup()->getVerticalCentered()) { + $objWriter->writeAttribute('verticalCentered', 'true'); + } + + $objWriter->endElement(); + } + + /** + * Write PageMargins + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePageMargins(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // pageMargins + $objWriter->startElement('pageMargins'); + $objWriter->writeAttribute('left', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft())); + $objWriter->writeAttribute('right', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight())); + $objWriter->writeAttribute('top', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop())); + $objWriter->writeAttribute('bottom', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom())); + $objWriter->writeAttribute('header', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getHeader())); + $objWriter->writeAttribute('footer', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getFooter())); + $objWriter->endElement(); + } + + /** + * Write AutoFilter + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeAutoFilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + // autoFilter + $objWriter->startElement('autoFilter'); + + // Strip any worksheet reference from the filter coordinates + $range = PHPExcel_Cell::splitRange($autoFilterRange); + $range = $range[0]; + // Strip any worksheet ref + if (strpos($range[0],'!') !== false) { + list($ws,$range[0]) = explode('!',$range[0]); + } + $range = implode(':', $range); + + $objWriter->writeAttribute('ref', str_replace('$','',$range)); + + $columns = $pSheet->getAutoFilter()->getColumns(); + if (count($columns > 0)) { + foreach($columns as $columnID => $column) { + $rules = $column->getRules(); + if (count($rules > 0)) { + $objWriter->startElement('filterColumn'); + $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID)); + + $objWriter->startElement( $column->getFilterType()); + if ($column->getJoin() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND) { + $objWriter->writeAttribute('and', 1); + } + + foreach ($rules as $rule) { + if (($column->getFilterType() === PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER) && + ($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) && + ($rule->getValue() === '')) { + // Filter rule for Blanks + $objWriter->writeAttribute('blank', 1); + } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) { + // Dynamic Filter Rule + $objWriter->writeAttribute('type', $rule->getGrouping()); + $val = $column->getAttribute('val'); + if ($val !== NULL) { + $objWriter->writeAttribute('val', $val); + } + $maxVal = $column->getAttribute('maxVal'); + if ($maxVal !== NULL) { + $objWriter->writeAttribute('maxVal', $maxVal); + } + } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) { + // Top 10 Filter Rule + $objWriter->writeAttribute('val', $rule->getValue()); + $objWriter->writeAttribute('percent', (($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0')); + $objWriter->writeAttribute('top', (($rule->getGrouping() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1': '0')); + } else { + // Filter, DateGroupItem or CustomFilter + $objWriter->startElement($rule->getRuleType()); + + if ($rule->getOperator() !== PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) { + $objWriter->writeAttribute('operator', $rule->getOperator()); + } + if ($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP) { + // Date Group filters + foreach($rule->getValue() as $key => $value) { + if ($value > '') $objWriter->writeAttribute($key, $value); + } + $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping()); + } else { + $objWriter->writeAttribute('val', $rule->getValue()); + } + + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + + $objWriter->endElement(); + } + } + + /** + * Write PageSetup + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePageSetup(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // pageSetup + $objWriter->startElement('pageSetup'); + $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize()); + $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation()); + + if (!is_null($pSheet->getPageSetup()->getScale())) { + $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); + } + if (!is_null($pSheet->getPageSetup()->getFitToHeight())) { + $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); + } else { + $objWriter->writeAttribute('fitToHeight', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFitToWidth())) { + $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); + } else { + $objWriter->writeAttribute('fitToWidth', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) { + $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber()); + $objWriter->writeAttribute('useFirstPageNumber', '1'); + } + + $objWriter->endElement(); + } + + /** + * Write Header / Footer + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeHeaderFooter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // headerFooter + $objWriter->startElement('headerFooter'); + $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false')); + $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false')); + $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false')); + $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false')); + + $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader()); + $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter()); + $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader()); + $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter()); + $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader()); + $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter()); + $objWriter->endElement(); + } + + /** + * Write Breaks + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeBreaks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Get row and column breaks + $aRowBreaks = array(); + $aColumnBreaks = array(); + foreach ($pSheet->getBreaks() as $cell => $breakType) { + if ($breakType == PHPExcel_Worksheet::BREAK_ROW) { + $aRowBreaks[] = $cell; + } else if ($breakType == PHPExcel_Worksheet::BREAK_COLUMN) { + $aColumnBreaks[] = $cell; + } + } + + // rowBreaks + if (!empty($aRowBreaks)) { + $objWriter->startElement('rowBreaks'); + $objWriter->writeAttribute('count', count($aRowBreaks)); + $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks)); + + foreach ($aRowBreaks as $cell) { + $coords = PHPExcel_Cell::coordinateFromString($cell); + + $objWriter->startElement('brk'); + $objWriter->writeAttribute('id', $coords[1]); + $objWriter->writeAttribute('man', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + // Second, write column breaks + if (!empty($aColumnBreaks)) { + $objWriter->startElement('colBreaks'); + $objWriter->writeAttribute('count', count($aColumnBreaks)); + $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks)); + + foreach ($aColumnBreaks as $cell) { + $coords = PHPExcel_Cell::coordinateFromString($cell); + + $objWriter->startElement('brk'); + $objWriter->writeAttribute('id', PHPExcel_Cell::columnIndexFromString($coords[0]) - 1); + $objWriter->writeAttribute('man', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write SheetData + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param string[] $pStringTable String table + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetData(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pStringTable = null) + { + if (is_array($pStringTable)) { + // Flipped stringtable, for faster index searching + $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable); + + // sheetData + $objWriter->startElement('sheetData'); + + // Get column count + $colCount = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()); + + // Highest row number + $highestRow = $pSheet->getHighestRow(); + + // Loop through cells + $cellsByRow = array(); + foreach ($pSheet->getCellCollection() as $cellID) { + $cellAddress = PHPExcel_Cell::coordinateFromString($cellID); + $cellsByRow[$cellAddress[1]][] = $cellID; + } + + $currentRow = 0; + while($currentRow++ < $highestRow) { + // Get row dimension + $rowDimension = $pSheet->getRowDimension($currentRow); + + // Write current row? + $writeCurrentRow = isset($cellsByRow[$currentRow]) || + $rowDimension->getRowHeight() >= 0 || + $rowDimension->getVisible() == false || + $rowDimension->getCollapsed() == true || + $rowDimension->getOutlineLevel() > 0 || + $rowDimension->getXfIndex() !== null; + + if ($writeCurrentRow) { + // Start a new row + $objWriter->startElement('row'); + $objWriter->writeAttribute('r', $currentRow); + $objWriter->writeAttribute('spans', '1:' . $colCount); + + // Row dimensions + if ($rowDimension->getRowHeight() >= 0) { + $objWriter->writeAttribute('customHeight', '1'); + $objWriter->writeAttribute('ht', PHPExcel_Shared_String::FormatNumber($rowDimension->getRowHeight())); + } + + // Row visibility + if ($rowDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Collapsed + if ($rowDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($rowDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); + } + + // Style + if ($rowDimension->getXfIndex() !== null) { + $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); + $objWriter->writeAttribute('customFormat', '1'); + } + + // Write cells + if (isset($cellsByRow[$currentRow])) { + foreach($cellsByRow[$currentRow] as $cellAddress) { + // Write cell + $this->_writeCell($objWriter, $pSheet, $cellAddress, $pStringTable, $aFlippedStringTable); + } + } + + // End row + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Cell + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param PHPExcel_Cell $pCellAddress Cell Address + * @param string[] $pStringTable String table + * @param string[] $pFlippedStringTable String table (flipped), for faster index searching + * @throws PHPExcel_Writer_Exception + */ + private function _writeCell(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pCellAddress = null, $pStringTable = null, $pFlippedStringTable = null) + { + if (is_array($pStringTable) && is_array($pFlippedStringTable)) { + // Cell + $pCell = $pSheet->getCell($pCellAddress); + $objWriter->startElement('c'); + $objWriter->writeAttribute('r', $pCellAddress); + + // Sheet styles + if ($pCell->getXfIndex() != '') { + $objWriter->writeAttribute('s', $pCell->getXfIndex()); + } + + // If cell value is supplied, write cell value + $cellValue = $pCell->getValue(); + if (is_object($cellValue) || $cellValue !== '') { + // Map type + $mappedType = $pCell->getDataType(); + + // Write data type depending on its type + switch (strtolower($mappedType)) { + case 'inlinestr': // Inline string + case 's': // String + case 'b': // Boolean + $objWriter->writeAttribute('t', $mappedType); + break; + case 'f': // Formula + $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ? + $pCell->getCalculatedValue() : + $cellValue; + if (is_string($calculatedValue)) { + $objWriter->writeAttribute('t', 'str'); + } + break; + case 'e': // Error + $objWriter->writeAttribute('t', $mappedType); + } + + // Write data depending on its type + switch (strtolower($mappedType)) { + case 'inlinestr': // Inline string + if (! $cellValue instanceof PHPExcel_RichText) { + $objWriter->writeElement('t', PHPExcel_Shared_String::ControlCharacterPHP2OOXML( htmlspecialchars($cellValue) ) ); + } else if ($cellValue instanceof PHPExcel_RichText) { + $objWriter->startElement('is'); + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue); + $objWriter->endElement(); + } + + break; + case 's': // String + if (! $cellValue instanceof PHPExcel_RichText) { + if (isset($pFlippedStringTable[$cellValue])) { + $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]); + } + } else if ($cellValue instanceof PHPExcel_RichText) { + $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]); + } + + break; + case 'f': // Formula + $attributes = $pCell->getFormulaAttributes(); + if($attributes['t'] == 'array') { + $objWriter->startElement('f'); + $objWriter->writeAttribute('t', 'array'); + $objWriter->writeAttribute('ref', $pCellAddress); + $objWriter->writeAttribute('aca', '1'); + $objWriter->writeAttribute('ca', '1'); + $objWriter->text(substr($cellValue, 1)); + $objWriter->endElement(); + } else { + $objWriter->writeElement('f', substr($cellValue, 1)); + } + if ($this->getParentWriter()->getOffice2003Compatibility() === false) { + if ($this->getParentWriter()->getPreCalculateFormulas()) { +// $calculatedValue = $pCell->getCalculatedValue(); + if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') { + $objWriter->writeElement('v', PHPExcel_Shared_String::FormatNumber($calculatedValue)); + } else { + $objWriter->writeElement('v', '0'); + } + } else { + $objWriter->writeElement('v', '0'); + } + } + break; + case 'n': // Numeric + // force point as decimal separator in case current locale uses comma + $objWriter->writeElement('v', str_replace(',', '.', $cellValue)); + break; + case 'b': // Boolean + $objWriter->writeElement('v', ($cellValue ? '1' : '0')); + break; + case 'e': // Error + if (substr($cellValue, 0, 1) == '=') { + $objWriter->writeElement('f', substr($cellValue, 1)); + $objWriter->writeElement('v', substr($cellValue, 1)); + } else { + $objWriter->writeElement('v', $cellValue); + } + + break; + } + } + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Drawings + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @throws PHPExcel_Writer_Exception + */ + private function _writeDrawings(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $includeCharts = FALSE) + { + $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0; + // If sheet contains drawings, add the relationships + if (($pSheet->getDrawingCollection()->count() > 0) || + ($chartCount > 0)) { + $objWriter->startElement('drawing'); + $objWriter->writeAttribute('r:id', 'rId1'); + $objWriter->endElement(); + } + } + + /** + * Write LegacyDrawing + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeLegacyDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // If sheet contains comments, add the relationships + if (count($pSheet->getComments()) > 0) { + $objWriter->startElement('legacyDrawing'); + $objWriter->writeAttribute('r:id', 'rId_comments_vml1'); + $objWriter->endElement(); + } + } + + /** + * Write LegacyDrawingHF + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeLegacyDrawingHF(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // If sheet contains images, add the relationships + if (count($pSheet->getHeaderFooter()->getImages()) > 0) { + $objWriter->startElement('legacyDrawingHF'); + $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1'); + $objWriter->endElement(); + } + } } diff --git a/Classes/PHPExcel/Writer/Excel2007/WriterPart.php b/Classes/PHPExcel/Writer/Excel2007/WriterPart.php index 4c2f9b4b..1ade577e 100644 --- a/Classes/PHPExcel/Writer/Excel2007/WriterPart.php +++ b/Classes/PHPExcel/Writer/Excel2007/WriterPart.php @@ -35,47 +35,47 @@ */ abstract class PHPExcel_Writer_Excel2007_WriterPart { - /** - * Parent IWriter object - * - * @var PHPExcel_Writer_IWriter - */ - private $_parentWriter; + /** + * Parent IWriter object + * + * @var PHPExcel_Writer_IWriter + */ + private $_parentWriter; - /** - * Set parent IWriter object - * - * @param PHPExcel_Writer_IWriter $pWriter - * @throws PHPExcel_Writer_Exception - */ - public function setParentWriter(PHPExcel_Writer_IWriter $pWriter = null) { - $this->_parentWriter = $pWriter; - } + /** + * Set parent IWriter object + * + * @param PHPExcel_Writer_IWriter $pWriter + * @throws PHPExcel_Writer_Exception + */ + public function setParentWriter(PHPExcel_Writer_IWriter $pWriter = null) { + $this->_parentWriter = $pWriter; + } - /** - * Get parent IWriter object - * - * @return PHPExcel_Writer_IWriter - * @throws PHPExcel_Writer_Exception - */ - public function getParentWriter() { - if (!is_null($this->_parentWriter)) { - return $this->_parentWriter; - } else { - throw new PHPExcel_Writer_Exception("No parent PHPExcel_Writer_IWriter assigned."); - } - } + /** + * Get parent IWriter object + * + * @return PHPExcel_Writer_IWriter + * @throws PHPExcel_Writer_Exception + */ + public function getParentWriter() { + if (!is_null($this->_parentWriter)) { + return $this->_parentWriter; + } else { + throw new PHPExcel_Writer_Exception("No parent PHPExcel_Writer_IWriter assigned."); + } + } - /** - * Set parent IWriter object - * - * @param PHPExcel_Writer_IWriter $pWriter - * @throws PHPExcel_Writer_Exception - */ - public function __construct(PHPExcel_Writer_IWriter $pWriter = null) { - if (!is_null($pWriter)) { - $this->_parentWriter = $pWriter; - } - } + /** + * Set parent IWriter object + * + * @param PHPExcel_Writer_IWriter $pWriter + * @throws PHPExcel_Writer_Exception + */ + public function __construct(PHPExcel_Writer_IWriter $pWriter = null) { + if (!is_null($pWriter)) { + $this->_parentWriter = $pWriter; + } + } } diff --git a/Classes/PHPExcel/Writer/Excel5.php b/Classes/PHPExcel/Writer/Excel5.php index 6875d9b2..63a4ca72 100644 --- a/Classes/PHPExcel/Writer/Excel5.php +++ b/Classes/PHPExcel/Writer/Excel5.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_Excel5 * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,915 +22,906 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## - */ - - -/** - * PHPExcel_Writer_Excel5 - * - * @category PHPExcel - * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * PHPExcel object - * - * @var PHPExcel - */ - private $_phpExcel; - - /** - * Total number of shared strings in workbook - * - * @var int - */ - private $_str_total = 0; - - /** - * Number of unique shared strings in workbook - * - * @var int - */ - private $_str_unique = 0; - - /** - * Array of unique shared strings in workbook - * - * @var array - */ - private $_str_table = array(); - - /** - * Color cache. Mapping between RGB value and color index. - * - * @var array - */ - private $_colors; - - /** - * Formula parser - * - * @var PHPExcel_Writer_Excel5_Parser - */ - private $_parser; - - /** - * Identifier clusters for drawings. Used in MSODRAWINGGROUP record. - * - * @var array - */ - private $_IDCLs; - - /** - * Basic OLE object summary information - * - * @var array - */ - private $_summaryInformation; - - /** - * Extended OLE object document summary information - * - * @var array - */ - private $_documentSummaryInformation; - - /** - * Create a new PHPExcel_Writer_Excel5 - * - * @param PHPExcel $phpExcel PHPExcel object - */ - public function __construct(PHPExcel $phpExcel) { - $this->_phpExcel = $phpExcel; - - $this->_parser = new PHPExcel_Writer_Excel5_Parser(); - } - - /** - * Save PHPExcel to file - * - * @param string $pFilename - * @throws PHPExcel_Writer_Exception - */ - public function save($pFilename = null) { - - // garbage collect - $this->_phpExcel->garbageCollect(); - - $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); - $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); - PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); - - // initialize colors array - $this->_colors = array(); - - // Initialise workbook writer - $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, - $this->_str_total, $this->_str_unique, $this->_str_table, - $this->_colors, $this->_parser); - - // Initialise worksheet writers - $countSheets = $this->_phpExcel->getSheetCount(); - for ($i = 0; $i < $countSheets; ++$i) { - $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique, - $this->_str_table, $this->_colors, - $this->_parser, - $this->_preCalculateFormulas, - $this->_phpExcel->getSheet($i)); - } - - // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook. - $this->_buildWorksheetEschers(); - $this->_buildWorkbookEscher(); - - // add 15 identical cell style Xfs - // for now, we use the first cellXf instead of cellStyleXf - $cellXfCollection = $this->_phpExcel->getCellXfCollection(); - for ($i = 0; $i < 15; ++$i) { - $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true); - } - - // add all the cell Xfs - foreach ($this->_phpExcel->getCellXfCollection() as $style) { - $this->_writerWorkbook->addXfWriter($style, false); - } - - // add fonts from rich text eleemnts - for ($i = 0; $i < $countSheets; ++$i) { - foreach ($this->_writerWorksheets[$i]->_phpSheet->getCellCollection() as $cellID) { - $cell = $this->_writerWorksheets[$i]->_phpSheet->getCell($cellID); - $cVal = $cell->getValue(); - if ($cVal instanceof PHPExcel_RichText) { - $elements = $cVal->getRichTextElements(); - foreach ($elements as $element) { - if ($element instanceof PHPExcel_RichText_Run) { - $font = $element->getFont(); - $this->_writerWorksheets[$i]->_fntHashIndex[$font->getHashCode()] = $this->_writerWorkbook->_addFont($font); - } - } - } - } - } - - // initialize OLE file - $workbookStreamName = 'Workbook'; - $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName)); - - // Write the worksheet streams before the global workbook stream, - // because the byte sizes of these are needed in the global workbook stream - $worksheetSizes = array(); - for ($i = 0; $i < $countSheets; ++$i) { - $this->_writerWorksheets[$i]->close(); - $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize; - } - - // add binary data for global workbook stream - $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes)); - - // add binary data for sheet streams - for ($i = 0; $i < $countSheets; ++$i) { - $OLE->append($this->_writerWorksheets[$i]->getData()); - } - - $this->_documentSummaryInformation = $this->_writeDocumentSummaryInformation(); - // initialize OLE Document Summary Information - if(isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)){ - $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation')); - $OLE_DocumentSummaryInformation->append($this->_documentSummaryInformation); - } - - $this->_summaryInformation = $this->_writeSummaryInformation(); - // initialize OLE Summary Information - if(isset($this->_summaryInformation) && !empty($this->_summaryInformation)){ - $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation')); - $OLE_SummaryInformation->append($this->_summaryInformation); - } - - // define OLE Parts - $arrRootData = array($OLE); - // initialize OLE Properties file - if(isset($OLE_SummaryInformation)){ - $arrRootData[] = $OLE_SummaryInformation; - } - // initialize OLE Extended Properties file - if(isset($OLE_DocumentSummaryInformation)){ - $arrRootData[] = $OLE_DocumentSummaryInformation; - } - - $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData); - // save the OLE file - $res = $root->save($pFilename); - - PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); - } - - /** - * Set temporary storage directory - * - * @deprecated - * @param string $pValue Temporary storage directory - * @throws PHPExcel_Writer_Exception when directory does not exist - * @return PHPExcel_Writer_Excel5 - */ - public function setTempDir($pValue = '') { - return $this; - } - - /** - * Build the Worksheet Escher objects - * - */ - private function _buildWorksheetEschers() - { - // 1-based index to BstoreContainer - $blipIndex = 0; - $lastReducedSpId = 0; - $lastSpId = 0; - - foreach ($this->_phpExcel->getAllsheets() as $sheet) { - // sheet index - $sheetIndex = $sheet->getParent()->getIndex($sheet); - - $escher = null; - - // check if there are any shapes for this sheet - $filterRange = $sheet->getAutoFilter()->getRange(); - if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) { - continue; - } - - // create intermediate Escher object - $escher = new PHPExcel_Shared_Escher(); - - // dgContainer - $dgContainer = new PHPExcel_Shared_Escher_DgContainer(); - - // set the drawing index (we use sheet index + 1) - $dgId = $sheet->getParent()->getIndex($sheet) + 1; - $dgContainer->setDgId($dgId); - $escher->setDgContainer($dgContainer); - - // spgrContainer - $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); - $dgContainer->setSpgrContainer($spgrContainer); - - // add one shape which is the group shape - $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); - $spContainer->setSpgr(true); - $spContainer->setSpType(0); - $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10); - $spgrContainer->addChild($spContainer); - - // add the shapes - - $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet - - foreach ($sheet->getDrawingCollection() as $drawing) { - ++$blipIndex; - - ++$countShapes[$sheetIndex]; - - // add the shape - $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); - - // set the shape type - $spContainer->setSpType(0x004B); - // set the shape flag - $spContainer->setSpFlag(0x02); - - // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) - $reducedSpId = $countShapes[$sheetIndex]; - $spId = $reducedSpId - | ($sheet->getParent()->getIndex($sheet) + 1) << 10; - $spContainer->setSpId($spId); - - // keep track of last reducedSpId - $lastReducedSpId = $reducedSpId; - - // keep track of last spId - $lastSpId = $spId; - - // set the BLIP index - $spContainer->setOPT(0x4104, $blipIndex); - - // set coordinates and offsets, client anchor - $coordinates = $drawing->getCoordinates(); - $offsetX = $drawing->getOffsetX(); - $offsetY = $drawing->getOffsetY(); - $width = $drawing->getWidth(); - $height = $drawing->getHeight(); - - $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height); - - $spContainer->setStartCoordinates($twoAnchor['startCoordinates']); - $spContainer->setStartOffsetX($twoAnchor['startOffsetX']); - $spContainer->setStartOffsetY($twoAnchor['startOffsetY']); - $spContainer->setEndCoordinates($twoAnchor['endCoordinates']); - $spContainer->setEndOffsetX($twoAnchor['endOffsetX']); - $spContainer->setEndOffsetY($twoAnchor['endOffsetY']); - - $spgrContainer->addChild($spContainer); - } - - // AutoFilters - if(!empty($filterRange)){ - $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange); - $iNumColStart = $rangeBounds[0][0]; - $iNumColEnd = $rangeBounds[1][0]; - - $iInc = $iNumColStart; - while($iInc <= $iNumColEnd){ - ++$countShapes[$sheetIndex]; - - // create an Drawing Object for the dropdown - $oDrawing = new PHPExcel_Worksheet_BaseDrawing(); - // get the coordinates of drawing - $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1]; - $oDrawing->setCoordinates($cDrawing); - $oDrawing->setWorksheet($sheet); - - // add the shape - $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); - // set the shape type - $spContainer->setSpType(0x00C9); - // set the shape flag - $spContainer->setSpFlag(0x01); - - // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) - $reducedSpId = $countShapes[$sheetIndex]; - $spId = $reducedSpId - | ($sheet->getParent()->getIndex($sheet) + 1) << 10; - $spContainer->setSpId($spId); - - // keep track of last reducedSpId - $lastReducedSpId = $reducedSpId; - - // keep track of last spId - $lastSpId = $spId; - - $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping - $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape - $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest - $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash - $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint - - // set coordinates and offsets, client anchor - $endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1)); - $endCoordinates .= $rangeBounds[0][1] + 1; - - $spContainer->setStartCoordinates($cDrawing); - $spContainer->setStartOffsetX(0); - $spContainer->setStartOffsetY(0); - $spContainer->setEndCoordinates($endCoordinates); - $spContainer->setEndOffsetX(0); - $spContainer->setEndOffsetY(0); - - $spgrContainer->addChild($spContainer); - $iInc++; - } - } - - // identifier clusters, used for workbook Escher object - $this->_IDCLs[$dgId] = $lastReducedSpId; - - // set last shape index - $dgContainer->setLastSpId($lastSpId); - - // set the Escher object - $this->_writerWorksheets[$sheetIndex]->setEscher($escher); - } - } - - /** - * Build the Escher object corresponding to the MSODRAWINGGROUP record - */ - private function _buildWorkbookEscher() - { - $escher = null; - - // any drawings in this workbook? - $found = false; - foreach ($this->_phpExcel->getAllSheets() as $sheet) { - if (count($sheet->getDrawingCollection()) > 0) { - $found = true; - break; - } - } - - // nothing to do if there are no drawings - if (!$found) { - return; - } - - // if we reach here, then there are drawings in the workbook - $escher = new PHPExcel_Shared_Escher(); - - // dggContainer - $dggContainer = new PHPExcel_Shared_Escher_DggContainer(); - $escher->setDggContainer($dggContainer); - - // set IDCLs (identifier clusters) - $dggContainer->setIDCLs($this->_IDCLs); - - // this loop is for determining maximum shape identifier of all drawing - $spIdMax = 0; - $totalCountShapes = 0; - $countDrawings = 0; - - foreach ($this->_phpExcel->getAllsheets() as $sheet) { - $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet - - if (count($sheet->getDrawingCollection()) > 0) { - ++$countDrawings; - - foreach ($sheet->getDrawingCollection() as $drawing) { - ++$sheetCountShapes; - ++$totalCountShapes; - - $spId = $sheetCountShapes - | ($this->_phpExcel->getIndex($sheet) + 1) << 10; - $spIdMax = max($spId, $spIdMax); - } - } - } - - $dggContainer->setSpIdMax($spIdMax + 1); - $dggContainer->setCDgSaved($countDrawings); - $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing - - // bstoreContainer - $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); - $dggContainer->setBstoreContainer($bstoreContainer); - - // the BSE's (all the images) - foreach ($this->_phpExcel->getAllsheets() as $sheet) { - foreach ($sheet->getDrawingCollection() as $drawing) { - if ($drawing instanceof PHPExcel_Worksheet_Drawing) { - - $filename = $drawing->getPath(); - - list($imagesx, $imagesy, $imageFormat) = getimagesize($filename); - - switch ($imageFormat) { - - case 1: // GIF, not supported by BIFF8, we convert to PNG - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; - ob_start(); - imagepng(imagecreatefromgif($filename)); - $blipData = ob_get_contents(); - ob_end_clean(); - break; - - case 2: // JPEG - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; - $blipData = file_get_contents($filename); - break; - - case 3: // PNG - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; - $blipData = file_get_contents($filename); - break; - - case 6: // Windows DIB (BMP), we convert to PNG - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; - ob_start(); - imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename)); - $blipData = ob_get_contents(); - ob_end_clean(); - break; - - default: continue 2; - - } - - $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); - $blip->setData($blipData); - - $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); - $BSE->setBlipType($blipType); - $BSE->setBlip($blip); - - $bstoreContainer->addBSE($BSE); - - } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) { - - switch ($drawing->getRenderingFunction()) { - - case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG: - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; - $renderingFunction = 'imagejpeg'; - break; - - case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF: - case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG: - case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT: - $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; - $renderingFunction = 'imagepng'; - break; - - } - - ob_start(); - call_user_func($renderingFunction, $drawing->getImageResource()); - $blipData = ob_get_contents(); - ob_end_clean(); - - $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); - $blip->setData($blipData); - - $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); - $BSE->setBlipType($blipType); - $BSE->setBlip($blip); - - $bstoreContainer->addBSE($BSE); - } - } - } - - // Set the Escher object - $this->_writerWorkbook->setEscher($escher); - } - - /** - * Build the OLE Part for DocumentSummary Information - * @return string - */ - private function _writeDocumentSummaryInformation(){ - - // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) - $data = pack('v', 0xFFFE); - // offset: 2; size: 2; - $data .= pack('v', 0x0000); - // offset: 4; size: 2; OS version - $data .= pack('v', 0x0106); - // offset: 6; size: 2; OS indicator - $data .= pack('v', 0x0002); - // offset: 8; size: 16 - $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); - // offset: 24; size: 4; section count - $data .= pack('V', 0x0001); - - // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae - $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9); - // offset: 44; size: 4; offset of the start - $data .= pack('V', 0x30); - - // SECTION - $dataSection = array(); - $dataSection_NumProps = 0; - $dataSection_Summary = ''; - $dataSection_Content = ''; - - // GKPIDDSI_CODEPAGE: CodePage - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer - 'data' => array('data' => 1252)); - $dataSection_NumProps++; - - // GKPIDDSI_CATEGORY : Category - if($this->_phpExcel->getProperties()->getCategory()){ - $dataProp = $this->_phpExcel->getProperties()->getCategory(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // GKPIDDSI_VERSION :Version of the application that wrote the property storage - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x17), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x03), - 'data' => array('pack' => 'V', 'data' => 0x000C0000)); - $dataSection_NumProps++; - // GKPIDDSI_SCALE : FALSE - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0B), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x0B), - 'data' => array('data' => false)); - $dataSection_NumProps++; - // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x10), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x0B), - 'data' => array('data' => false)); - $dataSection_NumProps++; - // GKPIDDSI_SHAREDOC : FALSE - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x0B), - 'data' => array('data' => false)); - $dataSection_NumProps++; - // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x16), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x0B), - 'data' => array('data' => false)); - $dataSection_NumProps++; - - // GKPIDDSI_DOCSPARTS - // MS-OSHARED p75 (2.3.3.2.2.1) - // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9) - // cElements - $dataProp = pack('v', 0x0001); - $dataProp .= pack('v', 0x0000); - // array of UnalignedLpstr - // cch - $dataProp .= pack('v', 0x000A); - $dataProp .= pack('v', 0x0000); - // value - $dataProp .= 'Worksheet'.chr(0); - - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x101E), - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - - // GKPIDDSI_HEADINGPAIR - // VtVecHeadingPairValue - // cElements - $dataProp = pack('v', 0x0002); - $dataProp .= pack('v', 0x0000); - // Array of vtHeadingPair - // vtUnalignedString - headingString - // stringType - $dataProp .= pack('v', 0x001E); - // padding - $dataProp .= pack('v', 0x0000); - // UnalignedLpstr - // cch - $dataProp .= pack('v', 0x0013); - $dataProp .= pack('v', 0x0000); - // value - $dataProp .= 'Feuilles de calcul'; - // vtUnalignedString - headingParts - // wType : 0x0003 = 32 bit signed integer - $dataProp .= pack('v', 0x0300); - // padding - $dataProp .= pack('v', 0x0000); - // value - $dataProp .= pack('v', 0x0100); - $dataProp .= pack('v', 0x0000); - $dataProp .= pack('v', 0x0000); - $dataProp .= pack('v', 0x0000); - - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x100C), - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + /** + * PHPExcel object + * + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Total number of shared strings in workbook + * + * @var int + */ + private $_str_total = 0; + + /** + * Number of unique shared strings in workbook + * + * @var int + */ + private $_str_unique = 0; + + /** + * Array of unique shared strings in workbook + * + * @var array + */ + private $_str_table = array(); + + /** + * Color cache. Mapping between RGB value and color index. + * + * @var array + */ + private $_colors; + + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * Identifier clusters for drawings. Used in MSODRAWINGGROUP record. + * + * @var array + */ + private $_IDCLs; + + /** + * Basic OLE object summary information + * + * @var array + */ + private $_summaryInformation; + + /** + * Extended OLE object document summary information + * + * @var array + */ + private $_documentSummaryInformation; + + /** + * Create a new PHPExcel_Writer_Excel5 + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) { + $this->_phpExcel = $phpExcel; + + $this->_parser = new PHPExcel_Writer_Excel5_Parser(); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + + // garbage collect + $this->_phpExcel->garbageCollect(); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + + // initialize colors array + $this->_colors = array(); + + // Initialise workbook writer + $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, + $this->_str_total, $this->_str_unique, $this->_str_table, + $this->_colors, $this->_parser); + + // Initialise worksheet writers + $countSheets = $this->_phpExcel->getSheetCount(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique, + $this->_str_table, $this->_colors, + $this->_parser, + $this->_preCalculateFormulas, + $this->_phpExcel->getSheet($i)); + } + + // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook. + $this->_buildWorksheetEschers(); + $this->_buildWorkbookEscher(); + + // add 15 identical cell style Xfs + // for now, we use the first cellXf instead of cellStyleXf + $cellXfCollection = $this->_phpExcel->getCellXfCollection(); + for ($i = 0; $i < 15; ++$i) { + $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true); + } + + // add all the cell Xfs + foreach ($this->_phpExcel->getCellXfCollection() as $style) { + $this->_writerWorkbook->addXfWriter($style, false); + } + + // add fonts from rich text eleemnts + for ($i = 0; $i < $countSheets; ++$i) { + foreach ($this->_writerWorksheets[$i]->_phpSheet->getCellCollection() as $cellID) { + $cell = $this->_writerWorksheets[$i]->_phpSheet->getCell($cellID); + $cVal = $cell->getValue(); + if ($cVal instanceof PHPExcel_RichText) { + $elements = $cVal->getRichTextElements(); + foreach ($elements as $element) { + if ($element instanceof PHPExcel_RichText_Run) { + $font = $element->getFont(); + $this->_writerWorksheets[$i]->_fntHashIndex[$font->getHashCode()] = $this->_writerWorkbook->_addFont($font); + } + } + } + } + } + + // initialize OLE file + $workbookStreamName = 'Workbook'; + $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName)); + + // Write the worksheet streams before the global workbook stream, + // because the byte sizes of these are needed in the global workbook stream + $worksheetSizes = array(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i]->close(); + $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize; + } + + // add binary data for global workbook stream + $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes)); + + // add binary data for sheet streams + for ($i = 0; $i < $countSheets; ++$i) { + $OLE->append($this->_writerWorksheets[$i]->getData()); + } + + $this->_documentSummaryInformation = $this->_writeDocumentSummaryInformation(); + // initialize OLE Document Summary Information + if(isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)){ + $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation')); + $OLE_DocumentSummaryInformation->append($this->_documentSummaryInformation); + } + + $this->_summaryInformation = $this->_writeSummaryInformation(); + // initialize OLE Summary Information + if(isset($this->_summaryInformation) && !empty($this->_summaryInformation)){ + $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation')); + $OLE_SummaryInformation->append($this->_summaryInformation); + } + + // define OLE Parts + $arrRootData = array($OLE); + // initialize OLE Properties file + if(isset($OLE_SummaryInformation)){ + $arrRootData[] = $OLE_SummaryInformation; + } + // initialize OLE Extended Properties file + if(isset($OLE_DocumentSummaryInformation)){ + $arrRootData[] = $OLE_DocumentSummaryInformation; + } + + $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData); + // save the OLE file + $res = $root->save($pFilename); + + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Set temporary storage directory + * + * @deprecated + * @param string $pValue Temporary storage directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel5 + */ + public function setTempDir($pValue = '') { + return $this; + } + + /** + * Build the Worksheet Escher objects + * + */ + private function _buildWorksheetEschers() + { + // 1-based index to BstoreContainer + $blipIndex = 0; + $lastReducedSpId = 0; + $lastSpId = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + // sheet index + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + $escher = null; + + // check if there are any shapes for this sheet + $filterRange = $sheet->getAutoFilter()->getRange(); + if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) { + continue; + } + + // create intermediate Escher object + $escher = new PHPExcel_Shared_Escher(); + + // dgContainer + $dgContainer = new PHPExcel_Shared_Escher_DgContainer(); + + // set the drawing index (we use sheet index + 1) + $dgId = $sheet->getParent()->getIndex($sheet) + 1; + $dgContainer->setDgId($dgId); + $escher->setDgContainer($dgContainer); + + // spgrContainer + $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); + $dgContainer->setSpgrContainer($spgrContainer); + + // add one shape which is the group shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + $spContainer->setSpgr(true); + $spContainer->setSpType(0); + $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10); + $spgrContainer->addChild($spContainer); + + // add the shapes + + $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$blipIndex; + + ++$countShapes[$sheetIndex]; + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + + // set the shape type + $spContainer->setSpType(0x004B); + // set the shape flag + $spContainer->setSpFlag(0x02); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + // set the BLIP index + $spContainer->setOPT(0x4104, $blipIndex); + + // set coordinates and offsets, client anchor + $coordinates = $drawing->getCoordinates(); + $offsetX = $drawing->getOffsetX(); + $offsetY = $drawing->getOffsetY(); + $width = $drawing->getWidth(); + $height = $drawing->getHeight(); + + $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height); + + $spContainer->setStartCoordinates($twoAnchor['startCoordinates']); + $spContainer->setStartOffsetX($twoAnchor['startOffsetX']); + $spContainer->setStartOffsetY($twoAnchor['startOffsetY']); + $spContainer->setEndCoordinates($twoAnchor['endCoordinates']); + $spContainer->setEndOffsetX($twoAnchor['endOffsetX']); + $spContainer->setEndOffsetY($twoAnchor['endOffsetY']); + + $spgrContainer->addChild($spContainer); + } + + // AutoFilters + if(!empty($filterRange)){ + $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange); + $iNumColStart = $rangeBounds[0][0]; + $iNumColEnd = $rangeBounds[1][0]; + + $iInc = $iNumColStart; + while($iInc <= $iNumColEnd){ + ++$countShapes[$sheetIndex]; + + // create an Drawing Object for the dropdown + $oDrawing = new PHPExcel_Worksheet_BaseDrawing(); + // get the coordinates of drawing + $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1]; + $oDrawing->setCoordinates($cDrawing); + $oDrawing->setWorksheet($sheet); + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + // set the shape type + $spContainer->setSpType(0x00C9); + // set the shape flag + $spContainer->setSpFlag(0x01); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping + $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape + $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest + $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash + $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint + + // set coordinates and offsets, client anchor + $endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1)); + $endCoordinates .= $rangeBounds[0][1] + 1; + + $spContainer->setStartCoordinates($cDrawing); + $spContainer->setStartOffsetX(0); + $spContainer->setStartOffsetY(0); + $spContainer->setEndCoordinates($endCoordinates); + $spContainer->setEndOffsetX(0); + $spContainer->setEndOffsetY(0); + + $spgrContainer->addChild($spContainer); + $iInc++; + } + } + + // identifier clusters, used for workbook Escher object + $this->_IDCLs[$dgId] = $lastReducedSpId; + + // set last shape index + $dgContainer->setLastSpId($lastSpId); + + // set the Escher object + $this->_writerWorksheets[$sheetIndex]->setEscher($escher); + } + } + + /** + * Build the Escher object corresponding to the MSODRAWINGGROUP record + */ + private function _buildWorkbookEscher() + { + $escher = null; + + // any drawings in this workbook? + $found = false; + foreach ($this->_phpExcel->getAllSheets() as $sheet) { + if (count($sheet->getDrawingCollection()) > 0) { + $found = true; + break; + } + } + + // nothing to do if there are no drawings + if (!$found) { + return; + } + + // if we reach here, then there are drawings in the workbook + $escher = new PHPExcel_Shared_Escher(); + + // dggContainer + $dggContainer = new PHPExcel_Shared_Escher_DggContainer(); + $escher->setDggContainer($dggContainer); + + // set IDCLs (identifier clusters) + $dggContainer->setIDCLs($this->_IDCLs); + + // this loop is for determining maximum shape identifier of all drawing + $spIdMax = 0; + $totalCountShapes = 0; + $countDrawings = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet + + if (count($sheet->getDrawingCollection()) > 0) { + ++$countDrawings; + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$sheetCountShapes; + ++$totalCountShapes; + + $spId = $sheetCountShapes + | ($this->_phpExcel->getIndex($sheet) + 1) << 10; + $spIdMax = max($spId, $spIdMax); + } + } + } + + $dggContainer->setSpIdMax($spIdMax + 1); + $dggContainer->setCDgSaved($countDrawings); + $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing + + // bstoreContainer + $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); + $dggContainer->setBstoreContainer($bstoreContainer); + + // the BSE's (all the images) + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + foreach ($sheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + + $filename = $drawing->getPath(); + + list($imagesx, $imagesy, $imageFormat) = getimagesize($filename); + + switch ($imageFormat) { + + case 1: // GIF, not supported by BIFF8, we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(imagecreatefromgif($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + case 2: // JPEG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $blipData = file_get_contents($filename); + break; + + case 3: // PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $blipData = file_get_contents($filename); + break; + + case 6: // Windows DIB (BMP), we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + default: continue 2; + + } + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + + } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) { + + switch ($drawing->getRenderingFunction()) { + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $renderingFunction = 'imagejpeg'; + break; + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $renderingFunction = 'imagepng'; + break; + + } + + ob_start(); + call_user_func($renderingFunction, $drawing->getImageResource()); + $blipData = ob_get_contents(); + ob_end_clean(); + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + } + } + } + + // Set the Escher object + $this->_writerWorkbook->setEscher($escher); + } + + /** + * Build the OLE Part for DocumentSummary Information + * @return string + */ + private function _writeDocumentSummaryInformation(){ + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae + $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // GKPIDDSI_CODEPAGE: CodePage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); $dataSection_NumProps++; - // 4 Section Length - // 4 Property count - // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) - $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; - foreach ($dataSection as $dataProp){ - // Summary - $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); - // Offset - $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); - // DataType - $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); - // Data - if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer - $dataSection_Content .= pack('V', $dataProp['data']['data']); + // GKPIDDSI_CATEGORY : Category + if($this->_phpExcel->getProperties()->getCategory()){ + $dataProp = $this->_phpExcel->getProperties()->getCategory(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // GKPIDDSI_VERSION :Version of the application that wrote the property storage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x17), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), + 'data' => array('pack' => 'V', 'data' => 0x000C0000)); + $dataSection_NumProps++; + // GKPIDDSI_SCALE : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0B), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x10), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_SHAREDOC : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x16), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; - $dataSection_Content_Offset += 4 + 4; - } - elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer - $dataSection_Content .= pack('V', $dataProp['data']['data']); + // GKPIDDSI_DOCSPARTS + // MS-OSHARED p75 (2.3.3.2.2.1) + // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9) + // cElements + $dataProp = pack('v', 0x0001); + $dataProp .= pack('v', 0x0000); + // array of UnalignedLpstr + // cch + $dataProp .= pack('v', 0x000A); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Worksheet'.chr(0); - $dataSection_Content_Offset += 4 + 4; - } - elseif($dataProp['type']['data'] == 0x0B){ // Boolean - if($dataProp['data']['data'] == false){ - $dataSection_Content .= pack('V', 0x0000); - } else { - $dataSection_Content .= pack('V', 0x0001); - } - $dataSection_Content_Offset += 4 + 4; - } - elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length - // Null-terminated string - $dataProp['data']['data'] .= chr(0); - $dataProp['data']['length'] += 1; - // Complete the string with null string for being a %4 - $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); - $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x101E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; - $dataSection_Content .= pack('V', $dataProp['data']['length']); - $dataSection_Content .= $dataProp['data']['data']; + // GKPIDDSI_HEADINGPAIR + // VtVecHeadingPairValue + // cElements + $dataProp = pack('v', 0x0002); + $dataProp .= pack('v', 0x0000); + // Array of vtHeadingPair + // vtUnalignedString - headingString + // stringType + $dataProp .= pack('v', 0x001E); + // padding + $dataProp .= pack('v', 0x0000); + // UnalignedLpstr + // cch + $dataProp .= pack('v', 0x0013); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Feuilles de calcul'; + // vtUnalignedString - headingParts + // wType : 0x0003 = 32 bit signed integer + $dataProp .= pack('v', 0x0300); + // padding + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= pack('v', 0x0100); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); - $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); - } - elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - $dataSection_Content .= $dataProp['data']['data']; + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x100C), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; - $dataSection_Content_Offset += 4 + 8; - } - else { - // Data Type Not Used at the moment - $dataSection_Content .= $dataProp['data']['data']; + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); - $dataSection_Content_Offset += 4 + $dataProp['data']['length']; - } - } - // Now $dataSection_Content_Offset contains the size of the content + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); - // section header - // offset: $secOffset; size: 4; section length - // + x Size of the content (summary + content) - $data .= pack('V', $dataSection_Content_Offset); - // offset: $secOffset+4; size: 4; property count - $data .= pack('V', $dataSection_NumProps); - // Section Summary - $data .= $dataSection_Summary; - // Section Content - $data .= $dataSection_Content; + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x0B){ // Boolean + if($dataProp['data']['data'] == false){ + $dataSection_Content .= pack('V', 0x0000); + } else { + $dataSection_Content .= pack('V', 0x0001); + } + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); - return $data; - } + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; - /** - * Build the OLE Part for Summary Information - * @return string - */ - private function _writeSummaryInformation(){ - // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) - $data = pack('v', 0xFFFE); - // offset: 2; size: 2; - $data .= pack('v', 0x0000); - // offset: 4; size: 2; OS version - $data .= pack('v', 0x0106); - // offset: 6; size: 2; OS indicator - $data .= pack('v', 0x0002); - // offset: 8; size: 16 - $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); - // offset: 24; size: 4; section count - $data .= pack('V', 0x0001); + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; - // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 - $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3); - // offset: 44; size: 4; offset of the start - $data .= pack('V', 0x30); + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + $dataSection_Content .= $dataProp['data']['data']; - // SECTION - $dataSection = array(); - $dataSection_NumProps = 0; - $dataSection_Summary = ''; - $dataSection_Content = ''; + $dataSection_Content_Offset += 4 + $dataProp['data']['length']; + } + } + // Now $dataSection_Content_Offset contains the size of the content - // CodePage : CP-1252 - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer - 'data' => array('data' => 1252)); - $dataSection_NumProps++; + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; - // Title - if($this->_phpExcel->getProperties()->getTitle()){ - $dataProp = $this->_phpExcel->getProperties()->getTitle(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Subject - if($this->_phpExcel->getProperties()->getSubject()){ - $dataProp = $this->_phpExcel->getProperties()->getSubject(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x03), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Author (Creator) - if($this->_phpExcel->getProperties()->getCreator()){ - $dataProp = $this->_phpExcel->getProperties()->getCreator(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x04), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Keywords - if($this->_phpExcel->getProperties()->getKeywords()){ - $dataProp = $this->_phpExcel->getProperties()->getKeywords(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x05), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Comments (Description) - if($this->_phpExcel->getProperties()->getDescription()){ - $dataProp = $this->_phpExcel->getProperties()->getDescription(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x06), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Last Saved By (LastModifiedBy) - if($this->_phpExcel->getProperties()->getLastModifiedBy()){ - $dataProp = $this->_phpExcel->getProperties()->getLastModifiedBy(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x08), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length - 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); - $dataSection_NumProps++; - } - // Created Date/Time - if($this->_phpExcel->getProperties()->getCreated()){ - $dataProp = $this->_phpExcel->getProperties()->getCreated(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); - $dataSection_NumProps++; - } - // Modified Date/Time - if($this->_phpExcel->getProperties()->getModified()){ - $dataProp = $this->_phpExcel->getProperties()->getModified(); - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); - $dataSection_NumProps++; - } - // Security - $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), - 'offset' => array('pack' => 'V'), - 'type' => array('pack' => 'V', 'data' => 0x03), // 4 byte signed integer - 'data' => array('data' => 0x00)); - $dataSection_NumProps++; + return $data; + } + + /** + * Build the OLE Part for Summary Information + * @return string + */ + private function _writeSummaryInformation(){ + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // CodePage : CP-1252 + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); + $dataSection_NumProps++; + + // Title + if($this->_phpExcel->getProperties()->getTitle()){ + $dataProp = $this->_phpExcel->getProperties()->getTitle(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Subject + if($this->_phpExcel->getProperties()->getSubject()){ + $dataProp = $this->_phpExcel->getProperties()->getSubject(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x03), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Author (Creator) + if($this->_phpExcel->getProperties()->getCreator()){ + $dataProp = $this->_phpExcel->getProperties()->getCreator(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x04), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Keywords + if($this->_phpExcel->getProperties()->getKeywords()){ + $dataProp = $this->_phpExcel->getProperties()->getKeywords(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x05), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Comments (Description) + if($this->_phpExcel->getProperties()->getDescription()){ + $dataProp = $this->_phpExcel->getProperties()->getDescription(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x06), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Last Saved By (LastModifiedBy) + if($this->_phpExcel->getProperties()->getLastModifiedBy()){ + $dataProp = $this->_phpExcel->getProperties()->getLastModifiedBy(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x08), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Created Date/Time + if($this->_phpExcel->getProperties()->getCreated()){ + $dataProp = $this->_phpExcel->getProperties()->getCreated(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Modified Date/Time + if($this->_phpExcel->getProperties()->getModified()){ + $dataProp = $this->_phpExcel->getProperties()->getModified(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Security + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), // 4 byte signed integer + 'data' => array('data' => 0x00)); + $dataSection_NumProps++; - // 4 Section Length - // 4 Property count - // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) - $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; - foreach ($dataSection as $dataProp){ - // Summary - $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); - // Offset - $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); - // DataType - $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); - // Data - if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer - $dataSection_Content .= pack('V', $dataProp['data']['data']); + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); - $dataSection_Content_Offset += 4 + 4; - } - elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer - $dataSection_Content .= pack('V', $dataProp['data']['data']); + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); - $dataSection_Content_Offset += 4 + 4; - } - elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length - // Null-terminated string - $dataProp['data']['data'] .= chr(0); - $dataProp['data']['length'] += 1; - // Complete the string with null string for being a %4 - $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); - $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); - $dataSection_Content .= pack('V', $dataProp['data']['length']); - $dataSection_Content .= $dataProp['data']['data']; + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; - $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); - } - elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - $dataSection_Content .= $dataProp['data']['data']; + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; - $dataSection_Content_Offset += 4 + 8; - } - else { - // Data Type Not Used at the moment - } - } - // Now $dataSection_Content_Offset contains the size of the content + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + } + } + // Now $dataSection_Content_Offset contains the size of the content - // section header - // offset: $secOffset; size: 4; section length - // + x Size of the content (summary + content) - $data .= pack('V', $dataSection_Content_Offset); - // offset: $secOffset+4; size: 4; property count - $data .= pack('V', $dataSection_NumProps); - // Section Summary - $data .= $dataSection_Summary; - // Section Content - $data .= $dataSection_Content; + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; - return $data; - } + return $data; + } } diff --git a/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php b/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php index 43eb5099..de062488 100644 --- a/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php +++ b/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -69,187 +69,187 @@ */ class PHPExcel_Writer_Excel5_BIFFwriter { - /** - * The byte order of this architecture. 0 => little endian, 1 => big endian - * @var integer - */ - private static $_byte_order; + /** + * The byte order of this architecture. 0 => little endian, 1 => big endian + * @var integer + */ + private static $_byte_order; - /** - * The string containing the data of the BIFF stream - * @var string - */ - public $_data; + /** + * The string containing the data of the BIFF stream + * @var string + */ + public $_data; - /** - * The size of the data in bytes. Should be the same as strlen($this->_data) - * @var integer - */ - public $_datasize; + /** + * The size of the data in bytes. Should be the same as strlen($this->_data) + * @var integer + */ + public $_datasize; - /** - * The maximum length for a BIFF record (excluding record header and length field). See _addContinue() - * @var integer - * @see _addContinue() - */ - public $_limit = 8224; + /** + * The maximum length for a BIFF record (excluding record header and length field). See _addContinue() + * @var integer + * @see _addContinue() + */ + public $_limit = 8224; - /** - * Constructor - */ - public function __construct() - { - $this->_data = ''; - $this->_datasize = 0; -// $this->_limit = 8224; - } + /** + * Constructor + */ + public function __construct() + { + $this->_data = ''; + $this->_datasize = 0; +// $this->_limit = 8224; + } - /** - * Determine the byte order and store it as class data to avoid - * recalculating it for each call to new(). - * - * @return int - */ - public static function getByteOrder() - { - if (!isset(self::$_byte_order)) { - // Check if "pack" gives the required IEEE 64bit float - $teststr = pack("d", 1.2345); - $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F); - if ($number == $teststr) { - $byte_order = 0; // Little Endian - } elseif ($number == strrev($teststr)){ - $byte_order = 1; // Big Endian - } else { - // Give up. I'll fix this in a later version. - throw new PHPExcel_Writer_Exception("Required floating point format not supported on this platform."); - } - self::$_byte_order = $byte_order; - } + /** + * Determine the byte order and store it as class data to avoid + * recalculating it for each call to new(). + * + * @return int + */ + public static function getByteOrder() + { + if (!isset(self::$_byte_order)) { + // Check if "pack" gives the required IEEE 64bit float + $teststr = pack("d", 1.2345); + $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F); + if ($number == $teststr) { + $byte_order = 0; // Little Endian + } elseif ($number == strrev($teststr)){ + $byte_order = 1; // Big Endian + } else { + // Give up. I'll fix this in a later version. + throw new PHPExcel_Writer_Exception("Required floating point format not supported on this platform."); + } + self::$_byte_order = $byte_order; + } - return self::$_byte_order; - } + return self::$_byte_order; + } - /** - * General storage function - * - * @param string $data binary data to append - * @access private - */ - function _append($data) - { - if (strlen($data) - 4 > $this->_limit) { - $data = $this->_addContinue($data); - } - $this->_data .= $data; - $this->_datasize += strlen($data); - } + /** + * General storage function + * + * @param string $data binary data to append + * @access private + */ + function _append($data) + { + if (strlen($data) - 4 > $this->_limit) { + $data = $this->_addContinue($data); + } + $this->_data .= $data; + $this->_datasize += strlen($data); + } - /** - * General storage function like _append, but returns string instead of modifying $this->_data - * - * @param string $data binary data to write - * @return string - */ - public function writeData($data) - { - if (strlen($data) - 4 > $this->_limit) { - $data = $this->_addContinue($data); - } - $this->_datasize += strlen($data); + /** + * General storage function like _append, but returns string instead of modifying $this->_data + * + * @param string $data binary data to write + * @return string + */ + public function writeData($data) + { + if (strlen($data) - 4 > $this->_limit) { + $data = $this->_addContinue($data); + } + $this->_datasize += strlen($data); - return $data; - } + return $data; + } - /** - * Writes Excel BOF record to indicate the beginning of a stream or - * sub-stream in the BIFF file. - * - * @param integer $type Type of BIFF file to write: 0x0005 Workbook, - * 0x0010 Worksheet. - * @access private - */ - function _storeBof($type) - { - $record = 0x0809; // Record identifier (BIFF5-BIFF8) - $length = 0x0010; + /** + * Writes Excel BOF record to indicate the beginning of a stream or + * sub-stream in the BIFF file. + * + * @param integer $type Type of BIFF file to write: 0x0005 Workbook, + * 0x0010 Worksheet. + * @access private + */ + function _storeBof($type) + { + $record = 0x0809; // Record identifier (BIFF5-BIFF8) + $length = 0x0010; - // by inspection of real files, MS Office Excel 2007 writes the following - $unknown = pack("VV", 0x000100D1, 0x00000406); + // by inspection of real files, MS Office Excel 2007 writes the following + $unknown = pack("VV", 0x000100D1, 0x00000406); - $build = 0x0DBB; // Excel 97 - $year = 0x07CC; // Excel 97 + $build = 0x0DBB; // Excel 97 + $year = 0x07CC; // Excel 97 - $version = 0x0600; // BIFF8 + $version = 0x0600; // BIFF8 - $header = pack("vv", $record, $length); - $data = pack("vvvv", $version, $type, $build, $year); - $this->_append($header . $data . $unknown); - } + $header = pack("vv", $record, $length); + $data = pack("vvvv", $version, $type, $build, $year); + $this->_append($header . $data . $unknown); + } - /** - * Writes Excel EOF record to indicate the end of a BIFF stream. - * - * @access private - */ - function _storeEof() - { - $record = 0x000A; // Record identifier - $length = 0x0000; // Number of bytes to follow + /** + * Writes Excel EOF record to indicate the end of a BIFF stream. + * + * @access private + */ + function _storeEof() + { + $record = 0x000A; // Record identifier + $length = 0x0000; // Number of bytes to follow - $header = pack("vv", $record, $length); - $this->_append($header); - } + $header = pack("vv", $record, $length); + $this->_append($header); + } - /** - * Writes Excel EOF record to indicate the end of a BIFF stream. - * - * @access private - */ - public function writeEof() - { - $record = 0x000A; // Record identifier - $length = 0x0000; // Number of bytes to follow - $header = pack("vv", $record, $length); - return $this->writeData($header); - } + /** + * Writes Excel EOF record to indicate the end of a BIFF stream. + * + * @access private + */ + public function writeEof() + { + $record = 0x000A; // Record identifier + $length = 0x0000; // Number of bytes to follow + $header = pack("vv", $record, $length); + return $this->writeData($header); + } - /** - * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In - * Excel 97 the limit is 8228 bytes. Records that are longer than these limits - * must be split up into CONTINUE blocks. - * - * This function takes a long BIFF record and inserts CONTINUE records as - * necessary. - * - * @param string $data The original binary data to be written - * @return string A very convenient string of continue blocks - * @access private - */ - function _addContinue($data) - { - $limit = $this->_limit; - $record = 0x003C; // Record identifier + /** + * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In + * Excel 97 the limit is 8228 bytes. Records that are longer than these limits + * must be split up into CONTINUE blocks. + * + * This function takes a long BIFF record and inserts CONTINUE records as + * necessary. + * + * @param string $data The original binary data to be written + * @return string A very convenient string of continue blocks + * @access private + */ + function _addContinue($data) + { + $limit = $this->_limit; + $record = 0x003C; // Record identifier - // The first 2080/8224 bytes remain intact. However, we have to change - // the length field of the record. - $tmp = substr($data, 0, 2) . pack("v", $limit) . substr($data, 4, $limit); + // The first 2080/8224 bytes remain intact. However, we have to change + // the length field of the record. + $tmp = substr($data, 0, 2) . pack("v", $limit) . substr($data, 4, $limit); - $header = pack("vv", $record, $limit); // Headers for continue records + $header = pack("vv", $record, $limit); // Headers for continue records - // Retrieve chunks of 2080/8224 bytes +4 for the header. - $data_length = strlen($data); - for ($i = $limit + 4; $i < ($data_length - $limit); $i += $limit) { - $tmp .= $header; - $tmp .= substr($data, $i, $limit); - } + // Retrieve chunks of 2080/8224 bytes +4 for the header. + $data_length = strlen($data); + for ($i = $limit + 4; $i < ($data_length - $limit); $i += $limit) { + $tmp .= $header; + $tmp .= substr($data, $i, $limit); + } - // Retrieve the last chunk of data - $header = pack("vv", $record, strlen($data) - $i); - $tmp .= $header; - $tmp .= substr($data, $i, strlen($data) - $i); + // Retrieve the last chunk of data + $header = pack("vv", $record, strlen($data) - $i); + $tmp .= $header; + $tmp .= substr($data, $i, strlen($data) - $i); - return $tmp; - } + return $tmp; + } } diff --git a/Classes/PHPExcel/Writer/Excel5/Escher.php b/Classes/PHPExcel/Writer/Excel5/Escher.php index a9007867..9b8ae871 100644 --- a/Classes/PHPExcel/Writer/Excel5/Escher.php +++ b/Classes/PHPExcel/Writer/Excel5/Escher.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,503 +35,503 @@ */ class PHPExcel_Writer_Excel5_Escher { - /** - * The object we are writing - */ - private $_object; - - /** - * The written binary data - */ - private $_data; - - /** - * Shape offsets. Positions in binary stream where a new shape record begins - * - * @var array - */ - private $_spOffsets; - - /** - * Shape types. - * - * @var array - */ - private $_spTypes; - - /** - * Constructor - * - * @param mixed - */ - public function __construct($object) - { - $this->_object = $object; - } - - /** - * Process the object to be written - */ - public function close() - { - // initialize - $this->_data = ''; - - switch (get_class($this->_object)) { - - case 'PHPExcel_Shared_Escher': - if ($dggContainer = $this->_object->getDggContainer()) { - $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer); - $this->_data = $writer->close(); - } else if ($dgContainer = $this->_object->getDgContainer()) { - $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer); - $this->_data = $writer->close(); - $this->_spOffsets = $writer->getSpOffsets(); - $this->_spTypes = $writer->getSpTypes(); - } - break; - - case 'PHPExcel_Shared_Escher_DggContainer': - // this is a container record - - // initialize - $innerData = ''; - - // write the dgg - $recVer = 0x0; - $recInstance = 0x0000; - $recType = 0xF006; - - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; - - // dgg data - $dggData = - pack('VVVV' - , $this->_object->getSpIdMax() // maximum shape identifier increased by one - , $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one - , $this->_object->getCSpSaved() - , $this->_object->getCDgSaved() // count total number of drawings saved - ); - - // add file identifier clusters (one per drawing) - $IDCLs = $this->_object->getIDCLs(); - - foreach ($IDCLs as $dgId => $maxReducedSpId) { - $dggData .= pack('VV', $dgId, $maxReducedSpId + 1); - } - - $header = pack('vvV', $recVerInstance, $recType, strlen($dggData)); - $innerData .= $header . $dggData; - - // write the bstoreContainer - if ($bstoreContainer = $this->_object->getBstoreContainer()) { - $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer); - $innerData .= $writer->close(); - } - - // write the record - $recVer = 0xF; - $recInstance = 0x0000; - $recType = 0xF000; - $length = strlen($innerData); - - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; - - $header = pack('vvV', $recVerInstance, $recType, $length); - - $this->_data = $header . $innerData; - break; - - case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer': - // this is a container record - - // initialize - $innerData = ''; - - // treat the inner data - if ($BSECollection = $this->_object->getBSECollection()) { - foreach ($BSECollection as $BSE) { - $writer = new PHPExcel_Writer_Excel5_Escher($BSE); - $innerData .= $writer->close(); - } - } - - // write the record - $recVer = 0xF; - $recInstance = count($this->_object->getBSECollection()); - $recType = 0xF001; - $length = strlen($innerData); + /** + * The object we are writing + */ + private $_object; + + /** + * The written binary data + */ + private $_data; + + /** + * Shape offsets. Positions in binary stream where a new shape record begins + * + * @var array + */ + private $_spOffsets; + + /** + * Shape types. + * + * @var array + */ + private $_spTypes; + + /** + * Constructor + * + * @param mixed + */ + public function __construct($object) + { + $this->_object = $object; + } + + /** + * Process the object to be written + */ + public function close() + { + // initialize + $this->_data = ''; + + switch (get_class($this->_object)) { + + case 'PHPExcel_Shared_Escher': + if ($dggContainer = $this->_object->getDggContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer); + $this->_data = $writer->close(); + } else if ($dgContainer = $this->_object->getDgContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer); + $this->_data = $writer->close(); + $this->_spOffsets = $writer->getSpOffsets(); + $this->_spTypes = $writer->getSpTypes(); + } + break; + + case 'PHPExcel_Shared_Escher_DggContainer': + // this is a container record + + // initialize + $innerData = ''; + + // write the dgg + $recVer = 0x0; + $recInstance = 0x0000; + $recType = 0xF006; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + // dgg data + $dggData = + pack('VVVV' + , $this->_object->getSpIdMax() // maximum shape identifier increased by one + , $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one + , $this->_object->getCSpSaved() + , $this->_object->getCDgSaved() // count total number of drawings saved + ); + + // add file identifier clusters (one per drawing) + $IDCLs = $this->_object->getIDCLs(); + + foreach ($IDCLs as $dgId => $maxReducedSpId) { + $dggData .= pack('VV', $dgId, $maxReducedSpId + 1); + } + + $header = pack('vvV', $recVerInstance, $recType, strlen($dggData)); + $innerData .= $header . $dggData; + + // write the bstoreContainer + if ($bstoreContainer = $this->_object->getBstoreContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer); + $innerData .= $writer->close(); + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF000; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer': + // this is a container record + + // initialize + $innerData = ''; + + // treat the inner data + if ($BSECollection = $this->_object->getBSECollection()) { + foreach ($BSECollection as $BSE) { + $writer = new PHPExcel_Writer_Excel5_Escher($BSE); + $innerData .= $writer->close(); + } + } + + // write the record + $recVer = 0xF; + $recInstance = count($this->_object->getBSECollection()); + $recType = 0xF001; + $length = strlen($innerData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header . $innerData; - break; + $this->_data = $header . $innerData; + break; - case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE': - // this is a semi-container record + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE': + // this is a semi-container record - // initialize - $innerData = ''; + // initialize + $innerData = ''; - // here we treat the inner data - if ($blip = $this->_object->getBlip()) { - $writer = new PHPExcel_Writer_Excel5_Escher($blip); - $innerData .= $writer->close(); - } + // here we treat the inner data + if ($blip = $this->_object->getBlip()) { + $writer = new PHPExcel_Writer_Excel5_Escher($blip); + $innerData .= $writer->close(); + } - // initialize - $data = ''; + // initialize + $data = ''; - $btWin32 = $this->_object->getBlipType(); - $btMacOS = $this->_object->getBlipType(); - $data .= pack('CC', $btWin32, $btMacOS); + $btWin32 = $this->_object->getBlipType(); + $btMacOS = $this->_object->getBlipType(); + $data .= pack('CC', $btWin32, $btMacOS); - $rgbUid = pack('VVVV', 0,0,0,0); // todo - $data .= $rgbUid; + $rgbUid = pack('VVVV', 0,0,0,0); // todo + $data .= $rgbUid; - $tag = 0; - $size = strlen($innerData); - $cRef = 1; - $foDelay = 0; //todo - $unused1 = 0x0; - $cbName = 0x0; - $unused2 = 0x0; - $unused3 = 0x0; - $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3); + $tag = 0; + $size = strlen($innerData); + $cRef = 1; + $foDelay = 0; //todo + $unused1 = 0x0; + $cbName = 0x0; + $unused2 = 0x0; + $unused3 = 0x0; + $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3); - $data .= $innerData; + $data .= $innerData; - // write the record - $recVer = 0x2; - $recInstance = $this->_object->getBlipType(); - $recType = 0xF007; - $length = strlen($data); + // write the record + $recVer = 0x2; + $recInstance = $this->_object->getBlipType(); + $recType = 0xF007; + $length = strlen($data); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header; + $this->_data = $header; - $this->_data .= $data; - break; + $this->_data .= $data; + break; - case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip': - // this is an atom record + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip': + // this is an atom record - // write the record - switch ($this->_object->getParent()->getBlipType()) { + // write the record + switch ($this->_object->getParent()->getBlipType()) { - case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: - // initialize - $innerData = ''; + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: + // initialize + $innerData = ''; - $rgbUid1 = pack('VVVV', 0,0,0,0); // todo - $innerData .= $rgbUid1; + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; - $tag = 0xFF; // todo - $innerData .= pack('C', $tag); + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); - $innerData .= $this->_object->getData(); + $innerData .= $this->_object->getData(); - $recVer = 0x0; - $recInstance = 0x46A; - $recType = 0xF01D; - $length = strlen($innerData); + $recVer = 0x0; + $recInstance = 0x46A; + $recType = 0xF01D; + $length = strlen($innerData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header; + $this->_data = $header; - $this->_data .= $innerData; - break; + $this->_data .= $innerData; + break; - case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: - // initialize - $innerData = ''; + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: + // initialize + $innerData = ''; - $rgbUid1 = pack('VVVV', 0,0,0,0); // todo - $innerData .= $rgbUid1; + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; - $tag = 0xFF; // todo - $innerData .= pack('C', $tag); + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); - $innerData .= $this->_object->getData(); + $innerData .= $this->_object->getData(); - $recVer = 0x0; - $recInstance = 0x6E0; - $recType = 0xF01E; - $length = strlen($innerData); + $recVer = 0x0; + $recInstance = 0x6E0; + $recType = 0xF01E; + $length = strlen($innerData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header; + $this->_data = $header; - $this->_data .= $innerData; - break; + $this->_data .= $innerData; + break; - } - break; + } + break; - case 'PHPExcel_Shared_Escher_DgContainer': - // this is a container record + case 'PHPExcel_Shared_Escher_DgContainer': + // this is a container record - // initialize - $innerData = ''; + // initialize + $innerData = ''; - // write the dg - $recVer = 0x0; - $recInstance = $this->_object->getDgId(); - $recType = 0xF008; - $length = 8; + // write the dg + $recVer = 0x0; + $recInstance = $this->_object->getDgId(); + $recType = 0xF008; + $length = 8; - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - // number of shapes in this drawing (including group shape) - $countShapes = count($this->_object->getSpgrContainer()->getChildren()); - $innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId()); - //$innerData .= $header . pack('VV', 0, 0); + // number of shapes in this drawing (including group shape) + $countShapes = count($this->_object->getSpgrContainer()->getChildren()); + $innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId()); + //$innerData .= $header . pack('VV', 0, 0); - // write the spgrContainer - if ($spgrContainer = $this->_object->getSpgrContainer()) { - $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer); - $innerData .= $writer->close(); + // write the spgrContainer + if ($spgrContainer = $this->_object->getSpgrContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer); + $innerData .= $writer->close(); - // get the shape offsets relative to the spgrContainer record - $spOffsets = $writer->getSpOffsets(); - $spTypes = $writer->getSpTypes(); - - // save the shape offsets relative to dgContainer - foreach ($spOffsets as & $spOffset) { - $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes) - } + // get the shape offsets relative to the spgrContainer record + $spOffsets = $writer->getSpOffsets(); + $spTypes = $writer->getSpTypes(); + + // save the shape offsets relative to dgContainer + foreach ($spOffsets as & $spOffset) { + $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes) + } - $this->_spOffsets = $spOffsets; - $this->_spTypes = $spTypes; - } + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + } - // write the record - $recVer = 0xF; - $recInstance = 0x0000; - $recType = 0xF002; - $length = strlen($innerData); + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF002; + $length = strlen($innerData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header . $innerData; - break; + $this->_data = $header . $innerData; + break; - case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer': - // this is a container record + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer': + // this is a container record - // initialize - $innerData = ''; + // initialize + $innerData = ''; - // initialize spape offsets - $totalSize = 8; - $spOffsets = array(); - $spTypes = array(); + // initialize spape offsets + $totalSize = 8; + $spOffsets = array(); + $spTypes = array(); - // treat the inner data - foreach ($this->_object->getChildren() as $spContainer) { - $writer = new PHPExcel_Writer_Excel5_Escher($spContainer); - $spData = $writer->close(); - $innerData .= $spData; + // treat the inner data + foreach ($this->_object->getChildren() as $spContainer) { + $writer = new PHPExcel_Writer_Excel5_Escher($spContainer); + $spData = $writer->close(); + $innerData .= $spData; - // save the shape offsets (where new shape records begin) - $totalSize += strlen($spData); - $spOffsets[] = $totalSize; - - $spTypes = array_merge($spTypes, $writer->getSpTypes()); - } + // save the shape offsets (where new shape records begin) + $totalSize += strlen($spData); + $spOffsets[] = $totalSize; + + $spTypes = array_merge($spTypes, $writer->getSpTypes()); + } - // write the record - $recVer = 0xF; - $recInstance = 0x0000; - $recType = 0xF003; - $length = strlen($innerData); + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF003; + $length = strlen($innerData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header . $innerData; - $this->_spOffsets = $spOffsets; - $this->_spTypes = $spTypes; - break; + $this->_data = $header . $innerData; + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + break; - case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer': - // initialize - $data = ''; + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer': + // initialize + $data = ''; - // build the data + // build the data - // write group shape record, if necessary? - if ($this->_object->getSpgr()) { - $recVer = 0x1; - $recInstance = 0x0000; - $recType = 0xF009; - $length = 0x00000010; + // write group shape record, if necessary? + if ($this->_object->getSpgr()) { + $recVer = 0x1; + $recInstance = 0x0000; + $recType = 0xF009; + $length = 0x00000010; - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . pack('VVVV', 0,0,0,0); - } - $this->_spTypes[] = ($this->_object->getSpType()); + $data .= $header . pack('VVVV', 0,0,0,0); + } + $this->_spTypes[] = ($this->_object->getSpType()); - // write the shape record - $recVer = 0x2; - $recInstance = $this->_object->getSpType(); // shape type - $recType = 0xF00A; - $length = 0x00000008; + // write the shape record + $recVer = 0x2; + $recInstance = $this->_object->getSpType(); // shape type + $recType = 0xF00A; + $length = 0x00000008; - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); + $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); + $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); - // the options - if ($this->_object->getOPTCollection()) { - $optData = ''; + // the options + if ($this->_object->getOPTCollection()) { + $optData = ''; - $recVer = 0x3; - $recInstance = count($this->_object->getOPTCollection()); - $recType = 0xF00B; - foreach ($this->_object->getOPTCollection() as $property => $value) { - $optData .= pack('vV', $property, $value); - } - $length = strlen($optData); + $recVer = 0x3; + $recInstance = count($this->_object->getOPTCollection()); + $recType = 0xF00B; + foreach ($this->_object->getOPTCollection() as $property => $value) { + $optData .= pack('vV', $property, $value); + } + $length = strlen($optData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . $optData; - } + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $optData; + } - // the client anchor - if ($this->_object->getStartCoordinates()) { - $clientAnchorData = ''; - - $recVer = 0x0; - $recInstance = 0x0; - $recType = 0xF010; - - // start coordinates - list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getStartCoordinates()); - $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1; - $r1 = $row - 1; - - // start offsetX - $startOffsetX = $this->_object->getStartOffsetX(); - - // start offsetY - $startOffsetY = $this->_object->getStartOffsetY(); - - // end coordinates - list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getEndCoordinates()); - $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1; - $r2 = $row - 1; - - // end offsetX - $endOffsetX = $this->_object->getEndOffsetX(); + // the client anchor + if ($this->_object->getStartCoordinates()) { + $clientAnchorData = ''; + + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF010; + + // start coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getStartCoordinates()); + $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r1 = $row - 1; + + // start offsetX + $startOffsetX = $this->_object->getStartOffsetX(); + + // start offsetY + $startOffsetY = $this->_object->getStartOffsetY(); + + // end coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getEndCoordinates()); + $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r2 = $row - 1; + + // end offsetX + $endOffsetX = $this->_object->getEndOffsetX(); - // end offsetY - $endOffsetY = $this->_object->getEndOffsetY(); + // end offsetY + $endOffsetY = $this->_object->getEndOffsetY(); - $clientAnchorData = pack('vvvvvvvvv', $this->_object->getSpFlag(), - $c1, $startOffsetX, $r1, $startOffsetY, - $c2, $endOffsetX, $r2, $endOffsetY); - - $length = strlen($clientAnchorData); + $clientAnchorData = pack('vvvvvvvvv', $this->_object->getSpFlag(), + $c1, $startOffsetX, $r1, $startOffsetY, + $c2, $endOffsetX, $r2, $endOffsetY); + + $length = strlen($clientAnchorData); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . $clientAnchorData; - } + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientAnchorData; + } - // the client data, just empty for now - if (!$this->_object->getSpgr()) { - $clientDataData = ''; + // the client data, just empty for now + if (!$this->_object->getSpgr()) { + $clientDataData = ''; - $recVer = 0x0; - $recInstance = 0x0; - $recType = 0xF011; + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF011; - $length = strlen($clientDataData); - - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; + $length = strlen($clientDataData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; - $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . $clientDataData; - } + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientDataData; + } - // write the record - $recVer = 0xF; - $recInstance = 0x0000; - $recType = 0xF004; - $length = strlen($data); + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF004; + $length = strlen($data); - $recVerInstance = $recVer; - $recVerInstance |= $recInstance << 4; - - $header = pack('vvV', $recVerInstance, $recType, $length); + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); - $this->_data = $header . $data; - break; + $this->_data = $header . $data; + break; - } + } - return $this->_data; - } - - /** - * Gets the shape offsets - * - * @return array - */ - public function getSpOffsets() - { - return $this->_spOffsets; - } - - /** - * Gets the shape types - * - * @return array - */ - public function getSpTypes() - { - return $this->_spTypes; - } - - + return $this->_data; + } + + /** + * Gets the shape offsets + * + * @return array + */ + public function getSpOffsets() + { + return $this->_spOffsets; + } + + /** + * Gets the shape types + * + * @return array + */ + public function getSpTypes() + { + return $this->_spTypes; + } + + } diff --git a/Classes/PHPExcel/Writer/Excel5/Font.php b/Classes/PHPExcel/Writer/Excel5/Font.php index 99779169..d4543db1 100644 --- a/Classes/PHPExcel/Writer/Excel5/Font.php +++ b/Classes/PHPExcel/Writer/Excel5/Font.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -35,131 +35,131 @@ */ class PHPExcel_Writer_Excel5_Font { - /** - * Color index - * - * @var int - */ - private $_colorIndex; + /** + * Color index + * + * @var int + */ + private $_colorIndex; - /** - * Font - * - * @var PHPExcel_Style_Font - */ - private $_font; + /** + * Font + * + * @var PHPExcel_Style_Font + */ + private $_font; - /** - * Constructor - * - * @param PHPExcel_Style_Font $font - */ - public function __construct(PHPExcel_Style_Font $font = null) - { - $this->_colorIndex = 0x7FFF; - $this->_font = $font; - } + /** + * Constructor + * + * @param PHPExcel_Style_Font $font + */ + public function __construct(PHPExcel_Style_Font $font = null) + { + $this->_colorIndex = 0x7FFF; + $this->_font = $font; + } - /** - * Set the color index - * - * @param int $colorIndex - */ - public function setColorIndex($colorIndex) - { - $this->_colorIndex = $colorIndex; - } + /** + * Set the color index + * + * @param int $colorIndex + */ + public function setColorIndex($colorIndex) + { + $this->_colorIndex = $colorIndex; + } - /** - * Get font record data - * - * @return string - */ - public function writeFont() - { - $font_outline = 0; - $font_shadow = 0; + /** + * Get font record data + * + * @return string + */ + public function writeFont() + { + $font_outline = 0; + $font_shadow = 0; - $icv = $this->_colorIndex; // Index to color palette - if ($this->_font->getSuperScript()) { - $sss = 1; - } else if ($this->_font->getSubScript()) { - $sss = 2; - } else { - $sss = 0; - } - $bFamily = 0; // Font family - $bCharSet = PHPExcel_Shared_Font::getCharsetFromFontName($this->_font->getName()); // Character set + $icv = $this->_colorIndex; // Index to color palette + if ($this->_font->getSuperScript()) { + $sss = 1; + } else if ($this->_font->getSubScript()) { + $sss = 2; + } else { + $sss = 0; + } + $bFamily = 0; // Font family + $bCharSet = PHPExcel_Shared_Font::getCharsetFromFontName($this->_font->getName()); // Character set - $record = 0x31; // Record identifier - $reserved = 0x00; // Reserved - $grbit = 0x00; // Font attributes - if ($this->_font->getItalic()) { - $grbit |= 0x02; - } - if ($this->_font->getStrikethrough()) { - $grbit |= 0x08; - } - if ($font_outline) { - $grbit |= 0x10; - } - if ($font_shadow) { - $grbit |= 0x20; - } + $record = 0x31; // Record identifier + $reserved = 0x00; // Reserved + $grbit = 0x00; // Font attributes + if ($this->_font->getItalic()) { + $grbit |= 0x02; + } + if ($this->_font->getStrikethrough()) { + $grbit |= 0x08; + } + if ($font_outline) { + $grbit |= 0x10; + } + if ($font_shadow) { + $grbit |= 0x20; + } - $data = pack("vvvvvCCCC", - $this->_font->getSize() * 20, // Fontsize (in twips) - $grbit, - $icv, // Colour - self::_mapBold($this->_font->getBold()), // Font weight - $sss, // Superscript/Subscript - self::_mapUnderline($this->_font->getUnderline()), - $bFamily, - $bCharSet, - $reserved - ); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($this->_font->getName()); + $data = pack("vvvvvCCCC", + $this->_font->getSize() * 20, // Fontsize (in twips) + $grbit, + $icv, // Colour + self::_mapBold($this->_font->getBold()), // Font weight + $sss, // Superscript/Subscript + self::_mapUnderline($this->_font->getUnderline()), + $bFamily, + $bCharSet, + $reserved + ); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($this->_font->getName()); - $length = strlen($data); - $header = pack("vv", $record, $length); + $length = strlen($data); + $header = pack("vv", $record, $length); - return($header . $data); - } + return($header . $data); + } - /** - * Map to BIFF5-BIFF8 codes for bold - * - * @param boolean $bold - * @return int - */ - private static function _mapBold($bold) { - if ($bold) { - return 0x2BC; // 700 = Bold font weight - } - return 0x190; // 400 = Normal font weight - } + /** + * Map to BIFF5-BIFF8 codes for bold + * + * @param boolean $bold + * @return int + */ + private static function _mapBold($bold) { + if ($bold) { + return 0x2BC; // 700 = Bold font weight + } + return 0x190; // 400 = Normal font weight + } - /** - * Map of BIFF2-BIFF8 codes for underline styles - * @static array of int - * - */ - private static $_mapUnderline = array( PHPExcel_Style_Font::UNDERLINE_NONE => 0x00, - PHPExcel_Style_Font::UNDERLINE_SINGLE => 0x01, - PHPExcel_Style_Font::UNDERLINE_DOUBLE => 0x02, - PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING => 0x21, - PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING => 0x22, - ); - /** - * Map underline - * - * @param string - * @return int - */ - private static function _mapUnderline($underline) { - if (isset(self::$_mapUnderline[$underline])) - return self::$_mapUnderline[$underline]; - return 0x00; - } + /** + * Map of BIFF2-BIFF8 codes for underline styles + * @static array of int + * + */ + private static $_mapUnderline = array( PHPExcel_Style_Font::UNDERLINE_NONE => 0x00, + PHPExcel_Style_Font::UNDERLINE_SINGLE => 0x01, + PHPExcel_Style_Font::UNDERLINE_DOUBLE => 0x02, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING => 0x21, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING => 0x22, + ); + /** + * Map underline + * + * @param string + * @return int + */ + private static function _mapUnderline($underline) { + if (isset(self::$_mapUnderline[$underline])) + return self::$_mapUnderline[$underline]; + return 0x00; + } } diff --git a/Classes/PHPExcel/Writer/Excel5/Parser.php b/Classes/PHPExcel/Writer/Excel5/Parser.php index 0379631b..c9b0bef7 100644 --- a/Classes/PHPExcel/Writer/Excel5/Parser.php +++ b/Classes/PHPExcel/Writer/Excel5/Parser.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -59,1525 +59,1525 @@ */ class PHPExcel_Writer_Excel5_Parser { - /** Constants */ - // Sheet title in unquoted form - // Invalid sheet title characters cannot occur in the sheet title: - // *:/\?[] - // Moreover, there are valid sheet title characters that cannot occur in unquoted form (there may be more?) - // +-% '^&<>=,;#()"{} - const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+'; + /** Constants */ + // Sheet title in unquoted form + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] + // Moreover, there are valid sheet title characters that cannot occur in unquoted form (there may be more?) + // +-% '^&<>=,;#()"{} + const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+'; - // Sheet title in quoted form (without surrounding quotes) - // Invalid sheet title characters cannot occur in the sheet title: - // *:/\?[] (usual invalid sheet title characters) - // Single quote is represented as a pair '' - const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+'; + // Sheet title in quoted form (without surrounding quotes) + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] (usual invalid sheet title characters) + // Single quote is represented as a pair '' + const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+'; - /** - * The index of the character we are currently looking at - * @var integer - */ - public $_current_char; + /** + * The index of the character we are currently looking at + * @var integer + */ + public $_current_char; - /** - * The token we are working on. - * @var string - */ - public $_current_token; + /** + * The token we are working on. + * @var string + */ + public $_current_token; - /** - * The formula to parse - * @var string - */ - public $_formula; + /** + * The formula to parse + * @var string + */ + public $_formula; - /** - * The character ahead of the current char - * @var string - */ - public $_lookahead; + /** + * The character ahead of the current char + * @var string + */ + public $_lookahead; - /** - * The parse tree to be generated - * @var string - */ - public $_parse_tree; + /** + * The parse tree to be generated + * @var string + */ + public $_parse_tree; - /** - * Array of external sheets - * @var array - */ - public $_ext_sheets; + /** + * Array of external sheets + * @var array + */ + public $_ext_sheets; - /** - * Array of sheet references in the form of REF structures - * @var array - */ - public $_references; + /** + * Array of sheet references in the form of REF structures + * @var array + */ + public $_references; - /** - * The class constructor - * - */ - public function __construct() - { - $this->_current_char = 0; - $this->_current_token = ''; // The token we are working on. - $this->_formula = ''; // The formula to parse. - $this->_lookahead = ''; // The character ahead of the current char. - $this->_parse_tree = ''; // The parse tree to be generated. - $this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's - $this->_ext_sheets = array(); - $this->_references = array(); - } + /** + * The class constructor + * + */ + public function __construct() + { + $this->_current_char = 0; + $this->_current_token = ''; // The token we are working on. + $this->_formula = ''; // The formula to parse. + $this->_lookahead = ''; // The character ahead of the current char. + $this->_parse_tree = ''; // The parse tree to be generated. + $this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's + $this->_ext_sheets = array(); + $this->_references = array(); + } - /** - * Initialize the ptg and function hashes. - * - * @access private - */ - function _initializeHashes() - { - // The Excel ptg indices - $this->ptg = array( - 'ptgExp' => 0x01, - 'ptgTbl' => 0x02, - 'ptgAdd' => 0x03, - 'ptgSub' => 0x04, - 'ptgMul' => 0x05, - 'ptgDiv' => 0x06, - 'ptgPower' => 0x07, - 'ptgConcat' => 0x08, - 'ptgLT' => 0x09, - 'ptgLE' => 0x0A, - 'ptgEQ' => 0x0B, - 'ptgGE' => 0x0C, - 'ptgGT' => 0x0D, - 'ptgNE' => 0x0E, - 'ptgIsect' => 0x0F, - 'ptgUnion' => 0x10, - 'ptgRange' => 0x11, - 'ptgUplus' => 0x12, - 'ptgUminus' => 0x13, - 'ptgPercent' => 0x14, - 'ptgParen' => 0x15, - 'ptgMissArg' => 0x16, - 'ptgStr' => 0x17, - 'ptgAttr' => 0x19, - 'ptgSheet' => 0x1A, - 'ptgEndSheet' => 0x1B, - 'ptgErr' => 0x1C, - 'ptgBool' => 0x1D, - 'ptgInt' => 0x1E, - 'ptgNum' => 0x1F, - 'ptgArray' => 0x20, - 'ptgFunc' => 0x21, - 'ptgFuncVar' => 0x22, - 'ptgName' => 0x23, - 'ptgRef' => 0x24, - 'ptgArea' => 0x25, - 'ptgMemArea' => 0x26, - 'ptgMemErr' => 0x27, - 'ptgMemNoMem' => 0x28, - 'ptgMemFunc' => 0x29, - 'ptgRefErr' => 0x2A, - 'ptgAreaErr' => 0x2B, - 'ptgRefN' => 0x2C, - 'ptgAreaN' => 0x2D, - 'ptgMemAreaN' => 0x2E, - 'ptgMemNoMemN' => 0x2F, - 'ptgNameX' => 0x39, - 'ptgRef3d' => 0x3A, - 'ptgArea3d' => 0x3B, - 'ptgRefErr3d' => 0x3C, - 'ptgAreaErr3d' => 0x3D, - 'ptgArrayV' => 0x40, - 'ptgFuncV' => 0x41, - 'ptgFuncVarV' => 0x42, - 'ptgNameV' => 0x43, - 'ptgRefV' => 0x44, - 'ptgAreaV' => 0x45, - 'ptgMemAreaV' => 0x46, - 'ptgMemErrV' => 0x47, - 'ptgMemNoMemV' => 0x48, - 'ptgMemFuncV' => 0x49, - 'ptgRefErrV' => 0x4A, - 'ptgAreaErrV' => 0x4B, - 'ptgRefNV' => 0x4C, - 'ptgAreaNV' => 0x4D, - 'ptgMemAreaNV' => 0x4E, - 'ptgMemNoMemN' => 0x4F, - 'ptgFuncCEV' => 0x58, - 'ptgNameXV' => 0x59, - 'ptgRef3dV' => 0x5A, - 'ptgArea3dV' => 0x5B, - 'ptgRefErr3dV' => 0x5C, - 'ptgAreaErr3d' => 0x5D, - 'ptgArrayA' => 0x60, - 'ptgFuncA' => 0x61, - 'ptgFuncVarA' => 0x62, - 'ptgNameA' => 0x63, - 'ptgRefA' => 0x64, - 'ptgAreaA' => 0x65, - 'ptgMemAreaA' => 0x66, - 'ptgMemErrA' => 0x67, - 'ptgMemNoMemA' => 0x68, - 'ptgMemFuncA' => 0x69, - 'ptgRefErrA' => 0x6A, - 'ptgAreaErrA' => 0x6B, - 'ptgRefNA' => 0x6C, - 'ptgAreaNA' => 0x6D, - 'ptgMemAreaNA' => 0x6E, - 'ptgMemNoMemN' => 0x6F, - 'ptgFuncCEA' => 0x78, - 'ptgNameXA' => 0x79, - 'ptgRef3dA' => 0x7A, - 'ptgArea3dA' => 0x7B, - 'ptgRefErr3dA' => 0x7C, - 'ptgAreaErr3d' => 0x7D - ); + /** + * Initialize the ptg and function hashes. + * + * @access private + */ + function _initializeHashes() + { + // The Excel ptg indices + $this->ptg = array( + 'ptgExp' => 0x01, + 'ptgTbl' => 0x02, + 'ptgAdd' => 0x03, + 'ptgSub' => 0x04, + 'ptgMul' => 0x05, + 'ptgDiv' => 0x06, + 'ptgPower' => 0x07, + 'ptgConcat' => 0x08, + 'ptgLT' => 0x09, + 'ptgLE' => 0x0A, + 'ptgEQ' => 0x0B, + 'ptgGE' => 0x0C, + 'ptgGT' => 0x0D, + 'ptgNE' => 0x0E, + 'ptgIsect' => 0x0F, + 'ptgUnion' => 0x10, + 'ptgRange' => 0x11, + 'ptgUplus' => 0x12, + 'ptgUminus' => 0x13, + 'ptgPercent' => 0x14, + 'ptgParen' => 0x15, + 'ptgMissArg' => 0x16, + 'ptgStr' => 0x17, + 'ptgAttr' => 0x19, + 'ptgSheet' => 0x1A, + 'ptgEndSheet' => 0x1B, + 'ptgErr' => 0x1C, + 'ptgBool' => 0x1D, + 'ptgInt' => 0x1E, + 'ptgNum' => 0x1F, + 'ptgArray' => 0x20, + 'ptgFunc' => 0x21, + 'ptgFuncVar' => 0x22, + 'ptgName' => 0x23, + 'ptgRef' => 0x24, + 'ptgArea' => 0x25, + 'ptgMemArea' => 0x26, + 'ptgMemErr' => 0x27, + 'ptgMemNoMem' => 0x28, + 'ptgMemFunc' => 0x29, + 'ptgRefErr' => 0x2A, + 'ptgAreaErr' => 0x2B, + 'ptgRefN' => 0x2C, + 'ptgAreaN' => 0x2D, + 'ptgMemAreaN' => 0x2E, + 'ptgMemNoMemN' => 0x2F, + 'ptgNameX' => 0x39, + 'ptgRef3d' => 0x3A, + 'ptgArea3d' => 0x3B, + 'ptgRefErr3d' => 0x3C, + 'ptgAreaErr3d' => 0x3D, + 'ptgArrayV' => 0x40, + 'ptgFuncV' => 0x41, + 'ptgFuncVarV' => 0x42, + 'ptgNameV' => 0x43, + 'ptgRefV' => 0x44, + 'ptgAreaV' => 0x45, + 'ptgMemAreaV' => 0x46, + 'ptgMemErrV' => 0x47, + 'ptgMemNoMemV' => 0x48, + 'ptgMemFuncV' => 0x49, + 'ptgRefErrV' => 0x4A, + 'ptgAreaErrV' => 0x4B, + 'ptgRefNV' => 0x4C, + 'ptgAreaNV' => 0x4D, + 'ptgMemAreaNV' => 0x4E, + 'ptgMemNoMemN' => 0x4F, + 'ptgFuncCEV' => 0x58, + 'ptgNameXV' => 0x59, + 'ptgRef3dV' => 0x5A, + 'ptgArea3dV' => 0x5B, + 'ptgRefErr3dV' => 0x5C, + 'ptgAreaErr3d' => 0x5D, + 'ptgArrayA' => 0x60, + 'ptgFuncA' => 0x61, + 'ptgFuncVarA' => 0x62, + 'ptgNameA' => 0x63, + 'ptgRefA' => 0x64, + 'ptgAreaA' => 0x65, + 'ptgMemAreaA' => 0x66, + 'ptgMemErrA' => 0x67, + 'ptgMemNoMemA' => 0x68, + 'ptgMemFuncA' => 0x69, + 'ptgRefErrA' => 0x6A, + 'ptgAreaErrA' => 0x6B, + 'ptgRefNA' => 0x6C, + 'ptgAreaNA' => 0x6D, + 'ptgMemAreaNA' => 0x6E, + 'ptgMemNoMemN' => 0x6F, + 'ptgFuncCEA' => 0x78, + 'ptgNameXA' => 0x79, + 'ptgRef3dA' => 0x7A, + 'ptgArea3dA' => 0x7B, + 'ptgRefErr3dA' => 0x7C, + 'ptgAreaErr3d' => 0x7D + ); - // Thanks to Michael Meeks and Gnumeric for the initial arg values. - // - // The following hash was generated by "function_locale.pl" in the distro. - // Refer to function_locale.pl for non-English function names. - // - // The array elements are as follow: - // ptg: The Excel function ptg code. - // args: The number of arguments that the function takes: - // >=0 is a fixed number of arguments. - // -1 is a variable number of arguments. - // class: The reference, value or array class of the function args. - // vol: The function is volatile. - // - $this->_functions = array( - // function ptg args class vol - 'COUNT' => array( 0, -1, 0, 0 ), - 'IF' => array( 1, -1, 1, 0 ), - 'ISNA' => array( 2, 1, 1, 0 ), - 'ISERROR' => array( 3, 1, 1, 0 ), - 'SUM' => array( 4, -1, 0, 0 ), - 'AVERAGE' => array( 5, -1, 0, 0 ), - 'MIN' => array( 6, -1, 0, 0 ), - 'MAX' => array( 7, -1, 0, 0 ), - 'ROW' => array( 8, -1, 0, 0 ), - 'COLUMN' => array( 9, -1, 0, 0 ), - 'NA' => array( 10, 0, 0, 0 ), - 'NPV' => array( 11, -1, 1, 0 ), - 'STDEV' => array( 12, -1, 0, 0 ), - 'DOLLAR' => array( 13, -1, 1, 0 ), - 'FIXED' => array( 14, -1, 1, 0 ), - 'SIN' => array( 15, 1, 1, 0 ), - 'COS' => array( 16, 1, 1, 0 ), - 'TAN' => array( 17, 1, 1, 0 ), - 'ATAN' => array( 18, 1, 1, 0 ), - 'PI' => array( 19, 0, 1, 0 ), - 'SQRT' => array( 20, 1, 1, 0 ), - 'EXP' => array( 21, 1, 1, 0 ), - 'LN' => array( 22, 1, 1, 0 ), - 'LOG10' => array( 23, 1, 1, 0 ), - 'ABS' => array( 24, 1, 1, 0 ), - 'INT' => array( 25, 1, 1, 0 ), - 'SIGN' => array( 26, 1, 1, 0 ), - 'ROUND' => array( 27, 2, 1, 0 ), - 'LOOKUP' => array( 28, -1, 0, 0 ), - 'INDEX' => array( 29, -1, 0, 1 ), - 'REPT' => array( 30, 2, 1, 0 ), - 'MID' => array( 31, 3, 1, 0 ), - 'LEN' => array( 32, 1, 1, 0 ), - 'VALUE' => array( 33, 1, 1, 0 ), - 'TRUE' => array( 34, 0, 1, 0 ), - 'FALSE' => array( 35, 0, 1, 0 ), - 'AND' => array( 36, -1, 0, 0 ), - 'OR' => array( 37, -1, 0, 0 ), - 'NOT' => array( 38, 1, 1, 0 ), - 'MOD' => array( 39, 2, 1, 0 ), - 'DCOUNT' => array( 40, 3, 0, 0 ), - 'DSUM' => array( 41, 3, 0, 0 ), - 'DAVERAGE' => array( 42, 3, 0, 0 ), - 'DMIN' => array( 43, 3, 0, 0 ), - 'DMAX' => array( 44, 3, 0, 0 ), - 'DSTDEV' => array( 45, 3, 0, 0 ), - 'VAR' => array( 46, -1, 0, 0 ), - 'DVAR' => array( 47, 3, 0, 0 ), - 'TEXT' => array( 48, 2, 1, 0 ), - 'LINEST' => array( 49, -1, 0, 0 ), - 'TREND' => array( 50, -1, 0, 0 ), - 'LOGEST' => array( 51, -1, 0, 0 ), - 'GROWTH' => array( 52, -1, 0, 0 ), - 'PV' => array( 56, -1, 1, 0 ), - 'FV' => array( 57, -1, 1, 0 ), - 'NPER' => array( 58, -1, 1, 0 ), - 'PMT' => array( 59, -1, 1, 0 ), - 'RATE' => array( 60, -1, 1, 0 ), - 'MIRR' => array( 61, 3, 0, 0 ), - 'IRR' => array( 62, -1, 0, 0 ), - 'RAND' => array( 63, 0, 1, 1 ), - 'MATCH' => array( 64, -1, 0, 0 ), - 'DATE' => array( 65, 3, 1, 0 ), - 'TIME' => array( 66, 3, 1, 0 ), - 'DAY' => array( 67, 1, 1, 0 ), - 'MONTH' => array( 68, 1, 1, 0 ), - 'YEAR' => array( 69, 1, 1, 0 ), - 'WEEKDAY' => array( 70, -1, 1, 0 ), - 'HOUR' => array( 71, 1, 1, 0 ), - 'MINUTE' => array( 72, 1, 1, 0 ), - 'SECOND' => array( 73, 1, 1, 0 ), - 'NOW' => array( 74, 0, 1, 1 ), - 'AREAS' => array( 75, 1, 0, 1 ), - 'ROWS' => array( 76, 1, 0, 1 ), - 'COLUMNS' => array( 77, 1, 0, 1 ), - 'OFFSET' => array( 78, -1, 0, 1 ), - 'SEARCH' => array( 82, -1, 1, 0 ), - 'TRANSPOSE' => array( 83, 1, 1, 0 ), - 'TYPE' => array( 86, 1, 1, 0 ), - 'ATAN2' => array( 97, 2, 1, 0 ), - 'ASIN' => array( 98, 1, 1, 0 ), - 'ACOS' => array( 99, 1, 1, 0 ), - 'CHOOSE' => array( 100, -1, 1, 0 ), - 'HLOOKUP' => array( 101, -1, 0, 0 ), - 'VLOOKUP' => array( 102, -1, 0, 0 ), - 'ISREF' => array( 105, 1, 0, 0 ), - 'LOG' => array( 109, -1, 1, 0 ), - 'CHAR' => array( 111, 1, 1, 0 ), - 'LOWER' => array( 112, 1, 1, 0 ), - 'UPPER' => array( 113, 1, 1, 0 ), - 'PROPER' => array( 114, 1, 1, 0 ), - 'LEFT' => array( 115, -1, 1, 0 ), - 'RIGHT' => array( 116, -1, 1, 0 ), - 'EXACT' => array( 117, 2, 1, 0 ), - 'TRIM' => array( 118, 1, 1, 0 ), - 'REPLACE' => array( 119, 4, 1, 0 ), - 'SUBSTITUTE' => array( 120, -1, 1, 0 ), - 'CODE' => array( 121, 1, 1, 0 ), - 'FIND' => array( 124, -1, 1, 0 ), - 'CELL' => array( 125, -1, 0, 1 ), - 'ISERR' => array( 126, 1, 1, 0 ), - 'ISTEXT' => array( 127, 1, 1, 0 ), - 'ISNUMBER' => array( 128, 1, 1, 0 ), - 'ISBLANK' => array( 129, 1, 1, 0 ), - 'T' => array( 130, 1, 0, 0 ), - 'N' => array( 131, 1, 0, 0 ), - 'DATEVALUE' => array( 140, 1, 1, 0 ), - 'TIMEVALUE' => array( 141, 1, 1, 0 ), - 'SLN' => array( 142, 3, 1, 0 ), - 'SYD' => array( 143, 4, 1, 0 ), - 'DDB' => array( 144, -1, 1, 0 ), - 'INDIRECT' => array( 148, -1, 1, 1 ), - 'CALL' => array( 150, -1, 1, 0 ), - 'CLEAN' => array( 162, 1, 1, 0 ), - 'MDETERM' => array( 163, 1, 2, 0 ), - 'MINVERSE' => array( 164, 1, 2, 0 ), - 'MMULT' => array( 165, 2, 2, 0 ), - 'IPMT' => array( 167, -1, 1, 0 ), - 'PPMT' => array( 168, -1, 1, 0 ), - 'COUNTA' => array( 169, -1, 0, 0 ), - 'PRODUCT' => array( 183, -1, 0, 0 ), - 'FACT' => array( 184, 1, 1, 0 ), - 'DPRODUCT' => array( 189, 3, 0, 0 ), - 'ISNONTEXT' => array( 190, 1, 1, 0 ), - 'STDEVP' => array( 193, -1, 0, 0 ), - 'VARP' => array( 194, -1, 0, 0 ), - 'DSTDEVP' => array( 195, 3, 0, 0 ), - 'DVARP' => array( 196, 3, 0, 0 ), - 'TRUNC' => array( 197, -1, 1, 0 ), - 'ISLOGICAL' => array( 198, 1, 1, 0 ), - 'DCOUNTA' => array( 199, 3, 0, 0 ), - 'USDOLLAR' => array( 204, -1, 1, 0 ), - 'FINDB' => array( 205, -1, 1, 0 ), - 'SEARCHB' => array( 206, -1, 1, 0 ), - 'REPLACEB' => array( 207, 4, 1, 0 ), - 'LEFTB' => array( 208, -1, 1, 0 ), - 'RIGHTB' => array( 209, -1, 1, 0 ), - 'MIDB' => array( 210, 3, 1, 0 ), - 'LENB' => array( 211, 1, 1, 0 ), - 'ROUNDUP' => array( 212, 2, 1, 0 ), - 'ROUNDDOWN' => array( 213, 2, 1, 0 ), - 'ASC' => array( 214, 1, 1, 0 ), - 'DBCS' => array( 215, 1, 1, 0 ), - 'RANK' => array( 216, -1, 0, 0 ), - 'ADDRESS' => array( 219, -1, 1, 0 ), - 'DAYS360' => array( 220, -1, 1, 0 ), - 'TODAY' => array( 221, 0, 1, 1 ), - 'VDB' => array( 222, -1, 1, 0 ), - 'MEDIAN' => array( 227, -1, 0, 0 ), - 'SUMPRODUCT' => array( 228, -1, 2, 0 ), - 'SINH' => array( 229, 1, 1, 0 ), - 'COSH' => array( 230, 1, 1, 0 ), - 'TANH' => array( 231, 1, 1, 0 ), - 'ASINH' => array( 232, 1, 1, 0 ), - 'ACOSH' => array( 233, 1, 1, 0 ), - 'ATANH' => array( 234, 1, 1, 0 ), - 'DGET' => array( 235, 3, 0, 0 ), - 'INFO' => array( 244, 1, 1, 1 ), - 'DB' => array( 247, -1, 1, 0 ), - 'FREQUENCY' => array( 252, 2, 0, 0 ), - 'ERROR.TYPE' => array( 261, 1, 1, 0 ), - 'REGISTER.ID' => array( 267, -1, 1, 0 ), - 'AVEDEV' => array( 269, -1, 0, 0 ), - 'BETADIST' => array( 270, -1, 1, 0 ), - 'GAMMALN' => array( 271, 1, 1, 0 ), - 'BETAINV' => array( 272, -1, 1, 0 ), - 'BINOMDIST' => array( 273, 4, 1, 0 ), - 'CHIDIST' => array( 274, 2, 1, 0 ), - 'CHIINV' => array( 275, 2, 1, 0 ), - 'COMBIN' => array( 276, 2, 1, 0 ), - 'CONFIDENCE' => array( 277, 3, 1, 0 ), - 'CRITBINOM' => array( 278, 3, 1, 0 ), - 'EVEN' => array( 279, 1, 1, 0 ), - 'EXPONDIST' => array( 280, 3, 1, 0 ), - 'FDIST' => array( 281, 3, 1, 0 ), - 'FINV' => array( 282, 3, 1, 0 ), - 'FISHER' => array( 283, 1, 1, 0 ), - 'FISHERINV' => array( 284, 1, 1, 0 ), - 'FLOOR' => array( 285, 2, 1, 0 ), - 'GAMMADIST' => array( 286, 4, 1, 0 ), - 'GAMMAINV' => array( 287, 3, 1, 0 ), - 'CEILING' => array( 288, 2, 1, 0 ), - 'HYPGEOMDIST' => array( 289, 4, 1, 0 ), - 'LOGNORMDIST' => array( 290, 3, 1, 0 ), - 'LOGINV' => array( 291, 3, 1, 0 ), - 'NEGBINOMDIST' => array( 292, 3, 1, 0 ), - 'NORMDIST' => array( 293, 4, 1, 0 ), - 'NORMSDIST' => array( 294, 1, 1, 0 ), - 'NORMINV' => array( 295, 3, 1, 0 ), - 'NORMSINV' => array( 296, 1, 1, 0 ), - 'STANDARDIZE' => array( 297, 3, 1, 0 ), - 'ODD' => array( 298, 1, 1, 0 ), - 'PERMUT' => array( 299, 2, 1, 0 ), - 'POISSON' => array( 300, 3, 1, 0 ), - 'TDIST' => array( 301, 3, 1, 0 ), - 'WEIBULL' => array( 302, 4, 1, 0 ), - 'SUMXMY2' => array( 303, 2, 2, 0 ), - 'SUMX2MY2' => array( 304, 2, 2, 0 ), - 'SUMX2PY2' => array( 305, 2, 2, 0 ), - 'CHITEST' => array( 306, 2, 2, 0 ), - 'CORREL' => array( 307, 2, 2, 0 ), - 'COVAR' => array( 308, 2, 2, 0 ), - 'FORECAST' => array( 309, 3, 2, 0 ), - 'FTEST' => array( 310, 2, 2, 0 ), - 'INTERCEPT' => array( 311, 2, 2, 0 ), - 'PEARSON' => array( 312, 2, 2, 0 ), - 'RSQ' => array( 313, 2, 2, 0 ), - 'STEYX' => array( 314, 2, 2, 0 ), - 'SLOPE' => array( 315, 2, 2, 0 ), - 'TTEST' => array( 316, 4, 2, 0 ), - 'PROB' => array( 317, -1, 2, 0 ), - 'DEVSQ' => array( 318, -1, 0, 0 ), - 'GEOMEAN' => array( 319, -1, 0, 0 ), - 'HARMEAN' => array( 320, -1, 0, 0 ), - 'SUMSQ' => array( 321, -1, 0, 0 ), - 'KURT' => array( 322, -1, 0, 0 ), - 'SKEW' => array( 323, -1, 0, 0 ), - 'ZTEST' => array( 324, -1, 0, 0 ), - 'LARGE' => array( 325, 2, 0, 0 ), - 'SMALL' => array( 326, 2, 0, 0 ), - 'QUARTILE' => array( 327, 2, 0, 0 ), - 'PERCENTILE' => array( 328, 2, 0, 0 ), - 'PERCENTRANK' => array( 329, -1, 0, 0 ), - 'MODE' => array( 330, -1, 2, 0 ), - 'TRIMMEAN' => array( 331, 2, 0, 0 ), - 'TINV' => array( 332, 2, 1, 0 ), - 'CONCATENATE' => array( 336, -1, 1, 0 ), - 'POWER' => array( 337, 2, 1, 0 ), - 'RADIANS' => array( 342, 1, 1, 0 ), - 'DEGREES' => array( 343, 1, 1, 0 ), - 'SUBTOTAL' => array( 344, -1, 0, 0 ), - 'SUMIF' => array( 345, -1, 0, 0 ), - 'COUNTIF' => array( 346, 2, 0, 0 ), - 'COUNTBLANK' => array( 347, 1, 0, 0 ), - 'ISPMT' => array( 350, 4, 1, 0 ), - 'DATEDIF' => array( 351, 3, 1, 0 ), - 'DATESTRING' => array( 352, 1, 1, 0 ), - 'NUMBERSTRING' => array( 353, 2, 1, 0 ), - 'ROMAN' => array( 354, -1, 1, 0 ), - 'GETPIVOTDATA' => array( 358, -1, 0, 0 ), - 'HYPERLINK' => array( 359, -1, 1, 0 ), - 'PHONETIC' => array( 360, 1, 0, 0 ), - 'AVERAGEA' => array( 361, -1, 0, 0 ), - 'MAXA' => array( 362, -1, 0, 0 ), - 'MINA' => array( 363, -1, 0, 0 ), - 'STDEVPA' => array( 364, -1, 0, 0 ), - 'VARPA' => array( 365, -1, 0, 0 ), - 'STDEVA' => array( 366, -1, 0, 0 ), - 'VARA' => array( 367, -1, 0, 0 ), - 'BAHTTEXT' => array( 368, 1, 0, 0 ), - ); - } + // Thanks to Michael Meeks and Gnumeric for the initial arg values. + // + // The following hash was generated by "function_locale.pl" in the distro. + // Refer to function_locale.pl for non-English function names. + // + // The array elements are as follow: + // ptg: The Excel function ptg code. + // args: The number of arguments that the function takes: + // >=0 is a fixed number of arguments. + // -1 is a variable number of arguments. + // class: The reference, value or array class of the function args. + // vol: The function is volatile. + // + $this->_functions = array( + // function ptg args class vol + 'COUNT' => array( 0, -1, 0, 0 ), + 'IF' => array( 1, -1, 1, 0 ), + 'ISNA' => array( 2, 1, 1, 0 ), + 'ISERROR' => array( 3, 1, 1, 0 ), + 'SUM' => array( 4, -1, 0, 0 ), + 'AVERAGE' => array( 5, -1, 0, 0 ), + 'MIN' => array( 6, -1, 0, 0 ), + 'MAX' => array( 7, -1, 0, 0 ), + 'ROW' => array( 8, -1, 0, 0 ), + 'COLUMN' => array( 9, -1, 0, 0 ), + 'NA' => array( 10, 0, 0, 0 ), + 'NPV' => array( 11, -1, 1, 0 ), + 'STDEV' => array( 12, -1, 0, 0 ), + 'DOLLAR' => array( 13, -1, 1, 0 ), + 'FIXED' => array( 14, -1, 1, 0 ), + 'SIN' => array( 15, 1, 1, 0 ), + 'COS' => array( 16, 1, 1, 0 ), + 'TAN' => array( 17, 1, 1, 0 ), + 'ATAN' => array( 18, 1, 1, 0 ), + 'PI' => array( 19, 0, 1, 0 ), + 'SQRT' => array( 20, 1, 1, 0 ), + 'EXP' => array( 21, 1, 1, 0 ), + 'LN' => array( 22, 1, 1, 0 ), + 'LOG10' => array( 23, 1, 1, 0 ), + 'ABS' => array( 24, 1, 1, 0 ), + 'INT' => array( 25, 1, 1, 0 ), + 'SIGN' => array( 26, 1, 1, 0 ), + 'ROUND' => array( 27, 2, 1, 0 ), + 'LOOKUP' => array( 28, -1, 0, 0 ), + 'INDEX' => array( 29, -1, 0, 1 ), + 'REPT' => array( 30, 2, 1, 0 ), + 'MID' => array( 31, 3, 1, 0 ), + 'LEN' => array( 32, 1, 1, 0 ), + 'VALUE' => array( 33, 1, 1, 0 ), + 'TRUE' => array( 34, 0, 1, 0 ), + 'FALSE' => array( 35, 0, 1, 0 ), + 'AND' => array( 36, -1, 0, 0 ), + 'OR' => array( 37, -1, 0, 0 ), + 'NOT' => array( 38, 1, 1, 0 ), + 'MOD' => array( 39, 2, 1, 0 ), + 'DCOUNT' => array( 40, 3, 0, 0 ), + 'DSUM' => array( 41, 3, 0, 0 ), + 'DAVERAGE' => array( 42, 3, 0, 0 ), + 'DMIN' => array( 43, 3, 0, 0 ), + 'DMAX' => array( 44, 3, 0, 0 ), + 'DSTDEV' => array( 45, 3, 0, 0 ), + 'VAR' => array( 46, -1, 0, 0 ), + 'DVAR' => array( 47, 3, 0, 0 ), + 'TEXT' => array( 48, 2, 1, 0 ), + 'LINEST' => array( 49, -1, 0, 0 ), + 'TREND' => array( 50, -1, 0, 0 ), + 'LOGEST' => array( 51, -1, 0, 0 ), + 'GROWTH' => array( 52, -1, 0, 0 ), + 'PV' => array( 56, -1, 1, 0 ), + 'FV' => array( 57, -1, 1, 0 ), + 'NPER' => array( 58, -1, 1, 0 ), + 'PMT' => array( 59, -1, 1, 0 ), + 'RATE' => array( 60, -1, 1, 0 ), + 'MIRR' => array( 61, 3, 0, 0 ), + 'IRR' => array( 62, -1, 0, 0 ), + 'RAND' => array( 63, 0, 1, 1 ), + 'MATCH' => array( 64, -1, 0, 0 ), + 'DATE' => array( 65, 3, 1, 0 ), + 'TIME' => array( 66, 3, 1, 0 ), + 'DAY' => array( 67, 1, 1, 0 ), + 'MONTH' => array( 68, 1, 1, 0 ), + 'YEAR' => array( 69, 1, 1, 0 ), + 'WEEKDAY' => array( 70, -1, 1, 0 ), + 'HOUR' => array( 71, 1, 1, 0 ), + 'MINUTE' => array( 72, 1, 1, 0 ), + 'SECOND' => array( 73, 1, 1, 0 ), + 'NOW' => array( 74, 0, 1, 1 ), + 'AREAS' => array( 75, 1, 0, 1 ), + 'ROWS' => array( 76, 1, 0, 1 ), + 'COLUMNS' => array( 77, 1, 0, 1 ), + 'OFFSET' => array( 78, -1, 0, 1 ), + 'SEARCH' => array( 82, -1, 1, 0 ), + 'TRANSPOSE' => array( 83, 1, 1, 0 ), + 'TYPE' => array( 86, 1, 1, 0 ), + 'ATAN2' => array( 97, 2, 1, 0 ), + 'ASIN' => array( 98, 1, 1, 0 ), + 'ACOS' => array( 99, 1, 1, 0 ), + 'CHOOSE' => array( 100, -1, 1, 0 ), + 'HLOOKUP' => array( 101, -1, 0, 0 ), + 'VLOOKUP' => array( 102, -1, 0, 0 ), + 'ISREF' => array( 105, 1, 0, 0 ), + 'LOG' => array( 109, -1, 1, 0 ), + 'CHAR' => array( 111, 1, 1, 0 ), + 'LOWER' => array( 112, 1, 1, 0 ), + 'UPPER' => array( 113, 1, 1, 0 ), + 'PROPER' => array( 114, 1, 1, 0 ), + 'LEFT' => array( 115, -1, 1, 0 ), + 'RIGHT' => array( 116, -1, 1, 0 ), + 'EXACT' => array( 117, 2, 1, 0 ), + 'TRIM' => array( 118, 1, 1, 0 ), + 'REPLACE' => array( 119, 4, 1, 0 ), + 'SUBSTITUTE' => array( 120, -1, 1, 0 ), + 'CODE' => array( 121, 1, 1, 0 ), + 'FIND' => array( 124, -1, 1, 0 ), + 'CELL' => array( 125, -1, 0, 1 ), + 'ISERR' => array( 126, 1, 1, 0 ), + 'ISTEXT' => array( 127, 1, 1, 0 ), + 'ISNUMBER' => array( 128, 1, 1, 0 ), + 'ISBLANK' => array( 129, 1, 1, 0 ), + 'T' => array( 130, 1, 0, 0 ), + 'N' => array( 131, 1, 0, 0 ), + 'DATEVALUE' => array( 140, 1, 1, 0 ), + 'TIMEVALUE' => array( 141, 1, 1, 0 ), + 'SLN' => array( 142, 3, 1, 0 ), + 'SYD' => array( 143, 4, 1, 0 ), + 'DDB' => array( 144, -1, 1, 0 ), + 'INDIRECT' => array( 148, -1, 1, 1 ), + 'CALL' => array( 150, -1, 1, 0 ), + 'CLEAN' => array( 162, 1, 1, 0 ), + 'MDETERM' => array( 163, 1, 2, 0 ), + 'MINVERSE' => array( 164, 1, 2, 0 ), + 'MMULT' => array( 165, 2, 2, 0 ), + 'IPMT' => array( 167, -1, 1, 0 ), + 'PPMT' => array( 168, -1, 1, 0 ), + 'COUNTA' => array( 169, -1, 0, 0 ), + 'PRODUCT' => array( 183, -1, 0, 0 ), + 'FACT' => array( 184, 1, 1, 0 ), + 'DPRODUCT' => array( 189, 3, 0, 0 ), + 'ISNONTEXT' => array( 190, 1, 1, 0 ), + 'STDEVP' => array( 193, -1, 0, 0 ), + 'VARP' => array( 194, -1, 0, 0 ), + 'DSTDEVP' => array( 195, 3, 0, 0 ), + 'DVARP' => array( 196, 3, 0, 0 ), + 'TRUNC' => array( 197, -1, 1, 0 ), + 'ISLOGICAL' => array( 198, 1, 1, 0 ), + 'DCOUNTA' => array( 199, 3, 0, 0 ), + 'USDOLLAR' => array( 204, -1, 1, 0 ), + 'FINDB' => array( 205, -1, 1, 0 ), + 'SEARCHB' => array( 206, -1, 1, 0 ), + 'REPLACEB' => array( 207, 4, 1, 0 ), + 'LEFTB' => array( 208, -1, 1, 0 ), + 'RIGHTB' => array( 209, -1, 1, 0 ), + 'MIDB' => array( 210, 3, 1, 0 ), + 'LENB' => array( 211, 1, 1, 0 ), + 'ROUNDUP' => array( 212, 2, 1, 0 ), + 'ROUNDDOWN' => array( 213, 2, 1, 0 ), + 'ASC' => array( 214, 1, 1, 0 ), + 'DBCS' => array( 215, 1, 1, 0 ), + 'RANK' => array( 216, -1, 0, 0 ), + 'ADDRESS' => array( 219, -1, 1, 0 ), + 'DAYS360' => array( 220, -1, 1, 0 ), + 'TODAY' => array( 221, 0, 1, 1 ), + 'VDB' => array( 222, -1, 1, 0 ), + 'MEDIAN' => array( 227, -1, 0, 0 ), + 'SUMPRODUCT' => array( 228, -1, 2, 0 ), + 'SINH' => array( 229, 1, 1, 0 ), + 'COSH' => array( 230, 1, 1, 0 ), + 'TANH' => array( 231, 1, 1, 0 ), + 'ASINH' => array( 232, 1, 1, 0 ), + 'ACOSH' => array( 233, 1, 1, 0 ), + 'ATANH' => array( 234, 1, 1, 0 ), + 'DGET' => array( 235, 3, 0, 0 ), + 'INFO' => array( 244, 1, 1, 1 ), + 'DB' => array( 247, -1, 1, 0 ), + 'FREQUENCY' => array( 252, 2, 0, 0 ), + 'ERROR.TYPE' => array( 261, 1, 1, 0 ), + 'REGISTER.ID' => array( 267, -1, 1, 0 ), + 'AVEDEV' => array( 269, -1, 0, 0 ), + 'BETADIST' => array( 270, -1, 1, 0 ), + 'GAMMALN' => array( 271, 1, 1, 0 ), + 'BETAINV' => array( 272, -1, 1, 0 ), + 'BINOMDIST' => array( 273, 4, 1, 0 ), + 'CHIDIST' => array( 274, 2, 1, 0 ), + 'CHIINV' => array( 275, 2, 1, 0 ), + 'COMBIN' => array( 276, 2, 1, 0 ), + 'CONFIDENCE' => array( 277, 3, 1, 0 ), + 'CRITBINOM' => array( 278, 3, 1, 0 ), + 'EVEN' => array( 279, 1, 1, 0 ), + 'EXPONDIST' => array( 280, 3, 1, 0 ), + 'FDIST' => array( 281, 3, 1, 0 ), + 'FINV' => array( 282, 3, 1, 0 ), + 'FISHER' => array( 283, 1, 1, 0 ), + 'FISHERINV' => array( 284, 1, 1, 0 ), + 'FLOOR' => array( 285, 2, 1, 0 ), + 'GAMMADIST' => array( 286, 4, 1, 0 ), + 'GAMMAINV' => array( 287, 3, 1, 0 ), + 'CEILING' => array( 288, 2, 1, 0 ), + 'HYPGEOMDIST' => array( 289, 4, 1, 0 ), + 'LOGNORMDIST' => array( 290, 3, 1, 0 ), + 'LOGINV' => array( 291, 3, 1, 0 ), + 'NEGBINOMDIST' => array( 292, 3, 1, 0 ), + 'NORMDIST' => array( 293, 4, 1, 0 ), + 'NORMSDIST' => array( 294, 1, 1, 0 ), + 'NORMINV' => array( 295, 3, 1, 0 ), + 'NORMSINV' => array( 296, 1, 1, 0 ), + 'STANDARDIZE' => array( 297, 3, 1, 0 ), + 'ODD' => array( 298, 1, 1, 0 ), + 'PERMUT' => array( 299, 2, 1, 0 ), + 'POISSON' => array( 300, 3, 1, 0 ), + 'TDIST' => array( 301, 3, 1, 0 ), + 'WEIBULL' => array( 302, 4, 1, 0 ), + 'SUMXMY2' => array( 303, 2, 2, 0 ), + 'SUMX2MY2' => array( 304, 2, 2, 0 ), + 'SUMX2PY2' => array( 305, 2, 2, 0 ), + 'CHITEST' => array( 306, 2, 2, 0 ), + 'CORREL' => array( 307, 2, 2, 0 ), + 'COVAR' => array( 308, 2, 2, 0 ), + 'FORECAST' => array( 309, 3, 2, 0 ), + 'FTEST' => array( 310, 2, 2, 0 ), + 'INTERCEPT' => array( 311, 2, 2, 0 ), + 'PEARSON' => array( 312, 2, 2, 0 ), + 'RSQ' => array( 313, 2, 2, 0 ), + 'STEYX' => array( 314, 2, 2, 0 ), + 'SLOPE' => array( 315, 2, 2, 0 ), + 'TTEST' => array( 316, 4, 2, 0 ), + 'PROB' => array( 317, -1, 2, 0 ), + 'DEVSQ' => array( 318, -1, 0, 0 ), + 'GEOMEAN' => array( 319, -1, 0, 0 ), + 'HARMEAN' => array( 320, -1, 0, 0 ), + 'SUMSQ' => array( 321, -1, 0, 0 ), + 'KURT' => array( 322, -1, 0, 0 ), + 'SKEW' => array( 323, -1, 0, 0 ), + 'ZTEST' => array( 324, -1, 0, 0 ), + 'LARGE' => array( 325, 2, 0, 0 ), + 'SMALL' => array( 326, 2, 0, 0 ), + 'QUARTILE' => array( 327, 2, 0, 0 ), + 'PERCENTILE' => array( 328, 2, 0, 0 ), + 'PERCENTRANK' => array( 329, -1, 0, 0 ), + 'MODE' => array( 330, -1, 2, 0 ), + 'TRIMMEAN' => array( 331, 2, 0, 0 ), + 'TINV' => array( 332, 2, 1, 0 ), + 'CONCATENATE' => array( 336, -1, 1, 0 ), + 'POWER' => array( 337, 2, 1, 0 ), + 'RADIANS' => array( 342, 1, 1, 0 ), + 'DEGREES' => array( 343, 1, 1, 0 ), + 'SUBTOTAL' => array( 344, -1, 0, 0 ), + 'SUMIF' => array( 345, -1, 0, 0 ), + 'COUNTIF' => array( 346, 2, 0, 0 ), + 'COUNTBLANK' => array( 347, 1, 0, 0 ), + 'ISPMT' => array( 350, 4, 1, 0 ), + 'DATEDIF' => array( 351, 3, 1, 0 ), + 'DATESTRING' => array( 352, 1, 1, 0 ), + 'NUMBERSTRING' => array( 353, 2, 1, 0 ), + 'ROMAN' => array( 354, -1, 1, 0 ), + 'GETPIVOTDATA' => array( 358, -1, 0, 0 ), + 'HYPERLINK' => array( 359, -1, 1, 0 ), + 'PHONETIC' => array( 360, 1, 0, 0 ), + 'AVERAGEA' => array( 361, -1, 0, 0 ), + 'MAXA' => array( 362, -1, 0, 0 ), + 'MINA' => array( 363, -1, 0, 0 ), + 'STDEVPA' => array( 364, -1, 0, 0 ), + 'VARPA' => array( 365, -1, 0, 0 ), + 'STDEVA' => array( 366, -1, 0, 0 ), + 'VARA' => array( 367, -1, 0, 0 ), + 'BAHTTEXT' => array( 368, 1, 0, 0 ), + ); + } - /** - * Convert a token to the proper ptg value. - * - * @access private - * @param mixed $token The token to convert. - * @return mixed the converted token on success - */ - function _convert($token) - { - if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $token)) { - return $this->_convertString($token); + /** + * Convert a token to the proper ptg value. + * + * @access private + * @param mixed $token The token to convert. + * @return mixed the converted token on success + */ + function _convert($token) + { + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $token)) { + return $this->_convertString($token); - } elseif (is_numeric($token)) { - return $this->_convertNumber($token); + } elseif (is_numeric($token)) { + return $this->_convertNumber($token); - // match references like A1 or $A$1 - } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { - return $this->_convertRef2d($token); + // match references like A1 or $A$1 + } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { + return $this->_convertRef2d($token); - // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 - } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { - return $this->_convertRef3d($token); + // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); - // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 - } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { - return $this->_convertRef3d($token); + // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); - // match ranges like A1:B2 or $A$1:$B$2 - } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) { - return $this->_convertRange2d($token); + // match ranges like A1:B2 or $A$1:$B$2 + } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) { + return $this->_convertRange2d($token); - // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 - } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { - return $this->_convertRange3d($token); + // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); - // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 - } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { - return $this->_convertRange3d($token); + // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); - // operators (including parentheses) - } elseif (isset($this->ptg[$token])) { - return pack("C", $this->ptg[$token]); + // operators (including parentheses) + } elseif (isset($this->ptg[$token])) { + return pack("C", $this->ptg[$token]); // match error codes - } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') { - return $this->_convertError($token); + } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') { + return $this->_convertError($token); - // commented so argument number can be processed correctly. See toReversePolish(). - /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token)) - { - return($this->_convertFunction($token,$this->_func_args)); - }*/ + // commented so argument number can be processed correctly. See toReversePolish(). + /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token)) + { + return($this->_convertFunction($token,$this->_func_args)); + }*/ - // if it's an argument, ignore the token (the argument remains) - } elseif ($token == 'arg') { - return ''; - } + // if it's an argument, ignore the token (the argument remains) + } elseif ($token == 'arg') { + return ''; + } - // TODO: use real error codes - throw new PHPExcel_Writer_Exception("Unknown token $token"); - } + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown token $token"); + } - /** - * Convert a number token to ptgInt or ptgNum - * - * @access private - * @param mixed $num an integer or double for conversion to its ptg value - */ - function _convertNumber($num) - { - // Integer in the range 0..2**16-1 - if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) { - return pack("Cv", $this->ptg['ptgInt'], $num); - } else { // A float - if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) { // if it's Big Endian - $num = strrev($num); - } - return pack("Cd", $this->ptg['ptgNum'], $num); - } - } + /** + * Convert a number token to ptgInt or ptgNum + * + * @access private + * @param mixed $num an integer or double for conversion to its ptg value + */ + function _convertNumber($num) + { + // Integer in the range 0..2**16-1 + if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) { + return pack("Cv", $this->ptg['ptgInt'], $num); + } else { // A float + if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) { // if it's Big Endian + $num = strrev($num); + } + return pack("Cd", $this->ptg['ptgNum'], $num); + } + } - /** - * Convert a string token to ptgStr - * - * @access private - * @param string $string A string for conversion to its ptg value. - * @return mixed the converted token on success - */ - function _convertString($string) - { - // chop away beggining and ending quotes - $string = substr($string, 1, strlen($string) - 2); - if (strlen($string) > 255) { - throw new PHPExcel_Writer_Exception("String is too long"); - } + /** + * Convert a string token to ptgStr + * + * @access private + * @param string $string A string for conversion to its ptg value. + * @return mixed the converted token on success + */ + function _convertString($string) + { + // chop away beggining and ending quotes + $string = substr($string, 1, strlen($string) - 2); + if (strlen($string) > 255) { + throw new PHPExcel_Writer_Exception("String is too long"); + } - return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string); - } + return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string); + } - /** - * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of - * args that it takes. - * - * @access private - * @param string $token The name of the function for convertion to ptg value. - * @param integer $num_args The number of arguments the function receives. - * @return string The packed ptg for the function - */ - function _convertFunction($token, $num_args) - { - $args = $this->_functions[$token][1]; -// $volatile = $this->_functions[$token][3]; + /** + * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of + * args that it takes. + * + * @access private + * @param string $token The name of the function for convertion to ptg value. + * @param integer $num_args The number of arguments the function receives. + * @return string The packed ptg for the function + */ + function _convertFunction($token, $num_args) + { + $args = $this->_functions[$token][1]; +// $volatile = $this->_functions[$token][3]; - // Fixed number of args eg. TIME($i,$j,$k). - if ($args >= 0) { - return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]); - } - // Variable number of args eg. SUM($i,$j,$k, ..). - if ($args == -1) { - return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]); - } - } + // Fixed number of args eg. TIME($i,$j,$k). + if ($args >= 0) { + return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]); + } + // Variable number of args eg. SUM($i,$j,$k, ..). + if ($args == -1) { + return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]); + } + } - /** - * Convert an Excel range such as A1:D4 to a ptgRefV. - * - * @access private - * @param string $range An Excel range in the A1:A2 - * @param int $class - */ - function _convertRange2d($range, $class=0) - { + /** + * Convert an Excel range such as A1:D4 to a ptgRefV. + * + * @access private + * @param string $range An Excel range in the A1:A2 + * @param int $class + */ + function _convertRange2d($range, $class=0) + { - // TODO: possible class value 0,1,2 check Formula.pm - // 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) = explode(':', $range); - } else { - // TODO: use real error codes - throw new PHPExcel_Writer_Exception("Unknown range separator"); - } + // TODO: possible class value 0,1,2 check Formula.pm + // 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) = explode(':', $range); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown range separator"); + } - // Convert the cell references - list($row1, $col1) = $this->_cellToPackedRowcol($cell1); - list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + // Convert the cell references + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); - // The ptg value depends on the class of the ptg. - if ($class == 0) { - $ptgArea = pack("C", $this->ptg['ptgArea']); - } elseif ($class == 1) { - $ptgArea = pack("C", $this->ptg['ptgAreaV']); - } elseif ($class == 2) { - $ptgArea = pack("C", $this->ptg['ptgAreaA']); - } else { - // TODO: use real error codes - throw new PHPExcel_Writer_Exception("Unknown class $class"); - } - return $ptgArea . $row1 . $row2 . $col1. $col2; - } + // The ptg value depends on the class of the ptg. + if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea']); + } elseif ($class == 1) { + $ptgArea = pack("C", $this->ptg['ptgAreaV']); + } elseif ($class == 2) { + $ptgArea = pack("C", $this->ptg['ptgAreaA']); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown class $class"); + } + return $ptgArea . $row1 . $row2 . $col1. $col2; + } - /** - * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to - * a ptgArea3d. - * - * @access private - * @param string $token An Excel range in the Sheet1!A1:A2 format. - * @return mixed The packed ptgArea3d token on success. - */ - function _convertRange3d($token) - { -// $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B) + /** + * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to + * a ptgArea3d. + * + * @access private + * @param string $token An Excel range in the Sheet1!A1:A2 format. + * @return mixed The packed ptgArea3d token on success. + */ + function _convertRange3d($token) + { +// $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B) - // Split the ref at the ! symbol - list($ext_ref, $range) = explode('!', $token); + // Split the ref at the ! symbol + list($ext_ref, $range) = explode('!', $token); - // Convert the external reference part (different for BIFF8) - $ext_ref = $this->_getRefIndex($ext_ref); + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); - // Split the range into 2 cell refs - list($cell1, $cell2) = explode(':', $range); + // Split the range into 2 cell refs + list($cell1, $cell2) = explode(':', $range); - // Convert the cell references - if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { - list($row1, $col1) = $this->_cellToPackedRowcol($cell1); - list($row2, $col2) = $this->_cellToPackedRowcol($cell2); - } else { // It's a rows range (like 26:27) - list($row1, $col1, $row2, $col2) = $this->_rangeToPackedRange($cell1.':'.$cell2); - } + // Convert the cell references + if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + } else { // It's a rows range (like 26:27) + list($row1, $col1, $row2, $col2) = $this->_rangeToPackedRange($cell1.':'.$cell2); + } - // The ptg value depends on the class of the ptg. -// if ($class == 0) { - $ptgArea = pack("C", $this->ptg['ptgArea3d']); -// } elseif ($class == 1) { -// $ptgArea = pack("C", $this->ptg['ptgArea3dV']); -// } elseif ($class == 2) { -// $ptgArea = pack("C", $this->ptg['ptgArea3dA']); -// } else { -// throw new PHPExcel_Writer_Exception("Unknown class $class"); -// } + // The ptg value depends on the class of the ptg. +// if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea3d']); +// } elseif ($class == 1) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dV']); +// } elseif ($class == 2) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } - return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; - } + return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; + } - /** - * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV. - * - * @access private - * @param string $cell An Excel cell reference - * @return string The cell in packed() format with the corresponding ptg - */ - function _convertRef2d($cell) - { -// $class = 2; // as far as I know, this is magick. + /** + * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV. + * + * @access private + * @param string $cell An Excel cell reference + * @return string The cell in packed() format with the corresponding ptg + */ + function _convertRef2d($cell) + { +// $class = 2; // as far as I know, this is magick. - // Convert the cell reference - $cell_array = $this->_cellToPackedRowcol($cell); - list($row, $col) = $cell_array; + // Convert the cell reference + $cell_array = $this->_cellToPackedRowcol($cell); + list($row, $col) = $cell_array; - // The ptg value depends on the class of the ptg. -// if ($class == 0) { -// $ptgRef = pack("C", $this->ptg['ptgRef']); -// } elseif ($class == 1) { -// $ptgRef = pack("C", $this->ptg['ptgRefV']); -// } elseif ($class == 2) { - $ptgRef = pack("C", $this->ptg['ptgRefA']); -// } else { -// // TODO: use real error codes -// throw new PHPExcel_Writer_Exception("Unknown class $class"); -// } - return $ptgRef.$row.$col; - } + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRefV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRefA']); +// } else { +// // TODO: use real error codes +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + return $ptgRef.$row.$col; + } - /** - * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a - * ptgRef3d. - * - * @access private - * @param string $cell An Excel cell reference - * @return mixed The packed ptgRef3d token on success. - */ - function _convertRef3d($cell) - { -// $class = 2; // as far as I know, this is magick. + /** + * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a + * ptgRef3d. + * + * @access private + * @param string $cell An Excel cell reference + * @return mixed The packed ptgRef3d token on success. + */ + function _convertRef3d($cell) + { +// $class = 2; // as far as I know, this is magick. - // Split the ref at the ! symbol - list($ext_ref, $cell) = explode('!', $cell); + // Split the ref at the ! symbol + list($ext_ref, $cell) = explode('!', $cell); - // Convert the external reference part (different for BIFF8) - $ext_ref = $this->_getRefIndex($ext_ref); + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); - // Convert the cell reference part - list($row, $col) = $this->_cellToPackedRowcol($cell); + // Convert the cell reference part + list($row, $col) = $this->_cellToPackedRowcol($cell); - // The ptg value depends on the class of the ptg. -// if ($class == 0) { -// $ptgRef = pack("C", $this->ptg['ptgRef3d']); -// } elseif ($class == 1) { -// $ptgRef = pack("C", $this->ptg['ptgRef3dV']); -// } elseif ($class == 2) { - $ptgRef = pack("C", $this->ptg['ptgRef3dA']); -// } else { -// throw new PHPExcel_Writer_Exception("Unknown class $class"); -// } + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef3d']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRef3dV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRef3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } - return $ptgRef . $ext_ref. $row . $col; - } + return $ptgRef . $ext_ref. $row . $col; + } /** * Convert an error code to a ptgErr * - * @access private - * @param string $errorCode The error code for conversion to its ptg value - * @return string The error code ptgErr + * @access private + * @param string $errorCode The error code for conversion to its ptg value + * @return string The error code ptgErr */ function _convertError($errorCode) { - switch ($errorCode) { - case '#NULL!': return pack("C", 0x00); - case '#DIV/0!': return pack("C", 0x07); - case '#VALUE!': return pack("C", 0x0F); - case '#REF!': return pack("C", 0x17); - case '#NAME?': return pack("C", 0x1D); - case '#NUM!': return pack("C", 0x24); - case '#N/A': return pack("C", 0x2A); - } - return pack("C", 0xFF); + switch ($errorCode) { + case '#NULL!': return pack("C", 0x00); + case '#DIV/0!': return pack("C", 0x07); + case '#VALUE!': return pack("C", 0x0F); + case '#REF!': return pack("C", 0x17); + case '#NAME?': return pack("C", 0x1D); + case '#NUM!': return pack("C", 0x24); + case '#N/A': return pack("C", 0x2A); + } + return pack("C", 0xFF); } - /** - * Convert the sheet name part of an external reference, for example "Sheet1" or - * "Sheet1:Sheet2", to a packed structure. - * - * @access private - * @param string $ext_ref The name of the external reference - * @return string The reference index in packed() format - */ - function _packExtRef($ext_ref) - { - $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. - $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + /** + * Convert the sheet name part of an external reference, for example "Sheet1" or + * "Sheet1:Sheet2", to a packed structure. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return string The reference index in packed() format + */ + function _packExtRef($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. - // Check if there is a sheet range eg., Sheet1:Sheet2. - if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); - $sheet1 = $this->_getSheetIndex($sheet_name1); - if ($sheet1 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); - } - $sheet2 = $this->_getSheetIndex($sheet_name2); - if ($sheet2 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); - } + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } - // Reverse max and min sheet numbers if necessary - if ($sheet1 > $sheet2) { - list($sheet1, $sheet2) = array($sheet2, $sheet1); - } - } else { // Single sheet name only. - $sheet1 = $this->_getSheetIndex($ext_ref); - if ($sheet1 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); - } - $sheet2 = $sheet1; - } + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } - // References are stored relative to 0xFFFF. - $offset = -1 - $sheet1; + // References are stored relative to 0xFFFF. + $offset = -1 - $sheet1; - return pack('vdvv', $offset, 0x00, $sheet1, $sheet2); - } + return pack('vdvv', $offset, 0x00, $sheet1, $sheet2); + } - /** - * Look up the REF index that corresponds to an external sheet name - * (or range). If it doesn't exist yet add it to the workbook's references - * array. It assumes all sheet names given must exist. - * - * @access private - * @param string $ext_ref The name of the external reference - * @return mixed The reference index in packed() format on success - */ - function _getRefIndex($ext_ref) - { - $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. - $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. - $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with ' + /** + * Look up the REF index that corresponds to an external sheet name + * (or range). If it doesn't exist yet add it to the workbook's references + * array. It assumes all sheet names given must exist. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return mixed The reference index in packed() format on success + */ + function _getRefIndex($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with ' - // Check if there is a sheet range eg., Sheet1:Sheet2. - if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); - $sheet1 = $this->_getSheetIndex($sheet_name1); - if ($sheet1 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); - } - $sheet2 = $this->_getSheetIndex($sheet_name2); - if ($sheet2 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); - } + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } - // Reverse max and min sheet numbers if necessary - if ($sheet1 > $sheet2) { - list($sheet1, $sheet2) = array($sheet2, $sheet1); - } - } else { // Single sheet name only. - $sheet1 = $this->_getSheetIndex($ext_ref); - if ($sheet1 == -1) { - throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); - } - $sheet2 = $sheet1; - } + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } - // assume all references belong to this document - $supbook_index = 0x00; - $ref = pack('vvv', $supbook_index, $sheet1, $sheet2); - $total_references = count($this->_references); - $index = -1; - for ($i = 0; $i < $total_references; ++$i) { - if ($ref == $this->_references[$i]) { - $index = $i; - break; - } - } - // if REF was not found add it to references array - if ($index == -1) { - $this->_references[$total_references] = $ref; - $index = $total_references; - } + // assume all references belong to this document + $supbook_index = 0x00; + $ref = pack('vvv', $supbook_index, $sheet1, $sheet2); + $total_references = count($this->_references); + $index = -1; + for ($i = 0; $i < $total_references; ++$i) { + if ($ref == $this->_references[$i]) { + $index = $i; + break; + } + } + // if REF was not found add it to references array + if ($index == -1) { + $this->_references[$total_references] = $ref; + $index = $total_references; + } - return pack('v', $index); - } + return pack('v', $index); + } - /** - * Look up the index that corresponds to an external sheet name. The hash of - * sheet names is updated by the addworksheet() method of the - * PHPExcel_Writer_Excel5_Workbook class. - * - * @access private - * @param string $sheet_name Sheet name - * @return integer The sheet index, -1 if the sheet was not found - */ - function _getSheetIndex($sheet_name) - { - if (!isset($this->_ext_sheets[$sheet_name])) { - return -1; - } else { - return $this->_ext_sheets[$sheet_name]; - } - } + /** + * Look up the index that corresponds to an external sheet name. The hash of + * sheet names is updated by the addworksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access private + * @param string $sheet_name Sheet name + * @return integer The sheet index, -1 if the sheet was not found + */ + function _getSheetIndex($sheet_name) + { + if (!isset($this->_ext_sheets[$sheet_name])) { + return -1; + } else { + return $this->_ext_sheets[$sheet_name]; + } + } - /** - * This method is used to update the array of sheet names. It is - * called by the addWorksheet() method of the - * PHPExcel_Writer_Excel5_Workbook class. - * - * @access public - * @see PHPExcel_Writer_Excel5_Workbook::addWorksheet() - * @param string $name The name of the worksheet being added - * @param integer $index The index of the worksheet being added - */ - function setExtSheet($name, $index) - { - $this->_ext_sheets[$name] = $index; - } + /** + * This method is used to update the array of sheet names. It is + * called by the addWorksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access public + * @see PHPExcel_Writer_Excel5_Workbook::addWorksheet() + * @param string $name The name of the worksheet being added + * @param integer $index The index of the worksheet being added + */ + function setExtSheet($name, $index) + { + $this->_ext_sheets[$name] = $index; + } - /** - * pack() row and column into the required 3 or 4 byte format. - * - * @access private - * @param string $cell The Excel cell reference to be packed - * @return array Array containing the row and column in packed() format - */ - function _cellToPackedRowcol($cell) - { - $cell = strtoupper($cell); - list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); - if ($col >= 256) { - throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255"); - } - if ($row >= 65536) { - throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 "); - } + /** + * pack() row and column into the required 3 or 4 byte format. + * + * @access private + * @param string $cell The Excel cell reference to be packed + * @return array Array containing the row and column in packed() format + */ + function _cellToPackedRowcol($cell) + { + $cell = strtoupper($cell); + list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); + if ($col >= 256) { + throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255"); + } + if ($row >= 65536) { + throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 "); + } - // Set the high bits to indicate if row or col are relative. - $col |= $col_rel << 14; - $col |= $row_rel << 15; - $col = pack('v', $col); + // Set the high bits to indicate if row or col are relative. + $col |= $col_rel << 14; + $col |= $row_rel << 15; + $col = pack('v', $col); - $row = pack('v', $row); + $row = pack('v', $row); - return array($row, $col); - } + return array($row, $col); + } - /** - * pack() row range into the required 3 or 4 byte format. - * Just using maximum col/rows, which is probably not the correct solution - * - * @access private - * @param string $range The Excel range to be packed - * @return array Array containing (row1,col1,row2,col2) in packed() format - */ - function _rangeToPackedRange($range) - { - preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match); - // return absolute rows if there is a $ in the ref - $row1_rel = empty($match[1]) ? 1 : 0; - $row1 = $match[2]; - $row2_rel = empty($match[3]) ? 1 : 0; - $row2 = $match[4]; - // Convert 1-index to zero-index - --$row1; - --$row2; - // Trick poor inocent Excel - $col1 = 0; - $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!) + /** + * pack() row range into the required 3 or 4 byte format. + * Just using maximum col/rows, which is probably not the correct solution + * + * @access private + * @param string $range The Excel range to be packed + * @return array Array containing (row1,col1,row2,col2) in packed() format + */ + function _rangeToPackedRange($range) + { + preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match); + // return absolute rows if there is a $ in the ref + $row1_rel = empty($match[1]) ? 1 : 0; + $row1 = $match[2]; + $row2_rel = empty($match[3]) ? 1 : 0; + $row2 = $match[4]; + // Convert 1-index to zero-index + --$row1; + --$row2; + // Trick poor inocent Excel + $col1 = 0; + $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!) - // FIXME: this changes for BIFF8 - if (($row1 >= 65536) or ($row2 >= 65536)) { - throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 "); - } + // FIXME: this changes for BIFF8 + if (($row1 >= 65536) or ($row2 >= 65536)) { + throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 "); + } - // Set the high bits to indicate if rows are relative. - $col1 |= $row1_rel << 15; - $col2 |= $row2_rel << 15; - $col1 = pack('v', $col1); - $col2 = pack('v', $col2); + // Set the high bits to indicate if rows are relative. + $col1 |= $row1_rel << 15; + $col2 |= $row2_rel << 15; + $col1 = pack('v', $col1); + $col2 = pack('v', $col2); - $row1 = pack('v', $row1); - $row2 = pack('v', $row2); + $row1 = pack('v', $row1); + $row2 = pack('v', $row2); - return array($row1, $col1, $row2, $col2); - } + return array($row1, $col1, $row2, $col2); + } - /** - * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero - * indexed row and column number. Also returns two (0,1) values to indicate - * whether the row or column are relative references. - * - * @access private - * @param string $cell The Excel cell reference in A1 format. - * @return array - */ - function _cellToRowcol($cell) - { - preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match); - // return absolute column if there is a $ in the ref - $col_rel = empty($match[1]) ? 1 : 0; - $col_ref = $match[2]; - $row_rel = empty($match[3]) ? 1 : 0; - $row = $match[4]; + /** + * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero + * indexed row and column number. Also returns two (0,1) values to indicate + * whether the row or column are relative references. + * + * @access private + * @param string $cell The Excel cell reference in A1 format. + * @return array + */ + function _cellToRowcol($cell) + { + preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match); + // return absolute column if there is a $ in the ref + $col_rel = empty($match[1]) ? 1 : 0; + $col_ref = $match[2]; + $row_rel = empty($match[3]) ? 1 : 0; + $row = $match[4]; - // Convert base26 column string to a number. - $expn = strlen($col_ref) - 1; - $col = 0; - $col_ref_length = strlen($col_ref); - for ($i = 0; $i < $col_ref_length; ++$i) { - $col += (ord($col_ref{$i}) - 64) * pow(26, $expn); - --$expn; - } + // Convert base26 column string to a number. + $expn = strlen($col_ref) - 1; + $col = 0; + $col_ref_length = strlen($col_ref); + for ($i = 0; $i < $col_ref_length; ++$i) { + $col += (ord($col_ref{$i}) - 64) * pow(26, $expn); + --$expn; + } - // Convert 1-index to zero-index - --$row; - --$col; + // Convert 1-index to zero-index + --$row; + --$col; - return array($row, $col, $row_rel, $col_rel); - } + return array($row, $col, $row_rel, $col_rel); + } - /** - * Advance to the next valid token. - * - * @access private - */ - function _advance() - { - $i = $this->_current_char; - $formula_length = strlen($this->_formula); - // eat up white spaces - if ($i < $formula_length) { - while ($this->_formula{$i} == " ") { - ++$i; - } + /** + * Advance to the next valid token. + * + * @access private + */ + function _advance() + { + $i = $this->_current_char; + $formula_length = strlen($this->_formula); + // eat up white spaces + if ($i < $formula_length) { + while ($this->_formula{$i} == " ") { + ++$i; + } - if ($i < ($formula_length - 1)) { - $this->_lookahead = $this->_formula{$i+1}; - } - $token = ''; - } + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } + $token = ''; + } - while ($i < $formula_length) { - $token .= $this->_formula{$i}; + while ($i < $formula_length) { + $token .= $this->_formula{$i}; - if ($i < ($formula_length - 1)) { - $this->_lookahead = $this->_formula{$i+1}; - } else { - $this->_lookahead = ''; - } + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } else { + $this->_lookahead = ''; + } - if ($this->_match($token) != '') { - //if ($i < strlen($this->_formula) - 1) { - // $this->_lookahead = $this->_formula{$i+1}; - //} - $this->_current_char = $i + 1; - $this->_current_token = $token; - return 1; - } + if ($this->_match($token) != '') { + //if ($i < strlen($this->_formula) - 1) { + // $this->_lookahead = $this->_formula{$i+1}; + //} + $this->_current_char = $i + 1; + $this->_current_token = $token; + return 1; + } - if ($i < ($formula_length - 2)) { - $this->_lookahead = $this->_formula{$i+2}; - } else { // if we run out of characters _lookahead becomes empty - $this->_lookahead = ''; - } - ++$i; - } - //die("Lexical error ".$this->_current_char); - } + if ($i < ($formula_length - 2)) { + $this->_lookahead = $this->_formula{$i+2}; + } else { // if we run out of characters _lookahead becomes empty + $this->_lookahead = ''; + } + ++$i; + } + //die("Lexical error ".$this->_current_char); + } - /** - * Checks if it's a valid token. - * - * @access private - * @param mixed $token The token to check. - * @return mixed The checked token or false on failure - */ - function _match($token) - { - switch($token) { - case "+": - case "-": - case "*": - case "/": - case "(": - case ")": - case ",": - case ";": - case ">=": - case "<=": - case "=": - case "<>": - case "^": - case "&": - case "%": - return $token; - break; - case ">": - if ($this->_lookahead == '=') { // it's a GE token - break; - } - return $token; - break; - case "<": - // it's a LE or a NE token - if (($this->_lookahead == '=') or ($this->_lookahead == '>')) { - break; - } - return $token; - break; - default: - // if it's a reference A1 or $A$1 or $A1 or A$1 - if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and - !preg_match("/[0-9]/",$this->_lookahead) and - ($this->_lookahead != ':') and ($this->_lookahead != '.') and - ($this->_lookahead != '!')) - { - return $token; - } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) - elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and - !preg_match("/[0-9]/",$this->_lookahead) and - ($this->_lookahead != ':') and ($this->_lookahead != '.')) - { - return $token; - } - // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) - elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and - !preg_match("/[0-9]/",$this->_lookahead) and - ($this->_lookahead != ':') and ($this->_lookahead != '.')) - { - return $token; - } - // if it's a range A1:A2 or $A$1:$A$2 - elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and - !preg_match("/[0-9]/",$this->_lookahead)) - { - return $token; - } - // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 - elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and - !preg_match("/[0-9]/",$this->_lookahead)) - { - return $token; - } - // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 - elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and - !preg_match("/[0-9]/",$this->_lookahead)) - { - return $token; - } - // If it's a number (check that it's not a sheet name or range) - elseif (is_numeric($token) and - (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and - ($this->_lookahead != '!') and ($this->_lookahead != ':')) - { - return $token; - } - // If it's a string (of maximum 255 characters) - elseif (preg_match("/\"([^\"]|\"\"){0,255}\"/",$token) and $this->_lookahead != '"' and (substr_count($token, '"')%2 == 0)) - { - return $token; - } - // If it's an error code - elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') - { - return $token; - } - // if it's a function call - elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) - { - return $token; - } - // It's an argument of some description (e.g. a named range), - // precise nature yet to be determined - elseif(substr($token,-1) == ')') { - return $token; - } - return ''; - } - } + /** + * Checks if it's a valid token. + * + * @access private + * @param mixed $token The token to check. + * @return mixed The checked token or false on failure + */ + function _match($token) + { + switch($token) { + case "+": + case "-": + case "*": + case "/": + case "(": + case ")": + case ",": + case ";": + case ">=": + case "<=": + case "=": + case "<>": + case "^": + case "&": + case "%": + return $token; + break; + case ">": + if ($this->_lookahead == '=') { // it's a GE token + break; + } + return $token; + break; + case "<": + // it's a LE or a NE token + if (($this->_lookahead == '=') or ($this->_lookahead == '>')) { + break; + } + return $token; + break; + default: + // if it's a reference A1 or $A$1 or $A1 or A$1 + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.') and + ($this->_lookahead != '!')) + { + return $token; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // if it's a range A1:A2 or $A$1:$A$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's a number (check that it's not a sheet name or range) + elseif (is_numeric($token) and + (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and + ($this->_lookahead != '!') and ($this->_lookahead != ':')) + { + return $token; + } + // If it's a string (of maximum 255 characters) + elseif (preg_match("/\"([^\"]|\"\"){0,255}\"/",$token) and $this->_lookahead != '"' and (substr_count($token, '"')%2 == 0)) + { + return $token; + } + // If it's an error code + elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') + { + return $token; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) + { + return $token; + } + // It's an argument of some description (e.g. a named range), + // precise nature yet to be determined + elseif(substr($token,-1) == ')') { + return $token; + } + return ''; + } + } - /** - * The parsing method. It parses a formula. - * - * @access public - * @param string $formula The formula to parse, without the initial equal - * sign (=). - * @return mixed true on success - */ - function parse($formula) - { - $this->_current_char = 0; - $this->_formula = $formula; - $this->_lookahead = isset($formula{1}) ? $formula{1} : ''; - $this->_advance(); - $this->_parse_tree = $this->_condition(); - return true; - } + /** + * The parsing method. It parses a formula. + * + * @access public + * @param string $formula The formula to parse, without the initial equal + * sign (=). + * @return mixed true on success + */ + function parse($formula) + { + $this->_current_char = 0; + $this->_formula = $formula; + $this->_lookahead = isset($formula{1}) ? $formula{1} : ''; + $this->_advance(); + $this->_parse_tree = $this->_condition(); + return true; + } - /** - * It parses a condition. It assumes the following rule: - * Cond -> Expr [(">" | "<") Expr] - * - * @access private - * @return mixed The parsed ptg'd tree on success - */ - function _condition() - { - $result = $this->_expression(); - if ($this->_current_token == "<") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgLT', $result, $result2); - } elseif ($this->_current_token == ">") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgGT', $result, $result2); - } elseif ($this->_current_token == "<=") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgLE', $result, $result2); - } elseif ($this->_current_token == ">=") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgGE', $result, $result2); - } elseif ($this->_current_token == "=") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgEQ', $result, $result2); - } elseif ($this->_current_token == "<>") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgNE', $result, $result2); - } elseif ($this->_current_token == "&") { - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgConcat', $result, $result2); - } - return $result; - } + /** + * It parses a condition. It assumes the following rule: + * Cond -> Expr [(">" | "<") Expr] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _condition() + { + $result = $this->_expression(); + if ($this->_current_token == "<") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLT', $result, $result2); + } elseif ($this->_current_token == ">") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGT', $result, $result2); + } elseif ($this->_current_token == "<=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLE', $result, $result2); + } elseif ($this->_current_token == ">=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGE', $result, $result2); + } elseif ($this->_current_token == "=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgEQ', $result, $result2); + } elseif ($this->_current_token == "<>") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgNE', $result, $result2); + } elseif ($this->_current_token == "&") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgConcat', $result, $result2); + } + return $result; + } - /** - * It parses a expression. It assumes the following rule: - * Expr -> Term [("+" | "-") Term] - * -> "string" - * -> "-" Term : Negative value - * -> "+" Term : Positive value - * -> Error code - * - * @access private - * @return mixed The parsed ptg'd tree on success - */ - function _expression() - { - // If it's a string return a string node - if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $this->_current_token)) { - $tmp = str_replace('""', '"', $this->_current_token); - if (($tmp == '"') || ($tmp == '')) $tmp = '""'; // Trap for "" that has been used for an empty string - $result = $this->_createTree($tmp, '', ''); - $this->_advance(); - return $result; + /** + * It parses a expression. It assumes the following rule: + * Expr -> Term [("+" | "-") Term] + * -> "string" + * -> "-" Term : Negative value + * -> "+" Term : Positive value + * -> Error code + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _expression() + { + // If it's a string return a string node + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $this->_current_token)) { + $tmp = str_replace('""', '"', $this->_current_token); + if (($tmp == '"') || ($tmp == '')) $tmp = '""'; // Trap for "" that has been used for an empty string + $result = $this->_createTree($tmp, '', ''); + $this->_advance(); + return $result; // If it's an error code } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $this->_current_token) or $this->_current_token == '#N/A'){ - $result = $this->_createTree($this->_current_token, 'ptgErr', ''); - $this->_advance(); - return $result; - // If it's a negative value + $result = $this->_createTree($this->_current_token, 'ptgErr', ''); + $this->_advance(); + return $result; + // If it's a negative value } elseif ($this->_current_token == "-") { - // catch "-" Term - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgUminus', $result2, ''); - return $result; + // catch "-" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUminus', $result2, ''); + return $result; // If it's a positive value - } elseif ($this->_current_token == "+") { - // catch "+" Term - $this->_advance(); - $result2 = $this->_expression(); - $result = $this->_createTree('ptgUplus', $result2, ''); - return $result; - } - $result = $this->_term(); - while (($this->_current_token == "+") or - ($this->_current_token == "-") or - ($this->_current_token == "^")) { - /**/ - if ($this->_current_token == "+") { - $this->_advance(); - $result2 = $this->_term(); - $result = $this->_createTree('ptgAdd', $result, $result2); - } elseif ($this->_current_token == "-") { - $this->_advance(); - $result2 = $this->_term(); - $result = $this->_createTree('ptgSub', $result, $result2); - } else { - $this->_advance(); - $result2 = $this->_term(); - $result = $this->_createTree('ptgPower', $result, $result2); - } - } - return $result; - } + } elseif ($this->_current_token == "+") { + // catch "+" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUplus', $result2, ''); + return $result; + } + $result = $this->_term(); + while (($this->_current_token == "+") or + ($this->_current_token == "-") or + ($this->_current_token == "^")) { + /**/ + if ($this->_current_token == "+") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgAdd', $result, $result2); + } elseif ($this->_current_token == "-") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgSub', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgPower', $result, $result2); + } + } + return $result; + } - /** - * This function just introduces a ptgParen element in the tree, so that Excel - * doesn't get confused when working with a parenthesized formula afterwards. - * - * @access private - * @see _fact() - * @return array The parsed ptg'd tree - */ - function _parenthesizedExpression() - { - $result = $this->_createTree('ptgParen', $this->_expression(), ''); - return $result; - } + /** + * This function just introduces a ptgParen element in the tree, so that Excel + * doesn't get confused when working with a parenthesized formula afterwards. + * + * @access private + * @see _fact() + * @return array The parsed ptg'd tree + */ + function _parenthesizedExpression() + { + $result = $this->_createTree('ptgParen', $this->_expression(), ''); + return $result; + } - /** - * It parses a term. It assumes the following rule: - * Term -> Fact [("*" | "/") Fact] - * - * @access private - * @return mixed The parsed ptg'd tree on success - */ - function _term() - { - $result = $this->_fact(); - while (($this->_current_token == "*") or - ($this->_current_token == "/")) { - /**/ - if ($this->_current_token == "*") { - $this->_advance(); - $result2 = $this->_fact(); - $result = $this->_createTree('ptgMul', $result, $result2); - } else { - $this->_advance(); - $result2 = $this->_fact(); - $result = $this->_createTree('ptgDiv', $result, $result2); - } - } - return $result; - } + /** + * It parses a term. It assumes the following rule: + * Term -> Fact [("*" | "/") Fact] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _term() + { + $result = $this->_fact(); + while (($this->_current_token == "*") or + ($this->_current_token == "/")) { + /**/ + if ($this->_current_token == "*") { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgMul', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgDiv', $result, $result2); + } + } + return $result; + } - /** - * It parses a factor. It assumes the following rule: - * Fact -> ( Expr ) - * | CellRef - * | CellRange - * | Number - * | Function - * - * @access private - * @return mixed The parsed ptg'd tree on success - */ - function _fact() - { - if ($this->_current_token == "(") { - $this->_advance(); // eat the "(" - $result = $this->_parenthesizedExpression(); - if ($this->_current_token != ")") { - throw new PHPExcel_Writer_Exception("')' token expected."); - } - $this->_advance(); // eat the ")" - return $result; - } - // if it's a reference - if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token)) - { - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) - elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) - { - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) - elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) - { - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // if it's a range A1:B2 or $A$1:$B$2 - elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or - preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token)) - { - // must be an error? - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) - elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) - { - // must be an error? - //$result = $this->_current_token; - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) - elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) - { - // must be an error? - //$result = $this->_current_token; - $result = $this->_createTree($this->_current_token, '', ''); - $this->_advance(); - return $result; - } - // If it's a number or a percent - elseif (is_numeric($this->_current_token)) - { - if($this->_lookahead == '%'){ - $result = $this->_createTree('ptgPercent', $this->_current_token, ''); + /** + * It parses a factor. It assumes the following rule: + * Fact -> ( Expr ) + * | CellRef + * | CellRange + * | Number + * | Function + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _fact() + { + if ($this->_current_token == "(") { + $this->_advance(); // eat the "(" + $result = $this->_parenthesizedExpression(); + if ($this->_current_token != ")") { + throw new PHPExcel_Writer_Exception("')' token expected."); + } + $this->_advance(); // eat the ")" + return $result; + } + // if it's a reference + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // if it's a range A1:B2 or $A$1:$B$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or + preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token)) + { + // must be an error? + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's a number or a percent + elseif (is_numeric($this->_current_token)) + { + if($this->_lookahead == '%'){ + $result = $this->_createTree('ptgPercent', $this->_current_token, ''); $this->_advance(); // Skip the percentage operator once we've pre-built that tree - } else { - $result = $this->_createTree($this->_current_token, '', ''); - } - $this->_advance(); - return $result; - } - // if it's a function call - elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) - { - $result = $this->_func(); - return $result; - } - throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token. - ", lookahead: ".$this->_lookahead. - ", current char: ".$this->_current_char); - } + } else { + $result = $this->_createTree($this->_current_token, '', ''); + } + $this->_advance(); + return $result; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) + { + $result = $this->_func(); + return $result; + } + throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token. + ", lookahead: ".$this->_lookahead. + ", current char: ".$this->_current_char); + } - /** - * It parses a function call. It assumes the following rule: - * Func -> ( Expr [,Expr]* ) - * - * @access private - * @return mixed The parsed ptg'd tree on success - */ - function _func() - { - $num_args = 0; // number of arguments received - $function = strtoupper($this->_current_token); - $result = ''; // initialize result - $this->_advance(); - $this->_advance(); // eat the "(" - while ($this->_current_token != ')') { - /**/ - if ($num_args > 0) { - if ($this->_current_token == "," or - $this->_current_token == ";") - { - $this->_advance(); // eat the "," or ";" - } else { - throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ". - "function $function, arg #{$num_args}"); - } - $result2 = $this->_condition(); - $result = $this->_createTree('arg', $result, $result2); - } else { // first argument - $result2 = $this->_condition(); - $result = $this->_createTree('arg', '', $result2); - } - ++$num_args; - } - if (!isset($this->_functions[$function])) { - throw new PHPExcel_Writer_Exception("Function $function() doesn't exist"); - } - $args = $this->_functions[$function][1]; - // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. - if (($args >= 0) and ($args != $num_args)) { - throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() "); - } + /** + * It parses a function call. It assumes the following rule: + * Func -> ( Expr [,Expr]* ) + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _func() + { + $num_args = 0; // number of arguments received + $function = strtoupper($this->_current_token); + $result = ''; // initialize result + $this->_advance(); + $this->_advance(); // eat the "(" + while ($this->_current_token != ')') { + /**/ + if ($num_args > 0) { + if ($this->_current_token == "," or + $this->_current_token == ";") + { + $this->_advance(); // eat the "," or ";" + } else { + throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ". + "function $function, arg #{$num_args}"); + } + $result2 = $this->_condition(); + $result = $this->_createTree('arg', $result, $result2); + } else { // first argument + $result2 = $this->_condition(); + $result = $this->_createTree('arg', '', $result2); + } + ++$num_args; + } + if (!isset($this->_functions[$function])) { + throw new PHPExcel_Writer_Exception("Function $function() doesn't exist"); + } + $args = $this->_functions[$function][1]; + // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. + if (($args >= 0) and ($args != $num_args)) { + throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() "); + } - $result = $this->_createTree($function, $result, $num_args); - $this->_advance(); // eat the ")" - return $result; - } + $result = $this->_createTree($function, $result, $num_args); + $this->_advance(); // eat the ")" + return $result; + } - /** - * Creates a tree. In fact an array which may have one or two arrays (sub-trees) - * as elements. - * - * @access private - * @param mixed $value The value of this node. - * @param mixed $left The left array (sub-tree) or a final node. - * @param mixed $right The right array (sub-tree) or a final node. - * @return array A tree - */ - function _createTree($value, $left, $right) - { - return array('value' => $value, 'left' => $left, 'right' => $right); - } + /** + * Creates a tree. In fact an array which may have one or two arrays (sub-trees) + * as elements. + * + * @access private + * @param mixed $value The value of this node. + * @param mixed $left The left array (sub-tree) or a final node. + * @param mixed $right The right array (sub-tree) or a final node. + * @return array A tree + */ + function _createTree($value, $left, $right) + { + return array('value' => $value, 'left' => $left, 'right' => $right); + } - /** - * Builds a string containing the tree in reverse polish notation (What you - * would use in a HP calculator stack). - * The following tree: - * - * + - * / \ - * 2 3 - * - * produces: "23+" - * - * The following tree: - * - * + - * / \ - * 3 * - * / \ - * 6 A1 - * - * produces: "36A1*+" - * - * In fact all operands, functions, references, etc... are written as ptg's - * - * @access public - * @param array $tree The optional tree to convert. - * @return string The tree in reverse polish notation - */ - function toReversePolish($tree = array()) - { - $polish = ""; // the string we are going to return - if (empty($tree)) { // If it's the first call use _parse_tree - $tree = $this->_parse_tree; - } + /** + * Builds a string containing the tree in reverse polish notation (What you + * would use in a HP calculator stack). + * The following tree: + * + * + + * / \ + * 2 3 + * + * produces: "23+" + * + * The following tree: + * + * + + * / \ + * 3 * + * / \ + * 6 A1 + * + * produces: "36A1*+" + * + * In fact all operands, functions, references, etc... are written as ptg's + * + * @access public + * @param array $tree The optional tree to convert. + * @return string The tree in reverse polish notation + */ + function toReversePolish($tree = array()) + { + $polish = ""; // the string we are going to return + if (empty($tree)) { // If it's the first call use _parse_tree + $tree = $this->_parse_tree; + } - if (is_array($tree['left'])) { - $converted_tree = $this->toReversePolish($tree['left']); - $polish .= $converted_tree; - } elseif ($tree['left'] != '') { // It's a final node - $converted_tree = $this->_convert($tree['left']); - $polish .= $converted_tree; - } - if (is_array($tree['right'])) { - $converted_tree = $this->toReversePolish($tree['right']); - $polish .= $converted_tree; - } elseif ($tree['right'] != '') { // It's a final node - $converted_tree = $this->_convert($tree['right']); - $polish .= $converted_tree; - } - // if it's a function convert it here (so we can set it's arguments) - if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and - !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and - !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and - !is_numeric($tree['value']) and - !isset($this->ptg[$tree['value']])) - { - // left subtree for a function is always an array. - if ($tree['left'] != '') { - $left_tree = $this->toReversePolish($tree['left']); - } else { - $left_tree = ''; - } - // add it's left subtree and return. - return $left_tree.$this->_convertFunction($tree['value'], $tree['right']); - } else { - $converted_tree = $this->_convert($tree['value']); - } - $polish .= $converted_tree; - return $polish; - } + if (is_array($tree['left'])) { + $converted_tree = $this->toReversePolish($tree['left']); + $polish .= $converted_tree; + } elseif ($tree['left'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['left']); + $polish .= $converted_tree; + } + if (is_array($tree['right'])) { + $converted_tree = $this->toReversePolish($tree['right']); + $polish .= $converted_tree; + } elseif ($tree['right'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['right']); + $polish .= $converted_tree; + } + // if it's a function convert it here (so we can set it's arguments) + if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and + !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and + !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and + !is_numeric($tree['value']) and + !isset($this->ptg[$tree['value']])) + { + // left subtree for a function is always an array. + if ($tree['left'] != '') { + $left_tree = $this->toReversePolish($tree['left']); + } else { + $left_tree = ''; + } + // add it's left subtree and return. + return $left_tree.$this->_convertFunction($tree['value'], $tree['right']); + } else { + $converted_tree = $this->_convert($tree['value']); + } + $polish .= $converted_tree; + return $polish; + } } diff --git a/Classes/PHPExcel/Writer/Excel5/Workbook.php b/Classes/PHPExcel/Writer/Excel5/Workbook.php index f1b3cc72..f5a47a43 100644 --- a/Classes/PHPExcel/Writer/Excel5/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel5/Workbook.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -70,1381 +70,1381 @@ */ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { - /** - * Formula parser - * - * @var PHPExcel_Writer_Excel5_Parser - */ - private $_parser; - - /** - * The BIFF file size for the workbook. - * @var integer - * @see _calcSheetOffsets() - */ - public $_biffsize; - - /** - * XF Writers - * @var PHPExcel_Writer_Excel5_Xf[] - */ - private $_xfWriters = array(); - - /** - * Array containing the colour palette - * @var array - */ - public $_palette; - - /** - * The codepage indicates the text encoding used for strings - * @var integer - */ - public $_codepage; - - /** - * The country code used for localization - * @var integer - */ - public $_country_code; - - /** - * Workbook - * @var PHPExcel - */ - private $_phpExcel; - - /** - * Fonts writers - * - * @var PHPExcel_Writer_Excel5_Font[] - */ - private $_fontWriters = array(); - - /** - * Added fonts. Maps from font's hash => index in workbook - * - * @var array - */ - private $_addedFonts = array(); - - /** - * Shared number formats - * - * @var array - */ - private $_numberFormats = array(); - - /** - * Added number formats. Maps from numberFormat's hash => index in workbook - * - * @var array - */ - private $_addedNumberFormats = array(); - - /** - * Sizes of the binary worksheet streams - * - * @var array - */ - private $_worksheetSizes = array(); - - /** - * Offsets of the binary worksheet streams relative to the start of the global workbook stream - * - * @var array - */ - private $_worksheetOffsets = array(); - - /** - * Total number of shared strings in workbook - * - * @var int - */ - private $_str_total; - - /** - * Number of unique shared strings in workbook - * - * @var int - */ - private $_str_unique; - - /** - * Array of unique shared strings in workbook - * - * @var array - */ - private $_str_table; - - /** - * Color cache - */ - private $_colors; - - /** - * Escher object corresponding to MSODRAWINGGROUP - * - * @var PHPExcel_Shared_Escher - */ - private $_escher; - - - /** - * Class constructor - * - * @param PHPExcel $phpExcel The Workbook - * @param int &$str_total Total number of strings - * @param int &$str_unique Total number of unique strings - * @param array &$str_table String Table - * @param array &$colors Colour Table - * @param mixed $parser The formula parser created for the Workbook - */ - public function __construct(PHPExcel $phpExcel = null, - &$str_total, &$str_unique, &$str_table, &$colors, - $parser ) - { - // It needs to call its parent's constructor explicitly - parent::__construct(); - - $this->_parser = $parser; - $this->_biffsize = 0; - $this->_palette = array(); - $this->_country_code = -1; - - $this->_str_total = &$str_total; - $this->_str_unique = &$str_unique; - $this->_str_table = &$str_table; - $this->_colors = &$colors; - $this->_setPaletteXl97(); - - $this->_phpExcel = $phpExcel; - - // set BIFFwriter limit for CONTINUE records - // $this->_limit = 8224; - $this->_codepage = 0x04B0; - - // Add empty sheets and Build color cache - $countSheets = $phpExcel->getSheetCount(); - for ($i = 0; $i < $countSheets; ++$i) { - $phpSheet = $phpExcel->getSheet($i); - - $this->_parser->setExtSheet($phpSheet->getTitle(), $i); // Register worksheet name with parser - - $supbook_index = 0x00; - $ref = pack('vvv', $supbook_index, $i, $i); - $this->_parser->_references[] = $ref; // Register reference with parser - - // Sheet tab colors? - if ($phpSheet->isTabColorSet()) { - $this->_addColor($phpSheet->getTabColor()->getRGB()); - } - } - - } - - /** - * Add a new XF writer - * - * @param PHPExcel_Style - * @param boolean Is it a style XF? - * @return int Index to XF record - */ - public function addXfWriter($style, $isStyleXf = false) - { - $xfWriter = new PHPExcel_Writer_Excel5_Xf($style); - $xfWriter->setIsStyleXf($isStyleXf); - - // Add the font if not already added - $fontIndex = $this->_addFont($style->getFont()); - - // Assign the font index to the xf record - $xfWriter->setFontIndex($fontIndex); - - // Background colors, best to treat these after the font so black will come after white in custom palette - $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); - $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); - $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); - $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); - $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); - $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); - $xfWriter->setDiagColor($this->_addColor($style->getBorders()->getDiagonal()->getColor()->getRGB())); - - // Add the number format if it is not a built-in one and not already added - if ($style->getNumberFormat()->getBuiltInFormatCode() === false) { - $numberFormatHashCode = $style->getNumberFormat()->getHashCode(); - - if (isset($this->_addedNumberFormats[$numberFormatHashCode])) { - $numberFormatIndex = $this->_addedNumberFormats[$numberFormatHashCode]; - } else { - $numberFormatIndex = 164 + count($this->_numberFormats); - $this->_numberFormats[$numberFormatIndex] = $style->getNumberFormat(); - $this->_addedNumberFormats[$numberFormatHashCode] = $numberFormatIndex; - } - } else { - $numberFormatIndex = (int) $style->getNumberFormat()->getBuiltInFormatCode(); - } - - // Assign the number format index to xf record - $xfWriter->setNumberFormatIndex($numberFormatIndex); - - $this->_xfWriters[] = $xfWriter; - - $xfIndex = count($this->_xfWriters) - 1; - return $xfIndex; - } - - /** - * Add a font to added fonts - * - * @param PHPExcel_Style_Font $font - * @return int Index to FONT record - */ - public function _addFont(PHPExcel_Style_Font $font) - { - $fontHashCode = $font->getHashCode(); - if(isset($this->_addedFonts[$fontHashCode])){ - $fontIndex = $this->_addedFonts[$fontHashCode]; - } else { - $countFonts = count($this->_fontWriters); - $fontIndex = ($countFonts < 4) ? $countFonts : $countFonts + 1; - - $fontWriter = new PHPExcel_Writer_Excel5_Font($font); - $fontWriter->setColorIndex($this->_addColor($font->getColor()->getRGB())); - $this->_fontWriters[] = $fontWriter; - - $this->_addedFonts[$fontHashCode] = $fontIndex; - } - return $fontIndex; - } - - /** - * Alter color palette adding a custom color - * - * @param string $rgb E.g. 'FF00AA' - * @return int Color index - */ - private function _addColor($rgb) { - if (!isset($this->_colors[$rgb])) { - if (count($this->_colors) < 57) { - // then we add a custom color altering the palette - $colorIndex = 8 + count($this->_colors); - $this->_palette[$colorIndex] = - array( - hexdec(substr($rgb, 0, 2)), - hexdec(substr($rgb, 2, 2)), - hexdec(substr($rgb, 4)), - 0 - ); - $this->_colors[$rgb] = $colorIndex; - } else { - // no room for more custom colors, just map to black - $colorIndex = 0; - } - } else { - // fetch already added custom color - $colorIndex = $this->_colors[$rgb]; - } - - return $colorIndex; - } - - /** - * Sets the colour palette to the Excel 97+ default. - * - * @access private - */ - function _setPaletteXl97() - { - $this->_palette = array( - 0x08 => array(0x00, 0x00, 0x00, 0x00), - 0x09 => array(0xff, 0xff, 0xff, 0x00), - 0x0A => array(0xff, 0x00, 0x00, 0x00), - 0x0B => array(0x00, 0xff, 0x00, 0x00), - 0x0C => array(0x00, 0x00, 0xff, 0x00), - 0x0D => array(0xff, 0xff, 0x00, 0x00), - 0x0E => array(0xff, 0x00, 0xff, 0x00), - 0x0F => array(0x00, 0xff, 0xff, 0x00), - 0x10 => array(0x80, 0x00, 0x00, 0x00), - 0x11 => array(0x00, 0x80, 0x00, 0x00), - 0x12 => array(0x00, 0x00, 0x80, 0x00), - 0x13 => array(0x80, 0x80, 0x00, 0x00), - 0x14 => array(0x80, 0x00, 0x80, 0x00), - 0x15 => array(0x00, 0x80, 0x80, 0x00), - 0x16 => array(0xc0, 0xc0, 0xc0, 0x00), - 0x17 => array(0x80, 0x80, 0x80, 0x00), - 0x18 => array(0x99, 0x99, 0xff, 0x00), - 0x19 => array(0x99, 0x33, 0x66, 0x00), - 0x1A => array(0xff, 0xff, 0xcc, 0x00), - 0x1B => array(0xcc, 0xff, 0xff, 0x00), - 0x1C => array(0x66, 0x00, 0x66, 0x00), - 0x1D => array(0xff, 0x80, 0x80, 0x00), - 0x1E => array(0x00, 0x66, 0xcc, 0x00), - 0x1F => array(0xcc, 0xcc, 0xff, 0x00), - 0x20 => array(0x00, 0x00, 0x80, 0x00), - 0x21 => array(0xff, 0x00, 0xff, 0x00), - 0x22 => array(0xff, 0xff, 0x00, 0x00), - 0x23 => array(0x00, 0xff, 0xff, 0x00), - 0x24 => array(0x80, 0x00, 0x80, 0x00), - 0x25 => array(0x80, 0x00, 0x00, 0x00), - 0x26 => array(0x00, 0x80, 0x80, 0x00), - 0x27 => array(0x00, 0x00, 0xff, 0x00), - 0x28 => array(0x00, 0xcc, 0xff, 0x00), - 0x29 => array(0xcc, 0xff, 0xff, 0x00), - 0x2A => array(0xcc, 0xff, 0xcc, 0x00), - 0x2B => array(0xff, 0xff, 0x99, 0x00), - 0x2C => array(0x99, 0xcc, 0xff, 0x00), - 0x2D => array(0xff, 0x99, 0xcc, 0x00), - 0x2E => array(0xcc, 0x99, 0xff, 0x00), - 0x2F => array(0xff, 0xcc, 0x99, 0x00), - 0x30 => array(0x33, 0x66, 0xff, 0x00), - 0x31 => array(0x33, 0xcc, 0xcc, 0x00), - 0x32 => array(0x99, 0xcc, 0x00, 0x00), - 0x33 => array(0xff, 0xcc, 0x00, 0x00), - 0x34 => array(0xff, 0x99, 0x00, 0x00), - 0x35 => array(0xff, 0x66, 0x00, 0x00), - 0x36 => array(0x66, 0x66, 0x99, 0x00), - 0x37 => array(0x96, 0x96, 0x96, 0x00), - 0x38 => array(0x00, 0x33, 0x66, 0x00), - 0x39 => array(0x33, 0x99, 0x66, 0x00), - 0x3A => array(0x00, 0x33, 0x00, 0x00), - 0x3B => array(0x33, 0x33, 0x00, 0x00), - 0x3C => array(0x99, 0x33, 0x00, 0x00), - 0x3D => array(0x99, 0x33, 0x66, 0x00), - 0x3E => array(0x33, 0x33, 0x99, 0x00), - 0x3F => array(0x33, 0x33, 0x33, 0x00), - ); - } - - /** - * Assemble worksheets into a workbook and send the BIFF data to an OLE - * storage. - * - * @param array $pWorksheetSizes The sizes in bytes of the binary worksheet streams - * @return string Binary data for workbook stream - */ - public function writeWorkbook($pWorksheetSizes = null) - { - $this->_worksheetSizes = $pWorksheetSizes; - - // Calculate the number of selected worksheet tabs and call the finalization - // methods for each worksheet - $total_worksheets = $this->_phpExcel->getSheetCount(); - - // Add part 1 of the Workbook globals, what goes before the SHEET records - $this->_storeBof(0x0005); - $this->_writeCodepage(); - $this->_writeWindow1(); - - $this->_writeDatemode(); - $this->_writeAllFonts(); - $this->_writeAllNumFormats(); - $this->_writeAllXfs(); - $this->_writeAllStyles(); - $this->_writePalette(); - - // Prepare part 3 of the workbook global stream, what goes after the SHEET records - $part3 = ''; - if ($this->_country_code != -1) { - $part3 .= $this->_writeCountry(); - } - $part3 .= $this->_writeRecalcId(); - - $part3 .= $this->_writeSupbookInternal(); - /* TODO: store external SUPBOOK records and XCT and CRN records - in case of external references for BIFF8 */ - $part3 .= $this->_writeExternsheetBiff8(); - $part3 .= $this->_writeAllDefinedNamesBiff8(); - $part3 .= $this->_writeMsoDrawingGroup(); - $part3 .= $this->_writeSharedStringsTable(); - - $part3 .= $this->writeEof(); - - // Add part 2 of the Workbook globals, the SHEET records - $this->_calcSheetOffsets(); - for ($i = 0; $i < $total_worksheets; ++$i) { - $this->_writeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); - } - - // Add part 3 of the Workbook globals - $this->_data .= $part3; - - return $this->_data; - } - - /** - * Calculate offsets for Worksheet BOF records. - * - * @access private - */ - function _calcSheetOffsets() - { - $boundsheet_length = 10; // fixed length for a BOUNDSHEET record - - // size of Workbook globals part 1 + 3 - $offset = $this->_datasize; - - // add size of Workbook globals part 2, the length of the SHEET records - $total_worksheets = count($this->_phpExcel->getAllSheets()); - foreach ($this->_phpExcel->getWorksheetIterator() as $sheet) { - $offset += $boundsheet_length + strlen(PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheet->getTitle())); - } - - // add the sizes of each of the Sheet substreams, respectively - for ($i = 0; $i < $total_worksheets; ++$i) { - $this->_worksheetOffsets[$i] = $offset; - $offset += $this->_worksheetSizes[$i]; - } - $this->_biffsize = $offset; - } - - /** - * Store the Excel FONT records. - */ - private function _writeAllFonts() - { - foreach ($this->_fontWriters as $fontWriter) { - $this->_append($fontWriter->writeFont()); - } - } - - /** - * Store user defined numerical formats i.e. FORMAT records - */ - private function _writeAllNumFormats() - { - foreach ($this->_numberFormats as $numberFormatIndex => $numberFormat) { - $this->_writeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex); - } - } - - /** - * Write all XF records. - */ - private function _writeAllXfs() - { - foreach ($this->_xfWriters as $xfWriter) { - $this->_append($xfWriter->writeXf()); - } - } - - /** - * Write all STYLE records. - */ - private function _writeAllStyles() - { - $this->_writeStyle(); - } - - /** - * Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for - * the NAME records. - */ - private function _writeExterns() - { - $countSheets = $this->_phpExcel->getSheetCount(); - // Create EXTERNCOUNT with number of worksheets - $this->_writeExterncount($countSheets); - - // Create EXTERNSHEET for each worksheet - for ($i = 0; $i < $countSheets; ++$i) { - $this->_writeExternsheet($this->_phpExcel->getSheet($i)->getTitle()); - } - } - - /** - * Write the NAME record to define the print area and the repeat rows and cols. - */ - private function _writeNames() - { - // total number of sheets - $total_worksheets = $this->_phpExcel->getSheetCount(); - - // Create the print area NAME records - for ($i = 0; $i < $total_worksheets; ++$i) { - $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); - // Write a Name record if the print area has been defined - if ($sheetSetup->isPrintAreaSet()) { - // Print area - $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); - $printArea = $printArea[0]; - $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); - $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); - - $print_rowmin = $printArea[0][1] - 1; - $print_rowmax = $printArea[1][1] - 1; - $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; - $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; - - $this->_writeNameShort( - $i, // sheet index - 0x06, // NAME type - $print_rowmin, - $print_rowmax, - $print_colmin, - $print_colmax - ); - } - } - - // Create the print title NAME records - for ($i = 0; $i < $total_worksheets; ++$i) { - $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); - - // simultaneous repeatColumns repeatRows - if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { - $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); - $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; - $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; - - $repeat = $sheetSetup->getRowsToRepeatAtTop(); - $rowmin = $repeat[0] - 1; - $rowmax = $repeat[1] - 1; - - $this->_writeNameLong( - $i, // sheet index - 0x07, // NAME type - $rowmin, - $rowmax, - $colmin, - $colmax - ); - - // (exclusive) either repeatColumns or repeatRows - } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { - - // Columns to repeat - if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { - $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); - $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; - $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; - } else { - $colmin = 0; - $colmax = 255; - } - - // Rows to repeat - if ($sheetSetup->isRowsToRepeatAtTopSet()) { - $repeat = $sheetSetup->getRowsToRepeatAtTop(); - $rowmin = $repeat[0] - 1; - $rowmax = $repeat[1] - 1; - } else { - $rowmin = 0; - $rowmax = 65535; - } - - $this->_writeNameShort( - $i, // sheet index - 0x07, // NAME type - $rowmin, - $rowmax, - $colmin, - $colmax - ); - } - } - } - - /** - * Writes all the DEFINEDNAME records (BIFF8). - * So far this is only used for repeating rows/columns (print titles) and print areas - */ - private function _writeAllDefinedNamesBiff8() - { - $chunk = ''; - - // Named ranges - if (count($this->_phpExcel->getNamedRanges()) > 0) { - // Loop named ranges - $namedRanges = $this->_phpExcel->getNamedRanges(); - foreach ($namedRanges as $namedRange) { - - // Create absolute coordinate - $range = PHPExcel_Cell::splitRange($namedRange->getRange()); - for ($i = 0; $i < count($range); $i++) { - $range[$i][0] = '\'' . str_replace("'", "''", $namedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); - if (isset($range[$i][1])) { - $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); - } - } - $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 - - // parse formula - try { - $error = $this->_parser->parse($range); - $formulaData = $this->_parser->toReversePolish(); - - // make sure tRef3d is of type tRef3dR (0x3A) - if (isset($formulaData{0}) and ($formulaData{0} == "\x7A" or $formulaData{0} == "\x5A")) { - $formulaData = "\x3A" . substr($formulaData, 1); - } - - if ($namedRange->getLocalOnly()) { - // local scope - $scope = $this->_phpExcel->getIndex($namedRange->getScope()) + 1; - } else { - // global scope - $scope = 0; - } - $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); - - } catch(PHPExcel_Exception $e) { - // do nothing - } - } - } - - // total number of sheets - $total_worksheets = $this->_phpExcel->getSheetCount(); - - // write the print titles (repeating rows, columns), if any - for ($i = 0; $i < $total_worksheets; ++$i) { - $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); - // simultaneous repeatColumns repeatRows - if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { - $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); - $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; - $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; - - $repeat = $sheetSetup->getRowsToRepeatAtTop(); - $rowmin = $repeat[0] - 1; - $rowmax = $repeat[1] - 1; - - // construct formula data manually - $formulaData = pack('Cv', 0x29, 0x17); // tMemFunc - $formulaData .= pack('Cvvvvv', 0x3B, $i, 0, 65535, $colmin, $colmax); // tArea3d - $formulaData .= pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, 0, 255); // tArea3d - $formulaData .= pack('C', 0x10); // tList - - // store the DEFINEDNAME record - $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); - - // (exclusive) either repeatColumns or repeatRows - } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { - - // Columns to repeat - if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { - $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); - $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; - $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; - } else { - $colmin = 0; - $colmax = 255; - } - // Rows to repeat - if ($sheetSetup->isRowsToRepeatAtTopSet()) { - $repeat = $sheetSetup->getRowsToRepeatAtTop(); - $rowmin = $repeat[0] - 1; - $rowmax = $repeat[1] - 1; - } else { - $rowmin = 0; - $rowmax = 65535; - } - - // construct formula data manually because parser does not recognize absolute 3d cell references - $formulaData = pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, $colmin, $colmax); - - // store the DEFINEDNAME record - $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); - } - } - - // write the print areas, if any - for ($i = 0; $i < $total_worksheets; ++$i) { - $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); - if ($sheetSetup->isPrintAreaSet()) { - // Print area, e.g. A3:J6,H1:X20 - $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); - $countPrintArea = count($printArea); - - $formulaData = ''; - for ($j = 0; $j < $countPrintArea; ++$j) { - $printAreaRect = $printArea[$j]; // e.g. A3:J6 - $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); - $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); - - $print_rowmin = $printAreaRect[0][1] - 1; - $print_rowmax = $printAreaRect[1][1] - 1; - $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; - $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; - - // construct formula data manually because parser does not recognize absolute 3d cell references - $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); - - if ($j > 0) { - $formulaData .= pack('C', 0x10); // list operator token ',' - } - } - - // store the DEFINEDNAME record - $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true)); - } - } - - // write autofilters, if any - for ($i = 0; $i < $total_worksheets; ++$i) { - $sheetAutoFilter = $this->_phpExcel->getSheet($i)->getAutoFilter(); - $autoFilterRange = $sheetAutoFilter->getRange(); - if(!empty($autoFilterRange)) { - $rangeBounds = PHPExcel_Cell::rangeBoundaries($autoFilterRange); - - //Autofilter built in name - $name = pack('C', 0x0D); - - $chunk .= $this->writeData($this->_writeShortNameBiff8($name, $i + 1, $rangeBounds, true)); - } - } - - return $chunk; - } - - /** - * Write a DEFINEDNAME record for BIFF8 using explicit binary formula data - * - * @param string $name The name in UTF-8 - * @param string $formulaData The binary formula data - * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global - * @param boolean $isBuiltIn Built-in name? - * @return string Complete binary record data - */ - private function _writeDefinedNameBiff8($name, $formulaData, $sheetIndex = 0, $isBuiltIn = false) - { - $record = 0x0018; - - // option flags - $options = $isBuiltIn ? 0x20 : 0x00; - - // length of the name, character count - $nlen = PHPExcel_Shared_String::CountCharacters($name); - - // name with stripped length field - $name = substr(PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($name), 2); - - // size of the formula (in bytes) - $sz = strlen($formulaData); - - // combine the parts - $data = pack('vCCvvvCCCC', $options, 0, $nlen, $sz, 0, $sheetIndex, 0, 0, 0, 0) - . $name . $formulaData; - $length = strlen($data); - - $header = pack('vv', $record, $length); - - return $header . $data; - } - - /** - * Write a short NAME record - * - * @param string $name - * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global - * @param integer[][] $rangeBounds range boundaries - * @param boolean $isHidden - * @return string Complete binary record data - * */ - private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){ - $record = 0x0018; - - // option flags - $options = ($isHidden ? 0x21 : 0x00); - - $extra = pack('Cvvvvv', - 0x3B, - $sheetIndex - 1, - $rangeBounds[0][1] - 1, - $rangeBounds[1][1] - 1, - $rangeBounds[0][0] - 1, - $rangeBounds[1][0] - 1); - - // size of the formula (in bytes) - $sz = strlen($extra); - - // combine the parts - $data = pack('vCCvvvCCCCC', $options, 0, 1, $sz, 0, $sheetIndex, 0, 0, 0, 0, 0) - . $name . $extra; - $length = strlen($data); - - $header = pack('vv', $record, $length); - - return $header . $data; - } - - /** - * Stores the CODEPAGE biff record. - */ - private function _writeCodepage() - { - $record = 0x0042; // Record identifier - $length = 0x0002; // Number of bytes to follow - $cv = $this->_codepage; // The code page - - $header = pack('vv', $record, $length); - $data = pack('v', $cv); - - $this->_append($header . $data); - } - - /** - * Write Excel BIFF WINDOW1 record. - */ - private function _writeWindow1() - { - $record = 0x003D; // Record identifier - $length = 0x0012; // Number of bytes to follow - - $xWn = 0x0000; // Horizontal position of window - $yWn = 0x0000; // Vertical position of window - $dxWn = 0x25BC; // Width of window - $dyWn = 0x1572; // Height of window - - $grbit = 0x0038; // Option flags - - // not supported by PHPExcel, so there is only one selected sheet, the active - $ctabsel = 1; // Number of workbook tabs selected - - $wTabRatio = 0x0258; // Tab to scrollbar ratio - - // not supported by PHPExcel, set to 0 - $itabFirst = 0; // 1st displayed worksheet - $itabCur = $this->_phpExcel->getActiveSheetIndex(); // Active worksheet - - $header = pack("vv", $record, $length); - $data = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn, - $grbit, - $itabCur, $itabFirst, - $ctabsel, $wTabRatio); - $this->_append($header . $data); - } - - /** - * Writes Excel BIFF BOUNDSHEET record. - * - * @param PHPExcel_Worksheet $sheet Worksheet name - * @param integer $offset Location of worksheet BOF - */ - private function _writeBoundsheet($sheet, $offset) - { - $sheetname = $sheet->getTitle(); - $record = 0x0085; // Record identifier - - // sheet state - switch ($sheet->getSheetState()) { - case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; - case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; - case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; - default: $ss = 0x00; break; - } - - // sheet type - $st = 0x00; - - $grbit = 0x0000; // Visibility and sheet type - - $data = pack("VCC", $offset, $ss, $st); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); - - $length = strlen($data); - $header = pack("vv", $record, $length); - $this->_append($header . $data); - } - - /** - * Write Internal SUPBOOK record - */ - private function _writeSupbookInternal() - { - $record = 0x01AE; // Record identifier - $length = 0x0004; // Bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("vv", $this->_phpExcel->getSheetCount(), 0x0401); - return $this->writeData($header . $data); - } - - /** - * Writes the Excel BIFF EXTERNSHEET record. These references are used by - * formulas. - * - */ - private function _writeExternsheetBiff8() - { - $total_references = count($this->_parser->_references); - $record = 0x0017; // Record identifier - $length = 2 + 6 * $total_references; // Number of bytes to follow - - $supbook_index = 0; // FIXME: only using internal SUPBOOK record - $header = pack("vv", $record, $length); - $data = pack('v', $total_references); - for ($i = 0; $i < $total_references; ++$i) { - $data .= $this->_parser->_references[$i]; - } - return $this->writeData($header . $data); - } - - /** - * Write Excel BIFF STYLE records. - */ - private function _writeStyle() - { - $record = 0x0293; // Record identifier - $length = 0x0004; // Bytes to follow - - $ixfe = 0x8000; // Index to cell style XF - $BuiltIn = 0x00; // Built-in style - $iLevel = 0xff; // Outline style level - - $header = pack("vv", $record, $length); - $data = pack("vCC", $ixfe, $BuiltIn, $iLevel); - $this->_append($header . $data); - } - - /** - * Writes Excel FORMAT record for non "built-in" numerical formats. - * - * @param string $format Custom format string - * @param integer $ifmt Format index code - */ - private function _writeNumFormat($format, $ifmt) - { - $record = 0x041E; // Record identifier - - $numberFormatString = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($format); - $length = 2 + strlen($numberFormatString); // Number of bytes to follow - - - $header = pack("vv", $record, $length); - $data = pack("v", $ifmt) . $numberFormatString; - $this->_append($header . $data); - } - - /** - * Write DATEMODE record to indicate the date system in use (1904 or 1900). - */ - private function _writeDatemode() - { - $record = 0x0022; // Record identifier - $length = 0x0002; // Bytes to follow - - $f1904 = (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) ? - 1 : 0; // Flag for 1904 date system - - $header = pack("vv", $record, $length); - $data = pack("v", $f1904); - $this->_append($header . $data); - } - - /** - * Write BIFF record EXTERNCOUNT to indicate the number of external sheet - * references in the workbook. - * - * Excel only stores references to external sheets that are used in NAME. - * The workbook NAME record is required to define the print area and the repeat - * rows and columns. - * - * A similar method is used in Worksheet.php for a slightly different purpose. - * - * @param integer $cxals Number of external references - */ - private function _writeExterncount($cxals) - { - $record = 0x0016; // Record identifier - $length = 0x0002; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("v", $cxals); - $this->_append($header . $data); - } - - /** - * Writes the Excel BIFF EXTERNSHEET record. These references are used by - * formulas. NAME record is required to define the print area and the repeat - * rows and columns. - * - * A similar method is used in Worksheet.php for a slightly different purpose. - * - * @param string $sheetname Worksheet name - */ - private function _writeExternsheet($sheetname) - { - $record = 0x0017; // Record identifier - $length = 0x02 + strlen($sheetname); // Number of bytes to follow - - $cch = strlen($sheetname); // Length of sheet name - $rgch = 0x03; // Filename encoding - - $header = pack("vv", $record, $length); - $data = pack("CC", $cch, $rgch); - $this->_append($header . $data . $sheetname); - } - - /** - * Store the NAME record in the short format that is used for storing the print - * area, repeat rows only and repeat columns only. - * - * @param integer $index Sheet index - * @param integer $type Built-in name type - * @param integer $rowmin Start row - * @param integer $rowmax End row - * @param integer $colmin Start colum - * @param integer $colmax End column - */ - private function _writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) - { - $record = 0x0018; // Record identifier - $length = 0x0024; // Number of bytes to follow - - $grbit = 0x0020; // Option flags - $chKey = 0x00; // Keyboard shortcut - $cch = 0x01; // Length of text name - $cce = 0x0015; // Length of text definition - $ixals = $index + 1; // Sheet index - $itab = $ixals; // Equal to ixals - $cchCustMenu = 0x00; // Length of cust menu text - $cchDescription = 0x00; // Length of description text - $cchHelptopic = 0x00; // Length of help topic text - $cchStatustext = 0x00; // Length of status bar text - $rgch = $type; // Built-in name type - - $unknown03 = 0x3b; - $unknown04 = 0xffff-$index; - $unknown05 = 0x0000; - $unknown06 = 0x0000; - $unknown07 = 0x1087; - $unknown08 = 0x8005; - - $header = pack("vv", $record, $length); - $data = pack("v", $grbit); - $data .= pack("C", $chKey); - $data .= pack("C", $cch); - $data .= pack("v", $cce); - $data .= pack("v", $ixals); - $data .= pack("v", $itab); - $data .= pack("C", $cchCustMenu); - $data .= pack("C", $cchDescription); - $data .= pack("C", $cchHelptopic); - $data .= pack("C", $cchStatustext); - $data .= pack("C", $rgch); - $data .= pack("C", $unknown03); - $data .= pack("v", $unknown04); - $data .= pack("v", $unknown05); - $data .= pack("v", $unknown06); - $data .= pack("v", $unknown07); - $data .= pack("v", $unknown08); - $data .= pack("v", $index); - $data .= pack("v", $index); - $data .= pack("v", $rowmin); - $data .= pack("v", $rowmax); - $data .= pack("C", $colmin); - $data .= pack("C", $colmax); - $this->_append($header . $data); - } - - /** - * Store the NAME record in the long format that is used for storing the repeat - * rows and columns when both are specified. This shares a lot of code with - * _writeNameShort() but we use a separate method to keep the code clean. - * Code abstraction for reuse can be carried too far, and I should know. ;-) - * - * @param integer $index Sheet index - * @param integer $type Built-in name type - * @param integer $rowmin Start row - * @param integer $rowmax End row - * @param integer $colmin Start colum - * @param integer $colmax End column - */ - private function _writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) - { - $record = 0x0018; // Record identifier - $length = 0x003d; // Number of bytes to follow - $grbit = 0x0020; // Option flags - $chKey = 0x00; // Keyboard shortcut - $cch = 0x01; // Length of text name - $cce = 0x002e; // Length of text definition - $ixals = $index + 1; // Sheet index - $itab = $ixals; // Equal to ixals - $cchCustMenu = 0x00; // Length of cust menu text - $cchDescription = 0x00; // Length of description text - $cchHelptopic = 0x00; // Length of help topic text - $cchStatustext = 0x00; // Length of status bar text - $rgch = $type; // Built-in name type - - $unknown01 = 0x29; - $unknown02 = 0x002b; - $unknown03 = 0x3b; - $unknown04 = 0xffff-$index; - $unknown05 = 0x0000; - $unknown06 = 0x0000; - $unknown07 = 0x1087; - $unknown08 = 0x8008; - - $header = pack("vv", $record, $length); - $data = pack("v", $grbit); - $data .= pack("C", $chKey); - $data .= pack("C", $cch); - $data .= pack("v", $cce); - $data .= pack("v", $ixals); - $data .= pack("v", $itab); - $data .= pack("C", $cchCustMenu); - $data .= pack("C", $cchDescription); - $data .= pack("C", $cchHelptopic); - $data .= pack("C", $cchStatustext); - $data .= pack("C", $rgch); - $data .= pack("C", $unknown01); - $data .= pack("v", $unknown02); - // Column definition - $data .= pack("C", $unknown03); - $data .= pack("v", $unknown04); - $data .= pack("v", $unknown05); - $data .= pack("v", $unknown06); - $data .= pack("v", $unknown07); - $data .= pack("v", $unknown08); - $data .= pack("v", $index); - $data .= pack("v", $index); - $data .= pack("v", 0x0000); - $data .= pack("v", 0x3fff); - $data .= pack("C", $colmin); - $data .= pack("C", $colmax); - // Row definition - $data .= pack("C", $unknown03); - $data .= pack("v", $unknown04); - $data .= pack("v", $unknown05); - $data .= pack("v", $unknown06); - $data .= pack("v", $unknown07); - $data .= pack("v", $unknown08); - $data .= pack("v", $index); - $data .= pack("v", $index); - $data .= pack("v", $rowmin); - $data .= pack("v", $rowmax); - $data .= pack("C", 0x00); - $data .= pack("C", 0xff); - // End of data - $data .= pack("C", 0x10); - $this->_append($header . $data); - } - - /** - * Stores the COUNTRY record for localization - * - * @return string - */ - private function _writeCountry() - { - $record = 0x008C; // Record identifier - $length = 4; // Number of bytes to follow - - $header = pack('vv', $record, $length); - /* using the same country code always for simplicity */ - $data = pack('vv', $this->_country_code, $this->_country_code); - //$this->_append($header . $data); - return $this->writeData($header . $data); - } - - /** - * Write the RECALCID record - * - * @return string - */ - private function _writeRecalcId() - { - $record = 0x01C1; // Record identifier - $length = 8; // Number of bytes to follow - - $header = pack('vv', $record, $length); - - // by inspection of real Excel files, MS Office Excel 2007 writes this - $data = pack('VV', 0x000001C1, 0x00001E667); - - return $this->writeData($header . $data); - } - - /** - * Stores the PALETTE biff record. - */ - private function _writePalette() - { - $aref = $this->_palette; - - $record = 0x0092; // Record identifier - $length = 2 + 4 * count($aref); // Number of bytes to follow - $ccv = count($aref); // Number of RGB values to follow - $data = ''; // The RGB data - - // Pack the RGB data - foreach ($aref as $color) { - foreach ($color as $byte) { - $data .= pack("C",$byte); - } - } - - $header = pack("vvv", $record, $length, $ccv); - $this->_append($header . $data); - } - - /** - * Handling of the SST continue blocks is complicated by the need to include an - * additional continuation byte depending on whether the string is split between - * blocks or whether it starts at the beginning of the block. (There are also - * additional complications that will arise later when/if Rich Strings are - * supported). - * - * The Excel documentation says that the SST record should be followed by an - * EXTSST record. The EXTSST record is a hash table that is used to optimise - * access to SST. However, despite the documentation it doesn't seem to be - * required so we will ignore it. - * - * @return string Binary data - */ - private function _writeSharedStringsTable() - { - // maximum size of record data (excluding record header) - $continue_limit = 8224; - - // initialize array of record data blocks - $recordDatas = array(); - - // start SST record data block with total number of strings, total number of unique strings - $recordData = pack("VV", $this->_str_total, $this->_str_unique); - - // loop through all (unique) strings in shared strings table - foreach (array_keys($this->_str_table) as $string) { - - // here $string is a BIFF8 encoded string - - // length = character count - $headerinfo = unpack("vlength/Cencoding", $string); - - // currently, this is always 1 = uncompressed - $encoding = $headerinfo["encoding"]; - - // initialize finished writing current $string - $finished = false; - - while ($finished === false) { - - // normally, there will be only one cycle, but if string cannot immediately be written as is - // there will be need for more than one cylcle, if string longer than one record data block, there - // may be need for even more cycles - - if (strlen($recordData) + strlen($string) <= $continue_limit) { - // then we can write the string (or remainder of string) without any problems - $recordData .= $string; - - if (strlen($recordData) + strlen($string) == $continue_limit) { - // we close the record data block, and initialize a new one - $recordDatas[] = $recordData; - $recordData = ''; - } - - // we are finished writing this string - $finished = true; - } else { - // special treatment writing the string (or remainder of the string) - // If the string is very long it may need to be written in more than one CONTINUE record. - - // check how many bytes more there is room for in the current record - $space_remaining = $continue_limit - strlen($recordData); - - // minimum space needed - // uncompressed: 2 byte string length length field + 1 byte option flags + 2 byte character - // compressed: 2 byte string length length field + 1 byte option flags + 1 byte character - $min_space_needed = ($encoding == 1) ? 5 : 4; - - // We have two cases - // 1. space remaining is less than minimum space needed - // here we must waste the space remaining and move to next record data block - // 2. space remaining is greater than or equal to minimum space needed - // here we write as much as we can in the current block, then move to next record data block - - // 1. space remaining is less than minimum space needed - if ($space_remaining < $min_space_needed) { - // we close the block, store the block data - $recordDatas[] = $recordData; - - // and start new record data block where we start writing the string - $recordData = ''; - - // 2. space remaining is greater than or equal to minimum space needed - } else { - // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below - $effective_space_remaining = $space_remaining; - - // for uncompressed strings, sometimes effective space remaining is reduced by 1 - if ( $encoding == 1 && (strlen($string) - $space_remaining) % 2 == 1 ) { - --$effective_space_remaining; - } - - // one block fininshed, store the block data - $recordData .= substr($string, 0, $effective_space_remaining); - - $string = substr($string, $effective_space_remaining); // for next cycle in while loop - $recordDatas[] = $recordData; - - // start new record data block with the repeated option flags - $recordData = pack('C', $encoding); - } - } - } - } - - // Store the last record data block unless it is empty - // if there was no need for any continue records, this will be the for SST record data block itself - if (strlen($recordData) > 0) { - $recordDatas[] = $recordData; - } - - // combine into one chunk with all the blocks SST, CONTINUE,... - $chunk = ''; - foreach ($recordDatas as $i => $recordData) { - // first block should have the SST record header, remaing should have CONTINUE header - $record = ($i == 0) ? 0x00FC : 0x003C; - - $header = pack("vv", $record, strlen($recordData)); - $data = $header . $recordData; - - $chunk .= $this->writeData($data); - } - - return $chunk; - } - - /** - * Writes the MSODRAWINGGROUP record if needed. Possibly split using CONTINUE records. - */ - private function _writeMsoDrawingGroup() - { - // write the Escher stream if necessary - if (isset($this->_escher)) { - $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); - $data = $writer->close(); - - $record = 0x00EB; - $length = strlen($data); - $header = pack("vv", $record, $length); - - return $this->writeData($header . $data); - - } else { - return ''; - } - } - - /** - * Get Escher object - * - * @return PHPExcel_Shared_Escher - */ - public function getEscher() - { - return $this->_escher; - } - - /** - * Set Escher object - * - * @param PHPExcel_Shared_Escher $pValue - */ - public function setEscher(PHPExcel_Shared_Escher $pValue = null) - { - $this->_escher = $pValue; - } + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * The BIFF file size for the workbook. + * @var integer + * @see _calcSheetOffsets() + */ + public $_biffsize; + + /** + * XF Writers + * @var PHPExcel_Writer_Excel5_Xf[] + */ + private $_xfWriters = array(); + + /** + * Array containing the colour palette + * @var array + */ + public $_palette; + + /** + * The codepage indicates the text encoding used for strings + * @var integer + */ + public $_codepage; + + /** + * The country code used for localization + * @var integer + */ + public $_country_code; + + /** + * Workbook + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Fonts writers + * + * @var PHPExcel_Writer_Excel5_Font[] + */ + private $_fontWriters = array(); + + /** + * Added fonts. Maps from font's hash => index in workbook + * + * @var array + */ + private $_addedFonts = array(); + + /** + * Shared number formats + * + * @var array + */ + private $_numberFormats = array(); + + /** + * Added number formats. Maps from numberFormat's hash => index in workbook + * + * @var array + */ + private $_addedNumberFormats = array(); + + /** + * Sizes of the binary worksheet streams + * + * @var array + */ + private $_worksheetSizes = array(); + + /** + * Offsets of the binary worksheet streams relative to the start of the global workbook stream + * + * @var array + */ + private $_worksheetOffsets = array(); + + /** + * Total number of shared strings in workbook + * + * @var int + */ + private $_str_total; + + /** + * Number of unique shared strings in workbook + * + * @var int + */ + private $_str_unique; + + /** + * Array of unique shared strings in workbook + * + * @var array + */ + private $_str_table; + + /** + * Color cache + */ + private $_colors; + + /** + * Escher object corresponding to MSODRAWINGGROUP + * + * @var PHPExcel_Shared_Escher + */ + private $_escher; + + + /** + * Class constructor + * + * @param PHPExcel $phpExcel The Workbook + * @param int &$str_total Total number of strings + * @param int &$str_unique Total number of unique strings + * @param array &$str_table String Table + * @param array &$colors Colour Table + * @param mixed $parser The formula parser created for the Workbook + */ + public function __construct(PHPExcel $phpExcel = null, + &$str_total, &$str_unique, &$str_table, &$colors, + $parser ) + { + // It needs to call its parent's constructor explicitly + parent::__construct(); + + $this->_parser = $parser; + $this->_biffsize = 0; + $this->_palette = array(); + $this->_country_code = -1; + + $this->_str_total = &$str_total; + $this->_str_unique = &$str_unique; + $this->_str_table = &$str_table; + $this->_colors = &$colors; + $this->_setPaletteXl97(); + + $this->_phpExcel = $phpExcel; + + // set BIFFwriter limit for CONTINUE records + // $this->_limit = 8224; + $this->_codepage = 0x04B0; + + // Add empty sheets and Build color cache + $countSheets = $phpExcel->getSheetCount(); + for ($i = 0; $i < $countSheets; ++$i) { + $phpSheet = $phpExcel->getSheet($i); + + $this->_parser->setExtSheet($phpSheet->getTitle(), $i); // Register worksheet name with parser + + $supbook_index = 0x00; + $ref = pack('vvv', $supbook_index, $i, $i); + $this->_parser->_references[] = $ref; // Register reference with parser + + // Sheet tab colors? + if ($phpSheet->isTabColorSet()) { + $this->_addColor($phpSheet->getTabColor()->getRGB()); + } + } + + } + + /** + * Add a new XF writer + * + * @param PHPExcel_Style + * @param boolean Is it a style XF? + * @return int Index to XF record + */ + public function addXfWriter($style, $isStyleXf = false) + { + $xfWriter = new PHPExcel_Writer_Excel5_Xf($style); + $xfWriter->setIsStyleXf($isStyleXf); + + // Add the font if not already added + $fontIndex = $this->_addFont($style->getFont()); + + // Assign the font index to the xf record + $xfWriter->setFontIndex($fontIndex); + + // Background colors, best to treat these after the font so black will come after white in custom palette + $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); + $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); + $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); + $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); + $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); + $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); + $xfWriter->setDiagColor($this->_addColor($style->getBorders()->getDiagonal()->getColor()->getRGB())); + + // Add the number format if it is not a built-in one and not already added + if ($style->getNumberFormat()->getBuiltInFormatCode() === false) { + $numberFormatHashCode = $style->getNumberFormat()->getHashCode(); + + if (isset($this->_addedNumberFormats[$numberFormatHashCode])) { + $numberFormatIndex = $this->_addedNumberFormats[$numberFormatHashCode]; + } else { + $numberFormatIndex = 164 + count($this->_numberFormats); + $this->_numberFormats[$numberFormatIndex] = $style->getNumberFormat(); + $this->_addedNumberFormats[$numberFormatHashCode] = $numberFormatIndex; + } + } else { + $numberFormatIndex = (int) $style->getNumberFormat()->getBuiltInFormatCode(); + } + + // Assign the number format index to xf record + $xfWriter->setNumberFormatIndex($numberFormatIndex); + + $this->_xfWriters[] = $xfWriter; + + $xfIndex = count($this->_xfWriters) - 1; + return $xfIndex; + } + + /** + * Add a font to added fonts + * + * @param PHPExcel_Style_Font $font + * @return int Index to FONT record + */ + public function _addFont(PHPExcel_Style_Font $font) + { + $fontHashCode = $font->getHashCode(); + if(isset($this->_addedFonts[$fontHashCode])){ + $fontIndex = $this->_addedFonts[$fontHashCode]; + } else { + $countFonts = count($this->_fontWriters); + $fontIndex = ($countFonts < 4) ? $countFonts : $countFonts + 1; + + $fontWriter = new PHPExcel_Writer_Excel5_Font($font); + $fontWriter->setColorIndex($this->_addColor($font->getColor()->getRGB())); + $this->_fontWriters[] = $fontWriter; + + $this->_addedFonts[$fontHashCode] = $fontIndex; + } + return $fontIndex; + } + + /** + * Alter color palette adding a custom color + * + * @param string $rgb E.g. 'FF00AA' + * @return int Color index + */ + private function _addColor($rgb) { + if (!isset($this->_colors[$rgb])) { + if (count($this->_colors) < 57) { + // then we add a custom color altering the palette + $colorIndex = 8 + count($this->_colors); + $this->_palette[$colorIndex] = + array( + hexdec(substr($rgb, 0, 2)), + hexdec(substr($rgb, 2, 2)), + hexdec(substr($rgb, 4)), + 0 + ); + $this->_colors[$rgb] = $colorIndex; + } else { + // no room for more custom colors, just map to black + $colorIndex = 0; + } + } else { + // fetch already added custom color + $colorIndex = $this->_colors[$rgb]; + } + + return $colorIndex; + } + + /** + * Sets the colour palette to the Excel 97+ default. + * + * @access private + */ + function _setPaletteXl97() + { + $this->_palette = array( + 0x08 => array(0x00, 0x00, 0x00, 0x00), + 0x09 => array(0xff, 0xff, 0xff, 0x00), + 0x0A => array(0xff, 0x00, 0x00, 0x00), + 0x0B => array(0x00, 0xff, 0x00, 0x00), + 0x0C => array(0x00, 0x00, 0xff, 0x00), + 0x0D => array(0xff, 0xff, 0x00, 0x00), + 0x0E => array(0xff, 0x00, 0xff, 0x00), + 0x0F => array(0x00, 0xff, 0xff, 0x00), + 0x10 => array(0x80, 0x00, 0x00, 0x00), + 0x11 => array(0x00, 0x80, 0x00, 0x00), + 0x12 => array(0x00, 0x00, 0x80, 0x00), + 0x13 => array(0x80, 0x80, 0x00, 0x00), + 0x14 => array(0x80, 0x00, 0x80, 0x00), + 0x15 => array(0x00, 0x80, 0x80, 0x00), + 0x16 => array(0xc0, 0xc0, 0xc0, 0x00), + 0x17 => array(0x80, 0x80, 0x80, 0x00), + 0x18 => array(0x99, 0x99, 0xff, 0x00), + 0x19 => array(0x99, 0x33, 0x66, 0x00), + 0x1A => array(0xff, 0xff, 0xcc, 0x00), + 0x1B => array(0xcc, 0xff, 0xff, 0x00), + 0x1C => array(0x66, 0x00, 0x66, 0x00), + 0x1D => array(0xff, 0x80, 0x80, 0x00), + 0x1E => array(0x00, 0x66, 0xcc, 0x00), + 0x1F => array(0xcc, 0xcc, 0xff, 0x00), + 0x20 => array(0x00, 0x00, 0x80, 0x00), + 0x21 => array(0xff, 0x00, 0xff, 0x00), + 0x22 => array(0xff, 0xff, 0x00, 0x00), + 0x23 => array(0x00, 0xff, 0xff, 0x00), + 0x24 => array(0x80, 0x00, 0x80, 0x00), + 0x25 => array(0x80, 0x00, 0x00, 0x00), + 0x26 => array(0x00, 0x80, 0x80, 0x00), + 0x27 => array(0x00, 0x00, 0xff, 0x00), + 0x28 => array(0x00, 0xcc, 0xff, 0x00), + 0x29 => array(0xcc, 0xff, 0xff, 0x00), + 0x2A => array(0xcc, 0xff, 0xcc, 0x00), + 0x2B => array(0xff, 0xff, 0x99, 0x00), + 0x2C => array(0x99, 0xcc, 0xff, 0x00), + 0x2D => array(0xff, 0x99, 0xcc, 0x00), + 0x2E => array(0xcc, 0x99, 0xff, 0x00), + 0x2F => array(0xff, 0xcc, 0x99, 0x00), + 0x30 => array(0x33, 0x66, 0xff, 0x00), + 0x31 => array(0x33, 0xcc, 0xcc, 0x00), + 0x32 => array(0x99, 0xcc, 0x00, 0x00), + 0x33 => array(0xff, 0xcc, 0x00, 0x00), + 0x34 => array(0xff, 0x99, 0x00, 0x00), + 0x35 => array(0xff, 0x66, 0x00, 0x00), + 0x36 => array(0x66, 0x66, 0x99, 0x00), + 0x37 => array(0x96, 0x96, 0x96, 0x00), + 0x38 => array(0x00, 0x33, 0x66, 0x00), + 0x39 => array(0x33, 0x99, 0x66, 0x00), + 0x3A => array(0x00, 0x33, 0x00, 0x00), + 0x3B => array(0x33, 0x33, 0x00, 0x00), + 0x3C => array(0x99, 0x33, 0x00, 0x00), + 0x3D => array(0x99, 0x33, 0x66, 0x00), + 0x3E => array(0x33, 0x33, 0x99, 0x00), + 0x3F => array(0x33, 0x33, 0x33, 0x00), + ); + } + + /** + * Assemble worksheets into a workbook and send the BIFF data to an OLE + * storage. + * + * @param array $pWorksheetSizes The sizes in bytes of the binary worksheet streams + * @return string Binary data for workbook stream + */ + public function writeWorkbook($pWorksheetSizes = null) + { + $this->_worksheetSizes = $pWorksheetSizes; + + // Calculate the number of selected worksheet tabs and call the finalization + // methods for each worksheet + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // Add part 1 of the Workbook globals, what goes before the SHEET records + $this->_storeBof(0x0005); + $this->_writeCodepage(); + $this->_writeWindow1(); + + $this->_writeDatemode(); + $this->_writeAllFonts(); + $this->_writeAllNumFormats(); + $this->_writeAllXfs(); + $this->_writeAllStyles(); + $this->_writePalette(); + + // Prepare part 3 of the workbook global stream, what goes after the SHEET records + $part3 = ''; + if ($this->_country_code != -1) { + $part3 .= $this->_writeCountry(); + } + $part3 .= $this->_writeRecalcId(); + + $part3 .= $this->_writeSupbookInternal(); + /* TODO: store external SUPBOOK records and XCT and CRN records + in case of external references for BIFF8 */ + $part3 .= $this->_writeExternsheetBiff8(); + $part3 .= $this->_writeAllDefinedNamesBiff8(); + $part3 .= $this->_writeMsoDrawingGroup(); + $part3 .= $this->_writeSharedStringsTable(); + + $part3 .= $this->writeEof(); + + // Add part 2 of the Workbook globals, the SHEET records + $this->_calcSheetOffsets(); + for ($i = 0; $i < $total_worksheets; ++$i) { + $this->_writeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); + } + + // Add part 3 of the Workbook globals + $this->_data .= $part3; + + return $this->_data; + } + + /** + * Calculate offsets for Worksheet BOF records. + * + * @access private + */ + function _calcSheetOffsets() + { + $boundsheet_length = 10; // fixed length for a BOUNDSHEET record + + // size of Workbook globals part 1 + 3 + $offset = $this->_datasize; + + // add size of Workbook globals part 2, the length of the SHEET records + $total_worksheets = count($this->_phpExcel->getAllSheets()); + foreach ($this->_phpExcel->getWorksheetIterator() as $sheet) { + $offset += $boundsheet_length + strlen(PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheet->getTitle())); + } + + // add the sizes of each of the Sheet substreams, respectively + for ($i = 0; $i < $total_worksheets; ++$i) { + $this->_worksheetOffsets[$i] = $offset; + $offset += $this->_worksheetSizes[$i]; + } + $this->_biffsize = $offset; + } + + /** + * Store the Excel FONT records. + */ + private function _writeAllFonts() + { + foreach ($this->_fontWriters as $fontWriter) { + $this->_append($fontWriter->writeFont()); + } + } + + /** + * Store user defined numerical formats i.e. FORMAT records + */ + private function _writeAllNumFormats() + { + foreach ($this->_numberFormats as $numberFormatIndex => $numberFormat) { + $this->_writeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex); + } + } + + /** + * Write all XF records. + */ + private function _writeAllXfs() + { + foreach ($this->_xfWriters as $xfWriter) { + $this->_append($xfWriter->writeXf()); + } + } + + /** + * Write all STYLE records. + */ + private function _writeAllStyles() + { + $this->_writeStyle(); + } + + /** + * Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for + * the NAME records. + */ + private function _writeExterns() + { + $countSheets = $this->_phpExcel->getSheetCount(); + // Create EXTERNCOUNT with number of worksheets + $this->_writeExterncount($countSheets); + + // Create EXTERNSHEET for each worksheet + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writeExternsheet($this->_phpExcel->getSheet($i)->getTitle()); + } + } + + /** + * Write the NAME record to define the print area and the repeat rows and cols. + */ + private function _writeNames() + { + // total number of sheets + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // Create the print area NAME records + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + // Write a Name record if the print area has been defined + if ($sheetSetup->isPrintAreaSet()) { + // Print area + $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); + $printArea = $printArea[0]; + $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); + $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); + + $print_rowmin = $printArea[0][1] - 1; + $print_rowmax = $printArea[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; + + $this->_writeNameShort( + $i, // sheet index + 0x06, // NAME type + $print_rowmin, + $print_rowmax, + $print_colmin, + $print_colmax + ); + } + } + + // Create the print title NAME records + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + + // simultaneous repeatColumns repeatRows + if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + + $this->_writeNameLong( + $i, // sheet index + 0x07, // NAME type + $rowmin, + $rowmax, + $colmin, + $colmax + ); + + // (exclusive) either repeatColumns or repeatRows + } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { + + // Columns to repeat + if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + } else { + $colmin = 0; + $colmax = 255; + } + + // Rows to repeat + if ($sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + } else { + $rowmin = 0; + $rowmax = 65535; + } + + $this->_writeNameShort( + $i, // sheet index + 0x07, // NAME type + $rowmin, + $rowmax, + $colmin, + $colmax + ); + } + } + } + + /** + * Writes all the DEFINEDNAME records (BIFF8). + * So far this is only used for repeating rows/columns (print titles) and print areas + */ + private function _writeAllDefinedNamesBiff8() + { + $chunk = ''; + + // Named ranges + if (count($this->_phpExcel->getNamedRanges()) > 0) { + // Loop named ranges + $namedRanges = $this->_phpExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + + // Create absolute coordinate + $range = PHPExcel_Cell::splitRange($namedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $namedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 + + // parse formula + try { + $error = $this->_parser->parse($range); + $formulaData = $this->_parser->toReversePolish(); + + // make sure tRef3d is of type tRef3dR (0x3A) + if (isset($formulaData{0}) and ($formulaData{0} == "\x7A" or $formulaData{0} == "\x5A")) { + $formulaData = "\x3A" . substr($formulaData, 1); + } + + if ($namedRange->getLocalOnly()) { + // local scope + $scope = $this->_phpExcel->getIndex($namedRange->getScope()) + 1; + } else { + // global scope + $scope = 0; + } + $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); + + } catch(PHPExcel_Exception $e) { + // do nothing + } + } + } + + // total number of sheets + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // write the print titles (repeating rows, columns), if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + // simultaneous repeatColumns repeatRows + if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + + // construct formula data manually + $formulaData = pack('Cv', 0x29, 0x17); // tMemFunc + $formulaData .= pack('Cvvvvv', 0x3B, $i, 0, 65535, $colmin, $colmax); // tArea3d + $formulaData .= pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, 0, 255); // tArea3d + $formulaData .= pack('C', 0x10); // tList + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); + + // (exclusive) either repeatColumns or repeatRows + } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { + + // Columns to repeat + if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + } else { + $colmin = 0; + $colmax = 255; + } + // Rows to repeat + if ($sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + } else { + $rowmin = 0; + $rowmax = 65535; + } + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData = pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, $colmin, $colmax); + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); + } + } + + // write the print areas, if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + if ($sheetSetup->isPrintAreaSet()) { + // Print area, e.g. A3:J6,H1:X20 + $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); + $countPrintArea = count($printArea); + + $formulaData = ''; + for ($j = 0; $j < $countPrintArea; ++$j) { + $printAreaRect = $printArea[$j]; // e.g. A3:J6 + $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); + + $print_rowmin = $printAreaRect[0][1] - 1; + $print_rowmax = $printAreaRect[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + + if ($j > 0) { + $formulaData .= pack('C', 0x10); // list operator token ',' + } + } + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true)); + } + } + + // write autofilters, if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetAutoFilter = $this->_phpExcel->getSheet($i)->getAutoFilter(); + $autoFilterRange = $sheetAutoFilter->getRange(); + if(!empty($autoFilterRange)) { + $rangeBounds = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + + //Autofilter built in name + $name = pack('C', 0x0D); + + $chunk .= $this->writeData($this->_writeShortNameBiff8($name, $i + 1, $rangeBounds, true)); + } + } + + return $chunk; + } + + /** + * Write a DEFINEDNAME record for BIFF8 using explicit binary formula data + * + * @param string $name The name in UTF-8 + * @param string $formulaData The binary formula data + * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global + * @param boolean $isBuiltIn Built-in name? + * @return string Complete binary record data + */ + private function _writeDefinedNameBiff8($name, $formulaData, $sheetIndex = 0, $isBuiltIn = false) + { + $record = 0x0018; + + // option flags + $options = $isBuiltIn ? 0x20 : 0x00; + + // length of the name, character count + $nlen = PHPExcel_Shared_String::CountCharacters($name); + + // name with stripped length field + $name = substr(PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($name), 2); + + // size of the formula (in bytes) + $sz = strlen($formulaData); + + // combine the parts + $data = pack('vCCvvvCCCC', $options, 0, $nlen, $sz, 0, $sheetIndex, 0, 0, 0, 0) + . $name . $formulaData; + $length = strlen($data); + + $header = pack('vv', $record, $length); + + return $header . $data; + } + + /** + * Write a short NAME record + * + * @param string $name + * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global + * @param integer[][] $rangeBounds range boundaries + * @param boolean $isHidden + * @return string Complete binary record data + * */ + private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){ + $record = 0x0018; + + // option flags + $options = ($isHidden ? 0x21 : 0x00); + + $extra = pack('Cvvvvv', + 0x3B, + $sheetIndex - 1, + $rangeBounds[0][1] - 1, + $rangeBounds[1][1] - 1, + $rangeBounds[0][0] - 1, + $rangeBounds[1][0] - 1); + + // size of the formula (in bytes) + $sz = strlen($extra); + + // combine the parts + $data = pack('vCCvvvCCCCC', $options, 0, 1, $sz, 0, $sheetIndex, 0, 0, 0, 0, 0) + . $name . $extra; + $length = strlen($data); + + $header = pack('vv', $record, $length); + + return $header . $data; + } + + /** + * Stores the CODEPAGE biff record. + */ + private function _writeCodepage() + { + $record = 0x0042; // Record identifier + $length = 0x0002; // Number of bytes to follow + $cv = $this->_codepage; // The code page + + $header = pack('vv', $record, $length); + $data = pack('v', $cv); + + $this->_append($header . $data); + } + + /** + * Write Excel BIFF WINDOW1 record. + */ + private function _writeWindow1() + { + $record = 0x003D; // Record identifier + $length = 0x0012; // Number of bytes to follow + + $xWn = 0x0000; // Horizontal position of window + $yWn = 0x0000; // Vertical position of window + $dxWn = 0x25BC; // Width of window + $dyWn = 0x1572; // Height of window + + $grbit = 0x0038; // Option flags + + // not supported by PHPExcel, so there is only one selected sheet, the active + $ctabsel = 1; // Number of workbook tabs selected + + $wTabRatio = 0x0258; // Tab to scrollbar ratio + + // not supported by PHPExcel, set to 0 + $itabFirst = 0; // 1st displayed worksheet + $itabCur = $this->_phpExcel->getActiveSheetIndex(); // Active worksheet + + $header = pack("vv", $record, $length); + $data = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn, + $grbit, + $itabCur, $itabFirst, + $ctabsel, $wTabRatio); + $this->_append($header . $data); + } + + /** + * Writes Excel BIFF BOUNDSHEET record. + * + * @param PHPExcel_Worksheet $sheet Worksheet name + * @param integer $offset Location of worksheet BOF + */ + private function _writeBoundsheet($sheet, $offset) + { + $sheetname = $sheet->getTitle(); + $record = 0x0085; // Record identifier + + // sheet state + switch ($sheet->getSheetState()) { + case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; + case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; + case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; + default: $ss = 0x00; break; + } + + // sheet type + $st = 0x00; + + $grbit = 0x0000; // Visibility and sheet type + + $data = pack("VCC", $offset, $ss, $st); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); + + $length = strlen($data); + $header = pack("vv", $record, $length); + $this->_append($header . $data); + } + + /** + * Write Internal SUPBOOK record + */ + private function _writeSupbookInternal() + { + $record = 0x01AE; // Record identifier + $length = 0x0004; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", $this->_phpExcel->getSheetCount(), 0x0401); + return $this->writeData($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. + * + */ + private function _writeExternsheetBiff8() + { + $total_references = count($this->_parser->_references); + $record = 0x0017; // Record identifier + $length = 2 + 6 * $total_references; // Number of bytes to follow + + $supbook_index = 0; // FIXME: only using internal SUPBOOK record + $header = pack("vv", $record, $length); + $data = pack('v', $total_references); + for ($i = 0; $i < $total_references; ++$i) { + $data .= $this->_parser->_references[$i]; + } + return $this->writeData($header . $data); + } + + /** + * Write Excel BIFF STYLE records. + */ + private function _writeStyle() + { + $record = 0x0293; // Record identifier + $length = 0x0004; // Bytes to follow + + $ixfe = 0x8000; // Index to cell style XF + $BuiltIn = 0x00; // Built-in style + $iLevel = 0xff; // Outline style level + + $header = pack("vv", $record, $length); + $data = pack("vCC", $ixfe, $BuiltIn, $iLevel); + $this->_append($header . $data); + } + + /** + * Writes Excel FORMAT record for non "built-in" numerical formats. + * + * @param string $format Custom format string + * @param integer $ifmt Format index code + */ + private function _writeNumFormat($format, $ifmt) + { + $record = 0x041E; // Record identifier + + $numberFormatString = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($format); + $length = 2 + strlen($numberFormatString); // Number of bytes to follow + + + $header = pack("vv", $record, $length); + $data = pack("v", $ifmt) . $numberFormatString; + $this->_append($header . $data); + } + + /** + * Write DATEMODE record to indicate the date system in use (1904 or 1900). + */ + private function _writeDatemode() + { + $record = 0x0022; // Record identifier + $length = 0x0002; // Bytes to follow + + $f1904 = (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) ? + 1 : 0; // Flag for 1904 date system + + $header = pack("vv", $record, $length); + $data = pack("v", $f1904); + $this->_append($header . $data); + } + + /** + * Write BIFF record EXTERNCOUNT to indicate the number of external sheet + * references in the workbook. + * + * Excel only stores references to external sheets that are used in NAME. + * The workbook NAME record is required to define the print area and the repeat + * rows and columns. + * + * A similar method is used in Worksheet.php for a slightly different purpose. + * + * @param integer $cxals Number of external references + */ + private function _writeExterncount($cxals) + { + $record = 0x0016; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cxals); + $this->_append($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. NAME record is required to define the print area and the repeat + * rows and columns. + * + * A similar method is used in Worksheet.php for a slightly different purpose. + * + * @param string $sheetname Worksheet name + */ + private function _writeExternsheet($sheetname) + { + $record = 0x0017; // Record identifier + $length = 0x02 + strlen($sheetname); // Number of bytes to follow + + $cch = strlen($sheetname); // Length of sheet name + $rgch = 0x03; // Filename encoding + + $header = pack("vv", $record, $length); + $data = pack("CC", $cch, $rgch); + $this->_append($header . $data . $sheetname); + } + + /** + * Store the NAME record in the short format that is used for storing the print + * area, repeat rows only and repeat columns only. + * + * @param integer $index Sheet index + * @param integer $type Built-in name type + * @param integer $rowmin Start row + * @param integer $rowmax End row + * @param integer $colmin Start colum + * @param integer $colmax End column + */ + private function _writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) + { + $record = 0x0018; // Record identifier + $length = 0x0024; // Number of bytes to follow + + $grbit = 0x0020; // Option flags + $chKey = 0x00; // Keyboard shortcut + $cch = 0x01; // Length of text name + $cce = 0x0015; // Length of text definition + $ixals = $index + 1; // Sheet index + $itab = $ixals; // Equal to ixals + $cchCustMenu = 0x00; // Length of cust menu text + $cchDescription = 0x00; // Length of description text + $cchHelptopic = 0x00; // Length of help topic text + $cchStatustext = 0x00; // Length of status bar text + $rgch = $type; // Built-in name type + + $unknown03 = 0x3b; + $unknown04 = 0xffff-$index; + $unknown05 = 0x0000; + $unknown06 = 0x0000; + $unknown07 = 0x1087; + $unknown08 = 0x8005; + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $data .= pack("C", $chKey); + $data .= pack("C", $cch); + $data .= pack("v", $cce); + $data .= pack("v", $ixals); + $data .= pack("v", $itab); + $data .= pack("C", $cchCustMenu); + $data .= pack("C", $cchDescription); + $data .= pack("C", $cchHelptopic); + $data .= pack("C", $cchStatustext); + $data .= pack("C", $rgch); + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", $rowmin); + $data .= pack("v", $rowmax); + $data .= pack("C", $colmin); + $data .= pack("C", $colmax); + $this->_append($header . $data); + } + + /** + * Store the NAME record in the long format that is used for storing the repeat + * rows and columns when both are specified. This shares a lot of code with + * _writeNameShort() but we use a separate method to keep the code clean. + * Code abstraction for reuse can be carried too far, and I should know. ;-) + * + * @param integer $index Sheet index + * @param integer $type Built-in name type + * @param integer $rowmin Start row + * @param integer $rowmax End row + * @param integer $colmin Start colum + * @param integer $colmax End column + */ + private function _writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) + { + $record = 0x0018; // Record identifier + $length = 0x003d; // Number of bytes to follow + $grbit = 0x0020; // Option flags + $chKey = 0x00; // Keyboard shortcut + $cch = 0x01; // Length of text name + $cce = 0x002e; // Length of text definition + $ixals = $index + 1; // Sheet index + $itab = $ixals; // Equal to ixals + $cchCustMenu = 0x00; // Length of cust menu text + $cchDescription = 0x00; // Length of description text + $cchHelptopic = 0x00; // Length of help topic text + $cchStatustext = 0x00; // Length of status bar text + $rgch = $type; // Built-in name type + + $unknown01 = 0x29; + $unknown02 = 0x002b; + $unknown03 = 0x3b; + $unknown04 = 0xffff-$index; + $unknown05 = 0x0000; + $unknown06 = 0x0000; + $unknown07 = 0x1087; + $unknown08 = 0x8008; + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $data .= pack("C", $chKey); + $data .= pack("C", $cch); + $data .= pack("v", $cce); + $data .= pack("v", $ixals); + $data .= pack("v", $itab); + $data .= pack("C", $cchCustMenu); + $data .= pack("C", $cchDescription); + $data .= pack("C", $cchHelptopic); + $data .= pack("C", $cchStatustext); + $data .= pack("C", $rgch); + $data .= pack("C", $unknown01); + $data .= pack("v", $unknown02); + // Column definition + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", 0x0000); + $data .= pack("v", 0x3fff); + $data .= pack("C", $colmin); + $data .= pack("C", $colmax); + // Row definition + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", $rowmin); + $data .= pack("v", $rowmax); + $data .= pack("C", 0x00); + $data .= pack("C", 0xff); + // End of data + $data .= pack("C", 0x10); + $this->_append($header . $data); + } + + /** + * Stores the COUNTRY record for localization + * + * @return string + */ + private function _writeCountry() + { + $record = 0x008C; // Record identifier + $length = 4; // Number of bytes to follow + + $header = pack('vv', $record, $length); + /* using the same country code always for simplicity */ + $data = pack('vv', $this->_country_code, $this->_country_code); + //$this->_append($header . $data); + return $this->writeData($header . $data); + } + + /** + * Write the RECALCID record + * + * @return string + */ + private function _writeRecalcId() + { + $record = 0x01C1; // Record identifier + $length = 8; // Number of bytes to follow + + $header = pack('vv', $record, $length); + + // by inspection of real Excel files, MS Office Excel 2007 writes this + $data = pack('VV', 0x000001C1, 0x00001E667); + + return $this->writeData($header . $data); + } + + /** + * Stores the PALETTE biff record. + */ + private function _writePalette() + { + $aref = $this->_palette; + + $record = 0x0092; // Record identifier + $length = 2 + 4 * count($aref); // Number of bytes to follow + $ccv = count($aref); // Number of RGB values to follow + $data = ''; // The RGB data + + // Pack the RGB data + foreach ($aref as $color) { + foreach ($color as $byte) { + $data .= pack("C",$byte); + } + } + + $header = pack("vvv", $record, $length, $ccv); + $this->_append($header . $data); + } + + /** + * Handling of the SST continue blocks is complicated by the need to include an + * additional continuation byte depending on whether the string is split between + * blocks or whether it starts at the beginning of the block. (There are also + * additional complications that will arise later when/if Rich Strings are + * supported). + * + * The Excel documentation says that the SST record should be followed by an + * EXTSST record. The EXTSST record is a hash table that is used to optimise + * access to SST. However, despite the documentation it doesn't seem to be + * required so we will ignore it. + * + * @return string Binary data + */ + private function _writeSharedStringsTable() + { + // maximum size of record data (excluding record header) + $continue_limit = 8224; + + // initialize array of record data blocks + $recordDatas = array(); + + // start SST record data block with total number of strings, total number of unique strings + $recordData = pack("VV", $this->_str_total, $this->_str_unique); + + // loop through all (unique) strings in shared strings table + foreach (array_keys($this->_str_table) as $string) { + + // here $string is a BIFF8 encoded string + + // length = character count + $headerinfo = unpack("vlength/Cencoding", $string); + + // currently, this is always 1 = uncompressed + $encoding = $headerinfo["encoding"]; + + // initialize finished writing current $string + $finished = false; + + while ($finished === false) { + + // normally, there will be only one cycle, but if string cannot immediately be written as is + // there will be need for more than one cylcle, if string longer than one record data block, there + // may be need for even more cycles + + if (strlen($recordData) + strlen($string) <= $continue_limit) { + // then we can write the string (or remainder of string) without any problems + $recordData .= $string; + + if (strlen($recordData) + strlen($string) == $continue_limit) { + // we close the record data block, and initialize a new one + $recordDatas[] = $recordData; + $recordData = ''; + } + + // we are finished writing this string + $finished = true; + } else { + // special treatment writing the string (or remainder of the string) + // If the string is very long it may need to be written in more than one CONTINUE record. + + // check how many bytes more there is room for in the current record + $space_remaining = $continue_limit - strlen($recordData); + + // minimum space needed + // uncompressed: 2 byte string length length field + 1 byte option flags + 2 byte character + // compressed: 2 byte string length length field + 1 byte option flags + 1 byte character + $min_space_needed = ($encoding == 1) ? 5 : 4; + + // We have two cases + // 1. space remaining is less than minimum space needed + // here we must waste the space remaining and move to next record data block + // 2. space remaining is greater than or equal to minimum space needed + // here we write as much as we can in the current block, then move to next record data block + + // 1. space remaining is less than minimum space needed + if ($space_remaining < $min_space_needed) { + // we close the block, store the block data + $recordDatas[] = $recordData; + + // and start new record data block where we start writing the string + $recordData = ''; + + // 2. space remaining is greater than or equal to minimum space needed + } else { + // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below + $effective_space_remaining = $space_remaining; + + // for uncompressed strings, sometimes effective space remaining is reduced by 1 + if ( $encoding == 1 && (strlen($string) - $space_remaining) % 2 == 1 ) { + --$effective_space_remaining; + } + + // one block fininshed, store the block data + $recordData .= substr($string, 0, $effective_space_remaining); + + $string = substr($string, $effective_space_remaining); // for next cycle in while loop + $recordDatas[] = $recordData; + + // start new record data block with the repeated option flags + $recordData = pack('C', $encoding); + } + } + } + } + + // Store the last record data block unless it is empty + // if there was no need for any continue records, this will be the for SST record data block itself + if (strlen($recordData) > 0) { + $recordDatas[] = $recordData; + } + + // combine into one chunk with all the blocks SST, CONTINUE,... + $chunk = ''; + foreach ($recordDatas as $i => $recordData) { + // first block should have the SST record header, remaing should have CONTINUE header + $record = ($i == 0) ? 0x00FC : 0x003C; + + $header = pack("vv", $record, strlen($recordData)); + $data = $header . $recordData; + + $chunk .= $this->writeData($data); + } + + return $chunk; + } + + /** + * Writes the MSODRAWINGGROUP record if needed. Possibly split using CONTINUE records. + */ + private function _writeMsoDrawingGroup() + { + // write the Escher stream if necessary + if (isset($this->_escher)) { + $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); + $data = $writer->close(); + + $record = 0x00EB; + $length = strlen($data); + $header = pack("vv", $record, $length); + + return $this->writeData($header . $data); + + } else { + return ''; + } + } + + /** + * Get Escher object + * + * @return PHPExcel_Shared_Escher + */ + public function getEscher() + { + return $this->_escher; + } + + /** + * Set Escher object + * + * @param PHPExcel_Shared_Escher $pValue + */ + public function setEscher(PHPExcel_Shared_Escher $pValue = null) + { + $this->_escher = $pValue; + } } diff --git a/Classes/PHPExcel/Writer/Excel5/Worksheet.php b/Classes/PHPExcel/Writer/Excel5/Worksheet.php index f73ac35a..f869abde 100644 --- a/Classes/PHPExcel/Writer/Excel5/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel5/Worksheet.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -70,3612 +70,3612 @@ */ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter { - /** - * Formula parser - * - * @var PHPExcel_Writer_Excel5_Parser - */ - private $_parser; - - /** - * Maximum number of characters for a string (LABEL record in BIFF5) - * @var integer - */ - public $_xls_strmax; - - /** - * Array containing format information for columns - * @var array - */ - public $_colinfo; - - /** - * Array containing the selected area for the worksheet - * @var array - */ - public $_selection; - - /** - * The active pane for the worksheet - * @var integer - */ - public $_active_pane; - - /** - * Whether to use outline. - * @var integer - */ - public $_outline_on; - - /** - * Auto outline styles. - * @var bool - */ - public $_outline_style; - - /** - * Whether to have outline summary below. - * @var bool - */ - public $_outline_below; - - /** - * Whether to have outline summary at the right. - * @var bool - */ - public $_outline_right; - - /** - * Reference to the total number of strings in the workbook - * @var integer - */ - public $_str_total; - - /** - * Reference to the number of unique strings in the workbook - * @var integer - */ - public $_str_unique; - - /** - * Reference to the array containing all the unique strings in the workbook - * @var array - */ - public $_str_table; - - /** - * Color cache - */ - private $_colors; - - /** - * Index of first used row (at least 0) - * @var int - */ - private $_firstRowIndex; - - /** - * Index of last used row. (no used rows means -1) - * @var int - */ - private $_lastRowIndex; - - /** - * Index of first used column (at least 0) - * @var int - */ - private $_firstColumnIndex; - - /** - * Index of last used column (no used columns means -1) - * @var int - */ - private $_lastColumnIndex; - - /** - * Sheet object - * @var PHPExcel_Worksheet - */ - public $_phpSheet; - - /** - * Count cell style Xfs - * - * @var int - */ - private $_countCellStyleXfs; - - /** - * Escher object corresponding to MSODRAWING - * - * @var PHPExcel_Shared_Escher - */ - private $_escher; - - /** - * Array of font hashes associated to FONT records index - * - * @var array - */ - public $_fntHashIndex; - - /** - * Constructor - * - * @param int &$str_total Total number of strings - * @param int &$str_unique Total number of unique strings - * @param array &$str_table String Table - * @param array &$colors Colour Table - * @param mixed $parser The formula parser created for the Workbook - * @param boolean $preCalculateFormulas Flag indicating whether formulas should be calculated or just written - * @param string $phpSheet The worksheet to write - * @param PHPExcel_Worksheet $phpSheet - */ - public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, - $parser, $preCalculateFormulas, $phpSheet) - { - // It needs to call its parent's constructor explicitly - parent::__construct(); - - // change BIFFwriter limit for CONTINUE records -// $this->_limit = 8224; - - - $this->_preCalculateFormulas = $preCalculateFormulas; - $this->_str_total = &$str_total; - $this->_str_unique = &$str_unique; - $this->_str_table = &$str_table; - $this->_colors = &$colors; - $this->_parser = $parser; - - $this->_phpSheet = $phpSheet; - - //$this->ext_sheets = array(); - //$this->offset = 0; - $this->_xls_strmax = 255; - $this->_colinfo = array(); - $this->_selection = array(0,0,0,0); - $this->_active_pane = 3; - - $this->_print_headers = 0; - - $this->_outline_style = 0; - $this->_outline_below = 1; - $this->_outline_right = 1; - $this->_outline_on = 1; - - $this->_fntHashIndex = array(); - - // calculate values for DIMENSIONS record - $minR = 1; - $minC = 'A'; - - $maxR = $this->_phpSheet->getHighestRow(); - $maxC = $this->_phpSheet->getHighestColumn(); - - // Determine lowest and highest column and row -// $this->_firstRowIndex = ($minR > 65535) ? 65535 : $minR; - $this->_lastRowIndex = ($maxR > 65535) ? 65535 : $maxR ; - - $this->_firstColumnIndex = PHPExcel_Cell::columnIndexFromString($minC); - $this->_lastColumnIndex = PHPExcel_Cell::columnIndexFromString($maxC); - -// if ($this->_firstColumnIndex > 255) $this->_firstColumnIndex = 255; - if ($this->_lastColumnIndex > 255) $this->_lastColumnIndex = 255; - - $this->_countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection()); - } - - /** - * Add data to the beginning of the workbook (note the reverse order) - * and to the end of the workbook. - * - * @access public - * @see PHPExcel_Writer_Excel5_Workbook::storeWorkbook() - */ - function close() - { - $_phpSheet = $this->_phpSheet; - - $num_sheets = $_phpSheet->getParent()->getSheetCount(); - - // Write BOF record - $this->_storeBof(0x0010); - - // Write PRINTHEADERS - $this->_writePrintHeaders(); - - // Write PRINTGRIDLINES - $this->_writePrintGridlines(); - - // Write GRIDSET - $this->_writeGridset(); - - // Calculate column widths - $_phpSheet->calculateColumnWidths(); - - // Column dimensions - if (($defaultWidth = $_phpSheet->getDefaultColumnDimension()->getWidth()) < 0) { - $defaultWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($_phpSheet->getParent()->getDefaultStyle()->getFont()); - } - - $columnDimensions = $_phpSheet->getColumnDimensions(); - $maxCol = $this->_lastColumnIndex -1; - for ($i = 0; $i <= $maxCol; ++$i) { - $hidden = 0; - $level = 0; - $xfIndex = 15; // there are 15 cell style Xfs - - $width = $defaultWidth; - - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i); - if (isset($columnDimensions[$columnLetter])) { - $columnDimension = $columnDimensions[$columnLetter]; - if ($columnDimension->getWidth() >= 0) { - $width = $columnDimension->getWidth(); - } - $hidden = $columnDimension->getVisible() ? 0 : 1; - $level = $columnDimension->getOutlineLevel(); - $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs - } - - // Components of _colinfo: - // $firstcol first column on the range - // $lastcol last column on the range - // $width width to set - // $xfIndex The optional cell style Xf index to apply to the columns - // $hidden The optional hidden atribute - // $level The optional outline level - $this->_colinfo[] = array($i, $i, $width, $xfIndex, $hidden, $level); - } - - // Write GUTS - $this->_writeGuts(); - - // Write DEFAULTROWHEIGHT - $this->_writeDefaultRowHeight(); - - // Write WSBOOL - $this->_writeWsbool(); - - // Write horizontal and vertical page breaks - $this->_writeBreaks(); - - // Write page header - $this->_writeHeader(); - - // Write page footer - $this->_writeFooter(); - - // Write page horizontal centering - $this->_writeHcenter(); - - // Write page vertical centering - $this->_writeVcenter(); - - // Write left margin - $this->_writeMarginLeft(); - - // Write right margin - $this->_writeMarginRight(); - - // Write top margin - $this->_writeMarginTop(); - - // Write bottom margin - $this->_writeMarginBottom(); - - // Write page setup - $this->_writeSetup(); - - // Write sheet protection - $this->_writeProtect(); - - // Write SCENPROTECT - $this->_writeScenProtect(); - - // Write OBJECTPROTECT - $this->_writeObjectProtect(); - - // Write sheet password - $this->_writePassword(); - - // Write DEFCOLWIDTH record - $this->_writeDefcol(); - - // Write the COLINFO records if they exist - if (!empty($this->_colinfo)) { - $colcount = count($this->_colinfo); - for ($i = 0; $i < $colcount; ++$i) { - $this->_writeColinfo($this->_colinfo[$i]); - } - } - $autoFilterRange = $_phpSheet->getAutoFilter()->getRange(); - if (!empty($autoFilterRange)) { - // Write AUTOFILTERINFO - $this->_writeAutoFilterInfo(); - } - - // Write sheet dimensions - $this->_writeDimensions(); - - // Row dimensions - foreach ($_phpSheet->getRowDimensions() as $rowDimension) { - $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs - $this->_writeRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); - } - - // Write Cells - foreach ($_phpSheet->getCellCollection() as $cellID) { - $cell = $_phpSheet->getCell($cellID); - $row = $cell->getRow() - 1; - $column = PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1; - - // Don't break Excel! -// if ($row + 1 > 65536 or $column + 1 > 256) { - if ($row > 65535 || $column > 255) { - break; - } - - // Write cell value - $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs - - $cVal = $cell->getValue(); - if ($cVal instanceof PHPExcel_RichText) { - // $this->_writeString($row, $column, $cVal->getPlainText(), $xfIndex); - $arrcRun = array(); - $str_len = PHPExcel_Shared_String::CountCharacters($cVal->getPlainText(), 'UTF-8'); - $str_pos = 0; - $elements = $cVal->getRichTextElements(); - foreach ($elements as $element) { - // FONT Index - if ($element instanceof PHPExcel_RichText_Run) { - $str_fontidx = $this->_fntHashIndex[$element->getFont()->getHashCode()]; - } - else { - $str_fontidx = 0; - } - $arrcRun[] = array('strlen' => $str_pos, 'fontidx' => $str_fontidx); - // Position FROM - $str_pos += PHPExcel_Shared_String::CountCharacters($element->getText(), 'UTF-8'); - } - $this->_writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun); - } else { - switch ($cell->getDatatype()) { - case PHPExcel_Cell_DataType::TYPE_STRING: - case PHPExcel_Cell_DataType::TYPE_NULL: - if ($cVal === '' || $cVal === null) { - $this->_writeBlank($row, $column, $xfIndex); - } else { - $this->_writeString($row, $column, $cVal, $xfIndex); - } - break; - - case PHPExcel_Cell_DataType::TYPE_NUMERIC: - $this->_writeNumber($row, $column, $cVal, $xfIndex); - break; - - case PHPExcel_Cell_DataType::TYPE_FORMULA: - $calculatedValue = $this->_preCalculateFormulas ? - $cell->getCalculatedValue() : null; - $this->_writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue); - break; - - case PHPExcel_Cell_DataType::TYPE_BOOL: - $this->_writeBoolErr($row, $column, $cVal, 0, $xfIndex); - break; - - case PHPExcel_Cell_DataType::TYPE_ERROR: - $this->_writeBoolErr($row, $column, self::_mapErrorCode($cVal), 1, $xfIndex); - break; - - } - } - } - - // Append - $this->_writeMsoDrawing(); - - // Write WINDOW2 record - $this->_writeWindow2(); - - // Write PLV record - $this->_writePageLayoutView(); - - // Write ZOOM record - $this->_writeZoom(); - if ($_phpSheet->getFreezePane()) { - $this->_writePanes(); - } - - // Write SELECTION record - $this->_writeSelection(); - - // Write MergedCellsTable Record - $this->_writeMergedCells(); - - // Hyperlinks - foreach ($_phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { - list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinate); - - $url = $hyperlink->getUrl(); - - if ( strpos($url, 'sheet://') !== false ) { - // internal to current workbook - $url = str_replace('sheet://', 'internal:', $url); - - } else if ( preg_match('/^(http:|https:|ftp:|mailto:)/', $url) ) { - // URL - // $url = $url; - - } else { - // external (local file) - $url = 'external:' . $url; - } - - $this->_writeUrl($row - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); - } - - $this->_writeDataValidity(); - $this->_writeSheetLayout(); - - // Write SHEETPROTECTION record - $this->_writeSheetProtection(); - $this->_writeRangeProtection(); - - $arrConditionalStyles = $_phpSheet->getConditionalStylesCollection(); - if(!empty($arrConditionalStyles)){ - $arrConditional = array(); - // @todo CFRule & CFHeader - // Write CFHEADER record - $this->_writeCFHeader(); - // Write ConditionalFormattingTable records - foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) { - foreach ($conditionalStyles as $conditional) { - if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION - || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ - if(!in_array($conditional->getHashCode(), $arrConditional)){ - $arrConditional[] = $conditional->getHashCode(); - // Write CFRULE record - $this->_writeCFRule($conditional); - } - } - } - } - } - - $this->_storeEof(); - } - - /** - * Write a cell range address in BIFF8 - * always fixed range - * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format - * - * @param string $range E.g. 'A1' or 'A1:B6' - * @return string Binary data - */ - private function _writeBIFF8CellRangeAddressFixed($range = 'A1') - { - $explodes = explode(':', $range); - - // extract first cell, e.g. 'A1' - $firstCell = $explodes[0]; - - // extract last cell, e.g. 'B6' - if (count($explodes) == 1) { - $lastCell = $firstCell; - } else { - $lastCell = $explodes[1]; - } - - $firstCellCoordinates = PHPExcel_Cell::coordinateFromString($firstCell); // e.g. array(0, 1) - $lastCellCoordinates = PHPExcel_Cell::coordinateFromString($lastCell); // e.g. array(1, 6) - - return(pack('vvvv', - $firstCellCoordinates[1] - 1, - $lastCellCoordinates[1] - 1, - PHPExcel_Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, - PHPExcel_Cell::columnIndexFromString($lastCellCoordinates[0]) - 1 - )); - } - - /** - * Retrieves data from memory in one chunk, or from disk in $buffer - * sized chunks. - * - * @return string The data - */ - function getData() - { - $buffer = 4096; - - // Return data stored in memory - if (isset($this->_data)) { - $tmp = $this->_data; - unset($this->_data); - return $tmp; - } - // No data to return - return false; - } - - /** - * Set the option to print the row and column headers on the printed page. - * - * @access public - * @param integer $print Whether to print the headers or not. Defaults to 1 (print). - */ - function printRowColHeaders($print = 1) - { - $this->_print_headers = $print; - } - - /** - * This method sets the properties for outlining and grouping. The defaults - * correspond to Excel's defaults. - * - * @param bool $visible - * @param bool $symbols_below - * @param bool $symbols_right - * @param bool $auto_style - */ - function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false) - { - $this->_outline_on = $visible; - $this->_outline_below = $symbols_below; - $this->_outline_right = $symbols_right; - $this->_outline_style = $auto_style; - - // Ensure this is a boolean vale for Window2 - if ($this->_outline_on) { - $this->_outline_on = 1; - } - } - - /** - * Write a double to the specified row and column (zero indexed). - * An integer can be written as a double. Excel will display an - * integer. $format is optional. - * - * Returns 0 : normal termination - * -2 : row or column out of range - * - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param float $num The number to write - * @param mixed $xfIndex The optional XF format - * @return integer - */ - private function _writeNumber($row, $col, $num, $xfIndex) - { - $record = 0x0203; // Record identifier - $length = 0x000E; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("vvv", $row, $col, $xfIndex); - $xl_double = pack("d", $num); - if (self::getByteOrder()) { // if it's Big Endian - $xl_double = strrev($xl_double); - } - - $this->_append($header.$data.$xl_double); - return(0); - } - - /** - * Write a LABELSST record or a LABEL record. Which one depends on BIFF version - * - * @param int $row Row index (0-based) - * @param int $col Column index (0-based) - * @param string $str The string - * @param int $xfIndex Index to XF record - */ - private function _writeString($row, $col, $str, $xfIndex) - { - $this->_writeLabelSst($row, $col, $str, $xfIndex); - } - - /** - * Write a LABELSST record or a LABEL record. Which one depends on BIFF version - * It differs from _writeString by the writing of rich text strings. - * @param int $row Row index (0-based) - * @param int $col Column index (0-based) - * @param string $str The string - * @param mixed $xfIndex The XF format index for the cell - * @param array $arrcRun Index to Font record and characters beginning - */ - private function _writeRichTextString($row, $col, $str, $xfIndex, $arrcRun){ - $record = 0x00FD; // Record identifier - $length = 0x000A; // Bytes to follow - $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($str, $arrcRun); - - /* check if string is already present */ - if (!isset($this->_str_table[$str])) { - $this->_str_table[$str] = $this->_str_unique++; - } - $this->_str_total++; - - $header = pack('vv', $record, $length); - $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); - $this->_append($header.$data); - } - - /** - * Write a string to the specified row and column (zero indexed). - * NOTE: there is an Excel 5 defined limit of 255 characters. - * $format is optional. - * Returns 0 : normal termination - * -2 : row or column out of range - * -3 : long string truncated to 255 chars - * - * @access public - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param string $str The string to write - * @param mixed $xfIndex The XF format index for the cell - * @return integer - */ - private function _writeLabel($row, $col, $str, $xfIndex) - { - $strlen = strlen($str); - $record = 0x0204; // Record identifier - $length = 0x0008 + $strlen; // Bytes to follow - - $str_error = 0; - - if ($strlen > $this->_xls_strmax) { // LABEL must be < 255 chars - $str = substr($str, 0, $this->_xls_strmax); - $length = 0x0008 + $this->_xls_strmax; - $strlen = $this->_xls_strmax; - $str_error = -3; - } - - $header = pack("vv", $record, $length); - $data = pack("vvvv", $row, $col, $xfIndex, $strlen); - $this->_append($header . $data . $str); - return($str_error); - } - - /** - * Write a string to the specified row and column (zero indexed). - * This is the BIFF8 version (no 255 chars limit). - * $format is optional. - * Returns 0 : normal termination - * -2 : row or column out of range - * -3 : long string truncated to 255 chars - * - * @access public - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param string $str The string to write - * @param mixed $xfIndex The XF format index for the cell - * @return integer - */ - private function _writeLabelSst($row, $col, $str, $xfIndex) - { - $record = 0x00FD; // Record identifier - $length = 0x000A; // Bytes to follow - - $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($str); - - /* check if string is already present */ - if (!isset($this->_str_table[$str])) { - $this->_str_table[$str] = $this->_str_unique++; - } - $this->_str_total++; - - $header = pack('vv', $record, $length); - $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); - $this->_append($header.$data); - } - - /** - * Writes a note associated with the cell given by the row and column. - * NOTE records don't have a length limit. - * - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param string $note The note to write - */ - private function _writeNote($row, $col, $note) - { - $note_length = strlen($note); - $record = 0x001C; // Record identifier - $max_length = 2048; // Maximun length for a NOTE record - - // Length for this record is no more than 2048 + 6 - $length = 0x0006 + min($note_length, 2048); - $header = pack("vv", $record, $length); - $data = pack("vvv", $row, $col, $note_length); - $this->_append($header . $data . substr($note, 0, 2048)); - - for ($i = $max_length; $i < $note_length; $i += $max_length) { - $chunk = substr($note, $i, $max_length); - $length = 0x0006 + strlen($chunk); - $header = pack("vv", $record, $length); - $data = pack("vvv", -1, 0, strlen($chunk)); - $this->_append($header.$data.$chunk); - } - return(0); - } - - /** - * Write a blank cell to the specified row and column (zero indexed). - * A blank cell is used to specify formatting without adding a string - * or a number. - * - * A blank cell without a format serves no purpose. Therefore, we don't write - * a BLANK record unless a format is specified. - * - * Returns 0 : normal termination (including no format) - * -1 : insufficient number of arguments - * -2 : row or column out of range - * - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param mixed $xfIndex The XF format index - */ - function _writeBlank($row, $col, $xfIndex) - { - $record = 0x0201; // Record identifier - $length = 0x0006; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("vvv", $row, $col, $xfIndex); - $this->_append($header . $data); - return 0; - } - - /** - * Write a boolean or an error type to the specified row and column (zero indexed) - * - * @param int $row Row index (0-based) - * @param int $col Column index (0-based) - * @param int $value - * @param boolean $isError Error or Boolean? - * @param int $xfIndex - */ - private function _writeBoolErr($row, $col, $value, $isError, $xfIndex) - { - $record = 0x0205; - $length = 8; - - $header = pack("vv", $record, $length); - $data = pack("vvvCC", $row, $col, $xfIndex, $value, $isError); - $this->_append($header . $data); - return 0; - } - - /** - * Write a formula to the specified row and column (zero indexed). - * The textual representation of the formula is passed to the parser in - * Parser.php which returns a packed binary string. - * - * Returns 0 : normal termination - * -1 : formula errors (bad formula) - * -2 : row or column out of range - * - * @param integer $row Zero indexed row - * @param integer $col Zero indexed column - * @param string $formula The formula text string - * @param mixed $xfIndex The XF format index - * @param mixed $calculatedValue Calculated value - * @return integer - */ - private function _writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) - { - $record = 0x0006; // Record identifier - - // Initialize possible additional value for STRING record that should be written after the FORMULA record? - $stringValue = null; - - // calculated value - if (isset($calculatedValue)) { - // Since we can't yet get the data type of the calculated value, - // we use best effort to determine data type - if (is_bool($calculatedValue)) { - // Boolean value - $num = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); - } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { - // Numeric value - $num = pack('d', $calculatedValue); - } elseif (is_string($calculatedValue)) { - if (array_key_exists($calculatedValue, PHPExcel_Cell_DataType::getErrorCodes())) { - // Error value - $num = pack('CCCvCv', 0x02, 0x00, self::_mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); - } elseif ($calculatedValue === '') { - // Empty string (and BIFF8) - $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); - } else { - // Non-empty string value (or empty string BIFF5) - $stringValue = $calculatedValue; - $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); - } - } else { - // We are really not supposed to reach here - $num = pack('d', 0x00); - } - } else { - $num = pack('d', 0x00); - } - - $grbit = 0x03; // Option flags - $unknown = 0x0000; // Must be zero - - // Strip the '=' or '@' sign at the beginning of the formula string - if ($formula{0} == '=') { - $formula = substr($formula,1); - } else { - // Error handling - $this->_writeString($row, $col, 'Unrecognised character for formula'); - return -1; - } - - // Parse the formula using the parser in Parser.php - try { - $error = $this->_parser->parse($formula); - $formula = $this->_parser->toReversePolish(); - - $formlen = strlen($formula); // Length of the binary string - $length = 0x16 + $formlen; // Length of the record data - - $header = pack("vv", $record, $length); - - $data = pack("vvv", $row, $col, $xfIndex) - . $num - . pack("vVv", $grbit, $unknown, $formlen); - $this->_append($header . $data . $formula); - - // Append also a STRING record if necessary - if ($stringValue !== null) { - $this->_writeStringRecord($stringValue); - } - - return 0; - - } catch (PHPExcel_Exception $e) { - // do nothing - } - - } - - /** - * Write a STRING record. This - * - * @param string $stringValue - */ - private function _writeStringRecord($stringValue) - { - $record = 0x0207; // Record identifier - $data = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue); - - $length = strlen($data); - $header = pack('vv', $record, $length); - - $this->_append($header . $data); - } - - /** - * Write a hyperlink. - * This is comprised of two elements: the visible label and - * the invisible link. The visible label is the same as the link unless an - * alternative string is specified. The label is written using the - * _writeString() method. Therefore the 255 characters string limit applies. - * $string and $format are optional. - * - * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external - * directory url. - * - * Returns 0 : normal termination - * -2 : row or column out of range - * -3 : long string truncated to 255 chars - * - * @param integer $row Row - * @param integer $col Column - * @param string $url URL string - * @return integer - */ - private function _writeUrl($row, $col, $url) - { - // Add start row and col to arg list - return($this->_writeUrlRange($row, $col, $row, $col, $url)); - } - - /** - * This is the more general form of _writeUrl(). It allows a hyperlink to be - * written to a range of cells. This function also decides the type of hyperlink - * to be written. These are either, Web (http, ftp, mailto), Internal - * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1'). - * - * @access private - * @see _writeUrl() - * @param integer $row1 Start row - * @param integer $col1 Start column - * @param integer $row2 End row - * @param integer $col2 End column - * @param string $url URL string - * @return integer - */ - function _writeUrlRange($row1, $col1, $row2, $col2, $url) - { - // Check for internal/external sheet links or default to web link - if (preg_match('[^internal:]', $url)) { - return($this->_writeUrlInternal($row1, $col1, $row2, $col2, $url)); - } - if (preg_match('[^external:]', $url)) { - return($this->_writeUrlExternal($row1, $col1, $row2, $col2, $url)); - } - return($this->_writeUrlWeb($row1, $col1, $row2, $col2, $url)); - } - - /** - * Used to write http, ftp and mailto hyperlinks. - * The link type ($options) is 0x03 is the same as absolute dir ref without - * sheet. However it is differentiated by the $unknown2 data stream. - * - * @access private - * @see _writeUrl() - * @param integer $row1 Start row - * @param integer $col1 Start column - * @param integer $row2 End row - * @param integer $col2 End column - * @param string $url URL string - * @return integer - */ - function _writeUrlWeb($row1, $col1, $row2, $col2, $url) - { - $record = 0x01B8; // Record identifier - $length = 0x00000; // Bytes to follow - - // Pack the undocumented parts of the hyperlink stream - $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); - $unknown2 = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B"); - - // Pack the option flags - $options = pack("V", 0x03); - - // Convert URL to a null terminated wchar string - $url = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY)); - $url = $url . "\0\0\0"; - - // Pack the length of the URL - $url_len = pack("V", strlen($url)); - - // Calculate the data length - $length = 0x34 + strlen($url); - - // Pack the header data - $header = pack("vv", $record, $length); - $data = pack("vvvv", $row1, $row2, $col1, $col2); - - // Write the packed data - $this->_append($header . $data . - $unknown1 . $options . - $unknown2 . $url_len . $url); - return 0; - } - - /** - * Used to write internal reference hyperlinks such as "Sheet1!A1". - * - * @access private - * @see _writeUrl() - * @param integer $row1 Start row - * @param integer $col1 Start column - * @param integer $row2 End row - * @param integer $col2 End column - * @param string $url URL string - * @return integer - */ - function _writeUrlInternal($row1, $col1, $row2, $col2, $url) - { - $record = 0x01B8; // Record identifier - $length = 0x00000; // Bytes to follow - - // Strip URL type - $url = preg_replace('/^internal:/', '', $url); - - // Pack the undocumented parts of the hyperlink stream - $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); - - // Pack the option flags - $options = pack("V", 0x08); - - // Convert the URL type and to a null terminated wchar string - $url .= "\0"; - - // character count - $url_len = PHPExcel_Shared_String::CountCharacters($url); - $url_len = pack('V', $url_len); - - $url = PHPExcel_Shared_String::ConvertEncoding($url, 'UTF-16LE', 'UTF-8'); - - // Calculate the data length - $length = 0x24 + strlen($url); - - // Pack the header data - $header = pack("vv", $record, $length); - $data = pack("vvvv", $row1, $row2, $col1, $col2); - - // Write the packed data - $this->_append($header . $data . - $unknown1 . $options . - $url_len . $url); - return 0; - } - - /** - * Write links to external directory names such as 'c:\foo.xls', - * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'. - * - * Note: Excel writes some relative links with the $dir_long string. We ignore - * these cases for the sake of simpler code. - * - * @access private - * @see _writeUrl() - * @param integer $row1 Start row - * @param integer $col1 Start column - * @param integer $row2 End row - * @param integer $col2 End column - * @param string $url URL string - * @return integer - */ - function _writeUrlExternal($row1, $col1, $row2, $col2, $url) - { - // Network drives are different. We will handle them separately - // MS/Novell network drives and shares start with \\ - if (preg_match('[^external:\\\\]', $url)) { - return; //($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format)); - } - - $record = 0x01B8; // Record identifier - $length = 0x00000; // Bytes to follow - - // Strip URL type and change Unix dir separator to Dos style (if needed) - // - $url = preg_replace('/^external:/', '', $url); - $url = preg_replace('/\//', "\\", $url); - - // Determine if the link is relative or absolute: - // relative if link contains no dir separator, "somefile.xls" - // relative if link starts with up-dir, "..\..\somefile.xls" - // otherwise, absolute - - $absolute = 0x00; // relative path - if ( preg_match('/^[A-Z]:/', $url) ) { - $absolute = 0x02; // absolute path on Windows, e.g. C:\... - } - $link_type = 0x01 | $absolute; - - // Determine if the link contains a sheet reference and change some of the - // parameters accordingly. - // Split the dir name and sheet name (if it exists) - $dir_long = $url; - if (preg_match("/\#/", $url)) { - $link_type |= 0x08; - } - - - // Pack the link type - $link_type = pack("V", $link_type); - - // Calculate the up-level dir count e.g.. (..\..\..\ == 3) - $up_count = preg_match_all("/\.\.\\\/", $dir_long, $useless); - $up_count = pack("v", $up_count); - - // Store the short dos dir name (null terminated) - $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0"; - - // Store the long dir name as a wchar string (non-null terminated) - $dir_long = $dir_long . "\0"; - - // Pack the lengths of the dir strings - $dir_short_len = pack("V", strlen($dir_short) ); - $dir_long_len = pack("V", strlen($dir_long) ); - $stream_len = pack("V", 0);//strlen($dir_long) + 0x06); - - // Pack the undocumented parts of the hyperlink stream - $unknown1 = pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000' ); - $unknown2 = pack("H*",'0303000000000000C000000000000046' ); - $unknown3 = pack("H*",'FFFFADDE000000000000000000000000000000000000000'); - $unknown4 = pack("v", 0x03 ); - - // Pack the main data stream - $data = pack("vvvv", $row1, $row2, $col1, $col2) . - $unknown1 . - $link_type . - $unknown2 . - $up_count . - $dir_short_len. - $dir_short . - $unknown3 . - $stream_len ;/*. - $dir_long_len . - $unknown4 . - $dir_long . - $sheet_len . - $sheet ;*/ - - // Pack the header data - $length = strlen($data); - $header = pack("vv", $record, $length); - - // Write the packed data - $this->_append($header. $data); - return 0; - } - - /** - * This method is used to set the height and format for a row. - * - * @param integer $row The row to set - * @param integer $height Height we are giving to the row. - * Use null to set XF without setting height - * @param integer $xfIndex The optional cell style Xf index to apply to the columns - * @param bool $hidden The optional hidden attribute - * @param integer $level The optional outline level for row, in range [0,7] - */ - private function _writeRow($row, $height, $xfIndex, $hidden = false, $level = 0) - { - $record = 0x0208; // Record identifier - $length = 0x0010; // Number of bytes to follow - - $colMic = 0x0000; // First defined column - $colMac = 0x0000; // Last defined column - $irwMac = 0x0000; // Used by Excel to optimise loading - $reserved = 0x0000; // Reserved - $grbit = 0x0000; // Option flags - $ixfe = $xfIndex; - - if ( $height < 0 ){ - $height = null; - } - - // Use _writeRow($row, null, $XF) to set XF format without setting height - if ($height != null) { - $miyRw = $height * 20; // row height - } else { - $miyRw = 0xff; // default row height is 256 - } - - // Set the options flags. fUnsynced is used to show that the font and row - // heights are not compatible. This is usually the case for WriteExcel. - // The collapsed flag 0x10 doesn't seem to be used to indicate that a row - // is collapsed. Instead it is used to indicate that the previous row is - // collapsed. The zero height flag, 0x20, is used to collapse a row. - - $grbit |= $level; - if ($hidden) { - $grbit |= 0x0030; - } - if ($height !== null) { - $grbit |= 0x0040; // fUnsynced - } - if ($xfIndex !== 0xF) { - $grbit |= 0x0080; - } - $grbit |= 0x0100; - - $header = pack("vv", $record, $length); - $data = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw, - $irwMac,$reserved, $grbit, $ixfe); - $this->_append($header.$data); - } - - /** - * Writes Excel DIMENSIONS to define the area in which there is data. - */ - private function _writeDimensions() - { - $record = 0x0200; // Record identifier - - $length = 0x000E; - $data = pack('VVvvv' - , $this->_firstRowIndex - , $this->_lastRowIndex + 1 - , $this->_firstColumnIndex - , $this->_lastColumnIndex + 1 - , 0x0000 // reserved - ); - - $header = pack("vv", $record, $length); - $this->_append($header.$data); - } - - /** - * Write BIFF record Window2. - */ - private function _writeWindow2() - { - $record = 0x023E; // Record identifier - $length = 0x0012; - - $grbit = 0x00B6; // Option flags - $rwTop = 0x0000; // Top row visible in window - $colLeft = 0x0000; // Leftmost column visible in window - - - // The options flags that comprise $grbit - $fDspFmla = 0; // 0 - bit - $fDspGrid = $this->_phpSheet->getShowGridlines() ? 1 : 0; // 1 - $fDspRwCol = $this->_phpSheet->getShowRowColHeaders() ? 1 : 0; // 2 - $fFrozen = $this->_phpSheet->getFreezePane() ? 1 : 0; // 3 - $fDspZeros = 1; // 4 - $fDefaultHdr = 1; // 5 - $fArabic = $this->_phpSheet->getRightToLeft() ? 1 : 0; // 6 - $fDspGuts = $this->_outline_on; // 7 - $fFrozenNoSplit = 0; // 0 - bit - // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet - $fSelected = ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) ? 1 : 0; - $fPaged = 1; // 2 - $fPageBreakPreview = $this->_phpSheet->getSheetView()->getView() === PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW; - - $grbit = $fDspFmla; - $grbit |= $fDspGrid << 1; - $grbit |= $fDspRwCol << 2; - $grbit |= $fFrozen << 3; - $grbit |= $fDspZeros << 4; - $grbit |= $fDefaultHdr << 5; - $grbit |= $fArabic << 6; - $grbit |= $fDspGuts << 7; - $grbit |= $fFrozenNoSplit << 8; - $grbit |= $fSelected << 9; - $grbit |= $fPaged << 10; - $grbit |= $fPageBreakPreview << 11; - - $header = pack("vv", $record, $length); - $data = pack("vvv", $grbit, $rwTop, $colLeft); - - // FIXME !!! - $rgbHdr = 0x0040; // Row/column heading and gridline color index - $zoom_factor_page_break = ($fPageBreakPreview? $this->_phpSheet->getSheetView()->getZoomScale() : 0x0000); - $zoom_factor_normal = $this->_phpSheet->getSheetView()->getZoomScaleNormal(); - - $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000); - - $this->_append($header.$data); - } - - /** - * Write BIFF record DEFAULTROWHEIGHT. - */ - private function _writeDefaultRowHeight() - { - $defaultRowHeight = $this->_phpSheet->getDefaultRowDimension()->getRowHeight(); - - if ($defaultRowHeight < 0) { - return; - } - - // convert to twips - $defaultRowHeight = (int) 20 * $defaultRowHeight; - - $record = 0x0225; // Record identifier - $length = 0x0004; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("vv", 1, $defaultRowHeight); - $this->_append($header . $data); - } - - /** - * Write BIFF record DEFCOLWIDTH if COLINFO records are in use. - */ - private function _writeDefcol() - { - $defaultColWidth = 8; - - $record = 0x0055; // Record identifier - $length = 0x0002; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("v", $defaultColWidth); - $this->_append($header . $data); - } - - /** - * Write BIFF record COLINFO to define column widths - * - * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C - * length record. - * - * @param array $col_array This is the only parameter received and is composed of the following: - * 0 => First formatted column, - * 1 => Last formatted column, - * 2 => Col width (8.43 is Excel default), - * 3 => The optional XF format of the column, - * 4 => Option flags. - * 5 => Optional outline level - */ - private function _writeColinfo($col_array) - { - if (isset($col_array[0])) { - $colFirst = $col_array[0]; - } - if (isset($col_array[1])) { - $colLast = $col_array[1]; - } - if (isset($col_array[2])) { - $coldx = $col_array[2]; - } else { - $coldx = 8.43; - } - if (isset($col_array[3])) { - $xfIndex = $col_array[3]; - } else { - $xfIndex = 15; - } - if (isset($col_array[4])) { - $grbit = $col_array[4]; - } else { - $grbit = 0; - } - if (isset($col_array[5])) { - $level = $col_array[5]; - } else { - $level = 0; - } - $record = 0x007D; // Record identifier - $length = 0x000C; // Number of bytes to follow - - $coldx *= 256; // Convert to units of 1/256 of a char - - $ixfe = $xfIndex; - $reserved = 0x0000; // Reserved - - $level = max(0, min($level, 7)); - $grbit |= $level << 8; - - $header = pack("vv", $record, $length); - $data = pack("vvvvvv", $colFirst, $colLast, $coldx, - $ixfe, $grbit, $reserved); - $this->_append($header.$data); - } - - /** - * Write BIFF record SELECTION. - */ - private function _writeSelection() - { - // look up the selected cell range - $selectedCells = $this->_phpSheet->getSelectedCells(); - $selectedCells = PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells()); - $selectedCells = $selectedCells[0]; - if (count($selectedCells) == 2) { - list($first, $last) = $selectedCells; - } else { - $first = $selectedCells[0]; - $last = $selectedCells[0]; - } - - list($colFirst, $rwFirst) = PHPExcel_Cell::coordinateFromString($first); - $colFirst = PHPExcel_Cell::columnIndexFromString($colFirst) - 1; // base 0 column index - --$rwFirst; // base 0 row index - - list($colLast, $rwLast) = PHPExcel_Cell::coordinateFromString($last); - $colLast = PHPExcel_Cell::columnIndexFromString($colLast) - 1; // base 0 column index - --$rwLast; // base 0 row index - - // make sure we are not out of bounds - $colFirst = min($colFirst, 255); - $colLast = min($colLast, 255); - - $rwFirst = min($rwFirst, 65535); - $rwLast = min($rwLast, 65535); - - $record = 0x001D; // Record identifier - $length = 0x000F; // Number of bytes to follow - - $pnn = $this->_active_pane; // Pane position - $rwAct = $rwFirst; // Active row - $colAct = $colFirst; // Active column - $irefAct = 0; // Active cell ref - $cref = 1; // Number of refs - - if (!isset($rwLast)) { - $rwLast = $rwFirst; // Last row in reference - } - if (!isset($colLast)) { - $colLast = $colFirst; // Last col in reference - } - - // Swap last row/col for first row/col as necessary - if ($rwFirst > $rwLast) { - list($rwFirst, $rwLast) = array($rwLast, $rwFirst); - } - - if ($colFirst > $colLast) { - list($colFirst, $colLast) = array($colLast, $colFirst); - } - - $header = pack("vv", $record, $length); - $data = pack("CvvvvvvCC", $pnn, $rwAct, $colAct, - $irefAct, $cref, - $rwFirst, $rwLast, - $colFirst, $colLast); - $this->_append($header . $data); - } - - /** - * Store the MERGEDCELLS records for all ranges of merged cells - */ - private function _writeMergedCells() - { - $mergeCells = $this->_phpSheet->getMergeCells(); - $countMergeCells = count($mergeCells); - - if ($countMergeCells == 0) { - return; - } - - // maximum allowed number of merged cells per record - $maxCountMergeCellsPerRecord = 1027; - - // record identifier - $record = 0x00E5; - - // counter for total number of merged cells treated so far by the writer - $i = 0; - - // counter for number of merged cells written in record currently being written - $j = 0; - - // initialize record data - $recordData = ''; - - // loop through the merged cells - foreach ($mergeCells as $mergeCell) { - ++$i; - ++$j; - - // extract the row and column indexes - $range = PHPExcel_Cell::splitRange($mergeCell); - list($first, $last) = $range[0]; - list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($first); - list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($last); - - $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, PHPExcel_Cell::columnIndexFromString($firstColumn) - 1, PHPExcel_Cell::columnIndexFromString($lastColumn) - 1); - - // flush record if we have reached limit for number of merged cells, or reached final merged cell - if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) { - $recordData = pack('v', $j) . $recordData; - $length = strlen($recordData); - $header = pack('vv', $record, $length); - $this->_append($header . $recordData); - - // initialize for next record, if any - $recordData = ''; - $j = 0; - } - } - } - - /** - * Write SHEETLAYOUT record - */ - private function _writeSheetLayout() - { - if (!$this->_phpSheet->isTabColorSet()) { - return; - } - - $recordData = pack( - 'vvVVVvv' - , 0x0862 - , 0x0000 // unused - , 0x00000000 // unused - , 0x00000000 // unused - , 0x00000014 // size of record data - , $this->_colors[$this->_phpSheet->getTabColor()->getRGB()] // color index - , 0x0000 // unused - ); - - $length = strlen($recordData); - - $record = 0x0862; // Record identifier - $header = pack('vv', $record, $length); - $this->_append($header . $recordData); - } - - /** - * Write SHEETPROTECTION - */ - private function _writeSheetProtection() - { - // record identifier - $record = 0x0867; - - // prepare options - $options = (int) !$this->_phpSheet->getProtection()->getObjects() - | (int) !$this->_phpSheet->getProtection()->getScenarios() << 1 - | (int) !$this->_phpSheet->getProtection()->getFormatCells() << 2 - | (int) !$this->_phpSheet->getProtection()->getFormatColumns() << 3 - | (int) !$this->_phpSheet->getProtection()->getFormatRows() << 4 - | (int) !$this->_phpSheet->getProtection()->getInsertColumns() << 5 - | (int) !$this->_phpSheet->getProtection()->getInsertRows() << 6 - | (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks() << 7 - | (int) !$this->_phpSheet->getProtection()->getDeleteColumns() << 8 - | (int) !$this->_phpSheet->getProtection()->getDeleteRows() << 9 - | (int) !$this->_phpSheet->getProtection()->getSelectLockedCells() << 10 - | (int) !$this->_phpSheet->getProtection()->getSort() << 11 - | (int) !$this->_phpSheet->getProtection()->getAutoFilter() << 12 - | (int) !$this->_phpSheet->getProtection()->getPivotTables() << 13 - | (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells() << 14 ; - - // record data - $recordData = pack( - 'vVVCVVvv' - , 0x0867 // repeated record identifier - , 0x0000 // not used - , 0x0000 // not used - , 0x00 // not used - , 0x01000200 // unknown data - , 0xFFFFFFFF // unknown data - , $options // options - , 0x0000 // not used - ); - - $length = strlen($recordData); - $header = pack('vv', $record, $length); - - $this->_append($header . $recordData); - } - - /** - * Write BIFF record RANGEPROTECTION - * - * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records - * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records - */ - private function _writeRangeProtection() - { - foreach ($this->_phpSheet->getProtectedCells() as $range => $password) { - // number of ranges, e.g. 'A1:B3 C20:D25' - $cellRanges = explode(' ', $range); - $cref = count($cellRanges); - - $recordData = pack( - 'vvVVvCVvVv', - 0x0868, - 0x00, - 0x0000, - 0x0000, - 0x02, - 0x0, - 0x0000, - $cref, - 0x0000, - 0x00 - ); - - foreach ($cellRanges as $cellRange) { - $recordData .= $this->_writeBIFF8CellRangeAddressFixed($cellRange); - } - - // the rgbFeat structure - $recordData .= pack( - 'VV', - 0x0000, - hexdec($password) - ); - - $recordData .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong('p' . md5($recordData)); - - $length = strlen($recordData); - - $record = 0x0868; // Record identifier - $header = pack("vv", $record, $length); - $this->_append($header . $recordData); - } - } - - /** - * Write BIFF record EXTERNCOUNT to indicate the number of external sheet - * references in a worksheet. - * - * Excel only stores references to external sheets that are used in formulas. - * For simplicity we store references to all the sheets in the workbook - * regardless of whether they are used or not. This reduces the overall - * complexity and eliminates the need for a two way dialogue between the formula - * parser the worksheet objects. - * - * @param integer $count The number of external sheet references in this worksheet - */ - private function _writeExterncount($count) - { - $record = 0x0016; // Record identifier - $length = 0x0002; // Number of bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("v", $count); - $this->_append($header . $data); - } - - /** - * Writes the Excel BIFF EXTERNSHEET record. These references are used by - * formulas. A formula references a sheet name via an index. Since we store a - * reference to all of the external worksheets the EXTERNSHEET index is the same - * as the worksheet index. - * - * @param string $sheetname The name of a external worksheet - */ - private function _writeExternsheet($sheetname) - { - $record = 0x0017; // Record identifier - - // References to the current sheet are encoded differently to references to - // external sheets. - // - if ($this->_phpSheet->getTitle() == $sheetname) { - $sheetname = ''; - $length = 0x02; // The following 2 bytes - $cch = 1; // The following byte - $rgch = 0x02; // Self reference - } else { - $length = 0x02 + strlen($sheetname); - $cch = strlen($sheetname); - $rgch = 0x03; // Reference to a sheet in the current workbook - } - - $header = pack("vv", $record, $length); - $data = pack("CC", $cch, $rgch); - $this->_append($header . $data . $sheetname); - } - - /** - * Writes the Excel BIFF PANE record. - * The panes can either be frozen or thawed (unfrozen). - * Frozen panes are specified in terms of an integer number of rows and columns. - * Thawed panes are specified in terms of Excel's units for rows and columns. - */ - private function _writePanes() - { - $panes = array(); - if ($freezePane = $this->_phpSheet->getFreezePane()) { - list($column, $row) = PHPExcel_Cell::coordinateFromString($freezePane); - $panes[0] = $row - 1; - $panes[1] = PHPExcel_Cell::columnIndexFromString($column) - 1; - } else { - // thaw panes - return; - } - - $y = isset($panes[0]) ? $panes[0] : null; - $x = isset($panes[1]) ? $panes[1] : null; - $rwTop = isset($panes[2]) ? $panes[2] : null; - $colLeft = isset($panes[3]) ? $panes[3] : null; - if (count($panes) > 4) { // if Active pane was received - $pnnAct = $panes[4]; - } else { - $pnnAct = null; - } - $record = 0x0041; // Record identifier - $length = 0x000A; // Number of bytes to follow - - // Code specific to frozen or thawed panes. - if ($this->_phpSheet->getFreezePane()) { - // Set default values for $rwTop and $colLeft - if (!isset($rwTop)) { - $rwTop = $y; - } - if (!isset($colLeft)) { - $colLeft = $x; - } - } else { - // Set default values for $rwTop and $colLeft - if (!isset($rwTop)) { - $rwTop = 0; - } - if (!isset($colLeft)) { - $colLeft = 0; - } - - // Convert Excel's row and column units to the internal units. - // The default row height is 12.75 - // The default column width is 8.43 - // The following slope and intersection values were interpolated. - // - $y = 20*$y + 255; - $x = 113.879*$x + 390; - } - - - // Determine which pane should be active. There is also the undocumented - // option to override this should it be necessary: may be removed later. - // - if (!isset($pnnAct)) { - if ($x != 0 && $y != 0) { - $pnnAct = 0; // Bottom right - } - if ($x != 0 && $y == 0) { - $pnnAct = 1; // Top right - } - if ($x == 0 && $y != 0) { - $pnnAct = 2; // Bottom left - } - if ($x == 0 && $y == 0) { - $pnnAct = 3; // Top left - } - } - - $this->_active_pane = $pnnAct; // Used in _writeSelection - - $header = pack("vv", $record, $length); - $data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct); - $this->_append($header . $data); - } - - /** - * Store the page setup SETUP BIFF record. - */ - private function _writeSetup() - { - $record = 0x00A1; // Record identifier - $length = 0x0022; // Number of bytes to follow - - $iPaperSize = $this->_phpSheet->getPageSetup()->getPaperSize(); // Paper size - - $iScale = $this->_phpSheet->getPageSetup()->getScale() ? - $this->_phpSheet->getPageSetup()->getScale() : 100; // Print scaling factor - - $iPageStart = 0x01; // Starting page number - $iFitWidth = (int) $this->_phpSheet->getPageSetup()->getFitToWidth(); // Fit to number of pages wide - $iFitHeight = (int) $this->_phpSheet->getPageSetup()->getFitToHeight(); // Fit to number of pages high - $grbit = 0x00; // Option flags - $iRes = 0x0258; // Print resolution - $iVRes = 0x0258; // Vertical print resolution - - $numHdr = $this->_phpSheet->getPageMargins()->getHeader(); // Header Margin - - $numFtr = $this->_phpSheet->getPageMargins()->getFooter(); // Footer Margin - $iCopies = 0x01; // Number of copies - - $fLeftToRight = 0x0; // Print over then down - - // Page orientation - $fLandscape = ($this->_phpSheet->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? - 0x0 : 0x1; - - $fNoPls = 0x0; // Setup not read from printer - $fNoColor = 0x0; // Print black and white - $fDraft = 0x0; // Print draft quality - $fNotes = 0x0; // Print notes - $fNoOrient = 0x0; // Orientation not set - $fUsePage = 0x0; // Use custom starting page - - $grbit = $fLeftToRight; - $grbit |= $fLandscape << 1; - $grbit |= $fNoPls << 2; - $grbit |= $fNoColor << 3; - $grbit |= $fDraft << 4; - $grbit |= $fNotes << 5; - $grbit |= $fNoOrient << 6; - $grbit |= $fUsePage << 7; - - $numHdr = pack("d", $numHdr); - $numFtr = pack("d", $numFtr); - if (self::getByteOrder()) { // if it's Big Endian - $numHdr = strrev($numHdr); - $numFtr = strrev($numFtr); - } - - $header = pack("vv", $record, $length); - $data1 = pack("vvvvvvvv", $iPaperSize, - $iScale, - $iPageStart, - $iFitWidth, - $iFitHeight, - $grbit, - $iRes, - $iVRes); - $data2 = $numHdr.$numFtr; - $data3 = pack("v", $iCopies); - $this->_append($header . $data1 . $data2 . $data3); - } - - /** - * Store the header caption BIFF record. - */ - private function _writeHeader() - { - $record = 0x0014; // Record identifier - - /* removing for now - // need to fix character count (multibyte!) - if (strlen($this->_phpSheet->getHeaderFooter()->getOddHeader()) <= 255) { - $str = $this->_phpSheet->getHeaderFooter()->getOddHeader(); // header string - } else { - $str = ''; - } - */ - - $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader()); - $length = strlen($recordData); - - $header = pack("vv", $record, $length); - - $this->_append($header . $recordData); - } - - /** - * Store the footer caption BIFF record. - */ - private function _writeFooter() - { - $record = 0x0015; // Record identifier - - /* removing for now - // need to fix character count (multibyte!) - if (strlen($this->_phpSheet->getHeaderFooter()->getOddFooter()) <= 255) { - $str = $this->_phpSheet->getHeaderFooter()->getOddFooter(); - } else { - $str = ''; - } - */ - - $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter()); - $length = strlen($recordData); - - $header = pack("vv", $record, $length); - - $this->_append($header . $recordData); - } - - /** - * Store the horizontal centering HCENTER BIFF record. - * - * @access private - */ - private function _writeHcenter() - { - $record = 0x0083; // Record identifier - $length = 0x0002; // Bytes to follow - - $fHCenter = $this->_phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0; // Horizontal centering - - $header = pack("vv", $record, $length); - $data = pack("v", $fHCenter); - - $this->_append($header.$data); - } - - /** - * Store the vertical centering VCENTER BIFF record. - */ - private function _writeVcenter() - { - $record = 0x0084; // Record identifier - $length = 0x0002; // Bytes to follow - - $fVCenter = $this->_phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0; // Horizontal centering - - $header = pack("vv", $record, $length); - $data = pack("v", $fVCenter); - $this->_append($header . $data); - } - - /** - * Store the LEFTMARGIN BIFF record. - */ - private function _writeMarginLeft() - { - $record = 0x0026; // Record identifier - $length = 0x0008; // Bytes to follow - - $margin = $this->_phpSheet->getPageMargins()->getLeft(); // Margin in inches - - $header = pack("vv", $record, $length); - $data = pack("d", $margin); - if (self::getByteOrder()) { // if it's Big Endian - $data = strrev($data); - } - - $this->_append($header . $data); - } - - /** - * Store the RIGHTMARGIN BIFF record. - */ - private function _writeMarginRight() - { - $record = 0x0027; // Record identifier - $length = 0x0008; // Bytes to follow - - $margin = $this->_phpSheet->getPageMargins()->getRight(); // Margin in inches - - $header = pack("vv", $record, $length); - $data = pack("d", $margin); - if (self::getByteOrder()) { // if it's Big Endian - $data = strrev($data); - } - - $this->_append($header . $data); - } - - /** - * Store the TOPMARGIN BIFF record. - */ - private function _writeMarginTop() - { - $record = 0x0028; // Record identifier - $length = 0x0008; // Bytes to follow - - $margin = $this->_phpSheet->getPageMargins()->getTop(); // Margin in inches - - $header = pack("vv", $record, $length); - $data = pack("d", $margin); - if (self::getByteOrder()) { // if it's Big Endian - $data = strrev($data); - } - - $this->_append($header . $data); - } - - /** - * Store the BOTTOMMARGIN BIFF record. - */ - private function _writeMarginBottom() - { - $record = 0x0029; // Record identifier - $length = 0x0008; // Bytes to follow - - $margin = $this->_phpSheet->getPageMargins()->getBottom(); // Margin in inches - - $header = pack("vv", $record, $length); - $data = pack("d", $margin); - if (self::getByteOrder()) { // if it's Big Endian - $data = strrev($data); - } - - $this->_append($header . $data); - } - - /** - * Write the PRINTHEADERS BIFF record. - */ - private function _writePrintHeaders() - { - $record = 0x002a; // Record identifier - $length = 0x0002; // Bytes to follow - - $fPrintRwCol = $this->_print_headers; // Boolean flag - - $header = pack("vv", $record, $length); - $data = pack("v", $fPrintRwCol); - $this->_append($header . $data); - } - - /** - * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the - * GRIDSET record. - */ - private function _writePrintGridlines() - { - $record = 0x002b; // Record identifier - $length = 0x0002; // Bytes to follow - - $fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag - - $header = pack("vv", $record, $length); - $data = pack("v", $fPrintGrid); - $this->_append($header . $data); - } - - /** - * Write the GRIDSET BIFF record. Must be used in conjunction with the - * PRINTGRIDLINES record. - */ - private function _writeGridset() - { - $record = 0x0082; // Record identifier - $length = 0x0002; // Bytes to follow - - $fGridSet = !$this->_phpSheet->getPrintGridlines(); // Boolean flag - - $header = pack("vv", $record, $length); - $data = pack("v", $fGridSet); - $this->_append($header . $data); - } - - /** - * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet. - */ - private function _writeAutoFilterInfo(){ - $record = 0x009D; // Record identifier - $length = 0x0002; // Bytes to follow - - $rangeBounds = PHPExcel_Cell::rangeBoundaries($this->_phpSheet->getAutoFilter()->getRange()); - $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0]; - - $header = pack("vv", $record, $length); - $data = pack("v", $iNumFilters); - $this->_append($header . $data); - } - - /** - * Write the GUTS BIFF record. This is used to configure the gutter margins - * where Excel outline symbols are displayed. The visibility of the gutters is - * controlled by a flag in WSBOOL. - * - * @see _writeWsbool() - */ - private function _writeGuts() - { - $record = 0x0080; // Record identifier - $length = 0x0008; // Bytes to follow - - $dxRwGut = 0x0000; // Size of row gutter - $dxColGut = 0x0000; // Size of col gutter - - // determine maximum row outline level - $maxRowOutlineLevel = 0; - foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { - $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel()); - } - - $col_level = 0; - - // Calculate the maximum column outline level. The equivalent calculation - // for the row outline level is carried out in _writeRow(). - $colcount = count($this->_colinfo); - for ($i = 0; $i < $colcount; ++$i) { - $col_level = max($this->_colinfo[$i][5], $col_level); - } - - // Set the limits for the outline levels (0 <= x <= 7). - $col_level = max(0, min($col_level, 7)); - - // The displayed level is one greater than the max outline levels - if ($maxRowOutlineLevel) { - ++$maxRowOutlineLevel; - } - if ($col_level) { - ++$col_level; - } - - $header = pack("vv", $record, $length); - $data = pack("vvvv", $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level); - - $this->_append($header.$data); - } - - /** - * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction - * with the SETUP record. - */ - private function _writeWsbool() - { - $record = 0x0081; // Record identifier - $length = 0x0002; // Bytes to follow - $grbit = 0x0000; - - // The only option that is of interest is the flag for fit to page. So we - // set all the options in one go. - // - // Set the option flags - $grbit |= 0x0001; // Auto page breaks visible - if ($this->_outline_style) { - $grbit |= 0x0020; // Auto outline styles - } - if ($this->_phpSheet->getShowSummaryBelow()) { - $grbit |= 0x0040; // Outline summary below - } - if ($this->_phpSheet->getShowSummaryRight()) { - $grbit |= 0x0080; // Outline summary right - } - if ($this->_phpSheet->getPageSetup()->getFitToPage()) { - $grbit |= 0x0100; // Page setup fit to page - } - if ($this->_outline_on) { - $grbit |= 0x0400; // Outline symbols displayed - } - - $header = pack("vv", $record, $length); - $data = pack("v", $grbit); - $this->_append($header . $data); - } - - /** - * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records. - */ - private function _writeBreaks() - { - // initialize - $vbreaks = array(); - $hbreaks = array(); - - foreach ($this->_phpSheet->getBreaks() as $cell => $breakType) { - // Fetch coordinates - $coordinates = PHPExcel_Cell::coordinateFromString($cell); - - // Decide what to do by the type of break - switch ($breakType) { - case PHPExcel_Worksheet::BREAK_COLUMN: - // Add to list of vertical breaks - $vbreaks[] = PHPExcel_Cell::columnIndexFromString($coordinates[0]) - 1; - break; - - case PHPExcel_Worksheet::BREAK_ROW: - // Add to list of horizontal breaks - $hbreaks[] = $coordinates[1]; - break; - - case PHPExcel_Worksheet::BREAK_NONE: - default: - // Nothing to do - break; - } - } - - //horizontal page breaks - if (!empty($hbreaks)) { - - // Sort and filter array of page breaks - sort($hbreaks, SORT_NUMERIC); - if ($hbreaks[0] == 0) { // don't use first break if it's 0 - array_shift($hbreaks); - } - - $record = 0x001b; // Record identifier - $cbrk = count($hbreaks); // Number of page breaks - $length = 2 + 6 * $cbrk; // Bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("v", $cbrk); - - // Append each page break - foreach ($hbreaks as $hbreak) { - $data .= pack("vvv", $hbreak, 0x0000, 0x00ff); - } - - $this->_append($header . $data); - } - - // vertical page breaks - if (!empty($vbreaks)) { - - // 1000 vertical pagebreaks appears to be an internal Excel 5 limit. - // It is slightly higher in Excel 97/200, approx. 1026 - $vbreaks = array_slice($vbreaks, 0, 1000); - - // Sort and filter array of page breaks - sort($vbreaks, SORT_NUMERIC); - if ($vbreaks[0] == 0) { // don't use first break if it's 0 - array_shift($vbreaks); - } - - $record = 0x001a; // Record identifier - $cbrk = count($vbreaks); // Number of page breaks - $length = 2 + 6 * $cbrk; // Bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("v", $cbrk); - - // Append each page break - foreach ($vbreaks as $vbreak) { - $data .= pack("vvv", $vbreak, 0x0000, 0xffff); - } - - $this->_append($header . $data); - } - } - - /** - * Set the Biff PROTECT record to indicate that the worksheet is protected. - */ - private function _writeProtect() - { - // Exit unless sheet protection has been specified - if (!$this->_phpSheet->getProtection()->getSheet()) { - return; - } - - $record = 0x0012; // Record identifier - $length = 0x0002; // Bytes to follow - - $fLock = 1; // Worksheet is protected - - $header = pack("vv", $record, $length); - $data = pack("v", $fLock); - - $this->_append($header.$data); - } - - /** - * Write SCENPROTECT - */ - private function _writeScenProtect() - { - // Exit if sheet protection is not active - if (!$this->_phpSheet->getProtection()->getSheet()) { - return; - } - - // Exit if scenarios are not protected - if (!$this->_phpSheet->getProtection()->getScenarios()) { - return; - } - - $record = 0x00DD; // Record identifier - $length = 0x0002; // Bytes to follow - - $header = pack('vv', $record, $length); - $data = pack('v', 1); - - $this->_append($header . $data); - } - - /** - * Write OBJECTPROTECT - */ - private function _writeObjectProtect() - { - // Exit if sheet protection is not active - if (!$this->_phpSheet->getProtection()->getSheet()) { - return; - } - - // Exit if objects are not protected - if (!$this->_phpSheet->getProtection()->getObjects()) { - return; - } - - $record = 0x0063; // Record identifier - $length = 0x0002; // Bytes to follow - - $header = pack('vv', $record, $length); - $data = pack('v', 1); - - $this->_append($header . $data); - } - - /** - * Write the worksheet PASSWORD record. - */ - private function _writePassword() - { - // Exit unless sheet protection and password have been specified - if (!$this->_phpSheet->getProtection()->getSheet() || !$this->_phpSheet->getProtection()->getPassword()) { - return; - } - - $record = 0x0013; // Record identifier - $length = 0x0002; // Bytes to follow - - $wPassword = hexdec($this->_phpSheet->getProtection()->getPassword()); // Encoded password - - $header = pack("vv", $record, $length); - $data = pack("v", $wPassword); - - $this->_append($header . $data); - } - - /** - * Insert a 24bit bitmap image in a worksheet. - * - * @access public - * @param integer $row The row we are going to insert the bitmap into - * @param integer $col The column we are going to insert the bitmap into - * @param mixed $bitmap The bitmap filename or GD-image resource - * @param integer $x The horizontal position (offset) of the image inside the cell. - * @param integer $y The vertical position (offset) of the image inside the cell. - * @param float $scale_x The horizontal scale - * @param float $scale_y The vertical scale - */ - function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) - { - $bitmap_array = (is_resource($bitmap) ? $this->_processBitmapGd($bitmap) : $this->_processBitmap($bitmap)); - list($width, $height, $size, $data) = $bitmap_array; //$this->_processBitmap($bitmap); - - // Scale the frame of the image. - $width *= $scale_x; - $height *= $scale_y; - - // Calculate the vertices of the image and write the OBJ record - $this->_positionImage($col, $row, $x, $y, $width, $height); - - // Write the IMDATA record to store the bitmap data - $record = 0x007f; - $length = 8 + $size; - $cf = 0x09; - $env = 0x01; - $lcb = $size; - - $header = pack("vvvvV", $record, $length, $cf, $env, $lcb); - $this->_append($header.$data); - } - - /** - * Calculate the vertices that define the position of the image as required by - * the OBJ record. - * - * +------------+------------+ - * | A | B | - * +-----+------------+------------+ - * | |(x1,y1) | | - * | 1 |(A1)._______|______ | - * | | | | | - * | | | | | - * +-----+----| BITMAP |-----+ - * | | | | | - * | 2 | |______________. | - * | | | (B2)| - * | | | (x2,y2)| - * +---- +------------+------------+ - * - * Example of a bitmap that covers some of the area from cell A1 to cell B2. - * - * Based on the width and height of the bitmap we need to calculate 8 vars: - * $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. - * The width and height of the cells are also variable and have to be taken into - * account. - * The values of $col_start and $row_start are passed in from the calling - * function. The values of $col_end and $row_end are calculated by subtracting - * the width and height of the bitmap from the width and height of the - * underlying cells. - * The vertices are expressed as a percentage of the underlying cell width as - * follows (rhs values are in pixels): - * - * x1 = X / W *1024 - * y1 = Y / H *256 - * x2 = (X-1) / W *1024 - * y2 = (Y-1) / H *256 - * - * Where: X is distance from the left side of the underlying cell - * Y is distance from the top of the underlying cell - * W is the width of the cell - * H is the height of the cell - * The SDK incorrectly states that the height should be expressed as a - * percentage of 1024. - * - * @access private - * @param integer $col_start Col containing upper left corner of object - * @param integer $row_start Row containing top left corner of object - * @param integer $x1 Distance to left side of object - * @param integer $y1 Distance to top of object - * @param integer $width Width of image frame - * @param integer $height Height of image frame - */ - function _positionImage($col_start, $row_start, $x1, $y1, $width, $height) - { - // Initialise end cell to the same as the start cell - $col_end = $col_start; // Col containing lower right corner of object - $row_end = $row_start; // Row containing bottom right corner of object - - // Zero the specified offset if greater than the cell dimensions - if ($x1 >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) { - $x1 = 0; - } - if ($y1 >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1)) { - $y1 = 0; - } - - $width = $width + $x1 -1; - $height = $height + $y1 -1; - - // Subtract the underlying cell widths to find the end cell of the image - while ($width >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) { - $width -= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)); - ++$col_end; - } - - // Subtract the underlying cell heights to find the end cell of the image - while ($height >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1)) { - $height -= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1); - ++$row_end; - } - - // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell - // with zero eight or width. - // - if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) { - return; - } - if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) { - return; - } - if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) == 0) { - return; - } - if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) == 0) { - return; - } - - // Convert the pixel values to the percentage value expected by Excel - $x1 = $x1 / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; - $y1 = $y1 / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) * 256; - $x2 = $width / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object - $y2 = $height / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) * 256; // Distance to bottom of object - - $this->_writeObjPicture($col_start, $x1, - $row_start, $y1, - $col_end, $x2, - $row_end, $y2); - } - - /** - * Store the OBJ record that precedes an IMDATA record. This could be generalise - * to support other Excel objects. - * - * @param integer $colL Column containing upper left corner of object - * @param integer $dxL Distance from left side of cell - * @param integer $rwT Row containing top left corner of object - * @param integer $dyT Distance from top of cell - * @param integer $colR Column containing lower right corner of object - * @param integer $dxR Distance from right of cell - * @param integer $rwB Row containing bottom right corner of object - * @param integer $dyB Distance from bottom of cell - */ - private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) - { - $record = 0x005d; // Record identifier - $length = 0x003c; // Bytes to follow - - $cObj = 0x0001; // Count of objects in file (set to 1) - $OT = 0x0008; // Object type. 8 = Picture - $id = 0x0001; // Object ID - $grbit = 0x0614; // Option flags - - $cbMacro = 0x0000; // Length of FMLA structure - $Reserved1 = 0x0000; // Reserved - $Reserved2 = 0x0000; // Reserved - - $icvBack = 0x09; // Background colour - $icvFore = 0x09; // Foreground colour - $fls = 0x00; // Fill pattern - $fAuto = 0x00; // Automatic fill - $icv = 0x08; // Line colour - $lns = 0xff; // Line style - $lnw = 0x01; // Line weight - $fAutoB = 0x00; // Automatic border - $frs = 0x0000; // Frame style - $cf = 0x0009; // Image format, 9 = bitmap - $Reserved3 = 0x0000; // Reserved - $cbPictFmla = 0x0000; // Length of FMLA structure - $Reserved4 = 0x0000; // Reserved - $grbit2 = 0x0001; // Option flags - $Reserved5 = 0x0000; // Reserved - - - $header = pack("vv", $record, $length); - $data = pack("V", $cObj); - $data .= pack("v", $OT); - $data .= pack("v", $id); - $data .= pack("v", $grbit); - $data .= pack("v", $colL); - $data .= pack("v", $dxL); - $data .= pack("v", $rwT); - $data .= pack("v", $dyT); - $data .= pack("v", $colR); - $data .= pack("v", $dxR); - $data .= pack("v", $rwB); - $data .= pack("v", $dyB); - $data .= pack("v", $cbMacro); - $data .= pack("V", $Reserved1); - $data .= pack("v", $Reserved2); - $data .= pack("C", $icvBack); - $data .= pack("C", $icvFore); - $data .= pack("C", $fls); - $data .= pack("C", $fAuto); - $data .= pack("C", $icv); - $data .= pack("C", $lns); - $data .= pack("C", $lnw); - $data .= pack("C", $fAutoB); - $data .= pack("v", $frs); - $data .= pack("V", $cf); - $data .= pack("v", $Reserved3); - $data .= pack("v", $cbPictFmla); - $data .= pack("v", $Reserved4); - $data .= pack("v", $grbit2); - $data .= pack("V", $Reserved5); - - $this->_append($header . $data); - } - - /** - * Convert a GD-image into the internal format. - * - * @access private - * @param resource $image The image to process - * @return array Array with data and properties of the bitmap - */ - function _processBitmapGd($image) { - $width = imagesx($image); - $height = imagesy($image); - - $data = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); - for ($j=$height; $j--; ) { - for ($i=0; $i < $width; ++$i) { - $color = imagecolorsforindex($image, imagecolorat($image, $i, $j)); - foreach (array("red", "green", "blue") as $key) { - $color[$key] = $color[$key] + round((255 - $color[$key]) * $color["alpha"] / 127); - } - $data .= chr($color["blue"]) . chr($color["green"]) . chr($color["red"]); - } - if (3*$width % 4) { - $data .= str_repeat("\x00", 4 - 3*$width % 4); - } - } - - return array($width, $height, strlen($data), $data); - } - - /** - * Convert a 24 bit bitmap into the modified internal format used by Windows. - * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the - * MSDN library. - * - * @access private - * @param string $bitmap The bitmap to process - * @return array Array with data and properties of the bitmap - */ - function _processBitmap($bitmap) - { - // Open file. - $bmp_fd = @fopen($bitmap,"rb"); - if (!$bmp_fd) { - throw new PHPExcel_Writer_Exception("Couldn't import $bitmap"); - } - - // Slurp the file into a string. - $data = fread($bmp_fd, filesize($bitmap)); - - // Check that the file is big enough to be a bitmap. - if (strlen($data) <= 0x36) { - throw new PHPExcel_Writer_Exception("$bitmap doesn't contain enough data.\n"); - } - - // The first 2 bytes are used to identify the bitmap. - $identity = unpack("A2ident", $data); - if ($identity['ident'] != "BM") { - throw new PHPExcel_Writer_Exception("$bitmap doesn't appear to be a valid bitmap image.\n"); - } - - // Remove bitmap data: ID. - $data = substr($data, 2); - - // Read and remove the bitmap size. This is more reliable than reading - // the data size at offset 0x22. - // - $size_array = unpack("Vsa", substr($data, 0, 4)); - $size = $size_array['sa']; - $data = substr($data, 4); - $size -= 0x36; // Subtract size of bitmap header. - $size += 0x0C; // Add size of BIFF header. - - // Remove bitmap data: reserved, offset, header length. - $data = substr($data, 12); - - // Read and remove the bitmap width and height. Verify the sizes. - $width_and_height = unpack("V2", substr($data, 0, 8)); - $width = $width_and_height[1]; - $height = $width_and_height[2]; - $data = substr($data, 8); - if ($width > 0xFFFF) { - throw new PHPExcel_Writer_Exception("$bitmap: largest image width supported is 65k.\n"); - } - if ($height > 0xFFFF) { - throw new PHPExcel_Writer_Exception("$bitmap: largest image height supported is 65k.\n"); - } - - // Read and remove the bitmap planes and bpp data. Verify them. - $planes_and_bitcount = unpack("v2", substr($data, 0, 4)); - $data = substr($data, 4); - if ($planes_and_bitcount[2] != 24) { // Bitcount - throw new PHPExcel_Writer_Exception("$bitmap isn't a 24bit true color bitmap.\n"); - } - if ($planes_and_bitcount[1] != 1) { - throw new PHPExcel_Writer_Exception("$bitmap: only 1 plane supported in bitmap image.\n"); - } - - // Read and remove the bitmap compression. Verify compression. - $compression = unpack("Vcomp", substr($data, 0, 4)); - $data = substr($data, 4); - - //$compression = 0; - if ($compression['comp'] != 0) { - throw new PHPExcel_Writer_Exception("$bitmap: compression not supported in bitmap image.\n"); - } - - // Remove bitmap data: data size, hres, vres, colours, imp. colours. - $data = substr($data, 20); - - // Add the BITMAPCOREHEADER data - $header = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); - $data = $header . $data; - - return (array($width, $height, $size, $data)); - } - - /** - * Store the window zoom factor. This should be a reduced fraction but for - * simplicity we will store all fractions with a numerator of 100. - */ - private function _writeZoom() - { - // If scale is 100 we don't need to write a record - if ($this->_phpSheet->getSheetView()->getZoomScale() == 100) { - return; - } - - $record = 0x00A0; // Record identifier - $length = 0x0004; // Bytes to follow - - $header = pack("vv", $record, $length); - $data = pack("vv", $this->_phpSheet->getSheetView()->getZoomScale(), 100); - $this->_append($header . $data); - } - - /** - * Get Escher object - * - * @return PHPExcel_Shared_Escher - */ - public function getEscher() - { - return $this->_escher; - } - - /** - * Set Escher object - * - * @param PHPExcel_Shared_Escher $pValue - */ - public function setEscher(PHPExcel_Shared_Escher $pValue = null) - { - $this->_escher = $pValue; - } - - /** - * Write MSODRAWING record - */ - private function _writeMsoDrawing() - { - // write the Escher stream if necessary - if (isset($this->_escher)) { - $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); - $data = $writer->close(); - $spOffsets = $writer->getSpOffsets(); - $spTypes = $writer->getSpTypes(); - // write the neccesary MSODRAWING, OBJ records - - // split the Escher stream - $spOffsets[0] = 0; - $nm = count($spOffsets) - 1; // number of shapes excluding first shape - for ($i = 1; $i <= $nm; ++$i) { - // MSODRAWING record - $record = 0x00EC; // Record identifier - - // chunk of Escher stream for one shape - $dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]); - - $length = strlen($dataChunk); - $header = pack("vv", $record, $length); - - $this->_append($header . $dataChunk); - - // OBJ record - $record = 0x005D; // record identifier - $objData = ''; - - // ftCmo - if($spTypes[$i] == 0x00C9){ - // Add ftCmo (common object data) subobject - $objData .= - pack('vvvvvVVV' - , 0x0015 // 0x0015 = ftCmo - , 0x0012 // length of ftCmo data - , 0x0014 // object type, 0x0014 = filter - , $i // object id number, Excel seems to use 1-based index, local for the sheet - , 0x2101 // option flags, 0x2001 is what OpenOffice.org uses - , 0 // reserved - , 0 // reserved - , 0 // reserved - ); - - // Add ftSbs Scroll bar subobject - $objData .= pack('vv', 0x00C, 0x0014); - $objData .= pack('H*', '0000000000000000640001000A00000010000100'); - // Add ftLbsData (List box data) subobject - $objData .= pack('vv', 0x0013, 0x1FEE); - $objData .= pack('H*', '00000000010001030000020008005700'); - } - else { - // Add ftCmo (common object data) subobject - $objData .= - pack('vvvvvVVV' - , 0x0015 // 0x0015 = ftCmo - , 0x0012 // length of ftCmo data - , 0x0008 // object type, 0x0008 = picture - , $i // object id number, Excel seems to use 1-based index, local for the sheet - , 0x6011 // option flags, 0x6011 is what OpenOffice.org uses - , 0 // reserved - , 0 // reserved - , 0 // reserved - ); - } - - // ftEnd - $objData .= - pack('vv' - , 0x0000 // 0x0000 = ftEnd - , 0x0000 // length of ftEnd data - ); - - $length = strlen($objData); - $header = pack('vv', $record, $length); - $this->_append($header . $objData); - } - } - } - - /** - * Store the DATAVALIDATIONS and DATAVALIDATION records. - */ - private function _writeDataValidity() - { - // Datavalidation collection - $dataValidationCollection = $this->_phpSheet->getDataValidationCollection(); - - // Write data validations? - if (!empty($dataValidationCollection)) { - - // DATAVALIDATIONS record - $record = 0x01B2; // Record identifier - $length = 0x0012; // Bytes to follow - - $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records - $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position - $verPos = 0x00000000; // Vertical position of prompt box, if fixed position - $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible - - $header = pack('vv', $record, $length); - $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, - count($dataValidationCollection)); - $this->_append($header.$data); - - // DATAVALIDATION records - $record = 0x01BE; // Record identifier - - foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) { - // initialize record data - $data = ''; - - // options - $options = 0x00000000; - - // data type - $type = $dataValidation->getType(); - switch ($type) { - case PHPExcel_Cell_DataValidation::TYPE_NONE: $type = 0x00; break; - case PHPExcel_Cell_DataValidation::TYPE_WHOLE: $type = 0x01; break; - case PHPExcel_Cell_DataValidation::TYPE_DECIMAL: $type = 0x02; break; - case PHPExcel_Cell_DataValidation::TYPE_LIST: $type = 0x03; break; - case PHPExcel_Cell_DataValidation::TYPE_DATE: $type = 0x04; break; - case PHPExcel_Cell_DataValidation::TYPE_TIME: $type = 0x05; break; - case PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH: $type = 0x06; break; - case PHPExcel_Cell_DataValidation::TYPE_CUSTOM: $type = 0x07; break; - } - $options |= $type << 0; - - // error style - $errorStyle = $dataValidation->getType(); - switch ($errorStyle) { - case PHPExcel_Cell_DataValidation::STYLE_STOP: $errorStyle = 0x00; break; - case PHPExcel_Cell_DataValidation::STYLE_WARNING: $errorStyle = 0x01; break; - case PHPExcel_Cell_DataValidation::STYLE_INFORMATION: $errorStyle = 0x02; break; - } - $options |= $errorStyle << 4; - - // explicit formula? - if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) { - $options |= 0x01 << 7; - } - - // empty cells allowed - $options |= $dataValidation->getAllowBlank() << 8; - - // show drop down - $options |= (!$dataValidation->getShowDropDown()) << 9; - - // show input message - $options |= $dataValidation->getShowInputMessage() << 18; - - // show error message - $options |= $dataValidation->getShowErrorMessage() << 19; - - // condition operator - $operator = $dataValidation->getOperator(); - switch ($operator) { - case PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN: $operator = 0x00 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN: $operator = 0x01 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_EQUAL: $operator = 0x02 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL: $operator = 0x03 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN: $operator = 0x04 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN: $operator = 0x05 ; break; - case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL: $operator = 0x06; break; - case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL: $operator = 0x07 ; break; - } - $options |= $operator << 20; - - $data = pack('V', $options); - - // prompt title - $promptTitle = $dataValidation->getPromptTitle() !== '' ? - $dataValidation->getPromptTitle() : chr(0); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle); - - // error title - $errorTitle = $dataValidation->getErrorTitle() !== '' ? - $dataValidation->getErrorTitle() : chr(0); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle); - - // prompt text - $prompt = $dataValidation->getPrompt() !== '' ? - $dataValidation->getPrompt() : chr(0); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt); - - // error text - $error = $dataValidation->getError() !== '' ? - $dataValidation->getError() : chr(0); - $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error); - - // formula 1 - try { - $formula1 = $dataValidation->getFormula1(); - if ($type == 0x03) { // list type - $formula1 = str_replace(',', chr(0), $formula1); - } - $this->_parser->parse($formula1); - $formula1 = $this->_parser->toReversePolish(); - $sz1 = strlen($formula1); - - } catch(PHPExcel_Exception $e) { - $sz1 = 0; - $formula1 = ''; - } - $data .= pack('vv', $sz1, 0x0000); - $data .= $formula1; - - // formula 2 - try { - $formula2 = $dataValidation->getFormula2(); - if ($formula2 === '') { - throw new PHPExcel_Writer_Exception('No formula2'); - } - $this->_parser->parse($formula2); - $formula2 = $this->_parser->toReversePolish(); - $sz2 = strlen($formula2); - - } catch(PHPExcel_Exception $e) { - $sz2 = 0; - $formula2 = ''; - } - $data .= pack('vv', $sz2, 0x0000); - $data .= $formula2; - - // cell range address list - $data .= pack('v', 0x0001); - $data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate); - - $length = strlen($data); - $header = pack("vv", $record, $length); - - $this->_append($header . $data); - } - } - } - - /** - * Map Error code - * - * @param string $errorCode - * @return int - */ - private static function _mapErrorCode($errorCode) { - switch ($errorCode) { - case '#NULL!': return 0x00; - case '#DIV/0!': return 0x07; - case '#VALUE!': return 0x0F; - case '#REF!': return 0x17; - case '#NAME?': return 0x1D; - case '#NUM!': return 0x24; - case '#N/A': return 0x2A; - } - - return 0; - } - - /** - * Write PLV Record - */ - private function _writePageLayoutView(){ - $record = 0x088B; // Record identifier - $length = 0x0010; // Bytes to follow - - $rt = 0x088B; // 2 - $grbitFrt = 0x0000; // 2 - $reserved = 0x0000000000000000; // 8 - $wScalvePLV = $this->_phpSheet->getSheetView()->getZoomScale(); // 2 - - // The options flags that comprise $grbit - if($this->_phpSheet->getSheetView()->getView() == PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT){ - $fPageLayoutView = 1; - } else { - $fPageLayoutView = 0; - } - $fRulerVisible = 0; - $fWhitespaceHidden = 0; - - $grbit = $fPageLayoutView; // 2 - $grbit |= $fRulerVisible << 1; - $grbit |= $fWhitespaceHidden << 3; - - $header = pack("vv", $record, $length); - $data = pack("vvVVvv", $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit); - $this->_append($header . $data); - } - - /** - * Write CFRule Record - * @param PHPExcel_Style_Conditional $conditional - */ - private function _writeCFRule(PHPExcel_Style_Conditional $conditional){ - $record = 0x01B1; // Record identifier - - // $type : Type of the CF - // $operatorType : Comparison operator - if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION){ - $type = 0x02; - $operatorType = 0x00; - } else if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ - $type = 0x01; - - switch ($conditional->getOperatorType()){ - case PHPExcel_Style_Conditional::OPERATOR_NONE: - $operatorType = 0x00; - break; - case PHPExcel_Style_Conditional::OPERATOR_EQUAL: - $operatorType = 0x03; - break; - case PHPExcel_Style_Conditional::OPERATOR_GREATERTHAN: - $operatorType = 0x05; - break; - case PHPExcel_Style_Conditional::OPERATOR_GREATERTHANOREQUAL: - $operatorType = 0x07; - break; - case PHPExcel_Style_Conditional::OPERATOR_LESSTHAN: - $operatorType = 0x06; - break; - case PHPExcel_Style_Conditional::OPERATOR_LESSTHANOREQUAL: - $operatorType = 0x08; - break; - case PHPExcel_Style_Conditional::OPERATOR_NOTEQUAL: - $operatorType = 0x04; - break; - case PHPExcel_Style_Conditional::OPERATOR_BETWEEN: - $operatorType = 0x01; - break; - // not OPERATOR_NOTBETWEEN 0x02 - } - } - - // $szValue1 : size of the formula data for first value or formula - // $szValue2 : size of the formula data for second value or formula - $arrConditions = $conditional->getConditions(); - $numConditions = sizeof($arrConditions); - if($numConditions == 1){ - $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); - $szValue2 = 0x0000; - $operand1 = pack('Cv', 0x1E, $arrConditions[0]); - $operand2 = null; - } else if($numConditions == 2 && ($conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BETWEEN)){ - $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); - $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000); - $operand1 = pack('Cv', 0x1E, $arrConditions[0]); - $operand2 = pack('Cv', 0x1E, $arrConditions[1]); - } else { - $szValue1 = 0x0000; - $szValue2 = 0x0000; - $operand1 = null; - $operand2 = null; - } - - // $flags : Option flags - // Alignment - $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0); - $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0); - $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0); - $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0); - $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0); - $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0); - if($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0){ - $bFormatAlign = 1; - } else { - $bFormatAlign = 0; - } - // Protection - $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0); - $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0); - if($bProtLocked == 0 || $bProtHidden == 0){ - $bFormatProt = 1; - } else { - $bFormatProt = 0; - } - // Border - $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK - && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); - $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK - && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); - $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK - && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); - $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK - && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); - if($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0){ - $bFormatBorder = 1; - } else { - $bFormatBorder = 0; - } - // Pattern - $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1); - $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1); - $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1); - if($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0){ - $bFormatFill = 1; - } else { - $bFormatFill = 0; - } - // Font - if($conditional->getStyle()->getFont()->getName() != null - || $conditional->getStyle()->getFont()->getSize() != null - || $conditional->getStyle()->getFont()->getBold() != null - || $conditional->getStyle()->getFont()->getItalic() != null - || $conditional->getStyle()->getFont()->getSuperScript() != null - || $conditional->getStyle()->getFont()->getSubScript() != null - || $conditional->getStyle()->getFont()->getUnderline() != null - || $conditional->getStyle()->getFont()->getStrikethrough() != null - || $conditional->getStyle()->getFont()->getColor()->getARGB() != null){ - $bFormatFont = 1; - } else { - $bFormatFont = 0; - } - // Alignment - $flags = 0; - $flags |= (1 == $bAlignHz ? 0x00000001 : 0); - $flags |= (1 == $bAlignVt ? 0x00000002 : 0); - $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0); - $flags |= (1 == $bTxRotation ? 0x00000008 : 0); - // Justify last line flag - $flags |= (1 == 1 ? 0x00000010 : 0); - $flags |= (1 == $bIndent ? 0x00000020 : 0); - $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0); - // Default - $flags |= (1 == 1 ? 0x00000080 : 0); - // Protection - $flags |= (1 == $bProtLocked ? 0x00000100 : 0); - $flags |= (1 == $bProtHidden ? 0x00000200 : 0); - // Border - $flags |= (1 == $bBorderLeft ? 0x00000400 : 0); - $flags |= (1 == $bBorderRight ? 0x00000800 : 0); - $flags |= (1 == $bBorderTop ? 0x00001000 : 0); - $flags |= (1 == $bBorderBottom ? 0x00002000 : 0); - $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border - $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border - // Pattern - $flags |= (1 == $bFillStyle ? 0x00010000 : 0); - $flags |= (1 == $bFillColor ? 0x00020000 : 0); - $flags |= (1 == $bFillColorBg ? 0x00040000 : 0); - $flags |= (1 == 1 ? 0x00380000 : 0); - // Font - $flags |= (1 == $bFormatFont ? 0x04000000 : 0); - // Alignment : - $flags |= (1 == $bFormatAlign ? 0x08000000 : 0); - // Border - $flags |= (1 == $bFormatBorder ? 0x10000000 : 0); - // Pattern - $flags |= (1 == $bFormatFill ? 0x20000000 : 0); - // Protection - $flags |= (1 == $bFormatProt ? 0x40000000 : 0); - // Text direction - $flags |= (1 == 0 ? 0x80000000 : 0); - - // Data Blocks - if($bFormatFont == 1){ - // Font Name - if($conditional->getStyle()->getFont()->getName() == null){ - $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); - $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); - } else { - $dataBlockFont = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName()); - } - // Font Size - if($conditional->getStyle()->getFont()->getSize() == null){ - $dataBlockFont .= pack('V', 20 * 11); - } else { - $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize()); - } - // Font Options - $dataBlockFont .= pack('V', 0); - // Font weight - if($conditional->getStyle()->getFont()->getBold() == true){ - $dataBlockFont .= pack('v', 0x02BC); - } else { - $dataBlockFont .= pack('v', 0x0190); - } - // Escapement type - if($conditional->getStyle()->getFont()->getSubScript() == true){ - $dataBlockFont .= pack('v', 0x02); - $fontEscapement = 0; - } else if($conditional->getStyle()->getFont()->getSuperScript() == true){ - $dataBlockFont .= pack('v', 0x01); - $fontEscapement = 0; - } else { - $dataBlockFont .= pack('v', 0x00); - $fontEscapement = 1; - } - // Underline type - switch ($conditional->getStyle()->getFont()->getUnderline()){ - case PHPExcel_Style_Font::UNDERLINE_NONE : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 0; break; - case PHPExcel_Style_Font::UNDERLINE_DOUBLE : $dataBlockFont .= pack('C', 0x02); $fontUnderline = 0; break; - case PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING : $dataBlockFont .= pack('C', 0x22); $fontUnderline = 0; break; - case PHPExcel_Style_Font::UNDERLINE_SINGLE : $dataBlockFont .= pack('C', 0x01); $fontUnderline = 0; break; - case PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING : $dataBlockFont .= pack('C', 0x21); $fontUnderline = 0; break; - default : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 1; break; - } - // Not used (3) - $dataBlockFont .= pack('vC', 0x0000, 0x00); - // Font color index - switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) { - case '000000': $colorIdx = 0x08; break; - case 'FFFFFF': $colorIdx = 0x09; break; - case 'FF0000': $colorIdx = 0x0A; break; - case '00FF00': $colorIdx = 0x0B; break; - case '0000FF': $colorIdx = 0x0C; break; - case 'FFFF00': $colorIdx = 0x0D; break; - case 'FF00FF': $colorIdx = 0x0E; break; - case '00FFFF': $colorIdx = 0x0F; break; - case '800000': $colorIdx = 0x10; break; - case '008000': $colorIdx = 0x11; break; - case '000080': $colorIdx = 0x12; break; - case '808000': $colorIdx = 0x13; break; - case '800080': $colorIdx = 0x14; break; - case '008080': $colorIdx = 0x15; break; - case 'C0C0C0': $colorIdx = 0x16; break; - case '808080': $colorIdx = 0x17; break; - case '9999FF': $colorIdx = 0x18; break; - case '993366': $colorIdx = 0x19; break; - case 'FFFFCC': $colorIdx = 0x1A; break; - case 'CCFFFF': $colorIdx = 0x1B; break; - case '660066': $colorIdx = 0x1C; break; - case 'FF8080': $colorIdx = 0x1D; break; - case '0066CC': $colorIdx = 0x1E; break; - case 'CCCCFF': $colorIdx = 0x1F; break; - case '000080': $colorIdx = 0x20; break; - case 'FF00FF': $colorIdx = 0x21; break; - case 'FFFF00': $colorIdx = 0x22; break; - case '00FFFF': $colorIdx = 0x23; break; - case '800080': $colorIdx = 0x24; break; - case '800000': $colorIdx = 0x25; break; - case '008080': $colorIdx = 0x26; break; - case '0000FF': $colorIdx = 0x27; break; - case '00CCFF': $colorIdx = 0x28; break; - case 'CCFFFF': $colorIdx = 0x29; break; - case 'CCFFCC': $colorIdx = 0x2A; break; - case 'FFFF99': $colorIdx = 0x2B; break; - case '99CCFF': $colorIdx = 0x2C; break; - case 'FF99CC': $colorIdx = 0x2D; break; - case 'CC99FF': $colorIdx = 0x2E; break; - case 'FFCC99': $colorIdx = 0x2F; break; - case '3366FF': $colorIdx = 0x30; break; - case '33CCCC': $colorIdx = 0x31; break; - case '99CC00': $colorIdx = 0x32; break; - case 'FFCC00': $colorIdx = 0x33; break; - case 'FF9900': $colorIdx = 0x34; break; - case 'FF6600': $colorIdx = 0x35; break; - case '666699': $colorIdx = 0x36; break; - case '969696': $colorIdx = 0x37; break; - case '003366': $colorIdx = 0x38; break; - case '339966': $colorIdx = 0x39; break; - case '003300': $colorIdx = 0x3A; break; - case '333300': $colorIdx = 0x3B; break; - case '993300': $colorIdx = 0x3C; break; - case '993366': $colorIdx = 0x3D; break; - case '333399': $colorIdx = 0x3E; break; - case '333333': $colorIdx = 0x3F; break; - default: $colorIdx = 0x00; break; - } - $dataBlockFont .= pack('V', $colorIdx); - // Not used (4) - $dataBlockFont .= pack('V', 0x00000000); - // Options flags for modified font attributes - $optionsFlags = 0; - $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0); - $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0); - $optionsFlags |= (1 == 1 ? 0x00000008 : 0); - $optionsFlags |= (1 == 1 ? 0x00000010 : 0); - $optionsFlags |= (1 == 0 ? 0x00000020 : 0); - $optionsFlags |= (1 == 1 ? 0x00000080 : 0); - $dataBlockFont .= pack('V', $optionsFlags); - // Escapement type - $dataBlockFont .= pack('V', $fontEscapement); - // Underline type - $dataBlockFont .= pack('V', $fontUnderline); - // Always - $dataBlockFont .= pack('V', 0x00000000); - // Always - $dataBlockFont .= pack('V', 0x00000000); - // Not used (8) - $dataBlockFont .= pack('VV', 0x00000000, 0x00000000); - // Always - $dataBlockFont .= pack('v', 0x0001); - } - if($bFormatAlign == 1){ - $blockAlign = 0; - // Alignment and text break - switch ($conditional->getStyle()->getAlignment()->getHorizontal()){ - case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL : $blockAlign = 0; break; - case PHPExcel_Style_Alignment::HORIZONTAL_LEFT : $blockAlign = 1; break; - case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT : $blockAlign = 3; break; - case PHPExcel_Style_Alignment::HORIZONTAL_CENTER : $blockAlign = 2; break; - case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS : $blockAlign = 6; break; - case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY : $blockAlign = 5; break; - } - if($conditional->getStyle()->getAlignment()->getWrapText() == true){ - $blockAlign |= 1 << 3; - } else { - $blockAlign |= 0 << 3; - } - switch ($conditional->getStyle()->getAlignment()->getVertical()){ - case PHPExcel_Style_Alignment::VERTICAL_BOTTOM : $blockAlign = 2 << 4; break; - case PHPExcel_Style_Alignment::VERTICAL_TOP : $blockAlign = 0 << 4; break; - case PHPExcel_Style_Alignment::VERTICAL_CENTER : $blockAlign = 1 << 4; break; - case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY : $blockAlign = 3 << 4; break; - } - $blockAlign |= 0 << 7; - - // Text rotation angle - $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation(); - - // Indentation - $blockIndent = $conditional->getStyle()->getAlignment()->getIndent(); - if($conditional->getStyle()->getAlignment()->getShrinkToFit() == true){ - $blockIndent |= 1 << 4; - } else { - $blockIndent |= 0 << 4; - } - $blockIndent |= 0 << 6; - - // Relative indentation - $blockIndentRelative = 255; - - $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000); - } - if($bFormatBorder == 1){ - $blockLineStyle = 0; - switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()){ - case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00; break; - case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01; break; - case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02; break; - case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03; break; - case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04; break; - case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05; break; - case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06; break; - case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08; break; - case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A; break; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C; break; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D; break; - } - switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()){ - case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 4; break; - case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 4; break; - case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 4; break; - case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 4; break; - case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 4; break; - case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 4; break; - case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 4; break; - case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 4; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 4; break; - case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 4; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 4; break; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 4; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 4; break; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 4; break; - } - switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()){ - case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 8; break; - case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 8; break; - case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 8; break; - case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 8; break; - case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 8; break; - case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 8; break; - case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 8; break; - case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 8; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 8; break; - case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 8; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 8; break; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 8; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 8; break; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 8; break; - } - switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()){ - case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 12; break; - case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 12; break; - case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 12; break; - case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 12; break; - case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 12; break; - case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 12; break; - case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 12; break; - case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 12; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 12; break; - case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 12; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 12; break; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 12; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 12; break; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 12; break; - } - //@todo _writeCFRule() => $blockLineStyle => Index Color for left line - //@todo _writeCFRule() => $blockLineStyle => Index Color for right line - //@todo _writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off - //@todo _writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off - $blockColor = 0; - //@todo _writeCFRule() => $blockColor => Index Color for top line - //@todo _writeCFRule() => $blockColor => Index Color for bottom line - //@todo _writeCFRule() => $blockColor => Index Color for diagonal line - switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()){ - case PHPExcel_Style_Border::BORDER_NONE : $blockColor |= 0x00 << 21; break; - case PHPExcel_Style_Border::BORDER_THIN : $blockColor |= 0x01 << 21; break; - case PHPExcel_Style_Border::BORDER_MEDIUM : $blockColor |= 0x02 << 21; break; - case PHPExcel_Style_Border::BORDER_DASHED : $blockColor |= 0x03 << 21; break; - case PHPExcel_Style_Border::BORDER_DOTTED : $blockColor |= 0x04 << 21; break; - case PHPExcel_Style_Border::BORDER_THICK : $blockColor |= 0x05 << 21; break; - case PHPExcel_Style_Border::BORDER_DOUBLE : $blockColor |= 0x06 << 21; break; - case PHPExcel_Style_Border::BORDER_HAIR : $blockColor |= 0x07 << 21; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockColor |= 0x08 << 21; break; - case PHPExcel_Style_Border::BORDER_DASHDOT : $blockColor |= 0x09 << 21; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockColor |= 0x0A << 21; break; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockColor |= 0x0B << 21; break; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockColor |= 0x0C << 21; break; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockColor |= 0x0D << 21; break; - } - $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor); - } - if($bFormatFill == 1){ - // Fill Patern Style - $blockFillPatternStyle = 0; - switch ($conditional->getStyle()->getFill()->getFillType()){ - case PHPExcel_Style_Fill::FILL_NONE : $blockFillPatternStyle = 0x00; break; - case PHPExcel_Style_Fill::FILL_SOLID : $blockFillPatternStyle = 0x01; break; - case PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY : $blockFillPatternStyle = 0x02; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY : $blockFillPatternStyle = 0x03; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY : $blockFillPatternStyle = 0x04; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL : $blockFillPatternStyle = 0x05; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL : $blockFillPatternStyle = 0x06; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN : $blockFillPatternStyle = 0x07; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKUP : $blockFillPatternStyle = 0x08; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID : $blockFillPatternStyle = 0x09; break; - case PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS : $blockFillPatternStyle = 0x0A; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL : $blockFillPatternStyle = 0x0B; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL : $blockFillPatternStyle = 0x0C; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN : $blockFillPatternStyle = 0x0D; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP : $blockFillPatternStyle = 0x0E; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID : $blockFillPatternStyle = 0x0F; break; - case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS : $blockFillPatternStyle = 0x10; break; - case PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 : $blockFillPatternStyle = 0x11; break; - case PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 : $blockFillPatternStyle = 0x12; break; - case PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 - case PHPExcel_Style_Fill::FILL_GRADIENT_PATH : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 - default : $blockFillPatternStyle = 0x00; break; - } - // Color - switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) { - case '000000': $colorIdxBg = 0x08; break; - case 'FFFFFF': $colorIdxBg = 0x09; break; - case 'FF0000': $colorIdxBg = 0x0A; break; - case '00FF00': $colorIdxBg = 0x0B; break; - case '0000FF': $colorIdxBg = 0x0C; break; - case 'FFFF00': $colorIdxBg = 0x0D; break; - case 'FF00FF': $colorIdxBg = 0x0E; break; - case '00FFFF': $colorIdxBg = 0x0F; break; - case '800000': $colorIdxBg = 0x10; break; - case '008000': $colorIdxBg = 0x11; break; - case '000080': $colorIdxBg = 0x12; break; - case '808000': $colorIdxBg = 0x13; break; - case '800080': $colorIdxBg = 0x14; break; - case '008080': $colorIdxBg = 0x15; break; - case 'C0C0C0': $colorIdxBg = 0x16; break; - case '808080': $colorIdxBg = 0x17; break; - case '9999FF': $colorIdxBg = 0x18; break; - case '993366': $colorIdxBg = 0x19; break; - case 'FFFFCC': $colorIdxBg = 0x1A; break; - case 'CCFFFF': $colorIdxBg = 0x1B; break; - case '660066': $colorIdxBg = 0x1C; break; - case 'FF8080': $colorIdxBg = 0x1D; break; - case '0066CC': $colorIdxBg = 0x1E; break; - case 'CCCCFF': $colorIdxBg = 0x1F; break; - case '000080': $colorIdxBg = 0x20; break; - case 'FF00FF': $colorIdxBg = 0x21; break; - case 'FFFF00': $colorIdxBg = 0x22; break; - case '00FFFF': $colorIdxBg = 0x23; break; - case '800080': $colorIdxBg = 0x24; break; - case '800000': $colorIdxBg = 0x25; break; - case '008080': $colorIdxBg = 0x26; break; - case '0000FF': $colorIdxBg = 0x27; break; - case '00CCFF': $colorIdxBg = 0x28; break; - case 'CCFFFF': $colorIdxBg = 0x29; break; - case 'CCFFCC': $colorIdxBg = 0x2A; break; - case 'FFFF99': $colorIdxBg = 0x2B; break; - case '99CCFF': $colorIdxBg = 0x2C; break; - case 'FF99CC': $colorIdxBg = 0x2D; break; - case 'CC99FF': $colorIdxBg = 0x2E; break; - case 'FFCC99': $colorIdxBg = 0x2F; break; - case '3366FF': $colorIdxBg = 0x30; break; - case '33CCCC': $colorIdxBg = 0x31; break; - case '99CC00': $colorIdxBg = 0x32; break; - case 'FFCC00': $colorIdxBg = 0x33; break; - case 'FF9900': $colorIdxBg = 0x34; break; - case 'FF6600': $colorIdxBg = 0x35; break; - case '666699': $colorIdxBg = 0x36; break; - case '969696': $colorIdxBg = 0x37; break; - case '003366': $colorIdxBg = 0x38; break; - case '339966': $colorIdxBg = 0x39; break; - case '003300': $colorIdxBg = 0x3A; break; - case '333300': $colorIdxBg = 0x3B; break; - case '993300': $colorIdxBg = 0x3C; break; - case '993366': $colorIdxBg = 0x3D; break; - case '333399': $colorIdxBg = 0x3E; break; - case '333333': $colorIdxBg = 0x3F; break; - default: $colorIdxBg = 0x41; break; - } - // Fg Color - switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) { - case '000000': $colorIdxFg = 0x08; break; - case 'FFFFFF': $colorIdxFg = 0x09; break; - case 'FF0000': $colorIdxFg = 0x0A; break; - case '00FF00': $colorIdxFg = 0x0B; break; - case '0000FF': $colorIdxFg = 0x0C; break; - case 'FFFF00': $colorIdxFg = 0x0D; break; - case 'FF00FF': $colorIdxFg = 0x0E; break; - case '00FFFF': $colorIdxFg = 0x0F; break; - case '800000': $colorIdxFg = 0x10; break; - case '008000': $colorIdxFg = 0x11; break; - case '000080': $colorIdxFg = 0x12; break; - case '808000': $colorIdxFg = 0x13; break; - case '800080': $colorIdxFg = 0x14; break; - case '008080': $colorIdxFg = 0x15; break; - case 'C0C0C0': $colorIdxFg = 0x16; break; - case '808080': $colorIdxFg = 0x17; break; - case '9999FF': $colorIdxFg = 0x18; break; - case '993366': $colorIdxFg = 0x19; break; - case 'FFFFCC': $colorIdxFg = 0x1A; break; - case 'CCFFFF': $colorIdxFg = 0x1B; break; - case '660066': $colorIdxFg = 0x1C; break; - case 'FF8080': $colorIdxFg = 0x1D; break; - case '0066CC': $colorIdxFg = 0x1E; break; - case 'CCCCFF': $colorIdxFg = 0x1F; break; - case '000080': $colorIdxFg = 0x20; break; - case 'FF00FF': $colorIdxFg = 0x21; break; - case 'FFFF00': $colorIdxFg = 0x22; break; - case '00FFFF': $colorIdxFg = 0x23; break; - case '800080': $colorIdxFg = 0x24; break; - case '800000': $colorIdxFg = 0x25; break; - case '008080': $colorIdxFg = 0x26; break; - case '0000FF': $colorIdxFg = 0x27; break; - case '00CCFF': $colorIdxFg = 0x28; break; - case 'CCFFFF': $colorIdxFg = 0x29; break; - case 'CCFFCC': $colorIdxFg = 0x2A; break; - case 'FFFF99': $colorIdxFg = 0x2B; break; - case '99CCFF': $colorIdxFg = 0x2C; break; - case 'FF99CC': $colorIdxFg = 0x2D; break; - case 'CC99FF': $colorIdxFg = 0x2E; break; - case 'FFCC99': $colorIdxFg = 0x2F; break; - case '3366FF': $colorIdxFg = 0x30; break; - case '33CCCC': $colorIdxFg = 0x31; break; - case '99CC00': $colorIdxFg = 0x32; break; - case 'FFCC00': $colorIdxFg = 0x33; break; - case 'FF9900': $colorIdxFg = 0x34; break; - case 'FF6600': $colorIdxFg = 0x35; break; - case '666699': $colorIdxFg = 0x36; break; - case '969696': $colorIdxFg = 0x37; break; - case '003366': $colorIdxFg = 0x38; break; - case '339966': $colorIdxFg = 0x39; break; - case '003300': $colorIdxFg = 0x3A; break; - case '333300': $colorIdxFg = 0x3B; break; - case '993300': $colorIdxFg = 0x3C; break; - case '993366': $colorIdxFg = 0x3D; break; - case '333399': $colorIdxFg = 0x3E; break; - case '333333': $colorIdxFg = 0x3F; break; - default: $colorIdxFg = 0x40; break; - } - $dataBlockFill = pack('v', $blockFillPatternStyle); - $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7)); - } - if($bFormatProt == 1){ - $dataBlockProtection = 0; - if($conditional->getStyle()->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ - $dataBlockProtection = 1; - } - if($conditional->getStyle()->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ - $dataBlockProtection = 1 << 1; - } - } - - $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000); - if($bFormatFont == 1){ // Block Formatting : OK - $data .= $dataBlockFont; - } - if($bFormatAlign == 1){ - $data .= $dataBlockAlign; - } - if($bFormatBorder == 1){ - $data .= $dataBlockBorder; - } - if($bFormatFill == 1){ // Block Formatting : OK - $data .= $dataBlockFill; - } - if($bFormatProt == 1){ - $data .= $dataBlockProtection; - } - if(!is_null($operand1)){ - $data .= $operand1; - } - if(!is_null($operand2)){ - $data .= $operand2; - } - $header = pack('vv', $record, strlen($data)); - $this->_append($header . $data); - } - - /** - * Write CFHeader record - */ - private function _writeCFHeader(){ - $record = 0x01B0; // Record identifier - $length = 0x0016; // Bytes to follow - - $numColumnMin = null; - $numColumnMax = null; - $numRowMin = null; - $numRowMax = null; - $arrConditional = array(); - foreach ($this->_phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { - foreach ($conditionalStyles as $conditional) { - if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION - || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ - if(!in_array($conditional->getHashCode(), $arrConditional)){ - $arrConditional[] = $conditional->getHashCode(); - } - // Cells - $arrCoord = PHPExcel_Cell::coordinateFromString($cellCoordinate); - if(!is_numeric($arrCoord[0])){ - $arrCoord[0] = PHPExcel_Cell::columnIndexFromString($arrCoord[0]); - } - if(is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])){ - $numColumnMin = $arrCoord[0]; - } - if(is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])){ - $numColumnMax = $arrCoord[0]; - } - if(is_null($numRowMin) || ($numRowMin > $arrCoord[1])){ - $numRowMin = $arrCoord[1]; - } - if(is_null($numRowMax) || ($numRowMax < $arrCoord[1])){ - $numRowMax = $arrCoord[1]; - } - } - } - } - $needRedraw = 1; - $cellRange = pack('vvvv', $numRowMin-1, $numRowMax-1, $numColumnMin-1, $numColumnMax-1); - - $header = pack('vv', $record, $length); - $data = pack('vv', count($arrConditional), $needRedraw); - $data .= $cellRange; - $data .= pack('v', 0x0001); - $data .= $cellRange; - $this->_append($header . $data); - } + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * Maximum number of characters for a string (LABEL record in BIFF5) + * @var integer + */ + public $_xls_strmax; + + /** + * Array containing format information for columns + * @var array + */ + public $_colinfo; + + /** + * Array containing the selected area for the worksheet + * @var array + */ + public $_selection; + + /** + * The active pane for the worksheet + * @var integer + */ + public $_active_pane; + + /** + * Whether to use outline. + * @var integer + */ + public $_outline_on; + + /** + * Auto outline styles. + * @var bool + */ + public $_outline_style; + + /** + * Whether to have outline summary below. + * @var bool + */ + public $_outline_below; + + /** + * Whether to have outline summary at the right. + * @var bool + */ + public $_outline_right; + + /** + * Reference to the total number of strings in the workbook + * @var integer + */ + public $_str_total; + + /** + * Reference to the number of unique strings in the workbook + * @var integer + */ + public $_str_unique; + + /** + * Reference to the array containing all the unique strings in the workbook + * @var array + */ + public $_str_table; + + /** + * Color cache + */ + private $_colors; + + /** + * Index of first used row (at least 0) + * @var int + */ + private $_firstRowIndex; + + /** + * Index of last used row. (no used rows means -1) + * @var int + */ + private $_lastRowIndex; + + /** + * Index of first used column (at least 0) + * @var int + */ + private $_firstColumnIndex; + + /** + * Index of last used column (no used columns means -1) + * @var int + */ + private $_lastColumnIndex; + + /** + * Sheet object + * @var PHPExcel_Worksheet + */ + public $_phpSheet; + + /** + * Count cell style Xfs + * + * @var int + */ + private $_countCellStyleXfs; + + /** + * Escher object corresponding to MSODRAWING + * + * @var PHPExcel_Shared_Escher + */ + private $_escher; + + /** + * Array of font hashes associated to FONT records index + * + * @var array + */ + public $_fntHashIndex; + + /** + * Constructor + * + * @param int &$str_total Total number of strings + * @param int &$str_unique Total number of unique strings + * @param array &$str_table String Table + * @param array &$colors Colour Table + * @param mixed $parser The formula parser created for the Workbook + * @param boolean $preCalculateFormulas Flag indicating whether formulas should be calculated or just written + * @param string $phpSheet The worksheet to write + * @param PHPExcel_Worksheet $phpSheet + */ + public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, + $parser, $preCalculateFormulas, $phpSheet) + { + // It needs to call its parent's constructor explicitly + parent::__construct(); + + // change BIFFwriter limit for CONTINUE records +// $this->_limit = 8224; + + + $this->_preCalculateFormulas = $preCalculateFormulas; + $this->_str_total = &$str_total; + $this->_str_unique = &$str_unique; + $this->_str_table = &$str_table; + $this->_colors = &$colors; + $this->_parser = $parser; + + $this->_phpSheet = $phpSheet; + + //$this->ext_sheets = array(); + //$this->offset = 0; + $this->_xls_strmax = 255; + $this->_colinfo = array(); + $this->_selection = array(0,0,0,0); + $this->_active_pane = 3; + + $this->_print_headers = 0; + + $this->_outline_style = 0; + $this->_outline_below = 1; + $this->_outline_right = 1; + $this->_outline_on = 1; + + $this->_fntHashIndex = array(); + + // calculate values for DIMENSIONS record + $minR = 1; + $minC = 'A'; + + $maxR = $this->_phpSheet->getHighestRow(); + $maxC = $this->_phpSheet->getHighestColumn(); + + // Determine lowest and highest column and row +// $this->_firstRowIndex = ($minR > 65535) ? 65535 : $minR; + $this->_lastRowIndex = ($maxR > 65535) ? 65535 : $maxR ; + + $this->_firstColumnIndex = PHPExcel_Cell::columnIndexFromString($minC); + $this->_lastColumnIndex = PHPExcel_Cell::columnIndexFromString($maxC); + +// if ($this->_firstColumnIndex > 255) $this->_firstColumnIndex = 255; + if ($this->_lastColumnIndex > 255) $this->_lastColumnIndex = 255; + + $this->_countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection()); + } + + /** + * Add data to the beginning of the workbook (note the reverse order) + * and to the end of the workbook. + * + * @access public + * @see PHPExcel_Writer_Excel5_Workbook::storeWorkbook() + */ + function close() + { + $_phpSheet = $this->_phpSheet; + + $num_sheets = $_phpSheet->getParent()->getSheetCount(); + + // Write BOF record + $this->_storeBof(0x0010); + + // Write PRINTHEADERS + $this->_writePrintHeaders(); + + // Write PRINTGRIDLINES + $this->_writePrintGridlines(); + + // Write GRIDSET + $this->_writeGridset(); + + // Calculate column widths + $_phpSheet->calculateColumnWidths(); + + // Column dimensions + if (($defaultWidth = $_phpSheet->getDefaultColumnDimension()->getWidth()) < 0) { + $defaultWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($_phpSheet->getParent()->getDefaultStyle()->getFont()); + } + + $columnDimensions = $_phpSheet->getColumnDimensions(); + $maxCol = $this->_lastColumnIndex -1; + for ($i = 0; $i <= $maxCol; ++$i) { + $hidden = 0; + $level = 0; + $xfIndex = 15; // there are 15 cell style Xfs + + $width = $defaultWidth; + + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i); + if (isset($columnDimensions[$columnLetter])) { + $columnDimension = $columnDimensions[$columnLetter]; + if ($columnDimension->getWidth() >= 0) { + $width = $columnDimension->getWidth(); + } + $hidden = $columnDimension->getVisible() ? 0 : 1; + $level = $columnDimension->getOutlineLevel(); + $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs + } + + // Components of _colinfo: + // $firstcol first column on the range + // $lastcol last column on the range + // $width width to set + // $xfIndex The optional cell style Xf index to apply to the columns + // $hidden The optional hidden atribute + // $level The optional outline level + $this->_colinfo[] = array($i, $i, $width, $xfIndex, $hidden, $level); + } + + // Write GUTS + $this->_writeGuts(); + + // Write DEFAULTROWHEIGHT + $this->_writeDefaultRowHeight(); + + // Write WSBOOL + $this->_writeWsbool(); + + // Write horizontal and vertical page breaks + $this->_writeBreaks(); + + // Write page header + $this->_writeHeader(); + + // Write page footer + $this->_writeFooter(); + + // Write page horizontal centering + $this->_writeHcenter(); + + // Write page vertical centering + $this->_writeVcenter(); + + // Write left margin + $this->_writeMarginLeft(); + + // Write right margin + $this->_writeMarginRight(); + + // Write top margin + $this->_writeMarginTop(); + + // Write bottom margin + $this->_writeMarginBottom(); + + // Write page setup + $this->_writeSetup(); + + // Write sheet protection + $this->_writeProtect(); + + // Write SCENPROTECT + $this->_writeScenProtect(); + + // Write OBJECTPROTECT + $this->_writeObjectProtect(); + + // Write sheet password + $this->_writePassword(); + + // Write DEFCOLWIDTH record + $this->_writeDefcol(); + + // Write the COLINFO records if they exist + if (!empty($this->_colinfo)) { + $colcount = count($this->_colinfo); + for ($i = 0; $i < $colcount; ++$i) { + $this->_writeColinfo($this->_colinfo[$i]); + } + } + $autoFilterRange = $_phpSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + // Write AUTOFILTERINFO + $this->_writeAutoFilterInfo(); + } + + // Write sheet dimensions + $this->_writeDimensions(); + + // Row dimensions + foreach ($_phpSheet->getRowDimensions() as $rowDimension) { + $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs + $this->_writeRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); + } + + // Write Cells + foreach ($_phpSheet->getCellCollection() as $cellID) { + $cell = $_phpSheet->getCell($cellID); + $row = $cell->getRow() - 1; + $column = PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1; + + // Don't break Excel! +// if ($row + 1 > 65536 or $column + 1 > 256) { + if ($row > 65535 || $column > 255) { + break; + } + + // Write cell value + $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs + + $cVal = $cell->getValue(); + if ($cVal instanceof PHPExcel_RichText) { + // $this->_writeString($row, $column, $cVal->getPlainText(), $xfIndex); + $arrcRun = array(); + $str_len = PHPExcel_Shared_String::CountCharacters($cVal->getPlainText(), 'UTF-8'); + $str_pos = 0; + $elements = $cVal->getRichTextElements(); + foreach ($elements as $element) { + // FONT Index + if ($element instanceof PHPExcel_RichText_Run) { + $str_fontidx = $this->_fntHashIndex[$element->getFont()->getHashCode()]; + } + else { + $str_fontidx = 0; + } + $arrcRun[] = array('strlen' => $str_pos, 'fontidx' => $str_fontidx); + // Position FROM + $str_pos += PHPExcel_Shared_String::CountCharacters($element->getText(), 'UTF-8'); + } + $this->_writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun); + } else { + switch ($cell->getDatatype()) { + case PHPExcel_Cell_DataType::TYPE_STRING: + case PHPExcel_Cell_DataType::TYPE_NULL: + if ($cVal === '' || $cVal === null) { + $this->_writeBlank($row, $column, $xfIndex); + } else { + $this->_writeString($row, $column, $cVal, $xfIndex); + } + break; + + case PHPExcel_Cell_DataType::TYPE_NUMERIC: + $this->_writeNumber($row, $column, $cVal, $xfIndex); + break; + + case PHPExcel_Cell_DataType::TYPE_FORMULA: + $calculatedValue = $this->_preCalculateFormulas ? + $cell->getCalculatedValue() : null; + $this->_writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue); + break; + + case PHPExcel_Cell_DataType::TYPE_BOOL: + $this->_writeBoolErr($row, $column, $cVal, 0, $xfIndex); + break; + + case PHPExcel_Cell_DataType::TYPE_ERROR: + $this->_writeBoolErr($row, $column, self::_mapErrorCode($cVal), 1, $xfIndex); + break; + + } + } + } + + // Append + $this->_writeMsoDrawing(); + + // Write WINDOW2 record + $this->_writeWindow2(); + + // Write PLV record + $this->_writePageLayoutView(); + + // Write ZOOM record + $this->_writeZoom(); + if ($_phpSheet->getFreezePane()) { + $this->_writePanes(); + } + + // Write SELECTION record + $this->_writeSelection(); + + // Write MergedCellsTable Record + $this->_writeMergedCells(); + + // Hyperlinks + foreach ($_phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinate); + + $url = $hyperlink->getUrl(); + + if ( strpos($url, 'sheet://') !== false ) { + // internal to current workbook + $url = str_replace('sheet://', 'internal:', $url); + + } else if ( preg_match('/^(http:|https:|ftp:|mailto:)/', $url) ) { + // URL + // $url = $url; + + } else { + // external (local file) + $url = 'external:' . $url; + } + + $this->_writeUrl($row - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); + } + + $this->_writeDataValidity(); + $this->_writeSheetLayout(); + + // Write SHEETPROTECTION record + $this->_writeSheetProtection(); + $this->_writeRangeProtection(); + + $arrConditionalStyles = $_phpSheet->getConditionalStylesCollection(); + if(!empty($arrConditionalStyles)){ + $arrConditional = array(); + // @todo CFRule & CFHeader + // Write CFHEADER record + $this->_writeCFHeader(); + // Write ConditionalFormattingTable records + foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + // Write CFRULE record + $this->_writeCFRule($conditional); + } + } + } + } + } + + $this->_storeEof(); + } + + /** + * Write a cell range address in BIFF8 + * always fixed range + * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format + * + * @param string $range E.g. 'A1' or 'A1:B6' + * @return string Binary data + */ + private function _writeBIFF8CellRangeAddressFixed($range = 'A1') + { + $explodes = explode(':', $range); + + // extract first cell, e.g. 'A1' + $firstCell = $explodes[0]; + + // extract last cell, e.g. 'B6' + if (count($explodes) == 1) { + $lastCell = $firstCell; + } else { + $lastCell = $explodes[1]; + } + + $firstCellCoordinates = PHPExcel_Cell::coordinateFromString($firstCell); // e.g. array(0, 1) + $lastCellCoordinates = PHPExcel_Cell::coordinateFromString($lastCell); // e.g. array(1, 6) + + return(pack('vvvv', + $firstCellCoordinates[1] - 1, + $lastCellCoordinates[1] - 1, + PHPExcel_Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, + PHPExcel_Cell::columnIndexFromString($lastCellCoordinates[0]) - 1 + )); + } + + /** + * Retrieves data from memory in one chunk, or from disk in $buffer + * sized chunks. + * + * @return string The data + */ + function getData() + { + $buffer = 4096; + + // Return data stored in memory + if (isset($this->_data)) { + $tmp = $this->_data; + unset($this->_data); + return $tmp; + } + // No data to return + return false; + } + + /** + * Set the option to print the row and column headers on the printed page. + * + * @access public + * @param integer $print Whether to print the headers or not. Defaults to 1 (print). + */ + function printRowColHeaders($print = 1) + { + $this->_print_headers = $print; + } + + /** + * This method sets the properties for outlining and grouping. The defaults + * correspond to Excel's defaults. + * + * @param bool $visible + * @param bool $symbols_below + * @param bool $symbols_right + * @param bool $auto_style + */ + function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false) + { + $this->_outline_on = $visible; + $this->_outline_below = $symbols_below; + $this->_outline_right = $symbols_right; + $this->_outline_style = $auto_style; + + // Ensure this is a boolean vale for Window2 + if ($this->_outline_on) { + $this->_outline_on = 1; + } + } + + /** + * Write a double to the specified row and column (zero indexed). + * An integer can be written as a double. Excel will display an + * integer. $format is optional. + * + * Returns 0 : normal termination + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param float $num The number to write + * @param mixed $xfIndex The optional XF format + * @return integer + */ + private function _writeNumber($row, $col, $num, $xfIndex) + { + $record = 0x0203; // Record identifier + $length = 0x000E; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $xfIndex); + $xl_double = pack("d", $num); + if (self::getByteOrder()) { // if it's Big Endian + $xl_double = strrev($xl_double); + } + + $this->_append($header.$data.$xl_double); + return(0); + } + + /** + * Write a LABELSST record or a LABEL record. Which one depends on BIFF version + * + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param string $str The string + * @param int $xfIndex Index to XF record + */ + private function _writeString($row, $col, $str, $xfIndex) + { + $this->_writeLabelSst($row, $col, $str, $xfIndex); + } + + /** + * Write a LABELSST record or a LABEL record. Which one depends on BIFF version + * It differs from _writeString by the writing of rich text strings. + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param string $str The string + * @param mixed $xfIndex The XF format index for the cell + * @param array $arrcRun Index to Font record and characters beginning + */ + private function _writeRichTextString($row, $col, $str, $xfIndex, $arrcRun){ + $record = 0x00FD; // Record identifier + $length = 0x000A; // Bytes to follow + $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($str, $arrcRun); + + /* check if string is already present */ + if (!isset($this->_str_table[$str])) { + $this->_str_table[$str] = $this->_str_unique++; + } + $this->_str_total++; + + $header = pack('vv', $record, $length); + $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); + $this->_append($header.$data); + } + + /** + * Write a string to the specified row and column (zero indexed). + * NOTE: there is an Excel 5 defined limit of 255 characters. + * $format is optional. + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @access public + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $str The string to write + * @param mixed $xfIndex The XF format index for the cell + * @return integer + */ + private function _writeLabel($row, $col, $str, $xfIndex) + { + $strlen = strlen($str); + $record = 0x0204; // Record identifier + $length = 0x0008 + $strlen; // Bytes to follow + + $str_error = 0; + + if ($strlen > $this->_xls_strmax) { // LABEL must be < 255 chars + $str = substr($str, 0, $this->_xls_strmax); + $length = 0x0008 + $this->_xls_strmax; + $strlen = $this->_xls_strmax; + $str_error = -3; + } + + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row, $col, $xfIndex, $strlen); + $this->_append($header . $data . $str); + return($str_error); + } + + /** + * Write a string to the specified row and column (zero indexed). + * This is the BIFF8 version (no 255 chars limit). + * $format is optional. + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @access public + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $str The string to write + * @param mixed $xfIndex The XF format index for the cell + * @return integer + */ + private function _writeLabelSst($row, $col, $str, $xfIndex) + { + $record = 0x00FD; // Record identifier + $length = 0x000A; // Bytes to follow + + $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($str); + + /* check if string is already present */ + if (!isset($this->_str_table[$str])) { + $this->_str_table[$str] = $this->_str_unique++; + } + $this->_str_total++; + + $header = pack('vv', $record, $length); + $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); + $this->_append($header.$data); + } + + /** + * Writes a note associated with the cell given by the row and column. + * NOTE records don't have a length limit. + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $note The note to write + */ + private function _writeNote($row, $col, $note) + { + $note_length = strlen($note); + $record = 0x001C; // Record identifier + $max_length = 2048; // Maximun length for a NOTE record + + // Length for this record is no more than 2048 + 6 + $length = 0x0006 + min($note_length, 2048); + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $note_length); + $this->_append($header . $data . substr($note, 0, 2048)); + + for ($i = $max_length; $i < $note_length; $i += $max_length) { + $chunk = substr($note, $i, $max_length); + $length = 0x0006 + strlen($chunk); + $header = pack("vv", $record, $length); + $data = pack("vvv", -1, 0, strlen($chunk)); + $this->_append($header.$data.$chunk); + } + return(0); + } + + /** + * Write a blank cell to the specified row and column (zero indexed). + * A blank cell is used to specify formatting without adding a string + * or a number. + * + * A blank cell without a format serves no purpose. Therefore, we don't write + * a BLANK record unless a format is specified. + * + * Returns 0 : normal termination (including no format) + * -1 : insufficient number of arguments + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param mixed $xfIndex The XF format index + */ + function _writeBlank($row, $col, $xfIndex) + { + $record = 0x0201; // Record identifier + $length = 0x0006; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $xfIndex); + $this->_append($header . $data); + return 0; + } + + /** + * Write a boolean or an error type to the specified row and column (zero indexed) + * + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param int $value + * @param boolean $isError Error or Boolean? + * @param int $xfIndex + */ + private function _writeBoolErr($row, $col, $value, $isError, $xfIndex) + { + $record = 0x0205; + $length = 8; + + $header = pack("vv", $record, $length); + $data = pack("vvvCC", $row, $col, $xfIndex, $value, $isError); + $this->_append($header . $data); + return 0; + } + + /** + * Write a formula to the specified row and column (zero indexed). + * The textual representation of the formula is passed to the parser in + * Parser.php which returns a packed binary string. + * + * Returns 0 : normal termination + * -1 : formula errors (bad formula) + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $formula The formula text string + * @param mixed $xfIndex The XF format index + * @param mixed $calculatedValue Calculated value + * @return integer + */ + private function _writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) + { + $record = 0x0006; // Record identifier + + // Initialize possible additional value for STRING record that should be written after the FORMULA record? + $stringValue = null; + + // calculated value + if (isset($calculatedValue)) { + // Since we can't yet get the data type of the calculated value, + // we use best effort to determine data type + if (is_bool($calculatedValue)) { + // Boolean value + $num = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { + // Numeric value + $num = pack('d', $calculatedValue); + } elseif (is_string($calculatedValue)) { + if (array_key_exists($calculatedValue, PHPExcel_Cell_DataType::getErrorCodes())) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, self::_mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + } elseif ($calculatedValue === '') { + // Empty string (and BIFF8) + $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } else { + // Non-empty string value (or empty string BIFF5) + $stringValue = $calculatedValue; + $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } + } else { + // We are really not supposed to reach here + $num = pack('d', 0x00); + } + } else { + $num = pack('d', 0x00); + } + + $grbit = 0x03; // Option flags + $unknown = 0x0000; // Must be zero + + // Strip the '=' or '@' sign at the beginning of the formula string + if ($formula{0} == '=') { + $formula = substr($formula,1); + } else { + // Error handling + $this->_writeString($row, $col, 'Unrecognised character for formula'); + return -1; + } + + // Parse the formula using the parser in Parser.php + try { + $error = $this->_parser->parse($formula); + $formula = $this->_parser->toReversePolish(); + + $formlen = strlen($formula); // Length of the binary string + $length = 0x16 + $formlen; // Length of the record data + + $header = pack("vv", $record, $length); + + $data = pack("vvv", $row, $col, $xfIndex) + . $num + . pack("vVv", $grbit, $unknown, $formlen); + $this->_append($header . $data . $formula); + + // Append also a STRING record if necessary + if ($stringValue !== null) { + $this->_writeStringRecord($stringValue); + } + + return 0; + + } catch (PHPExcel_Exception $e) { + // do nothing + } + + } + + /** + * Write a STRING record. This + * + * @param string $stringValue + */ + private function _writeStringRecord($stringValue) + { + $record = 0x0207; // Record identifier + $data = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue); + + $length = strlen($data); + $header = pack('vv', $record, $length); + + $this->_append($header . $data); + } + + /** + * Write a hyperlink. + * This is comprised of two elements: the visible label and + * the invisible link. The visible label is the same as the link unless an + * alternative string is specified. The label is written using the + * _writeString() method. Therefore the 255 characters string limit applies. + * $string and $format are optional. + * + * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external + * directory url. + * + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @param integer $row Row + * @param integer $col Column + * @param string $url URL string + * @return integer + */ + private function _writeUrl($row, $col, $url) + { + // Add start row and col to arg list + return($this->_writeUrlRange($row, $col, $row, $col, $url)); + } + + /** + * This is the more general form of _writeUrl(). It allows a hyperlink to be + * written to a range of cells. This function also decides the type of hyperlink + * to be written. These are either, Web (http, ftp, mailto), Internal + * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1'). + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlRange($row1, $col1, $row2, $col2, $url) + { + // Check for internal/external sheet links or default to web link + if (preg_match('[^internal:]', $url)) { + return($this->_writeUrlInternal($row1, $col1, $row2, $col2, $url)); + } + if (preg_match('[^external:]', $url)) { + return($this->_writeUrlExternal($row1, $col1, $row2, $col2, $url)); + } + return($this->_writeUrlWeb($row1, $col1, $row2, $col2, $url)); + } + + /** + * Used to write http, ftp and mailto hyperlinks. + * The link type ($options) is 0x03 is the same as absolute dir ref without + * sheet. However it is differentiated by the $unknown2 data stream. + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlWeb($row1, $col1, $row2, $col2, $url) + { + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); + $unknown2 = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B"); + + // Pack the option flags + $options = pack("V", 0x03); + + // Convert URL to a null terminated wchar string + $url = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY)); + $url = $url . "\0\0\0"; + + // Pack the length of the URL + $url_len = pack("V", strlen($url)); + + // Calculate the data length + $length = 0x34 + strlen($url); + + // Pack the header data + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row1, $row2, $col1, $col2); + + // Write the packed data + $this->_append($header . $data . + $unknown1 . $options . + $unknown2 . $url_len . $url); + return 0; + } + + /** + * Used to write internal reference hyperlinks such as "Sheet1!A1". + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlInternal($row1, $col1, $row2, $col2, $url) + { + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Strip URL type + $url = preg_replace('/^internal:/', '', $url); + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); + + // Pack the option flags + $options = pack("V", 0x08); + + // Convert the URL type and to a null terminated wchar string + $url .= "\0"; + + // character count + $url_len = PHPExcel_Shared_String::CountCharacters($url); + $url_len = pack('V', $url_len); + + $url = PHPExcel_Shared_String::ConvertEncoding($url, 'UTF-16LE', 'UTF-8'); + + // Calculate the data length + $length = 0x24 + strlen($url); + + // Pack the header data + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row1, $row2, $col1, $col2); + + // Write the packed data + $this->_append($header . $data . + $unknown1 . $options . + $url_len . $url); + return 0; + } + + /** + * Write links to external directory names such as 'c:\foo.xls', + * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'. + * + * Note: Excel writes some relative links with the $dir_long string. We ignore + * these cases for the sake of simpler code. + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlExternal($row1, $col1, $row2, $col2, $url) + { + // Network drives are different. We will handle them separately + // MS/Novell network drives and shares start with \\ + if (preg_match('[^external:\\\\]', $url)) { + return; //($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format)); + } + + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Strip URL type and change Unix dir separator to Dos style (if needed) + // + $url = preg_replace('/^external:/', '', $url); + $url = preg_replace('/\//', "\\", $url); + + // Determine if the link is relative or absolute: + // relative if link contains no dir separator, "somefile.xls" + // relative if link starts with up-dir, "..\..\somefile.xls" + // otherwise, absolute + + $absolute = 0x00; // relative path + if ( preg_match('/^[A-Z]:/', $url) ) { + $absolute = 0x02; // absolute path on Windows, e.g. C:\... + } + $link_type = 0x01 | $absolute; + + // Determine if the link contains a sheet reference and change some of the + // parameters accordingly. + // Split the dir name and sheet name (if it exists) + $dir_long = $url; + if (preg_match("/\#/", $url)) { + $link_type |= 0x08; + } + + + // Pack the link type + $link_type = pack("V", $link_type); + + // Calculate the up-level dir count e.g.. (..\..\..\ == 3) + $up_count = preg_match_all("/\.\.\\\/", $dir_long, $useless); + $up_count = pack("v", $up_count); + + // Store the short dos dir name (null terminated) + $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0"; + + // Store the long dir name as a wchar string (non-null terminated) + $dir_long = $dir_long . "\0"; + + // Pack the lengths of the dir strings + $dir_short_len = pack("V", strlen($dir_short) ); + $dir_long_len = pack("V", strlen($dir_long) ); + $stream_len = pack("V", 0);//strlen($dir_long) + 0x06); + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000' ); + $unknown2 = pack("H*",'0303000000000000C000000000000046' ); + $unknown3 = pack("H*",'FFFFADDE000000000000000000000000000000000000000'); + $unknown4 = pack("v", 0x03 ); + + // Pack the main data stream + $data = pack("vvvv", $row1, $row2, $col1, $col2) . + $unknown1 . + $link_type . + $unknown2 . + $up_count . + $dir_short_len. + $dir_short . + $unknown3 . + $stream_len ;/*. + $dir_long_len . + $unknown4 . + $dir_long . + $sheet_len . + $sheet ;*/ + + // Pack the header data + $length = strlen($data); + $header = pack("vv", $record, $length); + + // Write the packed data + $this->_append($header. $data); + return 0; + } + + /** + * This method is used to set the height and format for a row. + * + * @param integer $row The row to set + * @param integer $height Height we are giving to the row. + * Use null to set XF without setting height + * @param integer $xfIndex The optional cell style Xf index to apply to the columns + * @param bool $hidden The optional hidden attribute + * @param integer $level The optional outline level for row, in range [0,7] + */ + private function _writeRow($row, $height, $xfIndex, $hidden = false, $level = 0) + { + $record = 0x0208; // Record identifier + $length = 0x0010; // Number of bytes to follow + + $colMic = 0x0000; // First defined column + $colMac = 0x0000; // Last defined column + $irwMac = 0x0000; // Used by Excel to optimise loading + $reserved = 0x0000; // Reserved + $grbit = 0x0000; // Option flags + $ixfe = $xfIndex; + + if ( $height < 0 ){ + $height = null; + } + + // Use _writeRow($row, null, $XF) to set XF format without setting height + if ($height != null) { + $miyRw = $height * 20; // row height + } else { + $miyRw = 0xff; // default row height is 256 + } + + // Set the options flags. fUnsynced is used to show that the font and row + // heights are not compatible. This is usually the case for WriteExcel. + // The collapsed flag 0x10 doesn't seem to be used to indicate that a row + // is collapsed. Instead it is used to indicate that the previous row is + // collapsed. The zero height flag, 0x20, is used to collapse a row. + + $grbit |= $level; + if ($hidden) { + $grbit |= 0x0030; + } + if ($height !== null) { + $grbit |= 0x0040; // fUnsynced + } + if ($xfIndex !== 0xF) { + $grbit |= 0x0080; + } + $grbit |= 0x0100; + + $header = pack("vv", $record, $length); + $data = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw, + $irwMac,$reserved, $grbit, $ixfe); + $this->_append($header.$data); + } + + /** + * Writes Excel DIMENSIONS to define the area in which there is data. + */ + private function _writeDimensions() + { + $record = 0x0200; // Record identifier + + $length = 0x000E; + $data = pack('VVvvv' + , $this->_firstRowIndex + , $this->_lastRowIndex + 1 + , $this->_firstColumnIndex + , $this->_lastColumnIndex + 1 + , 0x0000 // reserved + ); + + $header = pack("vv", $record, $length); + $this->_append($header.$data); + } + + /** + * Write BIFF record Window2. + */ + private function _writeWindow2() + { + $record = 0x023E; // Record identifier + $length = 0x0012; + + $grbit = 0x00B6; // Option flags + $rwTop = 0x0000; // Top row visible in window + $colLeft = 0x0000; // Leftmost column visible in window + + + // The options flags that comprise $grbit + $fDspFmla = 0; // 0 - bit + $fDspGrid = $this->_phpSheet->getShowGridlines() ? 1 : 0; // 1 + $fDspRwCol = $this->_phpSheet->getShowRowColHeaders() ? 1 : 0; // 2 + $fFrozen = $this->_phpSheet->getFreezePane() ? 1 : 0; // 3 + $fDspZeros = 1; // 4 + $fDefaultHdr = 1; // 5 + $fArabic = $this->_phpSheet->getRightToLeft() ? 1 : 0; // 6 + $fDspGuts = $this->_outline_on; // 7 + $fFrozenNoSplit = 0; // 0 - bit + // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet + $fSelected = ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) ? 1 : 0; + $fPaged = 1; // 2 + $fPageBreakPreview = $this->_phpSheet->getSheetView()->getView() === PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW; + + $grbit = $fDspFmla; + $grbit |= $fDspGrid << 1; + $grbit |= $fDspRwCol << 2; + $grbit |= $fFrozen << 3; + $grbit |= $fDspZeros << 4; + $grbit |= $fDefaultHdr << 5; + $grbit |= $fArabic << 6; + $grbit |= $fDspGuts << 7; + $grbit |= $fFrozenNoSplit << 8; + $grbit |= $fSelected << 9; + $grbit |= $fPaged << 10; + $grbit |= $fPageBreakPreview << 11; + + $header = pack("vv", $record, $length); + $data = pack("vvv", $grbit, $rwTop, $colLeft); + + // FIXME !!! + $rgbHdr = 0x0040; // Row/column heading and gridline color index + $zoom_factor_page_break = ($fPageBreakPreview? $this->_phpSheet->getSheetView()->getZoomScale() : 0x0000); + $zoom_factor_normal = $this->_phpSheet->getSheetView()->getZoomScaleNormal(); + + $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000); + + $this->_append($header.$data); + } + + /** + * Write BIFF record DEFAULTROWHEIGHT. + */ + private function _writeDefaultRowHeight() + { + $defaultRowHeight = $this->_phpSheet->getDefaultRowDimension()->getRowHeight(); + + if ($defaultRowHeight < 0) { + return; + } + + // convert to twips + $defaultRowHeight = (int) 20 * $defaultRowHeight; + + $record = 0x0225; // Record identifier + $length = 0x0004; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", 1, $defaultRowHeight); + $this->_append($header . $data); + } + + /** + * Write BIFF record DEFCOLWIDTH if COLINFO records are in use. + */ + private function _writeDefcol() + { + $defaultColWidth = 8; + + $record = 0x0055; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $defaultColWidth); + $this->_append($header . $data); + } + + /** + * Write BIFF record COLINFO to define column widths + * + * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C + * length record. + * + * @param array $col_array This is the only parameter received and is composed of the following: + * 0 => First formatted column, + * 1 => Last formatted column, + * 2 => Col width (8.43 is Excel default), + * 3 => The optional XF format of the column, + * 4 => Option flags. + * 5 => Optional outline level + */ + private function _writeColinfo($col_array) + { + if (isset($col_array[0])) { + $colFirst = $col_array[0]; + } + if (isset($col_array[1])) { + $colLast = $col_array[1]; + } + if (isset($col_array[2])) { + $coldx = $col_array[2]; + } else { + $coldx = 8.43; + } + if (isset($col_array[3])) { + $xfIndex = $col_array[3]; + } else { + $xfIndex = 15; + } + if (isset($col_array[4])) { + $grbit = $col_array[4]; + } else { + $grbit = 0; + } + if (isset($col_array[5])) { + $level = $col_array[5]; + } else { + $level = 0; + } + $record = 0x007D; // Record identifier + $length = 0x000C; // Number of bytes to follow + + $coldx *= 256; // Convert to units of 1/256 of a char + + $ixfe = $xfIndex; + $reserved = 0x0000; // Reserved + + $level = max(0, min($level, 7)); + $grbit |= $level << 8; + + $header = pack("vv", $record, $length); + $data = pack("vvvvvv", $colFirst, $colLast, $coldx, + $ixfe, $grbit, $reserved); + $this->_append($header.$data); + } + + /** + * Write BIFF record SELECTION. + */ + private function _writeSelection() + { + // look up the selected cell range + $selectedCells = $this->_phpSheet->getSelectedCells(); + $selectedCells = PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells()); + $selectedCells = $selectedCells[0]; + if (count($selectedCells) == 2) { + list($first, $last) = $selectedCells; + } else { + $first = $selectedCells[0]; + $last = $selectedCells[0]; + } + + list($colFirst, $rwFirst) = PHPExcel_Cell::coordinateFromString($first); + $colFirst = PHPExcel_Cell::columnIndexFromString($colFirst) - 1; // base 0 column index + --$rwFirst; // base 0 row index + + list($colLast, $rwLast) = PHPExcel_Cell::coordinateFromString($last); + $colLast = PHPExcel_Cell::columnIndexFromString($colLast) - 1; // base 0 column index + --$rwLast; // base 0 row index + + // make sure we are not out of bounds + $colFirst = min($colFirst, 255); + $colLast = min($colLast, 255); + + $rwFirst = min($rwFirst, 65535); + $rwLast = min($rwLast, 65535); + + $record = 0x001D; // Record identifier + $length = 0x000F; // Number of bytes to follow + + $pnn = $this->_active_pane; // Pane position + $rwAct = $rwFirst; // Active row + $colAct = $colFirst; // Active column + $irefAct = 0; // Active cell ref + $cref = 1; // Number of refs + + if (!isset($rwLast)) { + $rwLast = $rwFirst; // Last row in reference + } + if (!isset($colLast)) { + $colLast = $colFirst; // Last col in reference + } + + // Swap last row/col for first row/col as necessary + if ($rwFirst > $rwLast) { + list($rwFirst, $rwLast) = array($rwLast, $rwFirst); + } + + if ($colFirst > $colLast) { + list($colFirst, $colLast) = array($colLast, $colFirst); + } + + $header = pack("vv", $record, $length); + $data = pack("CvvvvvvCC", $pnn, $rwAct, $colAct, + $irefAct, $cref, + $rwFirst, $rwLast, + $colFirst, $colLast); + $this->_append($header . $data); + } + + /** + * Store the MERGEDCELLS records for all ranges of merged cells + */ + private function _writeMergedCells() + { + $mergeCells = $this->_phpSheet->getMergeCells(); + $countMergeCells = count($mergeCells); + + if ($countMergeCells == 0) { + return; + } + + // maximum allowed number of merged cells per record + $maxCountMergeCellsPerRecord = 1027; + + // record identifier + $record = 0x00E5; + + // counter for total number of merged cells treated so far by the writer + $i = 0; + + // counter for number of merged cells written in record currently being written + $j = 0; + + // initialize record data + $recordData = ''; + + // loop through the merged cells + foreach ($mergeCells as $mergeCell) { + ++$i; + ++$j; + + // extract the row and column indexes + $range = PHPExcel_Cell::splitRange($mergeCell); + list($first, $last) = $range[0]; + list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($first); + list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($last); + + $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, PHPExcel_Cell::columnIndexFromString($firstColumn) - 1, PHPExcel_Cell::columnIndexFromString($lastColumn) - 1); + + // flush record if we have reached limit for number of merged cells, or reached final merged cell + if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) { + $recordData = pack('v', $j) . $recordData; + $length = strlen($recordData); + $header = pack('vv', $record, $length); + $this->_append($header . $recordData); + + // initialize for next record, if any + $recordData = ''; + $j = 0; + } + } + } + + /** + * Write SHEETLAYOUT record + */ + private function _writeSheetLayout() + { + if (!$this->_phpSheet->isTabColorSet()) { + return; + } + + $recordData = pack( + 'vvVVVvv' + , 0x0862 + , 0x0000 // unused + , 0x00000000 // unused + , 0x00000000 // unused + , 0x00000014 // size of record data + , $this->_colors[$this->_phpSheet->getTabColor()->getRGB()] // color index + , 0x0000 // unused + ); + + $length = strlen($recordData); + + $record = 0x0862; // Record identifier + $header = pack('vv', $record, $length); + $this->_append($header . $recordData); + } + + /** + * Write SHEETPROTECTION + */ + private function _writeSheetProtection() + { + // record identifier + $record = 0x0867; + + // prepare options + $options = (int) !$this->_phpSheet->getProtection()->getObjects() + | (int) !$this->_phpSheet->getProtection()->getScenarios() << 1 + | (int) !$this->_phpSheet->getProtection()->getFormatCells() << 2 + | (int) !$this->_phpSheet->getProtection()->getFormatColumns() << 3 + | (int) !$this->_phpSheet->getProtection()->getFormatRows() << 4 + | (int) !$this->_phpSheet->getProtection()->getInsertColumns() << 5 + | (int) !$this->_phpSheet->getProtection()->getInsertRows() << 6 + | (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks() << 7 + | (int) !$this->_phpSheet->getProtection()->getDeleteColumns() << 8 + | (int) !$this->_phpSheet->getProtection()->getDeleteRows() << 9 + | (int) !$this->_phpSheet->getProtection()->getSelectLockedCells() << 10 + | (int) !$this->_phpSheet->getProtection()->getSort() << 11 + | (int) !$this->_phpSheet->getProtection()->getAutoFilter() << 12 + | (int) !$this->_phpSheet->getProtection()->getPivotTables() << 13 + | (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells() << 14 ; + + // record data + $recordData = pack( + 'vVVCVVvv' + , 0x0867 // repeated record identifier + , 0x0000 // not used + , 0x0000 // not used + , 0x00 // not used + , 0x01000200 // unknown data + , 0xFFFFFFFF // unknown data + , $options // options + , 0x0000 // not used + ); + + $length = strlen($recordData); + $header = pack('vv', $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Write BIFF record RANGEPROTECTION + * + * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records + * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records + */ + private function _writeRangeProtection() + { + foreach ($this->_phpSheet->getProtectedCells() as $range => $password) { + // number of ranges, e.g. 'A1:B3 C20:D25' + $cellRanges = explode(' ', $range); + $cref = count($cellRanges); + + $recordData = pack( + 'vvVVvCVvVv', + 0x0868, + 0x00, + 0x0000, + 0x0000, + 0x02, + 0x0, + 0x0000, + $cref, + 0x0000, + 0x00 + ); + + foreach ($cellRanges as $cellRange) { + $recordData .= $this->_writeBIFF8CellRangeAddressFixed($cellRange); + } + + // the rgbFeat structure + $recordData .= pack( + 'VV', + 0x0000, + hexdec($password) + ); + + $recordData .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong('p' . md5($recordData)); + + $length = strlen($recordData); + + $record = 0x0868; // Record identifier + $header = pack("vv", $record, $length); + $this->_append($header . $recordData); + } + } + + /** + * Write BIFF record EXTERNCOUNT to indicate the number of external sheet + * references in a worksheet. + * + * Excel only stores references to external sheets that are used in formulas. + * For simplicity we store references to all the sheets in the workbook + * regardless of whether they are used or not. This reduces the overall + * complexity and eliminates the need for a two way dialogue between the formula + * parser the worksheet objects. + * + * @param integer $count The number of external sheet references in this worksheet + */ + private function _writeExterncount($count) + { + $record = 0x0016; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $count); + $this->_append($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. A formula references a sheet name via an index. Since we store a + * reference to all of the external worksheets the EXTERNSHEET index is the same + * as the worksheet index. + * + * @param string $sheetname The name of a external worksheet + */ + private function _writeExternsheet($sheetname) + { + $record = 0x0017; // Record identifier + + // References to the current sheet are encoded differently to references to + // external sheets. + // + if ($this->_phpSheet->getTitle() == $sheetname) { + $sheetname = ''; + $length = 0x02; // The following 2 bytes + $cch = 1; // The following byte + $rgch = 0x02; // Self reference + } else { + $length = 0x02 + strlen($sheetname); + $cch = strlen($sheetname); + $rgch = 0x03; // Reference to a sheet in the current workbook + } + + $header = pack("vv", $record, $length); + $data = pack("CC", $cch, $rgch); + $this->_append($header . $data . $sheetname); + } + + /** + * Writes the Excel BIFF PANE record. + * The panes can either be frozen or thawed (unfrozen). + * Frozen panes are specified in terms of an integer number of rows and columns. + * Thawed panes are specified in terms of Excel's units for rows and columns. + */ + private function _writePanes() + { + $panes = array(); + if ($freezePane = $this->_phpSheet->getFreezePane()) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($freezePane); + $panes[0] = $row - 1; + $panes[1] = PHPExcel_Cell::columnIndexFromString($column) - 1; + } else { + // thaw panes + return; + } + + $y = isset($panes[0]) ? $panes[0] : null; + $x = isset($panes[1]) ? $panes[1] : null; + $rwTop = isset($panes[2]) ? $panes[2] : null; + $colLeft = isset($panes[3]) ? $panes[3] : null; + if (count($panes) > 4) { // if Active pane was received + $pnnAct = $panes[4]; + } else { + $pnnAct = null; + } + $record = 0x0041; // Record identifier + $length = 0x000A; // Number of bytes to follow + + // Code specific to frozen or thawed panes. + if ($this->_phpSheet->getFreezePane()) { + // Set default values for $rwTop and $colLeft + if (!isset($rwTop)) { + $rwTop = $y; + } + if (!isset($colLeft)) { + $colLeft = $x; + } + } else { + // Set default values for $rwTop and $colLeft + if (!isset($rwTop)) { + $rwTop = 0; + } + if (!isset($colLeft)) { + $colLeft = 0; + } + + // Convert Excel's row and column units to the internal units. + // The default row height is 12.75 + // The default column width is 8.43 + // The following slope and intersection values were interpolated. + // + $y = 20*$y + 255; + $x = 113.879*$x + 390; + } + + + // Determine which pane should be active. There is also the undocumented + // option to override this should it be necessary: may be removed later. + // + if (!isset($pnnAct)) { + if ($x != 0 && $y != 0) { + $pnnAct = 0; // Bottom right + } + if ($x != 0 && $y == 0) { + $pnnAct = 1; // Top right + } + if ($x == 0 && $y != 0) { + $pnnAct = 2; // Bottom left + } + if ($x == 0 && $y == 0) { + $pnnAct = 3; // Top left + } + } + + $this->_active_pane = $pnnAct; // Used in _writeSelection + + $header = pack("vv", $record, $length); + $data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct); + $this->_append($header . $data); + } + + /** + * Store the page setup SETUP BIFF record. + */ + private function _writeSetup() + { + $record = 0x00A1; // Record identifier + $length = 0x0022; // Number of bytes to follow + + $iPaperSize = $this->_phpSheet->getPageSetup()->getPaperSize(); // Paper size + + $iScale = $this->_phpSheet->getPageSetup()->getScale() ? + $this->_phpSheet->getPageSetup()->getScale() : 100; // Print scaling factor + + $iPageStart = 0x01; // Starting page number + $iFitWidth = (int) $this->_phpSheet->getPageSetup()->getFitToWidth(); // Fit to number of pages wide + $iFitHeight = (int) $this->_phpSheet->getPageSetup()->getFitToHeight(); // Fit to number of pages high + $grbit = 0x00; // Option flags + $iRes = 0x0258; // Print resolution + $iVRes = 0x0258; // Vertical print resolution + + $numHdr = $this->_phpSheet->getPageMargins()->getHeader(); // Header Margin + + $numFtr = $this->_phpSheet->getPageMargins()->getFooter(); // Footer Margin + $iCopies = 0x01; // Number of copies + + $fLeftToRight = 0x0; // Print over then down + + // Page orientation + $fLandscape = ($this->_phpSheet->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? + 0x0 : 0x1; + + $fNoPls = 0x0; // Setup not read from printer + $fNoColor = 0x0; // Print black and white + $fDraft = 0x0; // Print draft quality + $fNotes = 0x0; // Print notes + $fNoOrient = 0x0; // Orientation not set + $fUsePage = 0x0; // Use custom starting page + + $grbit = $fLeftToRight; + $grbit |= $fLandscape << 1; + $grbit |= $fNoPls << 2; + $grbit |= $fNoColor << 3; + $grbit |= $fDraft << 4; + $grbit |= $fNotes << 5; + $grbit |= $fNoOrient << 6; + $grbit |= $fUsePage << 7; + + $numHdr = pack("d", $numHdr); + $numFtr = pack("d", $numFtr); + if (self::getByteOrder()) { // if it's Big Endian + $numHdr = strrev($numHdr); + $numFtr = strrev($numFtr); + } + + $header = pack("vv", $record, $length); + $data1 = pack("vvvvvvvv", $iPaperSize, + $iScale, + $iPageStart, + $iFitWidth, + $iFitHeight, + $grbit, + $iRes, + $iVRes); + $data2 = $numHdr.$numFtr; + $data3 = pack("v", $iCopies); + $this->_append($header . $data1 . $data2 . $data3); + } + + /** + * Store the header caption BIFF record. + */ + private function _writeHeader() + { + $record = 0x0014; // Record identifier + + /* removing for now + // need to fix character count (multibyte!) + if (strlen($this->_phpSheet->getHeaderFooter()->getOddHeader()) <= 255) { + $str = $this->_phpSheet->getHeaderFooter()->getOddHeader(); // header string + } else { + $str = ''; + } + */ + + $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader()); + $length = strlen($recordData); + + $header = pack("vv", $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Store the footer caption BIFF record. + */ + private function _writeFooter() + { + $record = 0x0015; // Record identifier + + /* removing for now + // need to fix character count (multibyte!) + if (strlen($this->_phpSheet->getHeaderFooter()->getOddFooter()) <= 255) { + $str = $this->_phpSheet->getHeaderFooter()->getOddFooter(); + } else { + $str = ''; + } + */ + + $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter()); + $length = strlen($recordData); + + $header = pack("vv", $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Store the horizontal centering HCENTER BIFF record. + * + * @access private + */ + private function _writeHcenter() + { + $record = 0x0083; // Record identifier + $length = 0x0002; // Bytes to follow + + $fHCenter = $this->_phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0; // Horizontal centering + + $header = pack("vv", $record, $length); + $data = pack("v", $fHCenter); + + $this->_append($header.$data); + } + + /** + * Store the vertical centering VCENTER BIFF record. + */ + private function _writeVcenter() + { + $record = 0x0084; // Record identifier + $length = 0x0002; // Bytes to follow + + $fVCenter = $this->_phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0; // Horizontal centering + + $header = pack("vv", $record, $length); + $data = pack("v", $fVCenter); + $this->_append($header . $data); + } + + /** + * Store the LEFTMARGIN BIFF record. + */ + private function _writeMarginLeft() + { + $record = 0x0026; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getLeft(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the RIGHTMARGIN BIFF record. + */ + private function _writeMarginRight() + { + $record = 0x0027; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getRight(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the TOPMARGIN BIFF record. + */ + private function _writeMarginTop() + { + $record = 0x0028; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getTop(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the BOTTOMMARGIN BIFF record. + */ + private function _writeMarginBottom() + { + $record = 0x0029; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getBottom(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Write the PRINTHEADERS BIFF record. + */ + private function _writePrintHeaders() + { + $record = 0x002a; // Record identifier + $length = 0x0002; // Bytes to follow + + $fPrintRwCol = $this->_print_headers; // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fPrintRwCol); + $this->_append($header . $data); + } + + /** + * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the + * GRIDSET record. + */ + private function _writePrintGridlines() + { + $record = 0x002b; // Record identifier + $length = 0x0002; // Bytes to follow + + $fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fPrintGrid); + $this->_append($header . $data); + } + + /** + * Write the GRIDSET BIFF record. Must be used in conjunction with the + * PRINTGRIDLINES record. + */ + private function _writeGridset() + { + $record = 0x0082; // Record identifier + $length = 0x0002; // Bytes to follow + + $fGridSet = !$this->_phpSheet->getPrintGridlines(); // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fGridSet); + $this->_append($header . $data); + } + + /** + * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet. + */ + private function _writeAutoFilterInfo(){ + $record = 0x009D; // Record identifier + $length = 0x0002; // Bytes to follow + + $rangeBounds = PHPExcel_Cell::rangeBoundaries($this->_phpSheet->getAutoFilter()->getRange()); + $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0]; + + $header = pack("vv", $record, $length); + $data = pack("v", $iNumFilters); + $this->_append($header . $data); + } + + /** + * Write the GUTS BIFF record. This is used to configure the gutter margins + * where Excel outline symbols are displayed. The visibility of the gutters is + * controlled by a flag in WSBOOL. + * + * @see _writeWsbool() + */ + private function _writeGuts() + { + $record = 0x0080; // Record identifier + $length = 0x0008; // Bytes to follow + + $dxRwGut = 0x0000; // Size of row gutter + $dxColGut = 0x0000; // Size of col gutter + + // determine maximum row outline level + $maxRowOutlineLevel = 0; + foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { + $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel()); + } + + $col_level = 0; + + // Calculate the maximum column outline level. The equivalent calculation + // for the row outline level is carried out in _writeRow(). + $colcount = count($this->_colinfo); + for ($i = 0; $i < $colcount; ++$i) { + $col_level = max($this->_colinfo[$i][5], $col_level); + } + + // Set the limits for the outline levels (0 <= x <= 7). + $col_level = max(0, min($col_level, 7)); + + // The displayed level is one greater than the max outline levels + if ($maxRowOutlineLevel) { + ++$maxRowOutlineLevel; + } + if ($col_level) { + ++$col_level; + } + + $header = pack("vv", $record, $length); + $data = pack("vvvv", $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level); + + $this->_append($header.$data); + } + + /** + * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction + * with the SETUP record. + */ + private function _writeWsbool() + { + $record = 0x0081; // Record identifier + $length = 0x0002; // Bytes to follow + $grbit = 0x0000; + + // The only option that is of interest is the flag for fit to page. So we + // set all the options in one go. + // + // Set the option flags + $grbit |= 0x0001; // Auto page breaks visible + if ($this->_outline_style) { + $grbit |= 0x0020; // Auto outline styles + } + if ($this->_phpSheet->getShowSummaryBelow()) { + $grbit |= 0x0040; // Outline summary below + } + if ($this->_phpSheet->getShowSummaryRight()) { + $grbit |= 0x0080; // Outline summary right + } + if ($this->_phpSheet->getPageSetup()->getFitToPage()) { + $grbit |= 0x0100; // Page setup fit to page + } + if ($this->_outline_on) { + $grbit |= 0x0400; // Outline symbols displayed + } + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $this->_append($header . $data); + } + + /** + * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records. + */ + private function _writeBreaks() + { + // initialize + $vbreaks = array(); + $hbreaks = array(); + + foreach ($this->_phpSheet->getBreaks() as $cell => $breakType) { + // Fetch coordinates + $coordinates = PHPExcel_Cell::coordinateFromString($cell); + + // Decide what to do by the type of break + switch ($breakType) { + case PHPExcel_Worksheet::BREAK_COLUMN: + // Add to list of vertical breaks + $vbreaks[] = PHPExcel_Cell::columnIndexFromString($coordinates[0]) - 1; + break; + + case PHPExcel_Worksheet::BREAK_ROW: + // Add to list of horizontal breaks + $hbreaks[] = $coordinates[1]; + break; + + case PHPExcel_Worksheet::BREAK_NONE: + default: + // Nothing to do + break; + } + } + + //horizontal page breaks + if (!empty($hbreaks)) { + + // Sort and filter array of page breaks + sort($hbreaks, SORT_NUMERIC); + if ($hbreaks[0] == 0) { // don't use first break if it's 0 + array_shift($hbreaks); + } + + $record = 0x001b; // Record identifier + $cbrk = count($hbreaks); // Number of page breaks + $length = 2 + 6 * $cbrk; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cbrk); + + // Append each page break + foreach ($hbreaks as $hbreak) { + $data .= pack("vvv", $hbreak, 0x0000, 0x00ff); + } + + $this->_append($header . $data); + } + + // vertical page breaks + if (!empty($vbreaks)) { + + // 1000 vertical pagebreaks appears to be an internal Excel 5 limit. + // It is slightly higher in Excel 97/200, approx. 1026 + $vbreaks = array_slice($vbreaks, 0, 1000); + + // Sort and filter array of page breaks + sort($vbreaks, SORT_NUMERIC); + if ($vbreaks[0] == 0) { // don't use first break if it's 0 + array_shift($vbreaks); + } + + $record = 0x001a; // Record identifier + $cbrk = count($vbreaks); // Number of page breaks + $length = 2 + 6 * $cbrk; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cbrk); + + // Append each page break + foreach ($vbreaks as $vbreak) { + $data .= pack("vvv", $vbreak, 0x0000, 0xffff); + } + + $this->_append($header . $data); + } + } + + /** + * Set the Biff PROTECT record to indicate that the worksheet is protected. + */ + private function _writeProtect() + { + // Exit unless sheet protection has been specified + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + $record = 0x0012; // Record identifier + $length = 0x0002; // Bytes to follow + + $fLock = 1; // Worksheet is protected + + $header = pack("vv", $record, $length); + $data = pack("v", $fLock); + + $this->_append($header.$data); + } + + /** + * Write SCENPROTECT + */ + private function _writeScenProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if scenarios are not protected + if (!$this->_phpSheet->getProtection()->getScenarios()) { + return; + } + + $record = 0x00DD; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + + /** + * Write OBJECTPROTECT + */ + private function _writeObjectProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if objects are not protected + if (!$this->_phpSheet->getProtection()->getObjects()) { + return; + } + + $record = 0x0063; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + + /** + * Write the worksheet PASSWORD record. + */ + private function _writePassword() + { + // Exit unless sheet protection and password have been specified + if (!$this->_phpSheet->getProtection()->getSheet() || !$this->_phpSheet->getProtection()->getPassword()) { + return; + } + + $record = 0x0013; // Record identifier + $length = 0x0002; // Bytes to follow + + $wPassword = hexdec($this->_phpSheet->getProtection()->getPassword()); // Encoded password + + $header = pack("vv", $record, $length); + $data = pack("v", $wPassword); + + $this->_append($header . $data); + } + + /** + * Insert a 24bit bitmap image in a worksheet. + * + * @access public + * @param integer $row The row we are going to insert the bitmap into + * @param integer $col The column we are going to insert the bitmap into + * @param mixed $bitmap The bitmap filename or GD-image resource + * @param integer $x The horizontal position (offset) of the image inside the cell. + * @param integer $y The vertical position (offset) of the image inside the cell. + * @param float $scale_x The horizontal scale + * @param float $scale_y The vertical scale + */ + function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) + { + $bitmap_array = (is_resource($bitmap) ? $this->_processBitmapGd($bitmap) : $this->_processBitmap($bitmap)); + list($width, $height, $size, $data) = $bitmap_array; //$this->_processBitmap($bitmap); + + // Scale the frame of the image. + $width *= $scale_x; + $height *= $scale_y; + + // Calculate the vertices of the image and write the OBJ record + $this->_positionImage($col, $row, $x, $y, $width, $height); + + // Write the IMDATA record to store the bitmap data + $record = 0x007f; + $length = 8 + $size; + $cf = 0x09; + $env = 0x01; + $lcb = $size; + + $header = pack("vvvvV", $record, $length, $cf, $env, $lcb); + $this->_append($header.$data); + } + + /** + * Calculate the vertices that define the position of the image as required by + * the OBJ record. + * + * +------------+------------+ + * | A | B | + * +-----+------------+------------+ + * | |(x1,y1) | | + * | 1 |(A1)._______|______ | + * | | | | | + * | | | | | + * +-----+----| BITMAP |-----+ + * | | | | | + * | 2 | |______________. | + * | | | (B2)| + * | | | (x2,y2)| + * +---- +------------+------------+ + * + * Example of a bitmap that covers some of the area from cell A1 to cell B2. + * + * Based on the width and height of the bitmap we need to calculate 8 vars: + * $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. + * The width and height of the cells are also variable and have to be taken into + * account. + * The values of $col_start and $row_start are passed in from the calling + * function. The values of $col_end and $row_end are calculated by subtracting + * the width and height of the bitmap from the width and height of the + * underlying cells. + * The vertices are expressed as a percentage of the underlying cell width as + * follows (rhs values are in pixels): + * + * x1 = X / W *1024 + * y1 = Y / H *256 + * x2 = (X-1) / W *1024 + * y2 = (Y-1) / H *256 + * + * Where: X is distance from the left side of the underlying cell + * Y is distance from the top of the underlying cell + * W is the width of the cell + * H is the height of the cell + * The SDK incorrectly states that the height should be expressed as a + * percentage of 1024. + * + * @access private + * @param integer $col_start Col containing upper left corner of object + * @param integer $row_start Row containing top left corner of object + * @param integer $x1 Distance to left side of object + * @param integer $y1 Distance to top of object + * @param integer $width Width of image frame + * @param integer $height Height of image frame + */ + function _positionImage($col_start, $row_start, $x1, $y1, $width, $height) + { + // Initialise end cell to the same as the start cell + $col_end = $col_start; // Col containing lower right corner of object + $row_end = $row_start; // Row containing bottom right corner of object + + // Zero the specified offset if greater than the cell dimensions + if ($x1 >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) { + $x1 = 0; + } + if ($y1 >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1)) { + $y1 = 0; + } + + $width = $width + $x1 -1; + $height = $height + $y1 -1; + + // Subtract the underlying cell widths to find the end cell of the image + while ($width >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) { + $width -= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)); + ++$col_end; + } + + // Subtract the underlying cell heights to find the end cell of the image + while ($height >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1)) { + $height -= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1); + ++$row_end; + } + + // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell + // with zero eight or width. + // + if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) == 0) { + return; + } + + // Convert the pixel values to the percentage value expected by Excel + $x1 = $x1 / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; + $y1 = $y1 / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) * 256; + $x2 = $width / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object + $y2 = $height / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) * 256; // Distance to bottom of object + + $this->_writeObjPicture($col_start, $x1, + $row_start, $y1, + $col_end, $x2, + $row_end, $y2); + } + + /** + * Store the OBJ record that precedes an IMDATA record. This could be generalise + * to support other Excel objects. + * + * @param integer $colL Column containing upper left corner of object + * @param integer $dxL Distance from left side of cell + * @param integer $rwT Row containing top left corner of object + * @param integer $dyT Distance from top of cell + * @param integer $colR Column containing lower right corner of object + * @param integer $dxR Distance from right of cell + * @param integer $rwB Row containing bottom right corner of object + * @param integer $dyB Distance from bottom of cell + */ + private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) + { + $record = 0x005d; // Record identifier + $length = 0x003c; // Bytes to follow + + $cObj = 0x0001; // Count of objects in file (set to 1) + $OT = 0x0008; // Object type. 8 = Picture + $id = 0x0001; // Object ID + $grbit = 0x0614; // Option flags + + $cbMacro = 0x0000; // Length of FMLA structure + $Reserved1 = 0x0000; // Reserved + $Reserved2 = 0x0000; // Reserved + + $icvBack = 0x09; // Background colour + $icvFore = 0x09; // Foreground colour + $fls = 0x00; // Fill pattern + $fAuto = 0x00; // Automatic fill + $icv = 0x08; // Line colour + $lns = 0xff; // Line style + $lnw = 0x01; // Line weight + $fAutoB = 0x00; // Automatic border + $frs = 0x0000; // Frame style + $cf = 0x0009; // Image format, 9 = bitmap + $Reserved3 = 0x0000; // Reserved + $cbPictFmla = 0x0000; // Length of FMLA structure + $Reserved4 = 0x0000; // Reserved + $grbit2 = 0x0001; // Option flags + $Reserved5 = 0x0000; // Reserved + + + $header = pack("vv", $record, $length); + $data = pack("V", $cObj); + $data .= pack("v", $OT); + $data .= pack("v", $id); + $data .= pack("v", $grbit); + $data .= pack("v", $colL); + $data .= pack("v", $dxL); + $data .= pack("v", $rwT); + $data .= pack("v", $dyT); + $data .= pack("v", $colR); + $data .= pack("v", $dxR); + $data .= pack("v", $rwB); + $data .= pack("v", $dyB); + $data .= pack("v", $cbMacro); + $data .= pack("V", $Reserved1); + $data .= pack("v", $Reserved2); + $data .= pack("C", $icvBack); + $data .= pack("C", $icvFore); + $data .= pack("C", $fls); + $data .= pack("C", $fAuto); + $data .= pack("C", $icv); + $data .= pack("C", $lns); + $data .= pack("C", $lnw); + $data .= pack("C", $fAutoB); + $data .= pack("v", $frs); + $data .= pack("V", $cf); + $data .= pack("v", $Reserved3); + $data .= pack("v", $cbPictFmla); + $data .= pack("v", $Reserved4); + $data .= pack("v", $grbit2); + $data .= pack("V", $Reserved5); + + $this->_append($header . $data); + } + + /** + * Convert a GD-image into the internal format. + * + * @access private + * @param resource $image The image to process + * @return array Array with data and properties of the bitmap + */ + function _processBitmapGd($image) { + $width = imagesx($image); + $height = imagesy($image); + + $data = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); + for ($j=$height; $j--; ) { + for ($i=0; $i < $width; ++$i) { + $color = imagecolorsforindex($image, imagecolorat($image, $i, $j)); + foreach (array("red", "green", "blue") as $key) { + $color[$key] = $color[$key] + round((255 - $color[$key]) * $color["alpha"] / 127); + } + $data .= chr($color["blue"]) . chr($color["green"]) . chr($color["red"]); + } + if (3*$width % 4) { + $data .= str_repeat("\x00", 4 - 3*$width % 4); + } + } + + return array($width, $height, strlen($data), $data); + } + + /** + * Convert a 24 bit bitmap into the modified internal format used by Windows. + * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the + * MSDN library. + * + * @access private + * @param string $bitmap The bitmap to process + * @return array Array with data and properties of the bitmap + */ + function _processBitmap($bitmap) + { + // Open file. + $bmp_fd = @fopen($bitmap,"rb"); + if (!$bmp_fd) { + throw new PHPExcel_Writer_Exception("Couldn't import $bitmap"); + } + + // Slurp the file into a string. + $data = fread($bmp_fd, filesize($bitmap)); + + // Check that the file is big enough to be a bitmap. + if (strlen($data) <= 0x36) { + throw new PHPExcel_Writer_Exception("$bitmap doesn't contain enough data.\n"); + } + + // The first 2 bytes are used to identify the bitmap. + $identity = unpack("A2ident", $data); + if ($identity['ident'] != "BM") { + throw new PHPExcel_Writer_Exception("$bitmap doesn't appear to be a valid bitmap image.\n"); + } + + // Remove bitmap data: ID. + $data = substr($data, 2); + + // Read and remove the bitmap size. This is more reliable than reading + // the data size at offset 0x22. + // + $size_array = unpack("Vsa", substr($data, 0, 4)); + $size = $size_array['sa']; + $data = substr($data, 4); + $size -= 0x36; // Subtract size of bitmap header. + $size += 0x0C; // Add size of BIFF header. + + // Remove bitmap data: reserved, offset, header length. + $data = substr($data, 12); + + // Read and remove the bitmap width and height. Verify the sizes. + $width_and_height = unpack("V2", substr($data, 0, 8)); + $width = $width_and_height[1]; + $height = $width_and_height[2]; + $data = substr($data, 8); + if ($width > 0xFFFF) { + throw new PHPExcel_Writer_Exception("$bitmap: largest image width supported is 65k.\n"); + } + if ($height > 0xFFFF) { + throw new PHPExcel_Writer_Exception("$bitmap: largest image height supported is 65k.\n"); + } + + // Read and remove the bitmap planes and bpp data. Verify them. + $planes_and_bitcount = unpack("v2", substr($data, 0, 4)); + $data = substr($data, 4); + if ($planes_and_bitcount[2] != 24) { // Bitcount + throw new PHPExcel_Writer_Exception("$bitmap isn't a 24bit true color bitmap.\n"); + } + if ($planes_and_bitcount[1] != 1) { + throw new PHPExcel_Writer_Exception("$bitmap: only 1 plane supported in bitmap image.\n"); + } + + // Read and remove the bitmap compression. Verify compression. + $compression = unpack("Vcomp", substr($data, 0, 4)); + $data = substr($data, 4); + + //$compression = 0; + if ($compression['comp'] != 0) { + throw new PHPExcel_Writer_Exception("$bitmap: compression not supported in bitmap image.\n"); + } + + // Remove bitmap data: data size, hres, vres, colours, imp. colours. + $data = substr($data, 20); + + // Add the BITMAPCOREHEADER data + $header = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); + $data = $header . $data; + + return (array($width, $height, $size, $data)); + } + + /** + * Store the window zoom factor. This should be a reduced fraction but for + * simplicity we will store all fractions with a numerator of 100. + */ + private function _writeZoom() + { + // If scale is 100 we don't need to write a record + if ($this->_phpSheet->getSheetView()->getZoomScale() == 100) { + return; + } + + $record = 0x00A0; // Record identifier + $length = 0x0004; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", $this->_phpSheet->getSheetView()->getZoomScale(), 100); + $this->_append($header . $data); + } + + /** + * Get Escher object + * + * @return PHPExcel_Shared_Escher + */ + public function getEscher() + { + return $this->_escher; + } + + /** + * Set Escher object + * + * @param PHPExcel_Shared_Escher $pValue + */ + public function setEscher(PHPExcel_Shared_Escher $pValue = null) + { + $this->_escher = $pValue; + } + + /** + * Write MSODRAWING record + */ + private function _writeMsoDrawing() + { + // write the Escher stream if necessary + if (isset($this->_escher)) { + $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); + $data = $writer->close(); + $spOffsets = $writer->getSpOffsets(); + $spTypes = $writer->getSpTypes(); + // write the neccesary MSODRAWING, OBJ records + + // split the Escher stream + $spOffsets[0] = 0; + $nm = count($spOffsets) - 1; // number of shapes excluding first shape + for ($i = 1; $i <= $nm; ++$i) { + // MSODRAWING record + $record = 0x00EC; // Record identifier + + // chunk of Escher stream for one shape + $dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]); + + $length = strlen($dataChunk); + $header = pack("vv", $record, $length); + + $this->_append($header . $dataChunk); + + // OBJ record + $record = 0x005D; // record identifier + $objData = ''; + + // ftCmo + if($spTypes[$i] == 0x00C9){ + // Add ftCmo (common object data) subobject + $objData .= + pack('vvvvvVVV' + , 0x0015 // 0x0015 = ftCmo + , 0x0012 // length of ftCmo data + , 0x0014 // object type, 0x0014 = filter + , $i // object id number, Excel seems to use 1-based index, local for the sheet + , 0x2101 // option flags, 0x2001 is what OpenOffice.org uses + , 0 // reserved + , 0 // reserved + , 0 // reserved + ); + + // Add ftSbs Scroll bar subobject + $objData .= pack('vv', 0x00C, 0x0014); + $objData .= pack('H*', '0000000000000000640001000A00000010000100'); + // Add ftLbsData (List box data) subobject + $objData .= pack('vv', 0x0013, 0x1FEE); + $objData .= pack('H*', '00000000010001030000020008005700'); + } + else { + // Add ftCmo (common object data) subobject + $objData .= + pack('vvvvvVVV' + , 0x0015 // 0x0015 = ftCmo + , 0x0012 // length of ftCmo data + , 0x0008 // object type, 0x0008 = picture + , $i // object id number, Excel seems to use 1-based index, local for the sheet + , 0x6011 // option flags, 0x6011 is what OpenOffice.org uses + , 0 // reserved + , 0 // reserved + , 0 // reserved + ); + } + + // ftEnd + $objData .= + pack('vv' + , 0x0000 // 0x0000 = ftEnd + , 0x0000 // length of ftEnd data + ); + + $length = strlen($objData); + $header = pack('vv', $record, $length); + $this->_append($header . $objData); + } + } + } + + /** + * Store the DATAVALIDATIONS and DATAVALIDATION records. + */ + private function _writeDataValidity() + { + // Datavalidation collection + $dataValidationCollection = $this->_phpSheet->getDataValidationCollection(); + + // Write data validations? + if (!empty($dataValidationCollection)) { + + // DATAVALIDATIONS record + $record = 0x01B2; // Record identifier + $length = 0x0012; // Bytes to follow + + $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records + $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position + $verPos = 0x00000000; // Vertical position of prompt box, if fixed position + $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible + + $header = pack('vv', $record, $length); + $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, + count($dataValidationCollection)); + $this->_append($header.$data); + + // DATAVALIDATION records + $record = 0x01BE; // Record identifier + + foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) { + // initialize record data + $data = ''; + + // options + $options = 0x00000000; + + // data type + $type = $dataValidation->getType(); + switch ($type) { + case PHPExcel_Cell_DataValidation::TYPE_NONE: $type = 0x00; break; + case PHPExcel_Cell_DataValidation::TYPE_WHOLE: $type = 0x01; break; + case PHPExcel_Cell_DataValidation::TYPE_DECIMAL: $type = 0x02; break; + case PHPExcel_Cell_DataValidation::TYPE_LIST: $type = 0x03; break; + case PHPExcel_Cell_DataValidation::TYPE_DATE: $type = 0x04; break; + case PHPExcel_Cell_DataValidation::TYPE_TIME: $type = 0x05; break; + case PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH: $type = 0x06; break; + case PHPExcel_Cell_DataValidation::TYPE_CUSTOM: $type = 0x07; break; + } + $options |= $type << 0; + + // error style + $errorStyle = $dataValidation->getType(); + switch ($errorStyle) { + case PHPExcel_Cell_DataValidation::STYLE_STOP: $errorStyle = 0x00; break; + case PHPExcel_Cell_DataValidation::STYLE_WARNING: $errorStyle = 0x01; break; + case PHPExcel_Cell_DataValidation::STYLE_INFORMATION: $errorStyle = 0x02; break; + } + $options |= $errorStyle << 4; + + // explicit formula? + if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) { + $options |= 0x01 << 7; + } + + // empty cells allowed + $options |= $dataValidation->getAllowBlank() << 8; + + // show drop down + $options |= (!$dataValidation->getShowDropDown()) << 9; + + // show input message + $options |= $dataValidation->getShowInputMessage() << 18; + + // show error message + $options |= $dataValidation->getShowErrorMessage() << 19; + + // condition operator + $operator = $dataValidation->getOperator(); + switch ($operator) { + case PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN: $operator = 0x00 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN: $operator = 0x01 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_EQUAL: $operator = 0x02 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL: $operator = 0x03 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN: $operator = 0x04 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN: $operator = 0x05 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL: $operator = 0x06; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL: $operator = 0x07 ; break; + } + $options |= $operator << 20; + + $data = pack('V', $options); + + // prompt title + $promptTitle = $dataValidation->getPromptTitle() !== '' ? + $dataValidation->getPromptTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle); + + // error title + $errorTitle = $dataValidation->getErrorTitle() !== '' ? + $dataValidation->getErrorTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle); + + // prompt text + $prompt = $dataValidation->getPrompt() !== '' ? + $dataValidation->getPrompt() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt); + + // error text + $error = $dataValidation->getError() !== '' ? + $dataValidation->getError() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error); + + // formula 1 + try { + $formula1 = $dataValidation->getFormula1(); + if ($type == 0x03) { // list type + $formula1 = str_replace(',', chr(0), $formula1); + } + $this->_parser->parse($formula1); + $formula1 = $this->_parser->toReversePolish(); + $sz1 = strlen($formula1); + + } catch(PHPExcel_Exception $e) { + $sz1 = 0; + $formula1 = ''; + } + $data .= pack('vv', $sz1, 0x0000); + $data .= $formula1; + + // formula 2 + try { + $formula2 = $dataValidation->getFormula2(); + if ($formula2 === '') { + throw new PHPExcel_Writer_Exception('No formula2'); + } + $this->_parser->parse($formula2); + $formula2 = $this->_parser->toReversePolish(); + $sz2 = strlen($formula2); + + } catch(PHPExcel_Exception $e) { + $sz2 = 0; + $formula2 = ''; + } + $data .= pack('vv', $sz2, 0x0000); + $data .= $formula2; + + // cell range address list + $data .= pack('v', 0x0001); + $data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate); + + $length = strlen($data); + $header = pack("vv", $record, $length); + + $this->_append($header . $data); + } + } + } + + /** + * Map Error code + * + * @param string $errorCode + * @return int + */ + private static function _mapErrorCode($errorCode) { + switch ($errorCode) { + case '#NULL!': return 0x00; + case '#DIV/0!': return 0x07; + case '#VALUE!': return 0x0F; + case '#REF!': return 0x17; + case '#NAME?': return 0x1D; + case '#NUM!': return 0x24; + case '#N/A': return 0x2A; + } + + return 0; + } + + /** + * Write PLV Record + */ + private function _writePageLayoutView(){ + $record = 0x088B; // Record identifier + $length = 0x0010; // Bytes to follow + + $rt = 0x088B; // 2 + $grbitFrt = 0x0000; // 2 + $reserved = 0x0000000000000000; // 8 + $wScalvePLV = $this->_phpSheet->getSheetView()->getZoomScale(); // 2 + + // The options flags that comprise $grbit + if($this->_phpSheet->getSheetView()->getView() == PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT){ + $fPageLayoutView = 1; + } else { + $fPageLayoutView = 0; + } + $fRulerVisible = 0; + $fWhitespaceHidden = 0; + + $grbit = $fPageLayoutView; // 2 + $grbit |= $fRulerVisible << 1; + $grbit |= $fWhitespaceHidden << 3; + + $header = pack("vv", $record, $length); + $data = pack("vvVVvv", $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit); + $this->_append($header . $data); + } + + /** + * Write CFRule Record + * @param PHPExcel_Style_Conditional $conditional + */ + private function _writeCFRule(PHPExcel_Style_Conditional $conditional){ + $record = 0x01B1; // Record identifier + + // $type : Type of the CF + // $operatorType : Comparison operator + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION){ + $type = 0x02; + $operatorType = 0x00; + } else if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + $type = 0x01; + + switch ($conditional->getOperatorType()){ + case PHPExcel_Style_Conditional::OPERATOR_NONE: + $operatorType = 0x00; + break; + case PHPExcel_Style_Conditional::OPERATOR_EQUAL: + $operatorType = 0x03; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHAN: + $operatorType = 0x05; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHANOREQUAL: + $operatorType = 0x07; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHAN: + $operatorType = 0x06; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHANOREQUAL: + $operatorType = 0x08; + break; + case PHPExcel_Style_Conditional::OPERATOR_NOTEQUAL: + $operatorType = 0x04; + break; + case PHPExcel_Style_Conditional::OPERATOR_BETWEEN: + $operatorType = 0x01; + break; + // not OPERATOR_NOTBETWEEN 0x02 + } + } + + // $szValue1 : size of the formula data for first value or formula + // $szValue2 : size of the formula data for second value or formula + $arrConditions = $conditional->getConditions(); + $numConditions = sizeof($arrConditions); + if($numConditions == 1){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = 0x0000; + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = null; + } else if($numConditions == 2 && ($conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BETWEEN)){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000); + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = pack('Cv', 0x1E, $arrConditions[1]); + } else { + $szValue1 = 0x0000; + $szValue2 = 0x0000; + $operand1 = null; + $operand2 = null; + } + + // $flags : Option flags + // Alignment + $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0); + $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0); + $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0); + $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0); + $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0); + $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0); + if($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0){ + $bFormatAlign = 1; + } else { + $bFormatAlign = 0; + } + // Protection + $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0); + $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0); + if($bProtLocked == 0 || $bProtHidden == 0){ + $bFormatProt = 1; + } else { + $bFormatProt = 0; + } + // Border + $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + if($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0){ + $bFormatBorder = 1; + } else { + $bFormatBorder = 0; + } + // Pattern + $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1); + $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1); + $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1); + if($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0){ + $bFormatFill = 1; + } else { + $bFormatFill = 0; + } + // Font + if($conditional->getStyle()->getFont()->getName() != null + || $conditional->getStyle()->getFont()->getSize() != null + || $conditional->getStyle()->getFont()->getBold() != null + || $conditional->getStyle()->getFont()->getItalic() != null + || $conditional->getStyle()->getFont()->getSuperScript() != null + || $conditional->getStyle()->getFont()->getSubScript() != null + || $conditional->getStyle()->getFont()->getUnderline() != null + || $conditional->getStyle()->getFont()->getStrikethrough() != null + || $conditional->getStyle()->getFont()->getColor()->getARGB() != null){ + $bFormatFont = 1; + } else { + $bFormatFont = 0; + } + // Alignment + $flags = 0; + $flags |= (1 == $bAlignHz ? 0x00000001 : 0); + $flags |= (1 == $bAlignVt ? 0x00000002 : 0); + $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0); + $flags |= (1 == $bTxRotation ? 0x00000008 : 0); + // Justify last line flag + $flags |= (1 == 1 ? 0x00000010 : 0); + $flags |= (1 == $bIndent ? 0x00000020 : 0); + $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0); + // Default + $flags |= (1 == 1 ? 0x00000080 : 0); + // Protection + $flags |= (1 == $bProtLocked ? 0x00000100 : 0); + $flags |= (1 == $bProtHidden ? 0x00000200 : 0); + // Border + $flags |= (1 == $bBorderLeft ? 0x00000400 : 0); + $flags |= (1 == $bBorderRight ? 0x00000800 : 0); + $flags |= (1 == $bBorderTop ? 0x00001000 : 0); + $flags |= (1 == $bBorderBottom ? 0x00002000 : 0); + $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border + $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border + // Pattern + $flags |= (1 == $bFillStyle ? 0x00010000 : 0); + $flags |= (1 == $bFillColor ? 0x00020000 : 0); + $flags |= (1 == $bFillColorBg ? 0x00040000 : 0); + $flags |= (1 == 1 ? 0x00380000 : 0); + // Font + $flags |= (1 == $bFormatFont ? 0x04000000 : 0); + // Alignment : + $flags |= (1 == $bFormatAlign ? 0x08000000 : 0); + // Border + $flags |= (1 == $bFormatBorder ? 0x10000000 : 0); + // Pattern + $flags |= (1 == $bFormatFill ? 0x20000000 : 0); + // Protection + $flags |= (1 == $bFormatProt ? 0x40000000 : 0); + // Text direction + $flags |= (1 == 0 ? 0x80000000 : 0); + + // Data Blocks + if($bFormatFont == 1){ + // Font Name + if($conditional->getStyle()->getFont()->getName() == null){ + $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + } else { + $dataBlockFont = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName()); + } + // Font Size + if($conditional->getStyle()->getFont()->getSize() == null){ + $dataBlockFont .= pack('V', 20 * 11); + } else { + $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize()); + } + // Font Options + $dataBlockFont .= pack('V', 0); + // Font weight + if($conditional->getStyle()->getFont()->getBold() == true){ + $dataBlockFont .= pack('v', 0x02BC); + } else { + $dataBlockFont .= pack('v', 0x0190); + } + // Escapement type + if($conditional->getStyle()->getFont()->getSubScript() == true){ + $dataBlockFont .= pack('v', 0x02); + $fontEscapement = 0; + } else if($conditional->getStyle()->getFont()->getSuperScript() == true){ + $dataBlockFont .= pack('v', 0x01); + $fontEscapement = 0; + } else { + $dataBlockFont .= pack('v', 0x00); + $fontEscapement = 1; + } + // Underline type + switch ($conditional->getStyle()->getFont()->getUnderline()){ + case PHPExcel_Style_Font::UNDERLINE_NONE : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLE : $dataBlockFont .= pack('C', 0x02); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING : $dataBlockFont .= pack('C', 0x22); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLE : $dataBlockFont .= pack('C', 0x01); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING : $dataBlockFont .= pack('C', 0x21); $fontUnderline = 0; break; + default : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 1; break; + } + // Not used (3) + $dataBlockFont .= pack('vC', 0x0000, 0x00); + // Font color index + switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) { + case '000000': $colorIdx = 0x08; break; + case 'FFFFFF': $colorIdx = 0x09; break; + case 'FF0000': $colorIdx = 0x0A; break; + case '00FF00': $colorIdx = 0x0B; break; + case '0000FF': $colorIdx = 0x0C; break; + case 'FFFF00': $colorIdx = 0x0D; break; + case 'FF00FF': $colorIdx = 0x0E; break; + case '00FFFF': $colorIdx = 0x0F; break; + case '800000': $colorIdx = 0x10; break; + case '008000': $colorIdx = 0x11; break; + case '000080': $colorIdx = 0x12; break; + case '808000': $colorIdx = 0x13; break; + case '800080': $colorIdx = 0x14; break; + case '008080': $colorIdx = 0x15; break; + case 'C0C0C0': $colorIdx = 0x16; break; + case '808080': $colorIdx = 0x17; break; + case '9999FF': $colorIdx = 0x18; break; + case '993366': $colorIdx = 0x19; break; + case 'FFFFCC': $colorIdx = 0x1A; break; + case 'CCFFFF': $colorIdx = 0x1B; break; + case '660066': $colorIdx = 0x1C; break; + case 'FF8080': $colorIdx = 0x1D; break; + case '0066CC': $colorIdx = 0x1E; break; + case 'CCCCFF': $colorIdx = 0x1F; break; + case '000080': $colorIdx = 0x20; break; + case 'FF00FF': $colorIdx = 0x21; break; + case 'FFFF00': $colorIdx = 0x22; break; + case '00FFFF': $colorIdx = 0x23; break; + case '800080': $colorIdx = 0x24; break; + case '800000': $colorIdx = 0x25; break; + case '008080': $colorIdx = 0x26; break; + case '0000FF': $colorIdx = 0x27; break; + case '00CCFF': $colorIdx = 0x28; break; + case 'CCFFFF': $colorIdx = 0x29; break; + case 'CCFFCC': $colorIdx = 0x2A; break; + case 'FFFF99': $colorIdx = 0x2B; break; + case '99CCFF': $colorIdx = 0x2C; break; + case 'FF99CC': $colorIdx = 0x2D; break; + case 'CC99FF': $colorIdx = 0x2E; break; + case 'FFCC99': $colorIdx = 0x2F; break; + case '3366FF': $colorIdx = 0x30; break; + case '33CCCC': $colorIdx = 0x31; break; + case '99CC00': $colorIdx = 0x32; break; + case 'FFCC00': $colorIdx = 0x33; break; + case 'FF9900': $colorIdx = 0x34; break; + case 'FF6600': $colorIdx = 0x35; break; + case '666699': $colorIdx = 0x36; break; + case '969696': $colorIdx = 0x37; break; + case '003366': $colorIdx = 0x38; break; + case '339966': $colorIdx = 0x39; break; + case '003300': $colorIdx = 0x3A; break; + case '333300': $colorIdx = 0x3B; break; + case '993300': $colorIdx = 0x3C; break; + case '993366': $colorIdx = 0x3D; break; + case '333399': $colorIdx = 0x3E; break; + case '333333': $colorIdx = 0x3F; break; + default: $colorIdx = 0x00; break; + } + $dataBlockFont .= pack('V', $colorIdx); + // Not used (4) + $dataBlockFont .= pack('V', 0x00000000); + // Options flags for modified font attributes + $optionsFlags = 0; + $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0); + $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0); + $optionsFlags |= (1 == 1 ? 0x00000008 : 0); + $optionsFlags |= (1 == 1 ? 0x00000010 : 0); + $optionsFlags |= (1 == 0 ? 0x00000020 : 0); + $optionsFlags |= (1 == 1 ? 0x00000080 : 0); + $dataBlockFont .= pack('V', $optionsFlags); + // Escapement type + $dataBlockFont .= pack('V', $fontEscapement); + // Underline type + $dataBlockFont .= pack('V', $fontUnderline); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Not used (8) + $dataBlockFont .= pack('VV', 0x00000000, 0x00000000); + // Always + $dataBlockFont .= pack('v', 0x0001); + } + if($bFormatAlign == 1){ + $blockAlign = 0; + // Alignment and text break + switch ($conditional->getStyle()->getAlignment()->getHorizontal()){ + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL : $blockAlign = 0; break; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT : $blockAlign = 1; break; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT : $blockAlign = 3; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER : $blockAlign = 2; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS : $blockAlign = 6; break; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY : $blockAlign = 5; break; + } + if($conditional->getStyle()->getAlignment()->getWrapText() == true){ + $blockAlign |= 1 << 3; + } else { + $blockAlign |= 0 << 3; + } + switch ($conditional->getStyle()->getAlignment()->getVertical()){ + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM : $blockAlign = 2 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_TOP : $blockAlign = 0 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_CENTER : $blockAlign = 1 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY : $blockAlign = 3 << 4; break; + } + $blockAlign |= 0 << 7; + + // Text rotation angle + $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation(); + + // Indentation + $blockIndent = $conditional->getStyle()->getAlignment()->getIndent(); + if($conditional->getStyle()->getAlignment()->getShrinkToFit() == true){ + $blockIndent |= 1 << 4; + } else { + $blockIndent |= 0 << 4; + } + $blockIndent |= 0 << 6; + + // Relative indentation + $blockIndentRelative = 255; + + $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000); + } + if($bFormatBorder == 1){ + $blockLineStyle = 0; + switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D; break; + } + switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 4; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 4; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 4; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 4; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 4; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 4; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 4; break; + } + switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 8; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 8; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 8; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 8; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 8; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 8; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 8; break; + } + switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 12; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 12; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 12; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 12; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 12; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 12; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 12; break; + } + //@todo _writeCFRule() => $blockLineStyle => Index Color for left line + //@todo _writeCFRule() => $blockLineStyle => Index Color for right line + //@todo _writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off + //@todo _writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off + $blockColor = 0; + //@todo _writeCFRule() => $blockColor => Index Color for top line + //@todo _writeCFRule() => $blockColor => Index Color for bottom line + //@todo _writeCFRule() => $blockColor => Index Color for diagonal line + switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockColor |= 0x00 << 21; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockColor |= 0x01 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockColor |= 0x02 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockColor |= 0x03 << 21; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockColor |= 0x04 << 21; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockColor |= 0x05 << 21; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockColor |= 0x06 << 21; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockColor |= 0x07 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockColor |= 0x08 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockColor |= 0x09 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockColor |= 0x0A << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockColor |= 0x0B << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockColor |= 0x0C << 21; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockColor |= 0x0D << 21; break; + } + $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor); + } + if($bFormatFill == 1){ + // Fill Patern Style + $blockFillPatternStyle = 0; + switch ($conditional->getStyle()->getFill()->getFillType()){ + case PHPExcel_Style_Fill::FILL_NONE : $blockFillPatternStyle = 0x00; break; + case PHPExcel_Style_Fill::FILL_SOLID : $blockFillPatternStyle = 0x01; break; + case PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY : $blockFillPatternStyle = 0x02; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY : $blockFillPatternStyle = 0x03; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY : $blockFillPatternStyle = 0x04; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL : $blockFillPatternStyle = 0x05; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL : $blockFillPatternStyle = 0x06; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN : $blockFillPatternStyle = 0x07; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKUP : $blockFillPatternStyle = 0x08; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID : $blockFillPatternStyle = 0x09; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS : $blockFillPatternStyle = 0x0A; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL : $blockFillPatternStyle = 0x0B; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL : $blockFillPatternStyle = 0x0C; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN : $blockFillPatternStyle = 0x0D; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP : $blockFillPatternStyle = 0x0E; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID : $blockFillPatternStyle = 0x0F; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS : $blockFillPatternStyle = 0x10; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 : $blockFillPatternStyle = 0x11; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 : $blockFillPatternStyle = 0x12; break; + case PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + case PHPExcel_Style_Fill::FILL_GRADIENT_PATH : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + default : $blockFillPatternStyle = 0x00; break; + } + // Color + switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) { + case '000000': $colorIdxBg = 0x08; break; + case 'FFFFFF': $colorIdxBg = 0x09; break; + case 'FF0000': $colorIdxBg = 0x0A; break; + case '00FF00': $colorIdxBg = 0x0B; break; + case '0000FF': $colorIdxBg = 0x0C; break; + case 'FFFF00': $colorIdxBg = 0x0D; break; + case 'FF00FF': $colorIdxBg = 0x0E; break; + case '00FFFF': $colorIdxBg = 0x0F; break; + case '800000': $colorIdxBg = 0x10; break; + case '008000': $colorIdxBg = 0x11; break; + case '000080': $colorIdxBg = 0x12; break; + case '808000': $colorIdxBg = 0x13; break; + case '800080': $colorIdxBg = 0x14; break; + case '008080': $colorIdxBg = 0x15; break; + case 'C0C0C0': $colorIdxBg = 0x16; break; + case '808080': $colorIdxBg = 0x17; break; + case '9999FF': $colorIdxBg = 0x18; break; + case '993366': $colorIdxBg = 0x19; break; + case 'FFFFCC': $colorIdxBg = 0x1A; break; + case 'CCFFFF': $colorIdxBg = 0x1B; break; + case '660066': $colorIdxBg = 0x1C; break; + case 'FF8080': $colorIdxBg = 0x1D; break; + case '0066CC': $colorIdxBg = 0x1E; break; + case 'CCCCFF': $colorIdxBg = 0x1F; break; + case '000080': $colorIdxBg = 0x20; break; + case 'FF00FF': $colorIdxBg = 0x21; break; + case 'FFFF00': $colorIdxBg = 0x22; break; + case '00FFFF': $colorIdxBg = 0x23; break; + case '800080': $colorIdxBg = 0x24; break; + case '800000': $colorIdxBg = 0x25; break; + case '008080': $colorIdxBg = 0x26; break; + case '0000FF': $colorIdxBg = 0x27; break; + case '00CCFF': $colorIdxBg = 0x28; break; + case 'CCFFFF': $colorIdxBg = 0x29; break; + case 'CCFFCC': $colorIdxBg = 0x2A; break; + case 'FFFF99': $colorIdxBg = 0x2B; break; + case '99CCFF': $colorIdxBg = 0x2C; break; + case 'FF99CC': $colorIdxBg = 0x2D; break; + case 'CC99FF': $colorIdxBg = 0x2E; break; + case 'FFCC99': $colorIdxBg = 0x2F; break; + case '3366FF': $colorIdxBg = 0x30; break; + case '33CCCC': $colorIdxBg = 0x31; break; + case '99CC00': $colorIdxBg = 0x32; break; + case 'FFCC00': $colorIdxBg = 0x33; break; + case 'FF9900': $colorIdxBg = 0x34; break; + case 'FF6600': $colorIdxBg = 0x35; break; + case '666699': $colorIdxBg = 0x36; break; + case '969696': $colorIdxBg = 0x37; break; + case '003366': $colorIdxBg = 0x38; break; + case '339966': $colorIdxBg = 0x39; break; + case '003300': $colorIdxBg = 0x3A; break; + case '333300': $colorIdxBg = 0x3B; break; + case '993300': $colorIdxBg = 0x3C; break; + case '993366': $colorIdxBg = 0x3D; break; + case '333399': $colorIdxBg = 0x3E; break; + case '333333': $colorIdxBg = 0x3F; break; + default: $colorIdxBg = 0x41; break; + } + // Fg Color + switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) { + case '000000': $colorIdxFg = 0x08; break; + case 'FFFFFF': $colorIdxFg = 0x09; break; + case 'FF0000': $colorIdxFg = 0x0A; break; + case '00FF00': $colorIdxFg = 0x0B; break; + case '0000FF': $colorIdxFg = 0x0C; break; + case 'FFFF00': $colorIdxFg = 0x0D; break; + case 'FF00FF': $colorIdxFg = 0x0E; break; + case '00FFFF': $colorIdxFg = 0x0F; break; + case '800000': $colorIdxFg = 0x10; break; + case '008000': $colorIdxFg = 0x11; break; + case '000080': $colorIdxFg = 0x12; break; + case '808000': $colorIdxFg = 0x13; break; + case '800080': $colorIdxFg = 0x14; break; + case '008080': $colorIdxFg = 0x15; break; + case 'C0C0C0': $colorIdxFg = 0x16; break; + case '808080': $colorIdxFg = 0x17; break; + case '9999FF': $colorIdxFg = 0x18; break; + case '993366': $colorIdxFg = 0x19; break; + case 'FFFFCC': $colorIdxFg = 0x1A; break; + case 'CCFFFF': $colorIdxFg = 0x1B; break; + case '660066': $colorIdxFg = 0x1C; break; + case 'FF8080': $colorIdxFg = 0x1D; break; + case '0066CC': $colorIdxFg = 0x1E; break; + case 'CCCCFF': $colorIdxFg = 0x1F; break; + case '000080': $colorIdxFg = 0x20; break; + case 'FF00FF': $colorIdxFg = 0x21; break; + case 'FFFF00': $colorIdxFg = 0x22; break; + case '00FFFF': $colorIdxFg = 0x23; break; + case '800080': $colorIdxFg = 0x24; break; + case '800000': $colorIdxFg = 0x25; break; + case '008080': $colorIdxFg = 0x26; break; + case '0000FF': $colorIdxFg = 0x27; break; + case '00CCFF': $colorIdxFg = 0x28; break; + case 'CCFFFF': $colorIdxFg = 0x29; break; + case 'CCFFCC': $colorIdxFg = 0x2A; break; + case 'FFFF99': $colorIdxFg = 0x2B; break; + case '99CCFF': $colorIdxFg = 0x2C; break; + case 'FF99CC': $colorIdxFg = 0x2D; break; + case 'CC99FF': $colorIdxFg = 0x2E; break; + case 'FFCC99': $colorIdxFg = 0x2F; break; + case '3366FF': $colorIdxFg = 0x30; break; + case '33CCCC': $colorIdxFg = 0x31; break; + case '99CC00': $colorIdxFg = 0x32; break; + case 'FFCC00': $colorIdxFg = 0x33; break; + case 'FF9900': $colorIdxFg = 0x34; break; + case 'FF6600': $colorIdxFg = 0x35; break; + case '666699': $colorIdxFg = 0x36; break; + case '969696': $colorIdxFg = 0x37; break; + case '003366': $colorIdxFg = 0x38; break; + case '339966': $colorIdxFg = 0x39; break; + case '003300': $colorIdxFg = 0x3A; break; + case '333300': $colorIdxFg = 0x3B; break; + case '993300': $colorIdxFg = 0x3C; break; + case '993366': $colorIdxFg = 0x3D; break; + case '333399': $colorIdxFg = 0x3E; break; + case '333333': $colorIdxFg = 0x3F; break; + default: $colorIdxFg = 0x40; break; + } + $dataBlockFill = pack('v', $blockFillPatternStyle); + $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7)); + } + if($bFormatProt == 1){ + $dataBlockProtection = 0; + if($conditional->getStyle()->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1; + } + if($conditional->getStyle()->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1 << 1; + } + } + + $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000); + if($bFormatFont == 1){ // Block Formatting : OK + $data .= $dataBlockFont; + } + if($bFormatAlign == 1){ + $data .= $dataBlockAlign; + } + if($bFormatBorder == 1){ + $data .= $dataBlockBorder; + } + if($bFormatFill == 1){ // Block Formatting : OK + $data .= $dataBlockFill; + } + if($bFormatProt == 1){ + $data .= $dataBlockProtection; + } + if(!is_null($operand1)){ + $data .= $operand1; + } + if(!is_null($operand2)){ + $data .= $operand2; + } + $header = pack('vv', $record, strlen($data)); + $this->_append($header . $data); + } + + /** + * Write CFHeader record + */ + private function _writeCFHeader(){ + $record = 0x01B0; // Record identifier + $length = 0x0016; // Bytes to follow + + $numColumnMin = null; + $numColumnMax = null; + $numRowMin = null; + $numRowMax = null; + $arrConditional = array(); + foreach ($this->_phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + } + // Cells + $arrCoord = PHPExcel_Cell::coordinateFromString($cellCoordinate); + if(!is_numeric($arrCoord[0])){ + $arrCoord[0] = PHPExcel_Cell::columnIndexFromString($arrCoord[0]); + } + if(is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])){ + $numColumnMin = $arrCoord[0]; + } + if(is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])){ + $numColumnMax = $arrCoord[0]; + } + if(is_null($numRowMin) || ($numRowMin > $arrCoord[1])){ + $numRowMin = $arrCoord[1]; + } + if(is_null($numRowMax) || ($numRowMax < $arrCoord[1])){ + $numRowMax = $arrCoord[1]; + } + } + } + } + $needRedraw = 1; + $cellRange = pack('vvvv', $numRowMin-1, $numRowMax-1, $numColumnMin-1, $numColumnMax-1); + + $header = pack('vv', $record, $length); + $data = pack('vv', count($arrConditional), $needRedraw); + $data .= $cellRange; + $data .= pack('v', 0x0001); + $data .= $cellRange; + $this->_append($header . $data); + } } \ No newline at end of file diff --git a/Classes/PHPExcel/Writer/Excel5/Xf.php b/Classes/PHPExcel/Writer/Excel5/Xf.php index 0fcdc691..7347aabb 100644 --- a/Classes/PHPExcel/Writer/Excel5/Xf.php +++ b/Classes/PHPExcel/Writer/Excel5/Xf.php @@ -21,7 +21,7 @@ * @category PHPExcel * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ @@ -71,477 +71,477 @@ class PHPExcel_Writer_Excel5_Xf { /** - * Style XF or a cell XF ? - * - * @var boolean - */ - private $_isStyleXf; + * Style XF or a cell XF ? + * + * @var boolean + */ + private $_isStyleXf; - /** - * Index to the FONT record. Index 4 does not exist - * @var integer - */ - private $_fontIndex; + /** + * Index to the FONT record. Index 4 does not exist + * @var integer + */ + private $_fontIndex; - /** - * An index (2 bytes) to a FORMAT record (number format). - * @var integer - */ - public $_numberFormatIndex; + /** + * An index (2 bytes) to a FORMAT record (number format). + * @var integer + */ + public $_numberFormatIndex; - /** - * 1 bit, apparently not used. - * @var integer - */ - public $_text_justlast; + /** + * 1 bit, apparently not used. + * @var integer + */ + public $_text_justlast; - /** - * The cell's foreground color. - * @var integer - */ - public $_fg_color; + /** + * The cell's foreground color. + * @var integer + */ + public $_fg_color; - /** - * The cell's background color. - * @var integer - */ - public $_bg_color; + /** + * The cell's background color. + * @var integer + */ + public $_bg_color; - /** - * Color of the bottom border of the cell. - * @var integer - */ - public $_bottom_color; + /** + * Color of the bottom border of the cell. + * @var integer + */ + public $_bottom_color; - /** - * Color of the top border of the cell. - * @var integer - */ - public $_top_color; + /** + * Color of the top border of the cell. + * @var integer + */ + public $_top_color; - /** - * Color of the left border of the cell. - * @var integer - */ - public $_left_color; + /** + * Color of the left border of the cell. + * @var integer + */ + public $_left_color; - /** - * Color of the right border of the cell. - * @var integer - */ - public $_right_color; + /** + * Color of the right border of the cell. + * @var integer + */ + public $_right_color; - /** - * Constructor - * - * @access public - * @param PHPExcel_Style The XF format - */ - public function __construct(PHPExcel_Style $style = null) - { - $this->_isStyleXf = false; - $this->_fontIndex = 0; + /** + * Constructor + * + * @access public + * @param PHPExcel_Style The XF format + */ + public function __construct(PHPExcel_Style $style = null) + { + $this->_isStyleXf = false; + $this->_fontIndex = 0; - $this->_numberFormatIndex = 0; + $this->_numberFormatIndex = 0; - $this->_text_justlast = 0; + $this->_text_justlast = 0; - $this->_fg_color = 0x40; - $this->_bg_color = 0x41; + $this->_fg_color = 0x40; + $this->_bg_color = 0x41; - $this->_diag = 0; + $this->_diag = 0; - $this->_bottom_color = 0x40; - $this->_top_color = 0x40; - $this->_left_color = 0x40; - $this->_right_color = 0x40; - $this->_diag_color = 0x40; - $this->_style = $style; + $this->_bottom_color = 0x40; + $this->_top_color = 0x40; + $this->_left_color = 0x40; + $this->_right_color = 0x40; + $this->_diag_color = 0x40; + $this->_style = $style; - } + } - /** - * Generate an Excel BIFF XF record (style or cell). - * - * @return string The XF record - */ - function writeXf() - { - // Set the type of the XF record and some of the attributes. - if ($this->_isStyleXf) { - $style = 0xFFF5; - } else { - $style = self::_mapLocked($this->_style->getProtection()->getLocked()); - $style |= self::_mapHidden($this->_style->getProtection()->getHidden()) << 1; - } + /** + * Generate an Excel BIFF XF record (style or cell). + * + * @return string The XF record + */ + function writeXf() + { + // Set the type of the XF record and some of the attributes. + if ($this->_isStyleXf) { + $style = 0xFFF5; + } else { + $style = self::_mapLocked($this->_style->getProtection()->getLocked()); + $style |= self::_mapHidden($this->_style->getProtection()->getHidden()) << 1; + } - // Flags to indicate if attributes have been set. - $atr_num = ($this->_numberFormatIndex != 0)?1:0; - $atr_fnt = ($this->_fontIndex != 0)?1:0; - $atr_alc = ((int) $this->_style->getAlignment()->getWrapText()) ? 1 : 0; - $atr_bdr = (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) || - self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) || - self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) || - self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()))?1:0; - $atr_pat = (($this->_fg_color != 0x40) || - ($this->_bg_color != 0x41) || - self::_mapFillType($this->_style->getFill()->getFillType()))?1:0; - $atr_prot = self::_mapLocked($this->_style->getProtection()->getLocked()) - | self::_mapHidden($this->_style->getProtection()->getHidden()); + // Flags to indicate if attributes have been set. + $atr_num = ($this->_numberFormatIndex != 0)?1:0; + $atr_fnt = ($this->_fontIndex != 0)?1:0; + $atr_alc = ((int) $this->_style->getAlignment()->getWrapText()) ? 1 : 0; + $atr_bdr = (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()))?1:0; + $atr_pat = (($this->_fg_color != 0x40) || + ($this->_bg_color != 0x41) || + self::_mapFillType($this->_style->getFill()->getFillType()))?1:0; + $atr_prot = self::_mapLocked($this->_style->getProtection()->getLocked()) + | self::_mapHidden($this->_style->getProtection()->getHidden()); - // Zero the default border colour if the border has not been set. - if (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) == 0) { - $this->_bottom_color = 0; - } - if (self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) == 0) { - $this->_top_color = 0; - } - if (self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) == 0) { - $this->_right_color = 0; - } - if (self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { - $this->_left_color = 0; - } - if (self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { - $this->_diag_color = 0; - } + // Zero the default border colour if the border has not been set. + if (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) == 0) { + $this->_bottom_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) == 0) { + $this->_top_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) == 0) { + $this->_right_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { + $this->_left_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { + $this->_diag_color = 0; + } - $record = 0x00E0; // Record identifier - $length = 0x0014; // Number of bytes to follow + $record = 0x00E0; // Record identifier + $length = 0x0014; // Number of bytes to follow - $ifnt = $this->_fontIndex; // Index to FONT record - $ifmt = $this->_numberFormatIndex; // Index to FORMAT record + $ifnt = $this->_fontIndex; // Index to FONT record + $ifmt = $this->_numberFormatIndex; // Index to FORMAT record - $align = $this->_mapHAlign($this->_style->getAlignment()->getHorizontal()); // Alignment - $align |= (int) $this->_style->getAlignment()->getWrapText() << 3; - $align |= self::_mapVAlign($this->_style->getAlignment()->getVertical()) << 4; - $align |= $this->_text_justlast << 7; + $align = $this->_mapHAlign($this->_style->getAlignment()->getHorizontal()); // Alignment + $align |= (int) $this->_style->getAlignment()->getWrapText() << 3; + $align |= self::_mapVAlign($this->_style->getAlignment()->getVertical()) << 4; + $align |= $this->_text_justlast << 7; - $used_attrib = $atr_num << 2; - $used_attrib |= $atr_fnt << 3; - $used_attrib |= $atr_alc << 4; - $used_attrib |= $atr_bdr << 5; - $used_attrib |= $atr_pat << 6; - $used_attrib |= $atr_prot << 7; + $used_attrib = $atr_num << 2; + $used_attrib |= $atr_fnt << 3; + $used_attrib |= $atr_alc << 4; + $used_attrib |= $atr_bdr << 5; + $used_attrib |= $atr_pat << 6; + $used_attrib |= $atr_prot << 7; - $icv = $this->_fg_color; // fg and bg pattern colors - $icv |= $this->_bg_color << 7; + $icv = $this->_fg_color; // fg and bg pattern colors + $icv |= $this->_bg_color << 7; - $border1 = self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()); // Border line style and color - $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) << 4; - $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) << 8; - $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; - $border1 |= $this->_left_color << 16; - $border1 |= $this->_right_color << 23; + $border1 = self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()); // Border line style and color + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) << 4; + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) << 8; + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; + $border1 |= $this->_left_color << 16; + $border1 |= $this->_right_color << 23; - $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); - $diag_tl_to_rb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH - || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_DOWN; - $diag_tr_to_lb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH - || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_UP; - $border1 |= $diag_tl_to_rb << 30; - $border1 |= $diag_tr_to_lb << 31; + $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); + $diag_tl_to_rb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_DOWN; + $diag_tr_to_lb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_UP; + $border1 |= $diag_tl_to_rb << 30; + $border1 |= $diag_tr_to_lb << 31; - $border2 = $this->_top_color; // Border color - $border2 |= $this->_bottom_color << 7; - $border2 |= $this->_diag_color << 14; - $border2 |= self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; - $border2 |= self::_mapFillType($this->_style->getFill()->getFillType()) << 26; + $border2 = $this->_top_color; // Border color + $border2 |= $this->_bottom_color << 7; + $border2 |= $this->_diag_color << 14; + $border2 |= self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; + $border2 |= self::_mapFillType($this->_style->getFill()->getFillType()) << 26; - $header = pack("vv", $record, $length); + $header = pack("vv", $record, $length); - //BIFF8 options: identation, shrinkToFit and text direction - $biff8_options = $this->_style->getAlignment()->getIndent(); - $biff8_options |= (int) $this->_style->getAlignment()->getShrinkToFit() << 4; + //BIFF8 options: identation, shrinkToFit and text direction + $biff8_options = $this->_style->getAlignment()->getIndent(); + $biff8_options |= (int) $this->_style->getAlignment()->getShrinkToFit() << 4; - $data = pack("vvvC", $ifnt, $ifmt, $style, $align); - $data .= pack("CCC" - , self::_mapTextRotation($this->_style->getAlignment()->getTextRotation()) - , $biff8_options - , $used_attrib - ); - $data .= pack("VVv", $border1, $border2, $icv); + $data = pack("vvvC", $ifnt, $ifmt, $style, $align); + $data .= pack("CCC" + , self::_mapTextRotation($this->_style->getAlignment()->getTextRotation()) + , $biff8_options + , $used_attrib + ); + $data .= pack("VVv", $border1, $border2, $icv); - return($header . $data); - } + return($header . $data); + } - /** - * Is this a style XF ? - * - * @param boolean $value - */ - public function setIsStyleXf($value) - { - $this->_isStyleXf = $value; - } + /** + * Is this a style XF ? + * + * @param boolean $value + */ + public function setIsStyleXf($value) + { + $this->_isStyleXf = $value; + } - /** - * Sets the cell's bottom border color - * - * @access public - * @param int $colorIndex Color index - */ - function setBottomColor($colorIndex) - { - $this->_bottom_color = $colorIndex; - } + /** + * Sets the cell's bottom border color + * + * @access public + * @param int $colorIndex Color index + */ + function setBottomColor($colorIndex) + { + $this->_bottom_color = $colorIndex; + } - /** - * Sets the cell's top border color - * - * @access public - * @param int $colorIndex Color index - */ - function setTopColor($colorIndex) - { - $this->_top_color = $colorIndex; - } + /** + * Sets the cell's top border color + * + * @access public + * @param int $colorIndex Color index + */ + function setTopColor($colorIndex) + { + $this->_top_color = $colorIndex; + } - /** - * Sets the cell's left border color - * - * @access public - * @param int $colorIndex Color index - */ - function setLeftColor($colorIndex) - { - $this->_left_color = $colorIndex; - } + /** + * Sets the cell's left border color + * + * @access public + * @param int $colorIndex Color index + */ + function setLeftColor($colorIndex) + { + $this->_left_color = $colorIndex; + } - /** - * Sets the cell's right border color - * - * @access public - * @param int $colorIndex Color index - */ - function setRightColor($colorIndex) - { - $this->_right_color = $colorIndex; - } + /** + * Sets the cell's right border color + * + * @access public + * @param int $colorIndex Color index + */ + function setRightColor($colorIndex) + { + $this->_right_color = $colorIndex; + } - /** - * Sets the cell's diagonal border color - * - * @access public - * @param int $colorIndex Color index - */ - function setDiagColor($colorIndex) - { - $this->_diag_color = $colorIndex; - } + /** + * Sets the cell's diagonal border color + * + * @access public + * @param int $colorIndex Color index + */ + function setDiagColor($colorIndex) + { + $this->_diag_color = $colorIndex; + } - /** - * Sets the cell's foreground color - * - * @access public - * @param int $colorIndex Color index - */ - function setFgColor($colorIndex) - { - $this->_fg_color = $colorIndex; - } + /** + * Sets the cell's foreground color + * + * @access public + * @param int $colorIndex Color index + */ + function setFgColor($colorIndex) + { + $this->_fg_color = $colorIndex; + } - /** - * Sets the cell's background color - * - * @access public - * @param int $colorIndex Color index - */ - function setBgColor($colorIndex) - { - $this->_bg_color = $colorIndex; - } + /** + * Sets the cell's background color + * + * @access public + * @param int $colorIndex Color index + */ + function setBgColor($colorIndex) + { + $this->_bg_color = $colorIndex; + } - /** - * Sets the index to the number format record - * It can be date, time, currency, etc... - * - * @access public - * @param integer $numberFormatIndex Index to format record - */ - function setNumberFormatIndex($numberFormatIndex) - { - $this->_numberFormatIndex = $numberFormatIndex; - } + /** + * Sets the index to the number format record + * It can be date, time, currency, etc... + * + * @access public + * @param integer $numberFormatIndex Index to format record + */ + function setNumberFormatIndex($numberFormatIndex) + { + $this->_numberFormatIndex = $numberFormatIndex; + } - /** - * Set the font index. - * - * @param int $value Font index, note that value 4 does not exist - */ - public function setFontIndex($value) - { - $this->_fontIndex = $value; - } + /** + * Set the font index. + * + * @param int $value Font index, note that value 4 does not exist + */ + public function setFontIndex($value) + { + $this->_fontIndex = $value; + } - /** - * Map of BIFF2-BIFF8 codes for border styles - * @static array of int - * - */ - private static $_mapBorderStyle = array ( PHPExcel_Style_Border::BORDER_NONE => 0x00, - PHPExcel_Style_Border::BORDER_THIN => 0x01, - PHPExcel_Style_Border::BORDER_MEDIUM => 0x02, - PHPExcel_Style_Border::BORDER_DASHED => 0x03, - PHPExcel_Style_Border::BORDER_DOTTED => 0x04, - PHPExcel_Style_Border::BORDER_THICK => 0x05, - PHPExcel_Style_Border::BORDER_DOUBLE => 0x06, - PHPExcel_Style_Border::BORDER_HAIR => 0x07, - PHPExcel_Style_Border::BORDER_MEDIUMDASHED => 0x08, - PHPExcel_Style_Border::BORDER_DASHDOT => 0x09, - PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT => 0x0A, - PHPExcel_Style_Border::BORDER_DASHDOTDOT => 0x0B, - PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT => 0x0C, - PHPExcel_Style_Border::BORDER_SLANTDASHDOT => 0x0D, - ); + /** + * Map of BIFF2-BIFF8 codes for border styles + * @static array of int + * + */ + private static $_mapBorderStyle = array ( PHPExcel_Style_Border::BORDER_NONE => 0x00, + PHPExcel_Style_Border::BORDER_THIN => 0x01, + PHPExcel_Style_Border::BORDER_MEDIUM => 0x02, + PHPExcel_Style_Border::BORDER_DASHED => 0x03, + PHPExcel_Style_Border::BORDER_DOTTED => 0x04, + PHPExcel_Style_Border::BORDER_THICK => 0x05, + PHPExcel_Style_Border::BORDER_DOUBLE => 0x06, + PHPExcel_Style_Border::BORDER_HAIR => 0x07, + PHPExcel_Style_Border::BORDER_MEDIUMDASHED => 0x08, + PHPExcel_Style_Border::BORDER_DASHDOT => 0x09, + PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT => 0x0A, + PHPExcel_Style_Border::BORDER_DASHDOTDOT => 0x0B, + PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT => 0x0C, + PHPExcel_Style_Border::BORDER_SLANTDASHDOT => 0x0D, + ); - /** - * Map border style - * - * @param string $borderStyle - * @return int - */ - private static function _mapBorderStyle($borderStyle) { - if (isset(self::$_mapBorderStyle[$borderStyle])) - return self::$_mapBorderStyle[$borderStyle]; - return 0x00; - } + /** + * Map border style + * + * @param string $borderStyle + * @return int + */ + private static function _mapBorderStyle($borderStyle) { + if (isset(self::$_mapBorderStyle[$borderStyle])) + return self::$_mapBorderStyle[$borderStyle]; + return 0x00; + } - /** - * Map of BIFF2-BIFF8 codes for fill types - * @static array of int - * - */ - private static $_mapFillType = array( PHPExcel_Style_Fill::FILL_NONE => 0x00, - PHPExcel_Style_Fill::FILL_SOLID => 0x01, - PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY => 0x02, - PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY => 0x03, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY => 0x04, - PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL => 0x05, - PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL => 0x06, - PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN => 0x07, - PHPExcel_Style_Fill::FILL_PATTERN_DARKUP => 0x08, - PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID => 0x09, - PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS => 0x0A, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL => 0x0B, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL => 0x0C, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN => 0x0D, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP => 0x0E, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID => 0x0F, - PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS => 0x10, - PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 => 0x11, - PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 => 0x12, - PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR => 0x00, // does not exist in BIFF8 - PHPExcel_Style_Fill::FILL_GRADIENT_PATH => 0x00, // does not exist in BIFF8 - ); - /** - * Map fill type - * - * @param string $fillType - * @return int - */ - private static function _mapFillType($fillType) { - if (isset(self::$_mapFillType[$fillType])) - return self::$_mapFillType[$fillType]; - return 0x00; - } + /** + * Map of BIFF2-BIFF8 codes for fill types + * @static array of int + * + */ + private static $_mapFillType = array( PHPExcel_Style_Fill::FILL_NONE => 0x00, + PHPExcel_Style_Fill::FILL_SOLID => 0x01, + PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY => 0x02, + PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY => 0x03, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY => 0x04, + PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL => 0x05, + PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL => 0x06, + PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN => 0x07, + PHPExcel_Style_Fill::FILL_PATTERN_DARKUP => 0x08, + PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID => 0x09, + PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS => 0x0A, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL => 0x0B, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL => 0x0C, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN => 0x0D, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP => 0x0E, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID => 0x0F, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS => 0x10, + PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 => 0x11, + PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 => 0x12, + PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR => 0x00, // does not exist in BIFF8 + PHPExcel_Style_Fill::FILL_GRADIENT_PATH => 0x00, // does not exist in BIFF8 + ); + /** + * Map fill type + * + * @param string $fillType + * @return int + */ + private static function _mapFillType($fillType) { + if (isset(self::$_mapFillType[$fillType])) + return self::$_mapFillType[$fillType]; + return 0x00; + } - /** - * Map of BIFF2-BIFF8 codes for horizontal alignment - * @static array of int - * - */ - private static $_mapHAlign = array( PHPExcel_Style_Alignment::HORIZONTAL_GENERAL => 0, - PHPExcel_Style_Alignment::HORIZONTAL_LEFT => 1, - PHPExcel_Style_Alignment::HORIZONTAL_CENTER => 2, - PHPExcel_Style_Alignment::HORIZONTAL_RIGHT => 3, - PHPExcel_Style_Alignment::HORIZONTAL_FILL => 4, - PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY => 5, - PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS => 6, - ); - /** - * Map to BIFF2-BIFF8 codes for horizontal alignment - * - * @param string $hAlign - * @return int - */ - private function _mapHAlign($hAlign) - { - if (isset(self::$_mapHAlign[$hAlign])) - return self::$_mapHAlign[$hAlign]; - return 0; - } + /** + * Map of BIFF2-BIFF8 codes for horizontal alignment + * @static array of int + * + */ + private static $_mapHAlign = array( PHPExcel_Style_Alignment::HORIZONTAL_GENERAL => 0, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT => 1, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER => 2, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT => 3, + PHPExcel_Style_Alignment::HORIZONTAL_FILL => 4, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY => 5, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS => 6, + ); + /** + * Map to BIFF2-BIFF8 codes for horizontal alignment + * + * @param string $hAlign + * @return int + */ + private function _mapHAlign($hAlign) + { + if (isset(self::$_mapHAlign[$hAlign])) + return self::$_mapHAlign[$hAlign]; + return 0; + } - /** - * Map of BIFF2-BIFF8 codes for vertical alignment - * @static array of int - * - */ - private static $_mapVAlign = array( PHPExcel_Style_Alignment::VERTICAL_TOP => 0, - PHPExcel_Style_Alignment::VERTICAL_CENTER => 1, - PHPExcel_Style_Alignment::VERTICAL_BOTTOM => 2, - PHPExcel_Style_Alignment::VERTICAL_JUSTIFY => 3, - ); - /** - * Map to BIFF2-BIFF8 codes for vertical alignment - * - * @param string $vAlign - * @return int - */ - private static function _mapVAlign($vAlign) { - if (isset(self::$_mapVAlign[$vAlign])) - return self::$_mapVAlign[$vAlign]; - return 2; - } + /** + * Map of BIFF2-BIFF8 codes for vertical alignment + * @static array of int + * + */ + private static $_mapVAlign = array( PHPExcel_Style_Alignment::VERTICAL_TOP => 0, + PHPExcel_Style_Alignment::VERTICAL_CENTER => 1, + PHPExcel_Style_Alignment::VERTICAL_BOTTOM => 2, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY => 3, + ); + /** + * Map to BIFF2-BIFF8 codes for vertical alignment + * + * @param string $vAlign + * @return int + */ + private static function _mapVAlign($vAlign) { + if (isset(self::$_mapVAlign[$vAlign])) + return self::$_mapVAlign[$vAlign]; + return 2; + } - /** - * Map to BIFF8 codes for text rotation angle - * - * @param int $textRotation - * @return int - */ - private static function _mapTextRotation($textRotation) { - if ($textRotation >= 0) { - return $textRotation; - } - if ($textRotation == -165) { - return 255; - } - if ($textRotation < 0) { - return 90 - $textRotation; - } - } + /** + * Map to BIFF8 codes for text rotation angle + * + * @param int $textRotation + * @return int + */ + private static function _mapTextRotation($textRotation) { + if ($textRotation >= 0) { + return $textRotation; + } + if ($textRotation == -165) { + return 255; + } + if ($textRotation < 0) { + return 90 - $textRotation; + } + } - /** - * Map locked - * - * @param string - * @return int - */ - private static function _mapLocked($locked) { - switch ($locked) { - case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 1; - case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; - case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; - default: return 1; - } - } + /** + * Map locked + * + * @param string + * @return int + */ + private static function _mapLocked($locked) { + switch ($locked) { + case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 1; + case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; + case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; + default: return 1; + } + } - /** - * Map hidden - * - * @param string - * @return int - */ - private static function _mapHidden($hidden) { - switch ($hidden) { - case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 0; - case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; - case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; - default: return 0; - } - } + /** + * Map hidden + * + * @param string + * @return int + */ + private static function _mapHidden($hidden) { + switch ($hidden) { + case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 0; + case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; + case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; + default: return 0; + } + } } diff --git a/Classes/PHPExcel/Writer/Exception.php b/Classes/PHPExcel/Writer/Exception.php index 5da3efd6..bfa00568 100644 --- a/Classes/PHPExcel/Writer/Exception.php +++ b/Classes/PHPExcel/Writer/Exception.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_Exception * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,32 +22,25 @@ * @category PHPExcel * @package PHPExcel_Writer * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_Exception - * - * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ -class PHPExcel_Writer_Exception extends PHPExcel_Exception { - /** - * Error handler callback - * - * @param mixed $code - * @param mixed $string - * @param mixed $file - * @param mixed $line - * @param mixed $context - */ - public static function errorHandlerCallback($code, $string, $file, $line, $context) { - $e = new self($string, $code); - $e->line = $line; - $e->file = $file; - throw $e; - } +class PHPExcel_Writer_Exception extends PHPExcel_Exception +{ + /** + * Error handler callback + * + * @param mixed $code + * @param mixed $string + * @param mixed $file + * @param mixed $line + * @param mixed $context + */ + public static function errorHandlerCallback($code, $string, $file, $line, $context) + { + $e = new self($string, $code); + $e->line = $line; + $e->file = $file; + throw $e; + } } diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index 788c03cb..42329b0e 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_HTML * * Copyright (c) 2006 - 2015 PHPExcel * @@ -19,1113 +20,1105 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Writer_HTML + * @package PHPExcel_Writer_HTML * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ +class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter +{ + /** + * PHPExcel object + * + * @var PHPExcel + */ + protected $_phpExcel; + /** + * Sheet index to write + * + * @var int + */ + private $_sheetIndex = 0; -/** - * PHPExcel_Writer_HTML - * - * @category PHPExcel - * @package PHPExcel_Writer_HTML - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ -class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * PHPExcel object - * - * @var PHPExcel - */ - protected $_phpExcel; + /** + * Images root + * + * @var string + */ + private $_imagesRoot = '.'; - /** - * Sheet index to write - * - * @var int - */ - private $_sheetIndex = 0; + /** + * embed images, or link to images + * + * @var boolean + */ + private $_embedImages = FALSE; - /** - * Images root - * - * @var string - */ - private $_imagesRoot = '.'; + /** + * Use inline CSS? + * + * @var boolean + */ + private $_useInlineCss = false; - /** - * embed images, or link to images - * - * @var boolean - */ - private $_embedImages = FALSE; + /** + * Array of CSS styles + * + * @var array + */ + private $_cssStyles = null; - /** - * Use inline CSS? - * - * @var boolean - */ - private $_useInlineCss = false; + /** + * Array of column widths in points + * + * @var array + */ + private $_columnWidths = null; - /** - * Array of CSS styles - * - * @var array - */ - private $_cssStyles = null; + /** + * Default font + * + * @var PHPExcel_Style_Font + */ + private $_defaultFont; - /** - * Array of column widths in points - * - * @var array - */ - private $_columnWidths = null; + /** + * Flag whether spans have been calculated + * + * @var boolean + */ + private $_spansAreCalculated = false; - /** - * Default font - * - * @var PHPExcel_Style_Font - */ - private $_defaultFont; + /** + * Excel cells that should not be written as HTML cells + * + * @var array + */ + private $_isSpannedCell = array(); - /** - * Flag whether spans have been calculated - * - * @var boolean - */ - private $_spansAreCalculated = false; + /** + * Excel cells that are upper-left corner in a cell merge + * + * @var array + */ + private $_isBaseCell = array(); - /** - * Excel cells that should not be written as HTML cells - * - * @var array - */ - private $_isSpannedCell = array(); + /** + * Excel rows that should not be written as HTML rows + * + * @var array + */ + private $_isSpannedRow = array(); - /** - * Excel cells that are upper-left corner in a cell merge - * - * @var array - */ - private $_isBaseCell = array(); + /** + * Is the current writer creating PDF? + * + * @var boolean + */ + protected $_isPdf = false; - /** - * Excel rows that should not be written as HTML rows - * - * @var array - */ - private $_isSpannedRow = array(); + /** + * Generate the Navigation block + * + * @var boolean + */ + private $_generateSheetNavigationBlock = true; - /** - * Is the current writer creating PDF? - * - * @var boolean - */ - protected $_isPdf = false; + /** + * Create a new PHPExcel_Writer_HTML + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) { + $this->_phpExcel = $phpExcel; + $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); + } - /** - * Generate the Navigation block - * - * @var boolean - */ - private $_generateSheetNavigationBlock = true; + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + // garbage collect + $this->_phpExcel->garbageCollect(); - /** - * Create a new PHPExcel_Writer_HTML - * - * @param PHPExcel $phpExcel PHPExcel object - */ - public function __construct(PHPExcel $phpExcel) { - $this->_phpExcel = $phpExcel; - $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); - } + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); - /** - * Save PHPExcel to file - * - * @param string $pFilename - * @throws PHPExcel_Writer_Exception - */ - public function save($pFilename = null) { - // garbage collect - $this->_phpExcel->garbageCollect(); + // Build CSS + $this->buildCSS(!$this->_useInlineCss); - $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); - $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); - PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + // Open file + $fileHandle = fopen($pFilename, 'wb+'); + if ($fileHandle === false) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } - // Build CSS - $this->buildCSS(!$this->_useInlineCss); + // Write headers + fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss)); - // Open file - $fileHandle = fopen($pFilename, 'wb+'); - if ($fileHandle === false) { - throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); - } + // Write navigation (tabs) + if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) { + fwrite($fileHandle, $this->generateNavigation()); + } - // Write headers - fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss)); + // Write data + fwrite($fileHandle, $this->generateSheetData()); - // Write navigation (tabs) - if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) { - fwrite($fileHandle, $this->generateNavigation()); - } + // Write footer + fwrite($fileHandle, $this->generateHTMLFooter()); - // Write data - fwrite($fileHandle, $this->generateSheetData()); + // Close file + fclose($fileHandle); - // Write footer - fwrite($fileHandle, $this->generateHTMLFooter()); + PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } - // Close file - fclose($fileHandle); + /** + * Map VAlign + * + * @param string $vAlign Vertical alignment + * @return string + */ + private function _mapVAlign($vAlign) { + switch ($vAlign) { + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM: return 'bottom'; + case PHPExcel_Style_Alignment::VERTICAL_TOP: return 'top'; + case PHPExcel_Style_Alignment::VERTICAL_CENTER: + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY: return 'middle'; + default: return 'baseline'; + } + } - PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); - } + /** + * Map HAlign + * + * @param string $hAlign Horizontal alignment + * @return string|false + */ + private function _mapHAlign($hAlign) { + switch ($hAlign) { + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL: return false; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT: return 'left'; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT: return 'right'; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER: + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS: return 'center'; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY: return 'justify'; + default: return false; + } + } - /** - * Map VAlign - * - * @param string $vAlign Vertical alignment - * @return string - */ - private function _mapVAlign($vAlign) { - switch ($vAlign) { - case PHPExcel_Style_Alignment::VERTICAL_BOTTOM: return 'bottom'; - case PHPExcel_Style_Alignment::VERTICAL_TOP: return 'top'; - case PHPExcel_Style_Alignment::VERTICAL_CENTER: - case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY: return 'middle'; - default: return 'baseline'; - } - } + /** + * Map border style + * + * @param int $borderStyle Sheet index + * @return string + */ + private function _mapBorderStyle($borderStyle) { + switch ($borderStyle) { + case PHPExcel_Style_Border::BORDER_NONE: return 'none'; + case PHPExcel_Style_Border::BORDER_DASHDOT: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; + case PHPExcel_Style_Border::BORDER_HAIR: return '1px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUM: return '2px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT: return '2px dotted'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_THICK: return '3px solid'; + case PHPExcel_Style_Border::BORDER_THIN: return '1px solid'; + default: return '1px solid'; // map others to thin + } + } - /** - * Map HAlign - * - * @param string $hAlign Horizontal alignment - * @return string|false - */ - private function _mapHAlign($hAlign) { - switch ($hAlign) { - case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL: return false; - case PHPExcel_Style_Alignment::HORIZONTAL_LEFT: return 'left'; - case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT: return 'right'; - case PHPExcel_Style_Alignment::HORIZONTAL_CENTER: - case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS: return 'center'; - case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY: return 'justify'; - default: return false; - } - } + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } - /** - * Map border style - * - * @param int $borderStyle Sheet index - * @return string - */ - private function _mapBorderStyle($borderStyle) { - switch ($borderStyle) { - case PHPExcel_Style_Border::BORDER_NONE: return 'none'; - case PHPExcel_Style_Border::BORDER_DASHDOT: return '1px dashed'; - case PHPExcel_Style_Border::BORDER_DASHDOTDOT: return '1px dotted'; - case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; - case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; - case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; - case PHPExcel_Style_Border::BORDER_HAIR: return '1px solid'; - case PHPExcel_Style_Border::BORDER_MEDIUM: return '2px solid'; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT: return '2px dashed'; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT: return '2px dotted'; - case PHPExcel_Style_Border::BORDER_MEDIUMDASHED: return '2px dashed'; - case PHPExcel_Style_Border::BORDER_SLANTDASHDOT: return '2px dashed'; - case PHPExcel_Style_Border::BORDER_THICK: return '3px solid'; - case PHPExcel_Style_Border::BORDER_THIN: return '1px solid'; - default: return '1px solid'; // map others to thin - } - } + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Writer_HTML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } - /** - * Get sheet index - * - * @return int - */ - public function getSheetIndex() { - return $this->_sheetIndex; - } + /** + * Get sheet index + * + * @return boolean + */ + public function getGenerateSheetNavigationBlock() { + return $this->_generateSheetNavigationBlock; + } - /** - * Set sheet index - * - * @param int $pValue Sheet index - * @return PHPExcel_Writer_HTML - */ - public function setSheetIndex($pValue = 0) { - $this->_sheetIndex = $pValue; - return $this; - } + /** + * Set sheet index + * + * @param boolean $pValue Flag indicating whether the sheet navigation block should be generated or not + * @return PHPExcel_Writer_HTML + */ + public function setGenerateSheetNavigationBlock($pValue = true) { + $this->_generateSheetNavigationBlock = (bool) $pValue; + return $this; + } - /** - * Get sheet index - * - * @return boolean - */ - public function getGenerateSheetNavigationBlock() { - return $this->_generateSheetNavigationBlock; - } + /** + * Write all sheets (resets sheetIndex to NULL) + */ + public function writeAllSheets() { + $this->_sheetIndex = null; + return $this; + } - /** - * Set sheet index - * - * @param boolean $pValue Flag indicating whether the sheet navigation block should be generated or not - * @return PHPExcel_Writer_HTML - */ - public function setGenerateSheetNavigationBlock($pValue = true) { - $this->_generateSheetNavigationBlock = (bool) $pValue; - return $this; - } + /** + * Generate HTML header + * + * @param boolean $pIncludeStyles Include styles? + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateHTMLHeader($pIncludeStyles = false) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } - /** - * Write all sheets (resets sheetIndex to NULL) - */ - public function writeAllSheets() { - $this->_sheetIndex = null; - return $this; - } + // Construct HTML + $properties = $this->_phpExcel->getProperties(); + $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; + if ($properties->getTitle() > '') + $html .= ' <title>' . htmlspecialchars($properties->getTitle()) . '</title>' . PHP_EOL; - /** - * Generate HTML header - * - * @param boolean $pIncludeStyles Include styles? - * @return string - * @throws PHPExcel_Writer_Exception - */ - public function generateHTMLHeader($pIncludeStyles = false) { - // PHPExcel object known? - if (is_null($this->_phpExcel)) { - throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); - } + if ($properties->getCreator() > '') + $html .= ' <meta name="author" content="' . htmlspecialchars($properties->getCreator()) . '" />' . PHP_EOL; + if ($properties->getTitle() > '') + $html .= ' <meta name="title" content="' . htmlspecialchars($properties->getTitle()) . '" />' . PHP_EOL; + if ($properties->getDescription() > '') + $html .= ' <meta name="description" content="' . htmlspecialchars($properties->getDescription()) . '" />' . PHP_EOL; + if ($properties->getSubject() > '') + $html .= ' <meta name="subject" content="' . htmlspecialchars($properties->getSubject()) . '" />' . PHP_EOL; + if ($properties->getKeywords() > '') + $html .= ' <meta name="keywords" content="' . htmlspecialchars($properties->getKeywords()) . '" />' . PHP_EOL; + if ($properties->getCategory() > '') + $html .= ' <meta name="category" content="' . htmlspecialchars($properties->getCategory()) . '" />' . PHP_EOL; + if ($properties->getCompany() > '') + $html .= ' <meta name="company" content="' . htmlspecialchars($properties->getCompany()) . '" />' . PHP_EOL; + if ($properties->getManager() > '') + $html .= ' <meta name="manager" content="' . htmlspecialchars($properties->getManager()) . '" />' . PHP_EOL; - // Construct HTML - $properties = $this->_phpExcel->getProperties(); - $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; - if ($properties->getTitle() > '') - $html .= ' <title>' . htmlspecialchars($properties->getTitle()) . '</title>' . PHP_EOL; + if ($pIncludeStyles) { + $html .= $this->generateStyles(true); + } - if ($properties->getCreator() > '') - $html .= ' <meta name="author" content="' . htmlspecialchars($properties->getCreator()) . '" />' . PHP_EOL; - if ($properties->getTitle() > '') - $html .= ' <meta name="title" content="' . htmlspecialchars($properties->getTitle()) . '" />' . PHP_EOL; - if ($properties->getDescription() > '') - $html .= ' <meta name="description" content="' . htmlspecialchars($properties->getDescription()) . '" />' . PHP_EOL; - if ($properties->getSubject() > '') - $html .= ' <meta name="subject" content="' . htmlspecialchars($properties->getSubject()) . '" />' . PHP_EOL; - if ($properties->getKeywords() > '') - $html .= ' <meta name="keywords" content="' . htmlspecialchars($properties->getKeywords()) . '" />' . PHP_EOL; - if ($properties->getCategory() > '') - $html .= ' <meta name="category" content="' . htmlspecialchars($properties->getCategory()) . '" />' . PHP_EOL; - if ($properties->getCompany() > '') - $html .= ' <meta name="company" content="' . htmlspecialchars($properties->getCompany()) . '" />' . PHP_EOL; - if ($properties->getManager() > '') - $html .= ' <meta name="manager" content="' . htmlspecialchars($properties->getManager()) . '" />' . PHP_EOL; + $html .= ' </head>' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' <body>' . PHP_EOL; - if ($pIncludeStyles) { - $html .= $this->generateStyles(true); - } + // Return + return $html; + } - $html .= ' </head>' . PHP_EOL; - $html .= '' . PHP_EOL; - $html .= ' <body>' . PHP_EOL; + /** + * Generate sheet data + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateSheetData() { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } - // Return - return $html; - } + // Ensure that Spans have been calculated? + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } - /** - * Generate sheet data - * - * @return string - * @throws PHPExcel_Writer_Exception - */ - public function generateSheetData() { - // PHPExcel object known? - if (is_null($this->_phpExcel)) { - throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); - } + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } - // Ensure that Spans have been calculated? - if (!$this->_spansAreCalculated) { - $this->_calculateSpans(); - } + // Construct HTML + $html = ''; - // Fetch sheets - $sheets = array(); - if (is_null($this->_sheetIndex)) { - $sheets = $this->_phpExcel->getAllSheets(); - } else { - $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); - } + // Loop all sheets + $sheetId = 0; + foreach ($sheets as $sheet) { + // Write table header + $html .= $this->_generateTableHeader($sheet); - // Construct HTML - $html = ''; + // Get worksheet dimension + $dimension = explode(':', $sheet->calculateWorksheetDimension()); + $dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]); + $dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1; + $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); + $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop all sheets - $sheetId = 0; - foreach ($sheets as $sheet) { - // Write table header - $html .= $this->_generateTableHeader($sheet); + // row min,max + $rowMin = $dimension[0][1]; + $rowMax = $dimension[1][1]; - // Get worksheet dimension - $dimension = explode(':', $sheet->calculateWorksheetDimension()); - $dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]); - $dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1; - $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); - $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; + // calculate start of <tbody>, <thead> + $tbodyStart = $rowMin; + $theadStart = $theadEnd = 0; // default: no <thead> no </thead> + if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); - // row min,max - $rowMin = $dimension[0][1]; - $rowMax = $dimension[1][1]; + // we can only support repeating rows that start at top row + if ($rowsToRepeatAtTop[0] == 1) { + $theadStart = $rowsToRepeatAtTop[0]; + $theadEnd = $rowsToRepeatAtTop[1]; + $tbodyStart = $rowsToRepeatAtTop[1] + 1; + } + } - // calculate start of <tbody>, <thead> - $tbodyStart = $rowMin; - $theadStart = $theadEnd = 0; // default: no <thead> no </thead> - if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { - $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); - - // we can only support repeating rows that start at top row - if ($rowsToRepeatAtTop[0] == 1) { - $theadStart = $rowsToRepeatAtTop[0]; - $theadEnd = $rowsToRepeatAtTop[1]; - $tbodyStart = $rowsToRepeatAtTop[1] + 1; - } - } - - // Loop through cells - $row = $rowMin-1; - while($row++ < $rowMax) { - // <thead> ? - if ($row == $theadStart) { - $html .= ' <thead>' . PHP_EOL; + // Loop through cells + $row = $rowMin-1; + while($row++ < $rowMax) { + // <thead> ? + if ($row == $theadStart) { + $html .= ' <thead>' . PHP_EOL; $cellType = 'th'; - } + } - // <tbody> ? - if ($row == $tbodyStart) { - $html .= ' <tbody>' . PHP_EOL; + // <tbody> ? + if ($row == $tbodyStart) { + $html .= ' <tbody>' . PHP_EOL; $cellType = 'td'; - } + } - // 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] = PHPExcel_Cell::stringFromColumnIndex($column) . $row; - } else { - $rowData[$column] = ''; - } - } - $html .= $this->_generateRow($sheet, $rowData, $row - 1, $cellType); - } + // 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] = PHPExcel_Cell::stringFromColumnIndex($column) . $row; + } else { + $rowData[$column] = ''; + } + } + $html .= $this->_generateRow($sheet, $rowData, $row - 1, $cellType); + } - // </thead> ? - if ($row == $theadEnd) { - $html .= ' </thead>' . PHP_EOL; - } - } - $html .= $this->_extendRowsForChartsAndImages($sheet, $row); + // </thead> ? + if ($row == $theadEnd) { + $html .= ' </thead>' . PHP_EOL; + } + } + $html .= $this->_extendRowsForChartsAndImages($sheet, $row); - // Close table body. - $html .= ' </tbody>' . PHP_EOL; + // Close table body. + $html .= ' </tbody>' . PHP_EOL; - // Write table footer - $html .= $this->_generateTableFooter(); + // Write table footer + $html .= $this->_generateTableFooter(); - // Writing PDF? - if ($this->_isPdf) { - if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) { - $html .= '<div style="page-break-before:always" />'; - } - } + // Writing PDF? + if ($this->_isPdf) { + if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) { + $html .= '<div style="page-break-before:always" />'; + } + } - // Next sheet - ++$sheetId; - } + // Next sheet + ++$sheetId; + } - // Return - return $html; - } + // Return + return $html; + } - /** - * Generate sheet tabs - * - * @return string - * @throws PHPExcel_Writer_Exception - */ - public function generateNavigation() - { - // PHPExcel object known? - if (is_null($this->_phpExcel)) { - throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); - } + /** + * Generate sheet tabs + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateNavigation() + { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } - // Fetch sheets - $sheets = array(); - if (is_null($this->_sheetIndex)) { - $sheets = $this->_phpExcel->getAllSheets(); - } else { - $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); - } + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } - // Construct HTML - $html = ''; + // Construct HTML + $html = ''; - // Only if there are more than 1 sheets - if (count($sheets) > 1) { - // Loop all sheets - $sheetId = 0; + // Only if there are more than 1 sheets + if (count($sheets) > 1) { + // Loop all sheets + $sheetId = 0; - $html .= '<ul class="navigation">' . PHP_EOL; + $html .= '<ul class="navigation">' . PHP_EOL; - foreach ($sheets as $sheet) { - $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL; - ++$sheetId; - } + foreach ($sheets as $sheet) { + $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL; + ++$sheetId; + } - $html .= '</ul>' . PHP_EOL; - } + $html .= '</ul>' . PHP_EOL; + } - return $html; - } + return $html; + } - private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) { - $rowMax = $row; - $colMax = 'A'; - if ($this->_includeCharts) { - foreach ($pSheet->getChartCollection() as $chart) { - if ($chart instanceof PHPExcel_Chart) { - $chartCoordinates = $chart->getTopLeftPosition(); - $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']); - $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); - if ($chartTL[1] > $rowMax) { - $rowMax = $chartTL[1]; - if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { - $colMax = $chartTL[0]; - } - } - } - } - } + private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) { + $rowMax = $row; + $colMax = 'A'; + if ($this->_includeCharts) { + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']); + $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); + if ($chartTL[1] > $rowMax) { + $rowMax = $chartTL[1]; + if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $chartTL[0]; + } + } + } + } + } - foreach ($pSheet->getDrawingCollection() as $drawing) { - if ($drawing instanceof PHPExcel_Worksheet_Drawing) { - $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates()); - $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); - if ($imageTL[1] > $rowMax) { - $rowMax = $imageTL[1]; - if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { - $colMax = $imageTL[0]; - } - } - } - } - $html = ''; - $colMax++; - while ($row < $rowMax) { - $html .= '<tr>'; - for ($col = 'A'; $col != $colMax; ++$col) { - $html .= '<td>'; - $html .= $this->_writeImageInCell($pSheet, $col.$row); - if ($this->_includeCharts) { - $html .= $this->_writeChartInCell($pSheet, $col.$row); - } - $html .= '</td>'; - } - ++$row; - $html .= '</tr>'; - } - return $html; - } + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates()); + $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); + if ($imageTL[1] > $rowMax) { + $rowMax = $imageTL[1]; + if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $imageTL[0]; + } + } + } + } + $html = ''; + $colMax++; + while ($row < $rowMax) { + $html .= '<tr>'; + for ($col = 'A'; $col != $colMax; ++$col) { + $html .= '<td>'; + $html .= $this->_writeImageInCell($pSheet, $col.$row); + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $col.$row); + } + $html .= '</td>'; + } + ++$row; + $html .= '</tr>'; + } + return $html; + } - /** - * Generate image tag in cell - * - * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet - * @param string $coordinates Cell coordinates - * @return string - * @throws PHPExcel_Writer_Exception - */ - private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) { - // Construct HTML - $html = ''; + /** + * Generate image tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; - // Write images - foreach ($pSheet->getDrawingCollection() as $drawing) { - if ($drawing instanceof PHPExcel_Worksheet_Drawing) { - if ($drawing->getCoordinates() == $coordinates) { - $filename = $drawing->getPath(); + // Write images + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + if ($drawing->getCoordinates() == $coordinates) { + $filename = $drawing->getPath(); - // Strip off eventual '.' - if (substr($filename, 0, 1) == '.') { - $filename = substr($filename, 1); - } + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.') { + $filename = substr($filename, 1); + } - // Prepend images root - $filename = $this->getImagesRoot() . $filename; + // Prepend images root + $filename = $this->getImagesRoot() . $filename; - // Strip off eventual '.' - if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') { - $filename = substr($filename, 1); - } + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') { + $filename = substr($filename, 1); + } - // Convert UTF8 data to PCDATA - $filename = htmlspecialchars($filename); + // Convert UTF8 data to PCDATA + $filename = htmlspecialchars($filename); - $html .= PHP_EOL; - if ((!$this->_embedImages) || ($this->_isPdf)) { - $imageData = $filename; - } else { - $imageDetails = getimagesize($filename); - if ($fp = fopen($filename,"rb", 0)) { - $picture = fread($fp,filesize($filename)); - fclose($fp); - // base64 encode the binary data, then break it - // into chunks according to RFC 2045 semantics - $base64 = chunk_split(base64_encode($picture)); - $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; - } else { - $imageData = $filename; - } - } + $html .= PHP_EOL; + if ((!$this->_embedImages) || ($this->_isPdf)) { + $imageData = $filename; + } else { + $imageDetails = getimagesize($filename); + if ($fp = fopen($filename,"rb", 0)) { + $picture = fread($fp,filesize($filename)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + } else { + $imageData = $filename; + } + } - $html .= '<div style="position: relative;">'; - $html .= '<img style="position: absolute; z-index: 1; left: ' . + $html .= '<div style="position: relative;">'; + $html .= '<img style="position: absolute; z-index: 1; left: ' . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . $imageData . '" border="0" />'; - $html .= '</div>'; - } - } - } - - // Return - return $html; - } - - /** - * Generate chart tag in cell - * - * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet - * @param string $coordinates Cell coordinates - * @return string - * @throws PHPExcel_Writer_Exception - */ - private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) { - // Construct HTML - $html = ''; - - // Write charts - foreach ($pSheet->getChartCollection() as $chart) { - if ($chart instanceof PHPExcel_Chart) { - $chartCoordinates = $chart->getTopLeftPosition(); - if ($chartCoordinates['cell'] == $coordinates) { - $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png'; - if (!$chart->render($chartFileName)) { - return; - } - - $html .= PHP_EOL; - $imageDetails = getimagesize($chartFileName); - if ($fp = fopen($chartFileName,"rb", 0)) { - $picture = fread($fp,filesize($chartFileName)); - fclose($fp); - // base64 encode the binary data, then break it - // into chunks according to RFC 2045 semantics - $base64 = chunk_split(base64_encode($picture)); - $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; - - $html .= '<div style="position: relative;">'; - $html .= '<img style="position: absolute; z-index: 1; left: ' . $chartCoordinates['xOffset'] . 'px; top: ' . $chartCoordinates['yOffset'] . 'px; width: ' . $imageDetails[0] . 'px; height: ' . $imageDetails[1] . 'px;" src="' . $imageData . '" border="0" />' . PHP_EOL; - $html .= '</div>'; - - unlink($chartFileName); - } - } - } - } - - // Return - return $html; - } - - /** - * Generate CSS styles - * - * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? (&lt;style&gt; and &lt;/style&gt;) - * @return string - * @throws PHPExcel_Writer_Exception - */ - public function generateStyles($generateSurroundingHTML = true) { - // PHPExcel object known? - if (is_null($this->_phpExcel)) { - throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); - } - - // Build CSS - $css = $this->buildCSS($generateSurroundingHTML); - - // Construct HTML - $html = ''; - - // Start styles - if ($generateSurroundingHTML) { - $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) . ' }' . PHP_EOL; - } - } - - // End styles - if ($generateSurroundingHTML) { - $html .= ' </style>' . PHP_EOL; - } - - // Return - return $html; - } - - /** - * Build CSS styles - * - * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { }) - * @return array - * @throws PHPExcel_Writer_Exception - */ - public function buildCSS($generateSurroundingHTML = true) { - // PHPExcel object known? - if (is_null($this->_phpExcel)) { - throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); - } - - // Cached? - if (!is_null($this->_cssStyles)) { - return $this->_cssStyles; - } - - // Ensure that spans have been calculated - if (!$this->_spansAreCalculated) { - $this->_calculateSpans(); - } - - // Construct CSS - $css = array(); - - // Start styles - if ($generateSurroundingHTML) { - // html { } - $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; - $css['html']['font-size'] = '11pt'; - $css['html']['background-color'] = 'white'; - } - - - // table { } - $css['table']['border-collapse'] = 'collapse'; - if (!$this->_isPdf) { - $css['table']['page-break-after'] = 'always'; - } - - // .gridlines td { } - $css['.gridlines td']['border'] = '1px dotted black'; - $css['.gridlines th']['border'] = '1px dotted black'; - - // .b {} - $css['.b']['text-align'] = 'center'; // BOOL - - // .e {} - $css['.e']['text-align'] = 'center'; // ERROR - - // .f {} - $css['.f']['text-align'] = 'right'; // FORMULA - - // .inlineStr {} - $css['.inlineStr']['text-align'] = 'left'; // INLINE - - // .n {} - $css['.n']['text-align'] = 'right'; // NUMERIC - - // .s {} - $css['.s']['text-align'] = 'left'; // STRING - - // Calculate cell style hashes - foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) { - $css['td.style' . $index] = $this->_createCSSStyle( $style ); - $css['th.style' . $index] = $this->_createCSSStyle( $style ); - } - - // Fetch sheets - $sheets = array(); - if (is_null($this->_sheetIndex)) { - $sheets = $this->_phpExcel->getAllSheets(); - } else { - $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); - } - - // Build styles per sheet - foreach ($sheets as $sheet) { - // Calculate hash code - $sheetIndex = $sheet->getParent()->getIndex($sheet); - - // Build styles - // Calculate column widths - $sheet->calculateColumnWidths(); - - // col elements, initialize - $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1; - $column = -1; - while($column++ < $highestColumnIndex) { - $this->_columnWidths[$sheetIndex][$column] = 42; // approximation - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt'; - } - - // col elements, loop through columnDimensions and set width - foreach ($sheet->getColumnDimensions() as $columnDimension) { - if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { - $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); - $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; - $this->_columnWidths[$sheetIndex][$column] = $width; - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; - - if ($columnDimension->getVisible() === false) { - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7 - } - } - } - - // Default row height - $rowDimension = $sheet->getDefaultRowDimension(); - - // table.sheetN tr { } - $css['table.sheet' . $sheetIndex . ' tr'] = array(); - - if ($rowDimension->getRowHeight() == -1) { - $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); - } else { - $pt_height = $rowDimension->getRowHeight(); - } - $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; - if ($rowDimension->getVisible() === false) { - $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; - $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; - } - - // Calculate row heights - foreach ($sheet->getRowDimensions() as $rowDimension) { - $row = $rowDimension->getRowIndex() - 1; - - // table.sheetN tr.rowYYYYYY { } - $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); - - if ($rowDimension->getRowHeight() == -1) { - $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); - } else { - $pt_height = $rowDimension->getRowHeight(); - } - $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; - if ($rowDimension->getVisible() === false) { - $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; - $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden'; - } - } - } - - // Cache - if (is_null($this->_cssStyles)) { - $this->_cssStyles = $css; - } - - // Return - return $css; - } - - /** - * Create CSS style - * - * @param PHPExcel_Style $pStyle PHPExcel_Style - * @return array - */ - private function _createCSSStyle(PHPExcel_Style $pStyle) { - // Construct CSS - $css = ''; - - // Create CSS - $css = array_merge( - $this->_createCSSStyleAlignment($pStyle->getAlignment()) - , $this->_createCSSStyleBorders($pStyle->getBorders()) - , $this->_createCSSStyleFont($pStyle->getFont()) - , $this->_createCSSStyleFill($pStyle->getFill()) - ); - - // Return - return $css; - } - - /** - * Create CSS style (PHPExcel_Style_Alignment) - * - * @param PHPExcel_Style_Alignment $pStyle PHPExcel_Style_Alignment - * @return array - */ - private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) { - // Construct CSS - $css = array(); - - // Create CSS - $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical()); - if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) { - $css['text-align'] = $textAlign; - if(in_array($textAlign,array('left','right'))) - $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; - } - - // Return - return $css; - } - - /** - * Create CSS style (PHPExcel_Style_Font) - * - * @param PHPExcel_Style_Font $pStyle PHPExcel_Style_Font - * @return array - */ - private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) { - // Construct CSS - $css = array(); - - // Create CSS - if ($pStyle->getBold()) { - $css['font-weight'] = 'bold'; - } - if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) { - $css['text-decoration'] = 'underline line-through'; - } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) { - $css['text-decoration'] = 'underline'; - } else if ($pStyle->getStrikethrough()) { - $css['text-decoration'] = 'line-through'; - } - if ($pStyle->getItalic()) { - $css['font-style'] = 'italic'; - } - - $css['color'] = '#' . $pStyle->getColor()->getRGB(); - $css['font-family'] = '\'' . $pStyle->getName() . '\''; - $css['font-size'] = $pStyle->getSize() . 'pt'; - - // Return - return $css; - } - - /** - * Create CSS style (PHPExcel_Style_Borders) - * - * @param PHPExcel_Style_Borders $pStyle PHPExcel_Style_Borders - * @return array - */ - private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) { - // Construct CSS - $css = array(); - - // Create CSS - $css['border-bottom'] = $this->_createCSSStyleBorder($pStyle->getBottom()); - $css['border-top'] = $this->_createCSSStyleBorder($pStyle->getTop()); - $css['border-left'] = $this->_createCSSStyleBorder($pStyle->getLeft()); - $css['border-right'] = $this->_createCSSStyleBorder($pStyle->getRight()); - - // Return - return $css; - } - - /** - * Create CSS style (PHPExcel_Style_Border) - * - * @param PHPExcel_Style_Border $pStyle PHPExcel_Style_Border - * @return string - */ - private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { - // Create CSS -// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); - // Create CSS - add !important to non-none border styles for merged cells - $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); - $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); - - // Return - return $css; - } - - /** - * Create CSS style (PHPExcel_Style_Fill) - * - * @param PHPExcel_Style_Fill $pStyle PHPExcel_Style_Fill - * @return array - */ - private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) { - // Construct HTML - $css = array(); - - // Create CSS - $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ? - 'white' : '#' . $pStyle->getStartColor()->getRGB(); - $css['background-color'] = $value; - - // Return - return $css; - } - - /** - * Generate HTML footer - */ - public function generateHTMLFooter() { - // Construct HTML - $html = ''; - $html .= ' </body>' . PHP_EOL; - $html .= '</html>' . PHP_EOL; - - // Return - return $html; - } - - /** - * Generate table header - * - * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing - * @return string - * @throws PHPExcel_Writer_Exception - */ - private function _generateTableHeader($pSheet) { - $sheetIndex = $pSheet->getParent()->getIndex($pSheet); - - // Construct HTML - $html = ''; - $html .= $this->_setMargins($pSheet); - - if (!$this->_useInlineCss) { - $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : ''; - $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="1" id="sheet' . $sheetIndex . '" cellspacing="1" style="' . $style . '">' . PHP_EOL; - } else { - $html .= ' <table border="0" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL; - } - } - - // Write <col> elements - $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1; - $i = -1; - while($i++ < $highestColumnIndex) { - if (!$this->_isPdf) { - if (!$this->_useInlineCss) { - $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 . '">' . PHP_EOL; - } - } - } - - // Return - return $html; - } - - /** - * Generate table footer - * - * @throws PHPExcel_Writer_Exception - */ - private function _generateTableFooter() { - // Construct HTML - $html = ''; - $html .= ' </table>' . PHP_EOL; - - // Return - return $html; - } - - /** - * Generate row - * - * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet - * @param array $pValues Array containing cells in a row - * @param int $pRow Row number (0-based) - * @return string - * @throws PHPExcel_Writer_Exception - */ - private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0, $cellType = 'td') { - if (is_array($pValues)) { - // Construct HTML - $html = ''; - - // Sheet index - $sheetIndex = $pSheet->getParent()->getIndex($pSheet); - - // DomPDF and breaks - if ($this->_isPdf && count($pSheet->getBreaks()) > 0) { - $breaks = $pSheet->getBreaks(); - - // check if a break is needed before this row - if (isset($breaks['A' . $pRow])) { - // close table: </table> - $html .= $this->_generateTableFooter(); - - // insert page break - $html .= '<div style="page-break-before:always" />'; - - // open table again: <table> + <col> etc. - $html .= $this->_generateTableHeader($pSheet); - } - } - - // Write row start - if (!$this->_useInlineCss) { - $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 . '">' . PHP_EOL; - } - - // Write cells - $colNum = 0; - foreach ($pValues as $cellAddress) { + $html .= '</div>'; + } + } + } + + // Return + return $html; + } + + /** + * Generate chart tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write charts + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + if ($chartCoordinates['cell'] == $coordinates) { + $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png'; + if (!$chart->render($chartFileName)) { + return; + } + + $html .= PHP_EOL; + $imageDetails = getimagesize($chartFileName); + if ($fp = fopen($chartFileName,"rb", 0)) { + $picture = fread($fp,filesize($chartFileName)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + + $html .= '<div style="position: relative;">'; + $html .= '<img style="position: absolute; z-index: 1; left: ' . $chartCoordinates['xOffset'] . 'px; top: ' . $chartCoordinates['yOffset'] . 'px; width: ' . $imageDetails[0] . 'px; height: ' . $imageDetails[1] . 'px;" src="' . $imageData . '" border="0" />' . PHP_EOL; + $html .= '</div>'; + + unlink($chartFileName); + } + } + } + } + + // Return + return $html; + } + + /** + * Generate CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? (&lt;style&gt; and &lt;/style&gt;) + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateStyles($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Build CSS + $css = $this->buildCSS($generateSurroundingHTML); + + // Construct HTML + $html = ''; + + // Start styles + if ($generateSurroundingHTML) { + $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) . ' }' . PHP_EOL; + } + } + + // End styles + if ($generateSurroundingHTML) { + $html .= ' </style>' . PHP_EOL; + } + + // Return + return $html; + } + + /** + * Build CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { }) + * @return array + * @throws PHPExcel_Writer_Exception + */ + public function buildCSS($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Cached? + if (!is_null($this->_cssStyles)) { + return $this->_cssStyles; + } + + // Ensure that spans have been calculated + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + + // Construct CSS + $css = array(); + + // Start styles + if ($generateSurroundingHTML) { + // html { } + $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; + $css['html']['font-size'] = '11pt'; + $css['html']['background-color'] = 'white'; + } + + + // table { } + $css['table']['border-collapse'] = 'collapse'; + if (!$this->_isPdf) { + $css['table']['page-break-after'] = 'always'; + } + + // .gridlines td { } + $css['.gridlines td']['border'] = '1px dotted black'; + $css['.gridlines th']['border'] = '1px dotted black'; + + // .b {} + $css['.b']['text-align'] = 'center'; // BOOL + + // .e {} + $css['.e']['text-align'] = 'center'; // ERROR + + // .f {} + $css['.f']['text-align'] = 'right'; // FORMULA + + // .inlineStr {} + $css['.inlineStr']['text-align'] = 'left'; // INLINE + + // .n {} + $css['.n']['text-align'] = 'right'; // NUMERIC + + // .s {} + $css['.s']['text-align'] = 'left'; // STRING + + // Calculate cell style hashes + foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) { + $css['td.style' . $index] = $this->_createCSSStyle( $style ); + $css['th.style' . $index] = $this->_createCSSStyle( $style ); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Build styles per sheet + foreach ($sheets as $sheet) { + // Calculate hash code + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + // Build styles + // Calculate column widths + $sheet->calculateColumnWidths(); + + // col elements, initialize + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1; + $column = -1; + while($column++ < $highestColumnIndex) { + $this->_columnWidths[$sheetIndex][$column] = 42; // approximation + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt'; + } + + // col elements, loop through columnDimensions and set width + foreach ($sheet->getColumnDimensions() as $columnDimension) { + if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { + $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); + $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; + $this->_columnWidths[$sheetIndex][$column] = $width; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; + + if ($columnDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7 + } + } + } + + // Default row height + $rowDimension = $sheet->getDefaultRowDimension(); + + // table.sheetN tr { } + $css['table.sheet' . $sheetIndex . ' tr'] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; + } + + // Calculate row heights + foreach ($sheet->getRowDimensions() as $rowDimension) { + $row = $rowDimension->getRowIndex() - 1; + + // table.sheetN tr.rowYYYYYY { } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden'; + } + } + } + + // Cache + if (is_null($this->_cssStyles)) { + $this->_cssStyles = $css; + } + + // Return + return $css; + } + + /** + * Create CSS style + * + * @param PHPExcel_Style $pStyle PHPExcel_Style + * @return array + */ + private function _createCSSStyle(PHPExcel_Style $pStyle) { + // Construct CSS + $css = ''; + + // Create CSS + $css = array_merge( + $this->_createCSSStyleAlignment($pStyle->getAlignment()) + , $this->_createCSSStyleBorders($pStyle->getBorders()) + , $this->_createCSSStyleFont($pStyle->getFont()) + , $this->_createCSSStyleFill($pStyle->getFill()) + ); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Alignment) + * + * @param PHPExcel_Style_Alignment $pStyle PHPExcel_Style_Alignment + * @return array + */ + private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical()); + if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) { + $css['text-align'] = $textAlign; + if(in_array($textAlign,array('left','right'))) + $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; + } + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Font) + * + * @param PHPExcel_Style_Font $pStyle PHPExcel_Style_Font + * @return array + */ + private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + if ($pStyle->getBold()) { + $css['font-weight'] = 'bold'; + } + if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) { + $css['text-decoration'] = 'underline line-through'; + } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) { + $css['text-decoration'] = 'underline'; + } else if ($pStyle->getStrikethrough()) { + $css['text-decoration'] = 'line-through'; + } + if ($pStyle->getItalic()) { + $css['font-style'] = 'italic'; + } + + $css['color'] = '#' . $pStyle->getColor()->getRGB(); + $css['font-family'] = '\'' . $pStyle->getName() . '\''; + $css['font-size'] = $pStyle->getSize() . 'pt'; + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Borders) + * + * @param PHPExcel_Style_Borders $pStyle PHPExcel_Style_Borders + * @return array + */ + private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['border-bottom'] = $this->_createCSSStyleBorder($pStyle->getBottom()); + $css['border-top'] = $this->_createCSSStyleBorder($pStyle->getTop()); + $css['border-left'] = $this->_createCSSStyleBorder($pStyle->getLeft()); + $css['border-right'] = $this->_createCSSStyleBorder($pStyle->getRight()); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Border) + * + * @param PHPExcel_Style_Border $pStyle PHPExcel_Style_Border + * @return string + */ + private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { + // Create CSS +// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); + // Create CSS - add !important to non-none border styles for merged cells + $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); + $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Fill) + * + * @param PHPExcel_Style_Fill $pStyle PHPExcel_Style_Fill + * @return array + */ + private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) { + // Construct HTML + $css = array(); + + // Create CSS + $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ? + 'white' : '#' . $pStyle->getStartColor()->getRGB(); + $css['background-color'] = $value; + + // Return + return $css; + } + + /** + * Generate HTML footer + */ + public function generateHTMLFooter() { + // Construct HTML + $html = ''; + $html .= ' </body>' . PHP_EOL; + $html .= '</html>' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate table header + * + * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableHeader($pSheet) { + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // Construct HTML + $html = ''; + $html .= $this->_setMargins($pSheet); + + if (!$this->_useInlineCss) { + $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : ''; + $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="1" id="sheet' . $sheetIndex . '" cellspacing="1" style="' . $style . '">' . PHP_EOL; + } else { + $html .= ' <table border="0" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL; + } + } + + // Write <col> elements + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1; + $i = -1; + while($i++ < $highestColumnIndex) { + if (!$this->_isPdf) { + if (!$this->_useInlineCss) { + $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 . '">' . PHP_EOL; + } + } + } + + // Return + return $html; + } + + /** + * Generate table footer + * + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableFooter() { + // Construct HTML + $html = ''; + $html .= ' </table>' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate row + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param array $pValues Array containing cells in a row + * @param int $pRow Row number (0-based) + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0, $cellType = 'td') { + if (is_array($pValues)) { + // Construct HTML + $html = ''; + + // Sheet index + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // DomPDF and breaks + if ($this->_isPdf && count($pSheet->getBreaks()) > 0) { + $breaks = $pSheet->getBreaks(); + + // check if a break is needed before this row + if (isset($breaks['A' . $pRow])) { + // close table: </table> + $html .= $this->_generateTableFooter(); + + // insert page break + $html .= '<div style="page-break-before:always" />'; + + // open table again: <table> + <col> etc. + $html .= $this->_generateTableHeader($pSheet); + } + } + + // Write row start + if (!$this->_useInlineCss) { + $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 . '">' . PHP_EOL; + } + + // Write cells + $colNum = 0; + foreach ($pValues as $cellAddress) { $cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : ''; - $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1); - if (!$this->_useInlineCss) { - $cssClass = ''; - $cssClass = 'column' . $colNum; - } else { - $cssClass = array(); + $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1); + if (!$this->_useInlineCss) { + $cssClass = ''; + $cssClass = 'column' . $colNum; + } else { + $cssClass = array(); if ($cellType == 'th') { if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) { $this->_cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum]; @@ -1135,83 +1128,83 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ $this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum]; } } - } - $colSpan = 1; - $rowSpan = 1; + } + $colSpan = 1; + $rowSpan = 1; - // initialize - $cellData = '&nbsp;'; + // initialize + $cellData = '&nbsp;'; - // PHPExcel_Cell - if ($cell instanceof PHPExcel_Cell) { - $cellData = ''; - if (is_null($cell->getParent())) { - $cell->attach($pSheet); - } - // Value - if ($cell->getValue() instanceof PHPExcel_RichText) { - // Loop through rich text elements - $elements = $cell->getValue()->getRichTextElements(); - foreach ($elements as $element) { - // Rich text start? - if ($element instanceof PHPExcel_RichText_Run) { - $cellData .= '<span style="' . $this->_assembleCSS($this->_createCSSStyleFont($element->getFont())) . '">'; + // PHPExcel_Cell + if ($cell instanceof PHPExcel_Cell) { + $cellData = ''; + if (is_null($cell->getParent())) { + $cell->attach($pSheet); + } + // Value + if ($cell->getValue() instanceof PHPExcel_RichText) { + // Loop through rich text elements + $elements = $cell->getValue()->getRichTextElements(); + foreach ($elements as $element) { + // Rich text start? + if ($element instanceof PHPExcel_RichText_Run) { + $cellData .= '<span style="' . $this->_assembleCSS($this->_createCSSStyleFont($element->getFont())) . '">'; - if ($element->getFont()->getSuperScript()) { - $cellData .= '<sup>'; - } else if ($element->getFont()->getSubScript()) { - $cellData .= '<sub>'; - } - } + if ($element->getFont()->getSuperScript()) { + $cellData .= '<sup>'; + } else if ($element->getFont()->getSubScript()) { + $cellData .= '<sub>'; + } + } - // Convert UTF8 data to PCDATA - $cellText = $element->getText(); - $cellData .= htmlspecialchars($cellText); + // Convert UTF8 data to PCDATA + $cellText = $element->getText(); + $cellData .= htmlspecialchars($cellText); - if ($element instanceof PHPExcel_RichText_Run) { - if ($element->getFont()->getSuperScript()) { - $cellData .= '</sup>'; - } else if ($element->getFont()->getSubScript()) { - $cellData .= '</sub>'; - } + if ($element instanceof PHPExcel_RichText_Run) { + if ($element->getFont()->getSuperScript()) { + $cellData .= '</sup>'; + } else if ($element->getFont()->getSubScript()) { + $cellData .= '</sub>'; + } - $cellData .= '</span>'; - } - } - } else { - if ($this->_preCalculateFormulas) { - $cellData = PHPExcel_Style_NumberFormat::toFormattedString( - $cell->getCalculatedValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), - array($this, 'formatColor') - ); - } else { - $cellData = PHPExcel_Style_NumberFormat::toFormattedString( - $cell->getValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), - array($this, 'formatColor') - ); - } - $cellData = htmlspecialchars($cellData); - if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) { - $cellData = '<sup>'.$cellData.'</sup>'; - } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) { - $cellData = '<sub>'.$cellData.'</sub>'; - } - } + $cellData .= '</span>'; + } + } + } else { + if ($this->_preCalculateFormulas) { + $cellData = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } else { + $cellData = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } + $cellData = htmlspecialchars($cellData); + if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) { + $cellData = '<sup>'.$cellData.'</sup>'; + } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) { + $cellData = '<sub>'.$cellData.'</sub>'; + } + } - // Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp; - // Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world" - $cellData = preg_replace("/(?m)(?:^|\\G) /", '&nbsp;', $cellData); + // Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp; + // Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world" + $cellData = preg_replace("/(?m)(?:^|\\G) /", '&nbsp;', $cellData); - // convert newline "\n" to '<br>' - $cellData = nl2br($cellData); + // convert newline "\n" to '<br>' + $cellData = nl2br($cellData); - // Extend CSS class? - if (!$this->_useInlineCss) { - $cssClass .= ' style' . $cell->getXfIndex(); - $cssClass .= ' ' . $cell->getDataType(); - } else { + // Extend CSS class? + if (!$this->_useInlineCss) { + $cssClass .= ' style' . $cell->getXfIndex(); + $cssClass .= ' ' . $cell->getDataType(); + } else { if ($cellType == 'th') { if (isset($this->_cssStyles['th.style' . $cell->getXfIndex()])) { $cssClass = array_merge($cssClass, $this->_cssStyles['th.style' . $cell->getXfIndex()]); @@ -1222,327 +1215,327 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ } } - // General horizontal alignment: Actual horizontal alignment depends on dataType - $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() ); - if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL - && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align'])) - { - $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align']; - } - } - } + // General horizontal alignment: Actual horizontal alignment depends on dataType + $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() ); + if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL + && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align'])) + { + $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align']; + } + } + } - // Hyperlink? - if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) { - $cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>'; - } + // Hyperlink? + if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) { + $cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>'; + } - // Should the cell be written or is it swallowed by a rowspan or colspan? - $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) - && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); + // Should the cell be written or is it swallowed by a rowspan or colspan? + $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) + && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); - // Colspan and Rowspan - $colspan = 1; - $rowspan = 1; - if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { - $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; - $rowSpan = $spans['rowspan']; - $colSpan = $spans['colspan']; + // Colspan and Rowspan + $colspan = 1; + $rowspan = 1; + if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { + $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; + $rowSpan = $spans['rowspan']; + $colSpan = $spans['colspan']; - // Also apply style from last cell in merge to fix borders - - // relies on !important for non-none border declarations in _createCSSStyleBorder - $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); - if (!$this->_useInlineCss) { - $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); - } - } + // Also apply style from last cell in merge to fix borders - + // relies on !important for non-none border declarations in _createCSSStyleBorder + $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); + if (!$this->_useInlineCss) { + $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); + } + } - // Write - if ($writeCell) { - // Column start - $html .= ' <' . $cellType; - if (!$this->_useInlineCss) { - $html .= ' class="' . $cssClass . '"'; - } else { - //** Necessary redundant code for the sake of PHPExcel_Writer_PDF ** - // We must explicitly write the width of the <td> element because TCPDF - // does not recognize e.g. <col style="width:42pt"> - $width = 0; - $i = $colNum - 1; - $e = $colNum + $colSpan - 1; - while($i++ < $e) { - if (isset($this->_columnWidths[$sheetIndex][$i])) { - $width += $this->_columnWidths[$sheetIndex][$i]; - } - } - $cssClass['width'] = $width . 'pt'; + // Write + if ($writeCell) { + // Column start + $html .= ' <' . $cellType; + if (!$this->_useInlineCss) { + $html .= ' class="' . $cssClass . '"'; + } else { + //** Necessary redundant code for the sake of PHPExcel_Writer_PDF ** + // We must explicitly write the width of the <td> element because TCPDF + // does not recognize e.g. <col style="width:42pt"> + $width = 0; + $i = $colNum - 1; + $e = $colNum + $colSpan - 1; + while($i++ < $e) { + if (isset($this->_columnWidths[$sheetIndex][$i])) { + $width += $this->_columnWidths[$sheetIndex][$i]; + } + } + $cssClass['width'] = $width . 'pt'; - // We must also explicitly write the height of the <td> element because TCPDF - // does not recognize e.g. <tr style="height:50pt"> - if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) { - $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height']; - $cssClass['height'] = $height; - } - //** end of redundant code ** + // We must also explicitly write the height of the <td> element because TCPDF + // does not recognize e.g. <tr style="height:50pt"> + if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) { + $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height']; + $cssClass['height'] = $height; + } + //** end of redundant code ** - $html .= ' style="' . $this->_assembleCSS($cssClass) . '"'; - } - if ($colSpan > 1) { - $html .= ' colspan="' . $colSpan . '"'; - } - if ($rowSpan > 1) { - $html .= ' rowspan="' . $rowSpan . '"'; - } - $html .= '>'; + $html .= ' style="' . $this->_assembleCSS($cssClass) . '"'; + } + if ($colSpan > 1) { + $html .= ' colspan="' . $colSpan . '"'; + } + if ($rowSpan > 1) { + $html .= ' rowspan="' . $rowSpan . '"'; + } + $html .= '>'; - // Image? - $html .= $this->_writeImageInCell($pSheet, $coordinate); + // Image? + $html .= $this->_writeImageInCell($pSheet, $coordinate); - // Chart? - if ($this->_includeCharts) { - $html .= $this->_writeChartInCell($pSheet, $coordinate); - } + // Chart? + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $coordinate); + } - // Cell data - $html .= $cellData; + // Cell data + $html .= $cellData; - // Column end - $html .= '</'.$cellType.'>' . PHP_EOL; - } + // Column end + $html .= '</'.$cellType.'>' . PHP_EOL; + } - // Next column - ++$colNum; - } + // Next column + ++$colNum; + } - // Write row end - $html .= ' </tr>' . PHP_EOL; + // Write row end + $html .= ' </tr>' . PHP_EOL; - // Return - return $html; - } else { - throw new PHPExcel_Writer_Exception("Invalid parameters passed."); - } - } + // Return + return $html; + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } - /** - * Takes array where of CSS properties / values and converts to CSS string - * - * @param array - * @return string - */ - private function _assembleCSS($pValue = array()) - { - $pairs = array(); - foreach ($pValue as $property => $value) { - $pairs[] = $property . ':' . $value; - } - $string = implode('; ', $pairs); + /** + * Takes array where of CSS properties / values and converts to CSS string + * + * @param array + * @return string + */ + private function _assembleCSS($pValue = array()) + { + $pairs = array(); + foreach ($pValue as $property => $value) { + $pairs[] = $property . ':' . $value; + } + $string = implode('; ', $pairs); - return $string; - } + return $string; + } - /** - * Get images root - * - * @return string - */ - public function getImagesRoot() { - return $this->_imagesRoot; - } + /** + * Get images root + * + * @return string + */ + public function getImagesRoot() { + return $this->_imagesRoot; + } - /** - * Set images root - * - * @param string $pValue - * @return PHPExcel_Writer_HTML - */ - public function setImagesRoot($pValue = '.') { - $this->_imagesRoot = $pValue; - return $this; - } + /** + * Set images root + * + * @param string $pValue + * @return PHPExcel_Writer_HTML + */ + public function setImagesRoot($pValue = '.') { + $this->_imagesRoot = $pValue; + return $this; + } - /** - * Get embed images - * - * @return boolean - */ - public function getEmbedImages() { - return $this->_embedImages; - } + /** + * Get embed images + * + * @return boolean + */ + public function getEmbedImages() { + return $this->_embedImages; + } - /** - * Set embed images - * - * @param boolean $pValue - * @return PHPExcel_Writer_HTML - */ - public function setEmbedImages($pValue = '.') { - $this->_embedImages = $pValue; - return $this; - } + /** + * Set embed images + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setEmbedImages($pValue = '.') { + $this->_embedImages = $pValue; + return $this; + } - /** - * Get use inline CSS? - * - * @return boolean - */ - public function getUseInlineCss() { - return $this->_useInlineCss; - } + /** + * Get use inline CSS? + * + * @return boolean + */ + public function getUseInlineCss() { + return $this->_useInlineCss; + } - /** - * Set use inline CSS? - * - * @param boolean $pValue - * @return PHPExcel_Writer_HTML - */ - public function setUseInlineCss($pValue = false) { - $this->_useInlineCss = $pValue; - return $this; - } + /** + * Set use inline CSS? + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setUseInlineCss($pValue = false) { + $this->_useInlineCss = $pValue; + return $this; + } - /** - * Add color to formatted string as inline style - * - * @param string $pValue Plain formatted value without color - * @param string $pFormat Format code - * @return string - */ - public function formatColor($pValue, $pFormat) - { - // Color information, e.g. [Red] is always at the beginning - $color = null; // initialize - $matches = array(); + /** + * Add color to formatted string as inline style + * + * @param string $pValue Plain formatted value without color + * @param string $pFormat Format code + * @return string + */ + public function formatColor($pValue, $pFormat) + { + // Color information, e.g. [Red] is always at the beginning + $color = null; // initialize + $matches = array(); - $color_regex = '/^\\[[a-zA-Z]+\\]/'; - if (preg_match($color_regex, $pFormat, $matches)) { - $color = str_replace('[', '', $matches[0]); - $color = str_replace(']', '', $color); - $color = strtolower($color); - } + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + if (preg_match($color_regex, $pFormat, $matches)) { + $color = str_replace('[', '', $matches[0]); + $color = str_replace(']', '', $color); + $color = strtolower($color); + } - // convert to PCDATA - $value = htmlspecialchars($pValue); + // convert to PCDATA + $value = htmlspecialchars($pValue); - // color span tag - if ($color !== null) { - $value = '<span style="color:' . $color . '">' . $value . '</span>'; - } + // color span tag + if ($color !== null) { + $value = '<span style="color:' . $color . '">' . $value . '</span>'; + } - return $value; - } + return $value; + } - /** - * Calculate information about HTML colspan and rowspan which is not always the same as Excel's - */ - private function _calculateSpans() - { - // Identify all cells that should be omitted in HTML due to cell merge. - // In HTML only the upper-left cell should be written and it should have - // appropriate rowspan / colspan attribute - $sheetIndexes = $this->_sheetIndex !== null ? - array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); + /** + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's + */ + private function _calculateSpans() + { + // Identify all cells that should be omitted in HTML due to cell merge. + // In HTML only the upper-left cell should be written and it should have + // appropriate rowspan / colspan attribute + $sheetIndexes = $this->_sheetIndex !== null ? + array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); - foreach ($sheetIndexes as $sheetIndex) { - $sheet = $this->_phpExcel->getSheet($sheetIndex); + foreach ($sheetIndexes as $sheetIndex) { + $sheet = $this->_phpExcel->getSheet($sheetIndex); - $candidateSpannedRow = array(); + $candidateSpannedRow = array(); - // loop through all Excel merged cells - foreach ($sheet->getMergeCells() as $cells) { - list($cells, ) = PHPExcel_Cell::splitRange($cells); - $first = $cells[0]; - $last = $cells[1]; + // loop through all Excel merged cells + foreach ($sheet->getMergeCells() as $cells) { + list($cells, ) = PHPExcel_Cell::splitRange($cells); + $first = $cells[0]; + $last = $cells[1]; - list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); - $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; + list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); + $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; - list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); - $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; + list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); + $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; - // loop through the individual cells in the individual merge - $r = $fr - 1; - while($r++ < $lr) { - // also, flag this row as a HTML row that is candidate to be omitted - $candidateSpannedRow[$r] = $r; + // loop through the individual cells in the individual merge + $r = $fr - 1; + while($r++ < $lr) { + // also, flag this row as a HTML row that is candidate to be omitted + $candidateSpannedRow[$r] = $r; - $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( - 'baseCell' => array($fr, $fc), - ); - } else { - // upper-left is the base cell that should hold the colspan/rowspan attribute - $this->_isBaseCell[$sheetIndex][$r][$c] = array( - 'xlrowspan' => $lr - $fr + 1, // Excel rowspan - 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change - 'xlcolspan' => $lc - $fc + 1, // Excel colspan - 'colspan' => $lc - $fc + 1, // HTML colspan, value may change - ); - } - } - } - } + $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( + 'baseCell' => array($fr, $fc), + ); + } else { + // upper-left is the base cell that should hold the colspan/rowspan attribute + $this->_isBaseCell[$sheetIndex][$r][$c] = array( + 'xlrowspan' => $lr - $fr + 1, // Excel rowspan + 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change + 'xlcolspan' => $lc - $fc + 1, // Excel colspan + 'colspan' => $lc - $fc + 1, // HTML colspan, value may change + ); + } + } + } + } - // Identify which rows should be omitted in HTML. These are the rows where all the cells - // participate in a merge and the where base cells are somewhere above. - $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); - foreach ($candidateSpannedRow as $rowIndex) { - if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { - if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { - $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; - }; - } - } + // Identify which rows should be omitted in HTML. These are the rows where all the cells + // participate in a merge and the where base cells are somewhere above. + $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); + foreach ($candidateSpannedRow as $rowIndex) { + if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { + if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { + $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; + }; + } + } - // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 - if ( isset($this->_isSpannedRow[$sheetIndex]) ) { - foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { - $adjustedBaseCells = array(); - $c = -1; - $e = $countColumns - 1; - while($c++ < $e) { - $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; + // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 + if ( isset($this->_isSpannedRow[$sheetIndex]) ) { + foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { + $adjustedBaseCells = array(); + $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; - } - } - } - } + if ( !in_array($baseCell, $adjustedBaseCells) ) { + // subtract rowspan by 1 + --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; + $adjustedBaseCells[] = $baseCell; + } + } + } + } - // TODO: Same for columns - } + // TODO: Same for columns + } - // We have calculated the spans - $this->_spansAreCalculated = true; - } + // We have calculated the spans + $this->_spansAreCalculated = true; + } - private function _setMargins(PHPExcel_Worksheet $pSheet) { - $htmlPage = '@page { '; - $htmlBody = 'body { '; + private function _setMargins(PHPExcel_Worksheet $pSheet) { + $htmlPage = '@page { '; + $htmlBody = 'body { '; - $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; - $htmlPage .= 'left-margin: ' . $left; - $htmlBody .= 'left-margin: ' . $left; - $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; - $htmlPage .= 'right-margin: ' . $right; - $htmlBody .= 'right-margin: ' . $right; - $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; - $htmlPage .= 'top-margin: ' . $top; - $htmlBody .= 'top-margin: ' . $top; - $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; - $htmlPage .= 'bottom-margin: ' . $bottom; - $htmlBody .= 'bottom-margin: ' . $bottom; + $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; + $htmlPage .= 'left-margin: ' . $left; + $htmlBody .= 'left-margin: ' . $left; + $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; + $htmlPage .= 'right-margin: ' . $right; + $htmlBody .= 'right-margin: ' . $right; + $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; + $htmlPage .= 'top-margin: ' . $top; + $htmlBody .= 'top-margin: ' . $top; + $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; + $htmlPage .= 'bottom-margin: ' . $bottom; + $htmlBody .= 'bottom-margin: ' . $bottom; - $htmlPage .= "}\n"; - $htmlBody .= "}\n"; + $htmlPage .= "}\n"; + $htmlBody .= "}\n"; - return "<style>\n" . $htmlPage . $htmlBody . "</style>\n"; - } - + return "<style>\n" . $htmlPage . $htmlBody . "</style>\n"; + } + } diff --git a/Classes/PHPExcel/Writer/IWriter.php b/Classes/PHPExcel/Writer/IWriter.php index 31624e50..fd993db6 100644 --- a/Classes/PHPExcel/Writer/IWriter.php +++ b/Classes/PHPExcel/Writer/IWriter.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_IWriter * * Copyright (c) 2006 - 2015 PHPExcel * @@ -24,15 +25,6 @@ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_IWriter - * - * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ interface PHPExcel_Writer_IWriter { /** @@ -41,6 +33,6 @@ interface PHPExcel_Writer_IWriter * @param string $pFilename Name of the file to save * @throws PHPExcel_Writer_Exception */ - public function save($pFilename = NULL); + public function save($pFilename = null); } diff --git a/Classes/PHPExcel/Writer/OpenDocument.php b/Classes/PHPExcel/Writer/OpenDocument.php index ef967e09..912ba9df 100644 --- a/Classes/PHPExcel/Writer/OpenDocument.php +++ b/Classes/PHPExcel/Writer/OpenDocument.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,20 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - * @link http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os.html - */ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { /** @@ -42,14 +32,14 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P * * @var PHPExcel_Writer_OpenDocument_WriterPart[] */ - private $_writerParts = array(); + private $writerParts = array(); /** * Private PHPExcel * * @var PHPExcel */ - private $_spreadSheet; + private $spreadSheet; /** * Create a new PHPExcel_Writer_OpenDocument @@ -71,7 +61,7 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P ); foreach ($writerPartsArray as $writer => $class) { - $this->_writerParts[$writer] = new $class($this); + $this->writerParts[$writer] = new $class($this); } } @@ -83,8 +73,8 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P */ public function getWriterPart($pPartName = '') { - if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { - return $this->_writerParts[strtolower($pPartName)]; + if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) { + return $this->writerParts[strtolower($pPartName)]; } else { return null; } @@ -96,14 +86,14 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P * @param string $pFilename * @throws PHPExcel_Writer_Exception */ - public function save($pFilename = NULL) + public function save($pFilename = null) { - if (!$this->_spreadSheet) { + if (!$this->spreadSheet) { throw new PHPExcel_Writer_Exception('PHPExcel object unassigned.'); } // garbage collect - $this->_spreadSheet->garbageCollect(); + $this->spreadSheet->garbageCollect(); // If $pFilename is php://output or php://stdout, make it a temporary file... $originalFilename = $pFilename; @@ -114,15 +104,15 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P } } - $objZip = $this->_createZip($pFilename); + $objZip = $this->createZip($pFilename); $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest()); $objZip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail()); - $objZip->addFromString('content.xml', $this->getWriterPart('content')->write()); - $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write()); - $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write()); + $objZip->addFromString('content.xml', $this->getWriterPart('content')->write()); + $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write()); + $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write()); $objZip->addFromString('settings.xml', $this->getWriterPart('settings')->write()); - $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write()); + $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write()); // Close file if ($objZip->close() === false) { @@ -145,7 +135,7 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P * @throws PHPExcel_Writer_Exception * @return ZipArchive */ - private function _createZip($pFilename) + private function createZip($pFilename) { // Create new ZIP file and open it for writing $zipClass = PHPExcel_Settings::getZipClass(); @@ -178,8 +168,8 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P */ public function getPHPExcel() { - if ($this->_spreadSheet !== null) { - return $this->_spreadSheet; + if ($this->spreadSheet !== null) { + return $this->spreadSheet; } else { throw new PHPExcel_Writer_Exception('No PHPExcel assigned.'); } @@ -194,7 +184,7 @@ class PHPExcel_Writer_OpenDocument extends PHPExcel_Writer_Abstract implements P */ public function setPHPExcel(PHPExcel $pPHPExcel = null) { - $this->_spreadSheet = $pPHPExcel; + $this->spreadSheet = $pPHPExcel; return $this; } } diff --git a/Classes/PHPExcel/Writer/OpenDocument/Meta.php b/Classes/PHPExcel/Writer/OpenDocument/Meta.php index b1542105..1a5c5fd0 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/Meta.php +++ b/Classes/PHPExcel/Writer/OpenDocument/Meta.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_Meta * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_Meta - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_Meta extends PHPExcel_Writer_OpenDocument_WriterPart { /** @@ -61,36 +52,42 @@ class PHPExcel_Writer_OpenDocument_Meta extends PHPExcel_Writer_OpenDocument_Wri // Meta $objWriter->startElement('office:document-meta'); - $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); - $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); - $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); - $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); - $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); - $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); - $objWriter->writeAttribute('office:version', '1.2'); - $objWriter->startElement('office:meta'); - $objWriter->writeElement('meta:initial-creator', $pPHPExcel->getProperties()->getCreator()); - $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); - $objWriter->writeElement('meta:creation-date', date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); - $objWriter->writeElement('dc:date', date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); - $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); - $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); - $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); - $keywords = explode(' ', $pPHPExcel->getProperties()->getKeywords()); - foreach ($keywords as $keyword) { - $objWriter->writeElement('meta:keyword', $keyword); - } - //<meta:document-statistic meta:table-count="XXX" meta:cell-count="XXX" meta:object-count="XXX"/> - $objWriter->startElement('meta:user-defined'); - $objWriter->writeAttribute('meta:name', 'Company'); - $objWriter->writeRaw($pPHPExcel->getProperties()->getCompany()); - $objWriter->endElement(); - $objWriter->startElement('meta:user-defined'); - $objWriter->writeAttribute('meta:name', 'category'); - $objWriter->writeRaw($pPHPExcel->getProperties()->getCategory()); - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); + $objWriter->writeAttribute('office:version', '1.2'); + + $objWriter->startElement('office:meta'); + + $objWriter->writeElement('meta:initial-creator', $pPHPExcel->getProperties()->getCreator()); + $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); + $objWriter->writeElement('meta:creation-date', date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); + $objWriter->writeElement('dc:date', date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); + $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); + $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); + $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); + $keywords = explode(' ', $pPHPExcel->getProperties()->getKeywords()); + foreach ($keywords as $keyword) { + $objWriter->writeElement('meta:keyword', $keyword); + } + + //<meta:document-statistic meta:table-count="XXX" meta:cell-count="XXX" meta:object-count="XXX"/> + $objWriter->startElement('meta:user-defined'); + $objWriter->writeAttribute('meta:name', 'Company'); + $objWriter->writeRaw($pPHPExcel->getProperties()->getCompany()); + $objWriter->endElement(); + + $objWriter->startElement('meta:user-defined'); + $objWriter->writeAttribute('meta:name', 'category'); + $objWriter->writeRaw($pPHPExcel->getProperties()->getCategory()); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); return $objWriter->getData(); diff --git a/Classes/PHPExcel/Writer/OpenDocument/MetaInf.php b/Classes/PHPExcel/Writer/OpenDocument/MetaInf.php index f4c03cf9..c43b7233 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/MetaInf.php +++ b/Classes/PHPExcel/Writer/OpenDocument/MetaInf.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_MetaInf * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_MetaInf - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_MetaInf extends PHPExcel_Writer_OpenDocument_WriterPart { /** diff --git a/Classes/PHPExcel/Writer/OpenDocument/Mimetype.php b/Classes/PHPExcel/Writer/OpenDocument/Mimetype.php index d93e4d14..d51a8b97 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/Mimetype.php +++ b/Classes/PHPExcel/Writer/OpenDocument/Mimetype.php @@ -1,8 +1,9 @@ <?php + /** * PHPExcel * - * Copyright (c) 2006 - 2015 PHPExcel + * PHPExcel_Writer_OpenDocument_Mimetype * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_Mimetype - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_Mimetype extends PHPExcel_Writer_OpenDocument_WriterPart { /** diff --git a/Classes/PHPExcel/Writer/OpenDocument/Settings.php b/Classes/PHPExcel/Writer/OpenDocument/Settings.php index 75363a8e..84161b6d 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/Settings.php +++ b/Classes/PHPExcel/Writer/OpenDocument/Settings.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_Settings * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_Settings - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_Settings extends PHPExcel_Writer_OpenDocument_WriterPart { /** diff --git a/Classes/PHPExcel/Writer/OpenDocument/Styles.php b/Classes/PHPExcel/Writer/OpenDocument/Styles.php index e2934d10..cc6e25b4 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/Styles.php +++ b/Classes/PHPExcel/Writer/OpenDocument/Styles.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_Styles * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_Styles - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_Styles extends PHPExcel_Writer_OpenDocument_WriterPart { /** diff --git a/Classes/PHPExcel/Writer/OpenDocument/Thumbnails.php b/Classes/PHPExcel/Writer/OpenDocument/Thumbnails.php index b48731f5..54247ae2 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/Thumbnails.php +++ b/Classes/PHPExcel/Writer/OpenDocument/Thumbnails.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_Thumbnails * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,19 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_Thumbnails - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @author Alexander Pervakov <frost-nzcr4@jagmort.com> - */ class PHPExcel_Writer_OpenDocument_Thumbnails extends PHPExcel_Writer_OpenDocument_WriterPart { /** diff --git a/Classes/PHPExcel/Writer/OpenDocument/WriterPart.php b/Classes/PHPExcel/Writer/OpenDocument/WriterPart.php index 1b2e52c3..562787a3 100644 --- a/Classes/PHPExcel/Writer/OpenDocument/WriterPart.php +++ b/Classes/PHPExcel/Writer/OpenDocument/WriterPart.php @@ -1,6 +1,7 @@ <?php + /** - * PHPExcel + * PHPExcel_Writer_OpenDocument_WriterPart * * Copyright (c) 2006 - 2015 PHPExcel * @@ -21,18 +22,9 @@ * @category PHPExcel * @package PHPExcel_Writer_OpenDocument * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version ##VERSION##, ##DATE## */ - - -/** - * PHPExcel_Writer_OpenDocument_WriterPart - * - * @category PHPExcel - * @package PHPExcel_Writer_OpenDocument - * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) - */ abstract class PHPExcel_Writer_OpenDocument_WriterPart extends PHPExcel_Writer_Excel2007_WriterPart { }