From 6ba19b8241543d7547b93644827a9dc2b25b6df1 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 20 Feb 2012 20:49:25 +0000 Subject: [PATCH] Initial chart writer code (still annoyingly buggy) git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@86721 2327b42d-5241-43d6-9e2a-de5ac946f064 --- Classes/PHPExcel/Chart/DataSeries.php | 18 + .../Chart/Renderer/PHP Charting Libraries.txt | 17 + Classes/PHPExcel/Reader/Excel2007.php | 92 +- Classes/PHPExcel/Writer/Excel2007.php | 71 +- Classes/PHPExcel/Writer/Excel2007/Chart.php | 827 ++++++++++++++++++ .../Writer/Excel2007/ContentTypes.php | 19 +- Classes/PHPExcel/Writer/Excel2007/Drawing.php | 85 +- Classes/PHPExcel/Writer/Excel2007/Rels.php | 45 +- .../PHPExcel/Writer/Excel2007/StringTable.php | 26 +- .../PHPExcel/Writer/Excel2007/Workbook.php | 9 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 12 +- 11 files changed, 1158 insertions(+), 63 deletions(-) create mode 100644 Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt create mode 100644 Classes/PHPExcel/Writer/Excel2007/Chart.php diff --git a/Classes/PHPExcel/Chart/DataSeries.php b/Classes/PHPExcel/Chart/DataSeries.php index 4367264..0c73c54 100644 --- a/Classes/PHPExcel/Chart/DataSeries.php +++ b/Classes/PHPExcel/Chart/DataSeries.php @@ -314,4 +314,22 @@ class PHPExcel_Chart_DataSeries return count($this->_plotValues); } + /** + * Get Smooth Line + * + * @return boolean + */ + public function getSmoothLine() { + return $this->_smoothLine; + } + + /** + * Set Smooth Line + * + * @param boolean $smoothLine + */ + public function setSmoothLine($smoothLine = TRUE) { + $this->_smoothLine = $smoothLine; + } + } diff --git a/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt b/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt new file mode 100644 index 0000000..20a8258 --- /dev/null +++ b/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt @@ -0,0 +1,17 @@ +ChartDirector + http://www.advsofteng.com/cdphp.html + +GraPHPite + http://graphpite.sourceforge.net/ + +JpGraph + http://www.aditus.nu/jpgraph/ + +LibChart + http://naku.dohcrew.com/libchart/pages/introduction/ + +pChart + http://pchart.sourceforge.net/ + +TeeChart + http://www.steema.com/products/teechart/overview.html diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index 8a547ac..c8793df 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -53,6 +53,14 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader */ private $_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 + */ + private $_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. @@ -108,6 +116,33 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader 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; + } + + /** + * 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_Excel2007 + */ + 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 @@ -1301,10 +1336,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader 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") { - $charts[self::dir_add($fileDrawing, $ele["Target"])] = array('id' => (string) $ele["Id"], - 'sheet' => $docSheet->getTitle() - ); - } + if ($this->_includeCharts) { + $charts[self::dir_add($fileDrawing, $ele["Target"])] = array('id' => (string) $ele["Id"], + 'sheet' => $docSheet->getTitle() + ); + } + } } } $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); @@ -1380,7 +1417,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); } $objDrawing->setWorksheet($docSheet); - } else { + } elseif($this->_includeCharts) { $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); @@ -1400,7 +1437,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader 'toOffsetY' => $toOffsetY, 'worksheetTitle' => $docSheet->getTitle() ); - } + } } } @@ -1567,29 +1604,32 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach ($contentTypes->Override as $contentType) { switch ($contentType["ContentType"]) { case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": - $chartEntryRef = ltrim($contentType['PartName'],'/'); - $chartElements = simplexml_load_string($this->_getFromZipArchive($zip, $chartEntryRef)); - $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); + if ($this->_includeCharts) { + $chartEntryRef = ltrim($contentType['PartName'],'/'); + $chartElements = simplexml_load_string($this->_getFromZipArchive($zip, $chartEntryRef)); + $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); -// echo 'Chart ',$chartEntryRef,'
'; -// var_dump($charts[$chartEntryRef]); +// 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'], - PHPExcel_Shared_Drawing::EMUToPixels($chartDetails[$chartPositionRef]['fromOffsetX']), - PHPExcel_Shared_Drawing::EMUToPixels($chartDetails[$chartPositionRef]['fromOffsetY']) - ); - $objChart->setBottomRightPosition( $chartDetails[$chartPositionRef]['toCoordinate'], - PHPExcel_Shared_Drawing::EMUToPixels($chartDetails[$chartPositionRef]['fromOffsetX']), - PHPExcel_Shared_Drawing::EMUToPixels($chartDetails[$chartPositionRef]['fromOffsetY']) + 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'] + ); + } + } } } } diff --git a/Classes/PHPExcel/Writer/Excel2007.php b/Classes/PHPExcel/Writer/Excel2007.php index 7823d0f..1934d81 100644 --- a/Classes/PHPExcel/Writer/Excel2007.php +++ b/Classes/PHPExcel/Writer/Excel2007.php @@ -35,6 +35,14 @@ */ class PHPExcel_Writer_Excel2007 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 + */ + private $_includeCharts = false; + /** * Pre-calculate formulas * @@ -145,8 +153,11 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter 'workbook' => 'PHPExcel_Writer_Excel2007_Workbook', 'worksheet' => 'PHPExcel_Writer_Excel2007_Worksheet', 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', - 'comments' => 'PHPExcel_Writer_Excel2007_Comments' + 'comments' => 'PHPExcel_Writer_Excel2007_Comments', ); + if ($this->_includeCharts) { + $writerPartsArray['chart'] = 'PHPExcel_Writer_Excel2007_Chart'; + } // Initialise writer parts // and Assign their parent IWriters @@ -241,7 +252,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } // Add [Content_Types].xml to ZIP file - $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet)); + $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); // Add relationships to ZIP file $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); @@ -265,26 +276,43 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter $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)); + $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)); + $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) { // Add relationships - $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1))); + $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts)); - // Add drawing relationship parts - if ($this->_spreadSheet->getSheet($i)->getDrawingCollection()->count() > 0) { + $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))); + $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))); + $objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts)); } // Add comment relationship parts @@ -453,6 +481,31 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter return $this->_drawingHashTable; } + /** + * 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_Excel2007 + */ + public function setIncludeCharts($pValue = false) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } + /** * Get Pre-Calculate Formulas * diff --git a/Classes/PHPExcel/Writer/Excel2007/Chart.php b/Classes/PHPExcel/Writer/Excel2007/Chart.php new file mode 100644 index 0000000..2ddfb09 --- /dev/null +++ b/Classes/PHPExcel/Writer/Excel2007/Chart.php @@ -0,0 +1,827 @@ +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'); + + // c:chartSpace + $objWriter->startElement('c:chartSpace'); + $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + $objWriter->startElement('c:date1904'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + $objWriter->startElement('c:lang'); + $objWriter->writeAttribute('val', "en-GB"); + $objWriter->endElement(); + $objWriter->startElement('c:roundedCorners'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $this->_writeAlternateContent($objWriter); + + $objWriter->startElement('c:chart'); + + $this->_writeTitle($pChart->getTitle(), $objWriter); + + $objWriter->startElement('c:autoTitleDeleted'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $this->_writePlotArea($pChart->getPlotArea(), $pChart->getXAxisLabel(), $pChart->getYAxisLabel(), $objWriter); + + $this->_writeLegend($pChart->getLegend(), $objWriter); + + + $objWriter->startElement('c:plotVisOnly'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:dispBlanksAs'); + $objWriter->writeAttribute('val', "gap"); + $objWriter->endElement(); + + $objWriter->startElement('c:showDLblsOverMax'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + + $this->_writePrintSettings($objWriter); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + private function _writeTitle(PHPExcel_Chart_Title $title = null, $objWriter) + { + if (is_null($title)) { + return; + } + + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + $objWriter->startElement('a:p'); + + $caption = $title->getCaption(); + if (is_array($caption)) + $caption = $caption[0]; + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $caption, 'a'); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $layout = $title->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + private function _writeLegend(PHPExcel_Chart_Legend $legend = null, $objWriter) + { + if (is_null($legend)) { + return; + } + + $objWriter->startElement('c:legend'); + + $objWriter->startElement('c:legendPos'); + $objWriter->writeAttribute('val', $legend->getPosition()); + $objWriter->endElement(); + + $layout = $legend->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0'); + $objWriter->endElement(); + + $objWriter->startElement('c:txPr'); + $objWriter->startElement('a:bodyPr'); + $objWriter->endElement(); + + $objWriter->startElement('a:lstStyle'); + $objWriter->endElement(); + + $objWriter->startElement('a:p'); + $objWriter->startElement('a:pPr'); + $objWriter->writeAttribute('rtl', 0); + + $objWriter->startElement('a:defRPr'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('a:endParaRPr'); + $objWriter->writeAttribute('lang', "en-US"); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + private function _writePlotArea(PHPExcel_Chart_PlotArea $plotArea, + PHPExcel_Chart_Title $xAxisLabel = NULL, + PHPExcel_Chart_Title $yAxisLabel = NULL, + $objWriter) + { + if (is_null($plotArea)) { + return; + } + + $id1 = $id2 = 0; + $objWriter->startElement('c:plotArea'); + + $layout = $plotArea->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $chartTypes = self::_getChartType($plotArea); + $catIsMultiLevelSeries = $valIsMultiLevelSeries = FALSE; + foreach($chartTypes as $chartType) { + $objWriter->startElement('c:'.$chartType); + + $groupCount = $plotArea->getPlotGroupCount(); + for($i = 0; $i < $groupCount; ++$i) { + $plotGroup = $plotArea->getPlotGroupByIndex($i); + $groupType = $plotGroup->getPlotType(); + if ($groupType == $chartType) { + $this->_writePlotGroup($plotGroup, $groupType, $objWriter, $catIsMultiLevelSeries, $valIsMultiLevelSeries); + } + } + + $this->_writeDataLbls($objWriter); + + if (($groupType === PHPExcel_Chart_DataSeries::TYPE_LINECHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_LINECHART_3D) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_AREACHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_AREACHART_3D)) { + $objWriter->startElement('c:smooth'); + $objWriter->writeAttribute('val', (integer) $plotGroup->getSmoothLine() ); + $objWriter->endElement(); + } elseif (($groupType === PHPExcel_Chart_DataSeries::TYPE_BARCHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_BARCHART_3D)) { + $objWriter->startElement('c:gapWidth'); + $objWriter->writeAttribute('val', 150 ); + $objWriter->endElement(); + } + + if (($groupType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART) && + ($groupType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) && + ($groupType !== PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + // Generate 2 unique numbers to use for axId values + $id1 = $id2 = rand(10000000,99999999); + do { + $id2 = rand(10000000,99999999); + } while ($id1 == $id2); + + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id1 ); + $objWriter->endElement(); + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id2 ); + $objWriter->endElement(); + } else { + $objWriter->startElement('c:firstSliceAng'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + $this->_writeCatAx($objWriter,$plotArea,$xAxisLabel,$id1,$id2,$catIsMultiLevelSeries); + + $this->_writeValAx($objWriter,$plotArea,$yAxisLabel,$id1,$id2,$valIsMultiLevelSeries); + + $objWriter->endElement(); + } + + private function _writeDataLbls($objWriter) + { + $objWriter->startElement('c:dLbls'); + + $objWriter->startElement('c:showLegendKey'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showVal'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showCatName'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showSerName'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showPercent'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showBubbleSize'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:showLeaderLines'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + private function _writeCatAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $xAxisLabel, $id1, $id2, $isMultiLevelSeries) + { + $objWriter->startElement('c:catAx'); + + if ($id1 > 0) { + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id1); + $objWriter->endElement(); + } + + $objWriter->startElement('c:scaling'); + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', "minMax"); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:delete'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:axPos'); + $objWriter->writeAttribute('val', "b"); + $objWriter->endElement(); + + $objWriter->startElement('c:numFmt'); + $objWriter->writeAttribute('formatCode', "General"); + $objWriter->writeAttribute('sourceLinked', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', "out"); + $objWriter->endElement(); + + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', "none"); + $objWriter->endElement(); + + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', "nextTo"); + $objWriter->endElement(); + + if (!is_null($xAxisLabel)) { + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + $objWriter->startElement('a:p'); + + $caption = $xAxisLabel->getCaption(); + if (is_array($caption)) + $caption = $caption[0]; + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $caption, 'a'); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $layout = $xAxisLabel->getLayout(); + $this->_writeLayout($layout, $objWriter); + + } + + if ($id2 > 0) { + $objWriter->startElement('c:crossAx'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', "autoZero"); + $objWriter->endElement(); + } + + $objWriter->startElement('c:auto'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:lblAlgn'); + $objWriter->writeAttribute('val', "ctr"); + $objWriter->endElement(); + + $objWriter->startElement('c:lblOffset'); + $objWriter->writeAttribute('val', 100); + $objWriter->endElement(); + + if ($isMultiLevelSeries) { + $objWriter->startElement('c:noMultiLvlLbl'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + $objWriter->endElement(); + + } + + + private function _writeValAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $yAxisLabel, $id1, $id2, $isMultiLevelSeries) + { + $objWriter->startElement('c:valAx'); + + if ($id2 > 0) { + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + } + + $objWriter->startElement('c:scaling'); + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', "minMax"); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:delete'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:axPos'); + $objWriter->writeAttribute('val', "l"); + $objWriter->endElement(); + + $objWriter->startElement('c:majorGridlines'); + $objWriter->endElement(); + + $objWriter->startElement('c:numFmt'); + $objWriter->writeAttribute('formatCode', "General"); + $objWriter->writeAttribute('sourceLinked', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', "out"); + $objWriter->endElement(); + + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', "none"); + $objWriter->endElement(); + + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', "nextTo"); + $objWriter->endElement(); + + if (!is_null($yAxisLabel)) { + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + $objWriter->startElement('a:p'); + + $caption = $yAxisLabel->getCaption(); + if (is_array($caption)) + $caption = $caption[0]; + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $caption, 'a'); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $layout = $yAxisLabel->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->endElement(); + } + + if ($id1 > 0) { + $objWriter->startElement('c:crossAx'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', "autoZero"); + $objWriter->endElement(); + + $objWriter->startElement('c:crossBetween'); + $objWriter->writeAttribute('val', "midCat"); + $objWriter->endElement(); + } + + if ($isMultiLevelSeries) { + $objWriter->startElement('c:noMultiLvlLbl'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + $objWriter->endElement(); + + } + + + private static function _getChartType($plotArea) + { + $groupCount = $plotArea->getPlotGroupCount(); + if ($groupCount == 1) { + $chartType = array($plotArea->getPlotGroupByIndex(0)->getPlotType()); + } else { + $chartTypes = array(); + for($i = 0; $i < $groupCount; ++$i) { + $chartTypes[] = $plotArea->getPlotGroupByIndex($i)->getPlotType(); + } + $chartType = array_unique($chartTypes); + if (count($chartTypes) == 0) { + throw new Exception('Chart is not yet implemented'); + } + } + + return $chartType; + } + + private function _writePlotGroup($plotGroup, $groupType, $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries) + { + if (is_null($plotGroup)) { + return; + } + + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_BARCHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_BARCHART_3D)) { + $objWriter->startElement('c:barDir'); + $objWriter->writeAttribute('val', $plotGroup->getPlotDirection()); + $objWriter->endElement(); + } + + if (!is_null($plotGroup->getPlotGrouping())) { + $objWriter->startElement('c:grouping'); + $objWriter->writeAttribute('val', $plotGroup->getPlotGrouping()); + $objWriter->endElement(); + } + + // TODO Set to 1 if any plotseries values don't have style colours defined, otherwise set to 0 + $objWriter->startElement('c:varyColors'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $plotSeriesOrder = $plotGroup->getPlotOrder(); + $plotSeriesCount = count($plotSeriesOrder); + foreach($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) { + $objWriter->startElement('c:ser'); + + $objWriter->startElement('c:idx'); + $objWriter->writeAttribute('val', $plotSeriesIdx); + $objWriter->endElement(); + + $objWriter->startElement('c:order'); + $objWriter->writeAttribute('val', $plotSeriesRef); + $objWriter->endElement(); + + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + $objWriter->startElement('c:dPt'); + $objWriter->startElement('c:idx'); + $objWriter->writeAttribute('val', 3); + $objWriter->endElement(); + + $objWriter->startElement('c:bubble3D'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:spPr'); + $objWriter->startElement('a:solidFill'); + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FF9900'); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + } + + // Labels + $plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesRef); + if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) { + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:strRef'); + $this->_writePlotSeriesLabel($plotSeriesLabel, $objWriter); + $objWriter->endElement(); + $objWriter->endElement(); + } + + // Formatting for the points + if ($groupType == PHPExcel_Chart_DataSeries::TYPE_LINECHART) { + $objWriter->startElement('c:spPr'); + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', 12700); + $objWriter->endElement(); + $objWriter->endElement(); + } + + if (($groupType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART) && + ($groupType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) && + ($groupType !== PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + $objWriter->startElement('c:invertIfNegative'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + + // Category Labels + $plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesRef); + if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) { + $catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries(); + $objWriter->startElement('c:cat'); + $this->_writePlotSeriesValues($plotSeriesCategory, $objWriter, 'str'); + $objWriter->endElement(); + } + + // Values + $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesRef); + if ($plotSeriesValues) { + $valIsMultiLevelSeries = $valIsMultiLevelSeries || $plotSeriesValues->isMultiLevelSeries(); + $objWriter->startElement('c:val'); + $this->_writePlotSeriesValues($plotSeriesValues, $objWriter, 'num'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + + } + } + + private function _writePlotSeriesLabel($plotSeriesLabel, $objWriter) + { + if (is_null($plotSeriesLabel)) { + return; + } + + $objWriter->startElement('c:f'); + $objWriter->writeRawData($plotSeriesLabel->getDataSource()); + $objWriter->endElement(); + + $objWriter->startElement('c:strCache'); + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesLabel->getPointCount() ); + $objWriter->endElement(); + + foreach($plotSeriesLabel->getDataValues() as $plotLabelKey => $plotLabelValue) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotLabelKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotLabelValue ); + $objWriter->endElement(); + $objWriter->endElement(); + } + $objWriter->endElement(); + + } + + private function _writePlotSeriesValues($plotSeriesValues, $objWriter, $dataType='str') + { + if (is_null($plotSeriesValues)) { + return; + } + + if ($plotSeriesValues->isMultiLevelSeries()) { + $levelCount = $plotSeriesValues->multiLevelCount(); + + $objWriter->startElement('c:multiLvlStrRef'); + + $objWriter->startElement('c:f'); + $objWriter->writeRawData( $plotSeriesValues->getDataSource() ); + $objWriter->endElement(); + + $objWriter->startElement('c:multiLvlStrCache'); + + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount() ); + $objWriter->endElement(); + + for ($level = 0; $level < $levelCount; ++$level) { + $objWriter->startElement('c:lvl'); + + foreach($plotSeriesValues->getDataValues() as $plotSeriesKey => $plotSeriesValue) { + if (isset($plotSeriesValue[$level])) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotSeriesKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotSeriesValue[$level] ); + $objWriter->endElement(); + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } else { + $objWriter->startElement('c:'.$dataType.'Ref'); + + $objWriter->startElement('c:f'); + $objWriter->writeRawData( $plotSeriesValues->getDataSource() ); + $objWriter->endElement(); + + $objWriter->startElement('c:'.$dataType.'Cache'); + + $objWriter->startElement('c:formatCode'); + $objWriter->writeRawData( $plotSeriesValues->getFormatCode() ); + $objWriter->endElement(); + + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount() ); + $objWriter->endElement(); + + foreach($plotSeriesValues->getDataValues() as $plotSeriesKey => $plotSeriesValue) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotSeriesKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotSeriesValue ); + $objWriter->endElement(); + $objWriter->endElement(); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + private function _writeLayout(PHPExcel_Chart_Layout $layout = NULL, $objWriter) + { + $objWriter->startElement('c:layout'); + + if (!is_null($layout)) { + $objWriter->startElement('c:manualLayout'); + + $layoutTarget = $layout->getLayoutTarget(); + if (!is_null($layoutTarget)) { + $objWriter->startElement('c:layoutTarget'); + $objWriter->writeAttribute('val', $layoutTarget); + $objWriter->endElement(); + } + + $xMode = $layout->getXMode(); + if (!is_null($xMode)) { + $objWriter->startElement('c:xMode'); + $objWriter->writeAttribute('val', $xMode); + $objWriter->endElement(); + } + + $yMode = $layout->getYMode(); + if (!is_null($yMode)) { + $objWriter->startElement('c:yMode'); + $objWriter->writeAttribute('val', $yMode); + $objWriter->endElement(); + } + + $x = $layout->getXPosition(); + if (!is_null($x)) { + $objWriter->startElement('c:x'); + $objWriter->writeAttribute('val', $x); + $objWriter->endElement(); + } + + $y = $layout->getYPosition(); + if (!is_null($y)) { + $objWriter->startElement('c:y'); + $objWriter->writeAttribute('val', $y); + $objWriter->endElement(); + } + + $w = $layout->getWidth(); + if (!is_null($w)) { + $objWriter->startElement('c:w'); + $objWriter->writeAttribute('val', $w); + $objWriter->endElement(); + } + + $h = $layout->getHeight(); + if (!is_null($h)) { + $objWriter->startElement('c:h'); + $objWriter->writeAttribute('val', $h); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + private function _writeAlternateContent($objWriter) + { + $objWriter->startElement('mc:AlternateContent'); + $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); + + $objWriter->startElement('mc:Choice'); + $objWriter->writeAttribute('xmlns:c14', 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart'); + $objWriter->writeAttribute('Requires', 'c14'); + + $objWriter->startElement('c14:style'); + $objWriter->writeAttribute('val', '102'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('mc:Fallback'); + $objWriter->startElement('c:style'); + $objWriter->writeAttribute('val', '2'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + private function _writePrintSettings($objWriter) + { + $objWriter->startElement('c:printSettings'); + + $objWriter->startElement('c:headerFooter'); + $objWriter->endElement(); + + $objWriter->startElement('c:pageMargins'); + $objWriter->writeAttribute('footer', 0.3); + $objWriter->writeAttribute('header', 0.3); + $objWriter->writeAttribute('r', 0.7); + $objWriter->writeAttribute('l', 0.7); + $objWriter->writeAttribute('t', 0.75); + $objWriter->writeAttribute('b', 0.75); + $objWriter->endElement(); + + $objWriter->startElement('c:pageSetup'); + $objWriter->writeAttribute('orientation', "portrait"); + $objWriter->endElement(); + + $objWriter->endElement(); + } + +} diff --git a/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php b/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php index 8d2c0a3..143c152 100644 --- a/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -42,7 +42,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W * @return string XML Output * @throws Exception */ - public function writeContentTypes(PHPExcel $pPHPExcel = null) + public function writeContentTypes(PHPExcel $pPHPExcel = null, $includeCharts = FALSE) { // Create XML writer $objWriter = null; @@ -119,12 +119,27 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W ); // Add worksheet relationship content types + $chart = 1; for ($i = 0; $i < $sheetCount; ++$i) { - if ($pPHPExcel->getSheet($i)->getDrawingCollection()->count() > 0) { + $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' ); } + + // 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 diff --git a/Classes/PHPExcel/Writer/Excel2007/Drawing.php b/Classes/PHPExcel/Writer/Excel2007/Drawing.php index a82fb72..93325f9 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Drawing.php +++ b/Classes/PHPExcel/Writer/Excel2007/Drawing.php @@ -42,7 +42,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * @return string XML Output * @throws Exception */ - public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null) + public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) { // Create XML writer $objWriter = null; @@ -70,12 +70,95 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer ++$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(); // Return return $objWriter->getData(); } + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet_BaseDrawing $pDrawing + * @param int $pRelationId + * @throws 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: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: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('xdr:clientData'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + /** * Write drawings to XML format * diff --git a/Classes/PHPExcel/Writer/Excel2007/Rels.php b/Classes/PHPExcel/Writer/Excel2007/Rels.php index 7a1487a..d665ae0 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Rels.php +++ b/Classes/PHPExcel/Writer/Excel2007/Rels.php @@ -178,7 +178,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * @return string XML Output * @throws Exception */ - public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1) + public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = FALSE) { // Create XML writer $objWriter = null; @@ -196,15 +196,37 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); // Write drawing relationships? - if ($pWorksheet->getDrawingCollection()->count() > 0) { + $d = 0; + if ($includeCharts) { + $charts = $pWorksheet->getChartCollection(); + } else { + $charts = array(); + } + if (($pWorksheet->getDrawingCollection()->count() > 0) || + (count($charts) > 0)) { $this->_writeRelationship( $objWriter, - 1, + ++$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) , '
'; +// 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) { @@ -263,7 +285,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * @return string XML Output * @throws Exception */ - public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null) + public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) { // Create XML writer $objWriter = null; @@ -299,6 +321,21 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar ++$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' + ); + } + } + } + $objWriter->endElement(); // Return diff --git a/Classes/PHPExcel/Writer/Excel2007/StringTable.php b/Classes/PHPExcel/Writer/Excel2007/StringTable.php index 3e429cd..8fe36ab 100644 --- a/Classes/PHPExcel/Writer/Excel2007/StringTable.php +++ b/Classes/PHPExcel/Writer/Excel2007/StringTable.php @@ -146,37 +146,39 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr * @param PHPExcel_RichText $pRichText Rich text * @throws Exception */ - public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null) + 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('r'); + $objWriter->startElement($prefix.'r'); // rPr if ($element instanceof PHPExcel_RichText_Run) { // rPr - $objWriter->startElement('rPr'); + $objWriter->startElement($prefix.'rPr'); // rFont - $objWriter->startElement('rFont'); + $objWriter->startElement($prefix.'rFont'); $objWriter->writeAttribute('val', $element->getFont()->getName()); $objWriter->endElement(); // Bold - $objWriter->startElement('b'); + $objWriter->startElement($prefix.'b'); $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false')); $objWriter->endElement(); // Italic - $objWriter->startElement('i'); + $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('vertAlign'); + $objWriter->startElement($prefix.'vertAlign'); if ($element->getFont()->getSuperScript()) { $objWriter->writeAttribute('val', 'superscript'); } else if ($element->getFont()->getSubScript()) { @@ -186,22 +188,22 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr } // Strikethrough - $objWriter->startElement('strike'); + $objWriter->startElement($prefix.'strike'); $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false')); $objWriter->endElement(); // Color - $objWriter->startElement('color'); + $objWriter->startElement($prefix.'color'); $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB()); $objWriter->endElement(); // Size - $objWriter->startElement('sz'); + $objWriter->startElement($prefix.'sz'); $objWriter->writeAttribute('val', $element->getFont()->getSize()); $objWriter->endElement(); // Underline - $objWriter->startElement('u'); + $objWriter->startElement($prefix.'u'); $objWriter->writeAttribute('val', $element->getFont()->getUnderline()); $objWriter->endElement(); @@ -209,7 +211,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr } // t - $objWriter->startElement('t'); + $objWriter->startElement($prefix.'t'); $objWriter->writeAttribute('xml:space', 'preserve'); $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); $objWriter->endElement(); diff --git a/Classes/PHPExcel/Writer/Excel2007/Workbook.php b/Classes/PHPExcel/Writer/Excel2007/Workbook.php index af3fa9c..8d547d5 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel2007/Workbook.php @@ -42,7 +42,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @return string XML Output * @throws Exception */ - public function writeWorkbook(PHPExcel $pPHPExcel = null) + public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = FALSE) { // Create XML writer $objWriter = null; @@ -82,7 +82,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write $this->_writeDefinedNames($objWriter, $pPHPExcel); // calcPr - $this->_writeCalcPr($objWriter); + $this->_writeCalcPr($objWriter,$recalcRequired); $objWriter->endElement(); @@ -188,13 +188,14 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @throws Exception */ - private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null) + private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = TRUE) { $objWriter->startElement('calcPr'); $objWriter->writeAttribute('calcId', '124519'); $objWriter->writeAttribute('calcMode', 'auto'); - $objWriter->writeAttribute('fullCalcOnLoad', '1'); + // fullCalcOnLoad isn't needed if we've recalculating for the save + $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1'); $objWriter->endElement(); } diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php index 754a365..441547e 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php @@ -43,7 +43,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @return string XML Output * @throws Exception */ - public function writeWorksheet($pSheet = null, $pStringTable = null) + public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = FALSE) { if (!is_null($pSheet)) { // Create XML writer @@ -117,8 +117,8 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Breaks $this->_writeBreaks($objWriter, $pSheet); - // Drawings - $this->_writeDrawings($objWriter, $pSheet); + // Drawings and/or Charts + $this->_writeDrawings($objWriter, $pSheet, $includeCharts); // LegacyDrawing $this->_writeLegacyDrawing($objWriter, $pSheet); @@ -1083,10 +1083,12 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @param PHPExcel_Worksheet $pSheet Worksheet * @throws Exception */ - private function _writeDrawings(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + 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) { + if (($pSheet->getDrawingCollection()->count() > 0) || + ($chartCount > 0)) { $objWriter->startElement('drawing'); $objWriter->writeAttribute('r:id', 'rId1'); $objWriter->endElement();