summaryrefslogtreecommitdiffstats
path: root/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx')
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php1516
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php232
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php240
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php223
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php239
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php505
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php451
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php45
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php40
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php282
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php676
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php837
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php225
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php1282
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php33
-rw-r--r--vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php159
16 files changed, 6985 insertions, 0 deletions
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php
new file mode 100644
index 0000000..4ac780b
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php
@@ -0,0 +1,1516 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Chart\Axis;
+use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
+use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
+use PhpOffice\PhpSpreadsheet\Chart\GridLines;
+use PhpOffice\PhpSpreadsheet\Chart\Layout;
+use PhpOffice\PhpSpreadsheet\Chart\Legend;
+use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
+use PhpOffice\PhpSpreadsheet\Chart\Title;
+use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
+
+class Chart extends WriterPart
+{
+ protected $calculateCellValues;
+
+ /**
+ * @var int
+ */
+ private $seriesIndex;
+
+ /**
+ * Write charts to XML format.
+ *
+ * @param mixed $calculateCellValues
+ *
+ * @return string XML Output
+ */
+ public function writeChart(\PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $calculateCellValues = true)
+ {
+ $this->calculateCellValues = $calculateCellValues;
+
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+ // Ensure that data series values are up-to-date before we save
+ if ($this->calculateCellValues) {
+ $pChart->refresh();
+ }
+
+ // 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($objWriter, $pChart->getTitle());
+
+ $objWriter->startElement('c:autoTitleDeleted');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $this->writePlotArea($objWriter, $pChart->getWorksheet(), $pChart->getPlotArea(), $pChart->getXAxisLabel(), $pChart->getYAxisLabel(), $pChart->getChartAxisX(), $pChart->getChartAxisY(), $pChart->getMajorGridlines(), $pChart->getMinorGridlines());
+
+ $this->writeLegend($objWriter, $pChart->getLegend());
+
+ $objWriter->startElement('c:plotVisOnly');
+ $objWriter->writeAttribute('val', (int) $pChart->getPlotVisibleOnly());
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:dispBlanksAs');
+ $objWriter->writeAttribute('val', $pChart->getDisplayBlanksAs());
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showDLblsOverMax');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $this->writePrintSettings($objWriter);
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write Chart Title.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Title $title
+ */
+ private function writeTitle(XMLWriter $objWriter, ?Title $title = null): void
+ {
+ if ($title === null) {
+ return;
+ }
+
+ $objWriter->startElement('c:title');
+ $objWriter->startElement('c:tx');
+ $objWriter->startElement('c:rich');
+
+ $objWriter->startElement('a:bodyPr');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:lstStyle');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:p');
+
+ $caption = $title->getCaption();
+ if ((is_array($caption)) && (count($caption) > 0)) {
+ $caption = $caption[0];
+ }
+ $this->getParentWriter()->getWriterPart('stringtable')->writeRichTextForCharts($objWriter, $caption, 'a');
+
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ $this->writeLayout($objWriter, $title->getLayout());
+
+ $objWriter->startElement('c:overlay');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Chart Legend.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Legend $legend
+ */
+ private function writeLegend(XMLWriter $objWriter, ?Legend $legend = null): void
+ {
+ if ($legend === null) {
+ return;
+ }
+
+ $objWriter->startElement('c:legend');
+
+ $objWriter->startElement('c:legendPos');
+ $objWriter->writeAttribute('val', $legend->getPosition());
+ $objWriter->endElement();
+
+ $this->writeLayout($objWriter, $legend->getLayout());
+
+ $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();
+ }
+
+ /**
+ * Write Chart Plot Area.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Title $xAxisLabel
+ * @param Title $yAxisLabel
+ * @param Axis $xAxis
+ * @param Axis $yAxis
+ */
+ private function writePlotArea(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pSheet, PlotArea $plotArea, ?Title $xAxisLabel = null, ?Title $yAxisLabel = null, ?Axis $xAxis = null, ?Axis $yAxis = null, ?GridLines $majorGridlines = null, ?GridLines $minorGridlines = null): void
+ {
+ if ($plotArea === null) {
+ return;
+ }
+
+ $id1 = $id2 = 0;
+ $this->seriesIndex = 0;
+ $objWriter->startElement('c:plotArea');
+
+ $layout = $plotArea->getLayout();
+
+ $this->writeLayout($objWriter, $layout);
+
+ $chartTypes = self::getChartType($plotArea);
+ $catIsMultiLevelSeries = $valIsMultiLevelSeries = false;
+ $plotGroupingType = '';
+ 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) {
+ $plotStyle = $plotGroup->getPlotStyle();
+ if ($groupType === DataSeries::TYPE_RADARCHART) {
+ $objWriter->startElement('c:radarStyle');
+ $objWriter->writeAttribute('val', $plotStyle);
+ $objWriter->endElement();
+ } elseif ($groupType === DataSeries::TYPE_SCATTERCHART) {
+ $objWriter->startElement('c:scatterStyle');
+ $objWriter->writeAttribute('val', $plotStyle);
+ $objWriter->endElement();
+ }
+
+ $this->writePlotGroup($plotGroup, $chartType, $objWriter, $catIsMultiLevelSeries, $valIsMultiLevelSeries, $plotGroupingType);
+ }
+ }
+
+ $this->writeDataLabels($objWriter, $layout);
+
+ if ($chartType === DataSeries::TYPE_LINECHART) {
+ // Line only, Line3D can't be smoothed
+ $objWriter->startElement('c:smooth');
+ $objWriter->writeAttribute('val', (int) $plotGroup->getSmoothLine());
+ $objWriter->endElement();
+ } elseif (($chartType === DataSeries::TYPE_BARCHART) || ($chartType === DataSeries::TYPE_BARCHART_3D)) {
+ $objWriter->startElement('c:gapWidth');
+ $objWriter->writeAttribute('val', 150);
+ $objWriter->endElement();
+
+ if ($plotGroupingType == 'percentStacked' || $plotGroupingType == 'stacked') {
+ $objWriter->startElement('c:overlap');
+ $objWriter->writeAttribute('val', 100);
+ $objWriter->endElement();
+ }
+ } elseif ($chartType === DataSeries::TYPE_BUBBLECHART) {
+ $objWriter->startElement('c:bubbleScale');
+ $objWriter->writeAttribute('val', 25);
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showNegBubbles');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+ } elseif ($chartType === DataSeries::TYPE_STOCKCHART) {
+ $objWriter->startElement('c:hiLowLines');
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:upDownBars');
+
+ $objWriter->startElement('c:gapWidth');
+ $objWriter->writeAttribute('val', 300);
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:upBars');
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:downBars');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ // Generate 2 unique numbers to use for axId values
+ $id1 = '75091328';
+ $id2 = '75089408';
+
+ if (($chartType !== DataSeries::TYPE_PIECHART) && ($chartType !== DataSeries::TYPE_PIECHART_3D) && ($chartType !== DataSeries::TYPE_DONUTCHART)) {
+ $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();
+
+ if ($chartType === DataSeries::TYPE_DONUTCHART) {
+ $objWriter->startElement('c:holeSize');
+ $objWriter->writeAttribute('val', 50);
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->endElement();
+ }
+
+ if (($chartType !== DataSeries::TYPE_PIECHART) && ($chartType !== DataSeries::TYPE_PIECHART_3D) && ($chartType !== DataSeries::TYPE_DONUTCHART)) {
+ if ($chartType === DataSeries::TYPE_BUBBLECHART) {
+ $this->writeValueAxis($objWriter, $xAxisLabel, $chartType, $id1, $id2, $catIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines);
+ } else {
+ $this->writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $catIsMultiLevelSeries, $yAxis);
+ }
+
+ $this->writeValueAxis($objWriter, $yAxisLabel, $chartType, $id1, $id2, $valIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines);
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Data Labels.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param \PhpOffice\PhpSpreadsheet\Chart\Layout $chartLayout Chart layout
+ */
+ private function writeDataLabels(XMLWriter $objWriter, ?Layout $chartLayout = null): void
+ {
+ $objWriter->startElement('c:dLbls');
+
+ $objWriter->startElement('c:showLegendKey');
+ $showLegendKey = (empty($chartLayout)) ? 0 : $chartLayout->getShowLegendKey();
+ $objWriter->writeAttribute('val', ((empty($showLegendKey)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showVal');
+ $showVal = (empty($chartLayout)) ? 0 : $chartLayout->getShowVal();
+ $objWriter->writeAttribute('val', ((empty($showVal)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showCatName');
+ $showCatName = (empty($chartLayout)) ? 0 : $chartLayout->getShowCatName();
+ $objWriter->writeAttribute('val', ((empty($showCatName)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showSerName');
+ $showSerName = (empty($chartLayout)) ? 0 : $chartLayout->getShowSerName();
+ $objWriter->writeAttribute('val', ((empty($showSerName)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showPercent');
+ $showPercent = (empty($chartLayout)) ? 0 : $chartLayout->getShowPercent();
+ $objWriter->writeAttribute('val', ((empty($showPercent)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showBubbleSize');
+ $showBubbleSize = (empty($chartLayout)) ? 0 : $chartLayout->getShowBubbleSize();
+ $objWriter->writeAttribute('val', ((empty($showBubbleSize)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:showLeaderLines');
+ $showLeaderLines = (empty($chartLayout)) ? 1 : $chartLayout->getShowLeaderLines();
+ $objWriter->writeAttribute('val', ((empty($showLeaderLines)) ? 0 : 1));
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Category Axis.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Title $xAxisLabel
+ * @param string $id1
+ * @param string $id2
+ * @param bool $isMultiLevelSeries
+ */
+ private function writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $isMultiLevelSeries, Axis $yAxis): void
+ {
+ $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', $yAxis->getAxisOptionsProperty('orientation'));
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:delete');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:axPos');
+ $objWriter->writeAttribute('val', 'b');
+ $objWriter->endElement();
+
+ if ($xAxisLabel !== null) {
+ $objWriter->startElement('c:title');
+ $objWriter->startElement('c:tx');
+ $objWriter->startElement('c:rich');
+
+ $objWriter->startElement('a:bodyPr');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:lstStyle');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:p');
+ $objWriter->startElement('a:r');
+
+ $caption = $xAxisLabel->getCaption();
+ if (is_array($caption)) {
+ $caption = $caption[0];
+ }
+ $objWriter->startElement('a:t');
+ $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($caption));
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ $layout = $xAxisLabel->getLayout();
+ $this->writeLayout($objWriter, $layout);
+
+ $objWriter->startElement('c:overlay');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('c:numFmt');
+ $objWriter->writeAttribute('formatCode', $yAxis->getAxisNumberFormat());
+ $objWriter->writeAttribute('sourceLinked', $yAxis->getAxisNumberSourceLinked());
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:majorTickMark');
+ $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark'));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:minorTickMark');
+ $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark'));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:tickLblPos');
+ $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels'));
+ $objWriter->endElement();
+
+ if ($id2 > 0) {
+ $objWriter->startElement('c:crossAx');
+ $objWriter->writeAttribute('val', $id2);
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:crosses');
+ $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses'));
+ $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();
+ }
+
+ /**
+ * Write Value Axis.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Title $yAxisLabel
+ * @param string $groupType Chart type
+ * @param string $id1
+ * @param string $id2
+ * @param bool $isMultiLevelSeries
+ */
+ private function writeValueAxis($objWriter, $yAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries, Axis $xAxis, GridLines $majorGridlines, GridLines $minorGridlines): void
+ {
+ $objWriter->startElement('c:valAx');
+
+ if ($id2 > 0) {
+ $objWriter->startElement('c:axId');
+ $objWriter->writeAttribute('val', $id2);
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('c:scaling');
+
+ if ($xAxis->getAxisOptionsProperty('maximum') !== null) {
+ $objWriter->startElement('c:max');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('maximum'));
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getAxisOptionsProperty('minimum') !== null) {
+ $objWriter->startElement('c:min');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minimum'));
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('c:orientation');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation'));
+
+ $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->startElement('c:spPr');
+
+ if ($majorGridlines->getLineColorProperty('value') !== null) {
+ $objWriter->startElement('a:ln');
+ $objWriter->writeAttribute('w', $majorGridlines->getLineStyleProperty('width'));
+ $objWriter->startElement('a:solidFill');
+ $objWriter->startElement("a:{$majorGridlines->getLineColorProperty('type')}");
+ $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('alpha'));
+ $objWriter->endElement(); //end alpha
+ $objWriter->endElement(); //end srgbClr
+ $objWriter->endElement(); //end solidFill
+
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', $majorGridlines->getLineStyleProperty('dash'));
+ $objWriter->endElement();
+
+ if ($majorGridlines->getLineStyleProperty('join') == 'miter') {
+ $objWriter->startElement('a:miter');
+ $objWriter->writeAttribute('lim', '800000');
+ $objWriter->endElement();
+ } else {
+ $objWriter->startElement('a:bevel');
+ $objWriter->endElement();
+ }
+
+ if ($majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
+ $objWriter->startElement('a:headEnd');
+ $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']));
+ $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('head', 'w'));
+ $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('head', 'len'));
+ $objWriter->endElement();
+ }
+
+ if ($majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
+ $objWriter->startElement('a:tailEnd');
+ $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']));
+ $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('end', 'w'));
+ $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('end', 'len'));
+ $objWriter->endElement();
+ }
+ $objWriter->endElement(); //end ln
+ }
+ $objWriter->startElement('a:effectLst');
+
+ if ($majorGridlines->getGlowSize() !== null) {
+ $objWriter->startElement('a:glow');
+ $objWriter->writeAttribute('rad', $majorGridlines->getGlowSize());
+ $objWriter->startElement("a:{$majorGridlines->getGlowColor('type')}");
+ $objWriter->writeAttribute('val', $majorGridlines->getGlowColor('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $majorGridlines->getGlowColor('alpha'));
+ $objWriter->endElement(); //end alpha
+ $objWriter->endElement(); //end schemeClr
+ $objWriter->endElement(); //end glow
+ }
+
+ if ($majorGridlines->getShadowProperty('presets') !== null) {
+ $objWriter->startElement("a:{$majorGridlines->getShadowProperty('effect')}");
+ if ($majorGridlines->getShadowProperty('blur') !== null) {
+ $objWriter->writeAttribute('blurRad', $majorGridlines->getShadowProperty('blur'));
+ }
+ if ($majorGridlines->getShadowProperty('distance') !== null) {
+ $objWriter->writeAttribute('dist', $majorGridlines->getShadowProperty('distance'));
+ }
+ if ($majorGridlines->getShadowProperty('direction') !== null) {
+ $objWriter->writeAttribute('dir', $majorGridlines->getShadowProperty('direction'));
+ }
+ if ($majorGridlines->getShadowProperty('algn') !== null) {
+ $objWriter->writeAttribute('algn', $majorGridlines->getShadowProperty('algn'));
+ }
+ if ($majorGridlines->getShadowProperty(['size', 'sx']) !== null) {
+ $objWriter->writeAttribute('sx', $majorGridlines->getShadowProperty(['size', 'sx']));
+ }
+ if ($majorGridlines->getShadowProperty(['size', 'sy']) !== null) {
+ $objWriter->writeAttribute('sy', $majorGridlines->getShadowProperty(['size', 'sy']));
+ }
+ if ($majorGridlines->getShadowProperty(['size', 'kx']) !== null) {
+ $objWriter->writeAttribute('kx', $majorGridlines->getShadowProperty(['size', 'kx']));
+ }
+ if ($majorGridlines->getShadowProperty('rotWithShape') !== null) {
+ $objWriter->writeAttribute('rotWithShape', $majorGridlines->getShadowProperty('rotWithShape'));
+ }
+ $objWriter->startElement("a:{$majorGridlines->getShadowProperty(['color', 'type'])}");
+ $objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'value']));
+
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'alpha']));
+ $objWriter->endElement(); //end alpha
+
+ $objWriter->endElement(); //end color:type
+ $objWriter->endElement(); //end shadow
+ }
+
+ if ($majorGridlines->getSoftEdgesSize() !== null) {
+ $objWriter->startElement('a:softEdge');
+ $objWriter->writeAttribute('rad', $majorGridlines->getSoftEdgesSize());
+ $objWriter->endElement(); //end softEdge
+ }
+
+ $objWriter->endElement(); //end effectLst
+ $objWriter->endElement(); //end spPr
+ $objWriter->endElement(); //end majorGridLines
+
+ if ($minorGridlines->getObjectState()) {
+ $objWriter->startElement('c:minorGridlines');
+ $objWriter->startElement('c:spPr');
+
+ if ($minorGridlines->getLineColorProperty('value') !== null) {
+ $objWriter->startElement('a:ln');
+ $objWriter->writeAttribute('w', $minorGridlines->getLineStyleProperty('width'));
+ $objWriter->startElement('a:solidFill');
+ $objWriter->startElement("a:{$minorGridlines->getLineColorProperty('type')}");
+ $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('alpha'));
+ $objWriter->endElement(); //end alpha
+ $objWriter->endElement(); //end srgbClr
+ $objWriter->endElement(); //end solidFill
+
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', $minorGridlines->getLineStyleProperty('dash'));
+ $objWriter->endElement();
+
+ if ($minorGridlines->getLineStyleProperty('join') == 'miter') {
+ $objWriter->startElement('a:miter');
+ $objWriter->writeAttribute('lim', '800000');
+ $objWriter->endElement();
+ } else {
+ $objWriter->startElement('a:bevel');
+ $objWriter->endElement();
+ }
+
+ if ($minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
+ $objWriter->startElement('a:headEnd');
+ $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']));
+ $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('head', 'w'));
+ $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('head', 'len'));
+ $objWriter->endElement();
+ }
+
+ if ($minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
+ $objWriter->startElement('a:tailEnd');
+ $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']));
+ $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('end', 'w'));
+ $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('end', 'len'));
+ $objWriter->endElement();
+ }
+ $objWriter->endElement(); //end ln
+ }
+
+ $objWriter->startElement('a:effectLst');
+
+ if ($minorGridlines->getGlowSize() !== null) {
+ $objWriter->startElement('a:glow');
+ $objWriter->writeAttribute('rad', $minorGridlines->getGlowSize());
+ $objWriter->startElement("a:{$minorGridlines->getGlowColor('type')}");
+ $objWriter->writeAttribute('val', $minorGridlines->getGlowColor('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $minorGridlines->getGlowColor('alpha'));
+ $objWriter->endElement(); //end alpha
+ $objWriter->endElement(); //end schemeClr
+ $objWriter->endElement(); //end glow
+ }
+
+ if ($minorGridlines->getShadowProperty('presets') !== null) {
+ $objWriter->startElement("a:{$minorGridlines->getShadowProperty('effect')}");
+ if ($minorGridlines->getShadowProperty('blur') !== null) {
+ $objWriter->writeAttribute('blurRad', $minorGridlines->getShadowProperty('blur'));
+ }
+ if ($minorGridlines->getShadowProperty('distance') !== null) {
+ $objWriter->writeAttribute('dist', $minorGridlines->getShadowProperty('distance'));
+ }
+ if ($minorGridlines->getShadowProperty('direction') !== null) {
+ $objWriter->writeAttribute('dir', $minorGridlines->getShadowProperty('direction'));
+ }
+ if ($minorGridlines->getShadowProperty('algn') !== null) {
+ $objWriter->writeAttribute('algn', $minorGridlines->getShadowProperty('algn'));
+ }
+ if ($minorGridlines->getShadowProperty(['size', 'sx']) !== null) {
+ $objWriter->writeAttribute('sx', $minorGridlines->getShadowProperty(['size', 'sx']));
+ }
+ if ($minorGridlines->getShadowProperty(['size', 'sy']) !== null) {
+ $objWriter->writeAttribute('sy', $minorGridlines->getShadowProperty(['size', 'sy']));
+ }
+ if ($minorGridlines->getShadowProperty(['size', 'kx']) !== null) {
+ $objWriter->writeAttribute('kx', $minorGridlines->getShadowProperty(['size', 'kx']));
+ }
+ if ($minorGridlines->getShadowProperty('rotWithShape') !== null) {
+ $objWriter->writeAttribute('rotWithShape', $minorGridlines->getShadowProperty('rotWithShape'));
+ }
+ $objWriter->startElement("a:{$minorGridlines->getShadowProperty(['color', 'type'])}");
+ $objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'value']));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'alpha']));
+ $objWriter->endElement(); //end alpha
+ $objWriter->endElement(); //end color:type
+ $objWriter->endElement(); //end shadow
+ }
+
+ if ($minorGridlines->getSoftEdgesSize() !== null) {
+ $objWriter->startElement('a:softEdge');
+ $objWriter->writeAttribute('rad', $minorGridlines->getSoftEdgesSize());
+ $objWriter->endElement(); //end softEdge
+ }
+
+ $objWriter->endElement(); //end effectLst
+ $objWriter->endElement(); //end spPr
+ $objWriter->endElement(); //end minorGridLines
+ }
+
+ if ($yAxisLabel !== null) {
+ $objWriter->startElement('c:title');
+ $objWriter->startElement('c:tx');
+ $objWriter->startElement('c:rich');
+
+ $objWriter->startElement('a:bodyPr');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:lstStyle');
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:p');
+ $objWriter->startElement('a:r');
+
+ $caption = $yAxisLabel->getCaption();
+ if (is_array($caption)) {
+ $caption = $caption[0];
+ }
+
+ $objWriter->startElement('a:t');
+ $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($caption));
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ if ($groupType !== DataSeries::TYPE_BUBBLECHART) {
+ $layout = $yAxisLabel->getLayout();
+ $this->writeLayout($objWriter, $layout);
+ }
+
+ $objWriter->startElement('c:overlay');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('c:numFmt');
+ $objWriter->writeAttribute('formatCode', $xAxis->getAxisNumberFormat());
+ $objWriter->writeAttribute('sourceLinked', $xAxis->getAxisNumberSourceLinked());
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:majorTickMark');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark'));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:minorTickMark');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark'));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:tickLblPos');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels'));
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:spPr');
+
+ if ($xAxis->getFillProperty('value') !== null) {
+ $objWriter->startElement('a:solidFill');
+ $objWriter->startElement('a:' . $xAxis->getFillProperty('type'));
+ $objWriter->writeAttribute('val', $xAxis->getFillProperty('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $xAxis->getFillProperty('alpha'));
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('a:ln');
+
+ $objWriter->writeAttribute('w', $xAxis->getLineStyleProperty('width'));
+ $objWriter->writeAttribute('cap', $xAxis->getLineStyleProperty('cap'));
+ $objWriter->writeAttribute('cmpd', $xAxis->getLineStyleProperty('compound'));
+
+ if ($xAxis->getLineProperty('value') !== null) {
+ $objWriter->startElement('a:solidFill');
+ $objWriter->startElement('a:' . $xAxis->getLineProperty('type'));
+ $objWriter->writeAttribute('val', $xAxis->getLineProperty('value'));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $xAxis->getLineProperty('alpha'));
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', $xAxis->getLineStyleProperty('dash'));
+ $objWriter->endElement();
+
+ if ($xAxis->getLineStyleProperty('join') == 'miter') {
+ $objWriter->startElement('a:miter');
+ $objWriter->writeAttribute('lim', '800000');
+ $objWriter->endElement();
+ } else {
+ $objWriter->startElement('a:bevel');
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
+ $objWriter->startElement('a:headEnd');
+ $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'head', 'type']));
+ $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('head'));
+ $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('head'));
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
+ $objWriter->startElement('a:tailEnd');
+ $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'end', 'type']));
+ $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('end'));
+ $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('end'));
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+
+ $objWriter->startElement('a:effectLst');
+
+ if ($xAxis->getGlowProperty('size') !== null) {
+ $objWriter->startElement('a:glow');
+ $objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size'));
+ $objWriter->startElement("a:{$xAxis->getGlowProperty(['color', 'type'])}");
+ $objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'value']));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'alpha']));
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getShadowProperty('presets') !== null) {
+ $objWriter->startElement("a:{$xAxis->getShadowProperty('effect')}");
+
+ if ($xAxis->getShadowProperty('blur') !== null) {
+ $objWriter->writeAttribute('blurRad', $xAxis->getShadowProperty('blur'));
+ }
+ if ($xAxis->getShadowProperty('distance') !== null) {
+ $objWriter->writeAttribute('dist', $xAxis->getShadowProperty('distance'));
+ }
+ if ($xAxis->getShadowProperty('direction') !== null) {
+ $objWriter->writeAttribute('dir', $xAxis->getShadowProperty('direction'));
+ }
+ if ($xAxis->getShadowProperty('algn') !== null) {
+ $objWriter->writeAttribute('algn', $xAxis->getShadowProperty('algn'));
+ }
+ if ($xAxis->getShadowProperty(['size', 'sx']) !== null) {
+ $objWriter->writeAttribute('sx', $xAxis->getShadowProperty(['size', 'sx']));
+ }
+ if ($xAxis->getShadowProperty(['size', 'sy']) !== null) {
+ $objWriter->writeAttribute('sy', $xAxis->getShadowProperty(['size', 'sy']));
+ }
+ if ($xAxis->getShadowProperty(['size', 'kx']) !== null) {
+ $objWriter->writeAttribute('kx', $xAxis->getShadowProperty(['size', 'kx']));
+ }
+ if ($xAxis->getShadowProperty('rotWithShape') !== null) {
+ $objWriter->writeAttribute('rotWithShape', $xAxis->getShadowProperty('rotWithShape'));
+ }
+
+ $objWriter->startElement("a:{$xAxis->getShadowProperty(['color', 'type'])}");
+ $objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'value']));
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'alpha']));
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getSoftEdgesSize() !== null) {
+ $objWriter->startElement('a:softEdge');
+ $objWriter->writeAttribute('rad', $xAxis->getSoftEdgesSize());
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement(); //effectList
+ $objWriter->endElement(); //end spPr
+
+ if ($id1 > 0) {
+ $objWriter->startElement('c:crossAx');
+ $objWriter->writeAttribute('val', $id2);
+ $objWriter->endElement();
+
+ if ($xAxis->getAxisOptionsProperty('horizontal_crosses_value') !== null) {
+ $objWriter->startElement('c:crossesAt');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses_value'));
+ $objWriter->endElement();
+ } else {
+ $objWriter->startElement('c:crosses');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses'));
+ $objWriter->endElement();
+ }
+
+ $objWriter->startElement('c:crossBetween');
+ $objWriter->writeAttribute('val', 'midCat');
+ $objWriter->endElement();
+
+ if ($xAxis->getAxisOptionsProperty('major_unit') !== null) {
+ $objWriter->startElement('c:majorUnit');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_unit'));
+ $objWriter->endElement();
+ }
+
+ if ($xAxis->getAxisOptionsProperty('minor_unit') !== null) {
+ $objWriter->startElement('c:minorUnit');
+ $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_unit'));
+ $objWriter->endElement();
+ }
+ }
+
+ if ($isMultiLevelSeries) {
+ if ($groupType !== DataSeries::TYPE_BUBBLECHART) {
+ $objWriter->startElement('c:noMultiLvlLbl');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Get the data series type(s) for a chart plot series.
+ *
+ * @param PlotArea $plotArea
+ *
+ * @return array|string
+ */
+ private static function getChartType($plotArea)
+ {
+ $groupCount = $plotArea->getPlotGroupCount();
+
+ if ($groupCount == 1) {
+ $chartType = [$plotArea->getPlotGroupByIndex(0)->getPlotType()];
+ } else {
+ $chartTypes = [];
+ for ($i = 0; $i < $groupCount; ++$i) {
+ $chartTypes[] = $plotArea->getPlotGroupByIndex($i)->getPlotType();
+ }
+ $chartType = array_unique($chartTypes);
+ if (count($chartTypes) == 0) {
+ throw new WriterException('Chart is not yet implemented');
+ }
+ }
+
+ return $chartType;
+ }
+
+ /**
+ * Method writing plot series values.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param int $val value for idx (default: 3)
+ * @param string $fillColor hex color (default: FF9900)
+ *
+ * @return XMLWriter XML Writer
+ */
+ private function writePlotSeriesValuesElement($objWriter, $val = 3, $fillColor = 'FF9900')
+ {
+ $objWriter->startElement('c:dPt');
+ $objWriter->startElement('c:idx');
+ $objWriter->writeAttribute('val', $val);
+ $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', $fillColor);
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ return $objWriter;
+ }
+
+ /**
+ * Write Plot Group (series of related plots).
+ *
+ * @param DataSeries $plotGroup
+ * @param string $groupType Type of plot for dataseries
+ * @param XMLWriter $objWriter XML Writer
+ * @param bool &$catIsMultiLevelSeries Is category a multi-series category
+ * @param bool &$valIsMultiLevelSeries Is value set a multi-series set
+ * @param string &$plotGroupingType Type of grouping for multi-series values
+ */
+ private function writePlotGroup($plotGroup, $groupType, $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries, &$plotGroupingType): void
+ {
+ if ($plotGroup === null) {
+ return;
+ }
+
+ if (($groupType == DataSeries::TYPE_BARCHART) || ($groupType == DataSeries::TYPE_BARCHART_3D)) {
+ $objWriter->startElement('c:barDir');
+ $objWriter->writeAttribute('val', $plotGroup->getPlotDirection());
+ $objWriter->endElement();
+ }
+
+ if ($plotGroup->getPlotGrouping() !== null) {
+ $plotGroupingType = $plotGroup->getPlotGrouping();
+ $objWriter->startElement('c:grouping');
+ $objWriter->writeAttribute('val', $plotGroupingType);
+ $objWriter->endElement();
+ }
+
+ // Get these details before the loop, because we can use the count to check for varyColors
+ $plotSeriesOrder = $plotGroup->getPlotOrder();
+ $plotSeriesCount = count($plotSeriesOrder);
+
+ if (($groupType !== DataSeries::TYPE_RADARCHART) && ($groupType !== DataSeries::TYPE_STOCKCHART)) {
+ if ($groupType !== DataSeries::TYPE_LINECHART) {
+ if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART) || ($plotSeriesCount > 1)) {
+ $objWriter->startElement('c:varyColors');
+ $objWriter->writeAttribute('val', 1);
+ $objWriter->endElement();
+ } else {
+ $objWriter->startElement('c:varyColors');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+ }
+ }
+ }
+
+ foreach ($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) {
+ $objWriter->startElement('c:ser');
+
+ $plotLabel = $plotGroup->getPlotLabelByIndex($plotSeriesIdx);
+ if ($plotLabel) {
+ $fillColor = $plotLabel->getFillColor();
+ if ($fillColor !== null && !is_array($fillColor)) {
+ $objWriter->startElement('c:spPr');
+ $objWriter->startElement('a:solidFill');
+ $objWriter->startElement('a:srgbClr');
+ $objWriter->writeAttribute('val', $fillColor);
+ $objWriter->endElement();
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->startElement('c:idx');
+ $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesIdx);
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:order');
+ $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesRef);
+ $objWriter->endElement();
+
+ // Values
+ $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesRef);
+
+ if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART)) {
+ $fillColorValues = $plotSeriesValues->getFillColor();
+ if ($fillColorValues !== null && is_array($fillColorValues)) {
+ foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) {
+ $this->writePlotSeriesValuesElement($objWriter, $dataKey, ($fillColorValues[$dataKey] ?? 'FF9900'));
+ }
+ } else {
+ $this->writePlotSeriesValuesElement($objWriter);
+ }
+ }
+
+ // 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 == DataSeries::TYPE_LINECHART) || ($groupType == DataSeries::TYPE_STOCKCHART)) {
+ $plotLineWidth = 12700;
+ if ($plotSeriesValues) {
+ $plotLineWidth = $plotSeriesValues->getLineWidth();
+ }
+
+ $objWriter->startElement('c:spPr');
+ $objWriter->startElement('a:ln');
+ $objWriter->writeAttribute('w', $plotLineWidth);
+ if ($groupType == DataSeries::TYPE_STOCKCHART) {
+ $objWriter->startElement('a:noFill');
+ $objWriter->endElement();
+ }
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+
+ if ($plotSeriesValues) {
+ $plotSeriesMarker = $plotSeriesValues->getPointMarker();
+ if ($plotSeriesMarker) {
+ $objWriter->startElement('c:marker');
+ $objWriter->startElement('c:symbol');
+ $objWriter->writeAttribute('val', $plotSeriesMarker);
+ $objWriter->endElement();
+
+ if ($plotSeriesMarker !== 'none') {
+ $objWriter->startElement('c:size');
+ $objWriter->writeAttribute('val', 3);
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+ }
+
+ if (($groupType === DataSeries::TYPE_BARCHART) || ($groupType === DataSeries::TYPE_BARCHART_3D) || ($groupType === DataSeries::TYPE_BUBBLECHART)) {
+ $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();
+
+ if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART)) {
+ if ($plotGroup->getPlotStyle() !== null) {
+ $plotStyle = $plotGroup->getPlotStyle();
+ if ($plotStyle) {
+ $objWriter->startElement('c:explosion');
+ $objWriter->writeAttribute('val', 25);
+ $objWriter->endElement();
+ }
+ }
+ }
+
+ if (($groupType === DataSeries::TYPE_BUBBLECHART) || ($groupType === DataSeries::TYPE_SCATTERCHART)) {
+ $objWriter->startElement('c:xVal');
+ } else {
+ $objWriter->startElement('c:cat');
+ }
+
+ $this->writePlotSeriesValues($plotSeriesCategory, $objWriter, $groupType, 'str');
+ $objWriter->endElement();
+ }
+
+ // Values
+ if ($plotSeriesValues) {
+ $valIsMultiLevelSeries = $valIsMultiLevelSeries || $plotSeriesValues->isMultiLevelSeries();
+
+ if (($groupType === DataSeries::TYPE_BUBBLECHART) || ($groupType === DataSeries::TYPE_SCATTERCHART)) {
+ $objWriter->startElement('c:yVal');
+ } else {
+ $objWriter->startElement('c:val');
+ }
+
+ $this->writePlotSeriesValues($plotSeriesValues, $objWriter, $groupType, 'num');
+ $objWriter->endElement();
+ }
+
+ if ($groupType === DataSeries::TYPE_BUBBLECHART) {
+ $this->writeBubbles($plotSeriesValues, $objWriter);
+ }
+
+ $objWriter->endElement();
+ }
+
+ $this->seriesIndex += $plotSeriesIdx + 1;
+ }
+
+ /**
+ * Write Plot Series Label.
+ *
+ * @param DataSeriesValues $plotSeriesLabel
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writePlotSeriesLabel($plotSeriesLabel, $objWriter): void
+ {
+ if ($plotSeriesLabel === null) {
+ 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();
+ }
+
+ /**
+ * Write Plot Series Values.
+ *
+ * @param DataSeriesValues $plotSeriesValues
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $groupType Type of plot for dataseries
+ * @param string $dataType Datatype of series values
+ */
+ private function writePlotSeriesValues($plotSeriesValues, XMLWriter $objWriter, $groupType, $dataType = 'str'): void
+ {
+ if ($plotSeriesValues === null) {
+ 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');
+
+ if (($groupType != DataSeries::TYPE_PIECHART) && ($groupType != DataSeries::TYPE_PIECHART_3D) && ($groupType != DataSeries::TYPE_DONUTCHART)) {
+ if (($plotSeriesValues->getFormatCode() !== null) && ($plotSeriesValues->getFormatCode() !== '')) {
+ $objWriter->startElement('c:formatCode');
+ $objWriter->writeRawData($plotSeriesValues->getFormatCode());
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->startElement('c:ptCount');
+ $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount());
+ $objWriter->endElement();
+
+ $dataValues = $plotSeriesValues->getDataValues();
+ if (!empty($dataValues)) {
+ if (is_array($dataValues)) {
+ foreach ($dataValues 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();
+ }
+ }
+
+ /**
+ * Write Bubble Chart Details.
+ *
+ * @param DataSeriesValues $plotSeriesValues
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeBubbles($plotSeriesValues, $objWriter): void
+ {
+ if ($plotSeriesValues === null) {
+ return;
+ }
+
+ $objWriter->startElement('c:bubbleSize');
+ $objWriter->startElement('c:numLit');
+
+ $objWriter->startElement('c:formatCode');
+ $objWriter->writeRawData('General');
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:ptCount');
+ $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount());
+ $objWriter->endElement();
+
+ $dataValues = $plotSeriesValues->getDataValues();
+ if (!empty($dataValues)) {
+ if (is_array($dataValues)) {
+ foreach ($dataValues as $plotSeriesKey => $plotSeriesValue) {
+ $objWriter->startElement('c:pt');
+ $objWriter->writeAttribute('idx', $plotSeriesKey);
+ $objWriter->startElement('c:v');
+ $objWriter->writeRawData(1);
+ $objWriter->endElement();
+ $objWriter->endElement();
+ }
+ }
+ }
+
+ $objWriter->endElement();
+ $objWriter->endElement();
+
+ $objWriter->startElement('c:bubble3D');
+ $objWriter->writeAttribute('val', 0);
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Layout.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Layout $layout
+ */
+ private function writeLayout(XMLWriter $objWriter, ?Layout $layout = null): void
+ {
+ $objWriter->startElement('c:layout');
+
+ if ($layout !== null) {
+ $objWriter->startElement('c:manualLayout');
+
+ $layoutTarget = $layout->getLayoutTarget();
+ if ($layoutTarget !== null) {
+ $objWriter->startElement('c:layoutTarget');
+ $objWriter->writeAttribute('val', $layoutTarget);
+ $objWriter->endElement();
+ }
+
+ $xMode = $layout->getXMode();
+ if ($xMode !== null) {
+ $objWriter->startElement('c:xMode');
+ $objWriter->writeAttribute('val', $xMode);
+ $objWriter->endElement();
+ }
+
+ $yMode = $layout->getYMode();
+ if ($yMode !== null) {
+ $objWriter->startElement('c:yMode');
+ $objWriter->writeAttribute('val', $yMode);
+ $objWriter->endElement();
+ }
+
+ $x = $layout->getXPosition();
+ if ($x !== null) {
+ $objWriter->startElement('c:x');
+ $objWriter->writeAttribute('val', $x);
+ $objWriter->endElement();
+ }
+
+ $y = $layout->getYPosition();
+ if ($y !== null) {
+ $objWriter->startElement('c:y');
+ $objWriter->writeAttribute('val', $y);
+ $objWriter->endElement();
+ }
+
+ $w = $layout->getWidth();
+ if ($w !== null) {
+ $objWriter->startElement('c:w');
+ $objWriter->writeAttribute('val', $w);
+ $objWriter->endElement();
+ }
+
+ $h = $layout->getHeight();
+ if ($h !== null) {
+ $objWriter->startElement('c:h');
+ $objWriter->writeAttribute('val', $h);
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Alternate Content block.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeAlternateContent($objWriter): void
+ {
+ $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();
+ }
+
+ /**
+ * Write Printer Settings.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writePrintSettings($objWriter): void
+ {
+ $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/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php
new file mode 100644
index 0000000..3d012fe
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+use PhpOffice\PhpSpreadsheet\Comment;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+
+class Comments extends WriterPart
+{
+ /**
+ * Write comments to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // Comments cache
+ $comments = $pWorksheet->getComments();
+
+ // Authors cache
+ $authors = [];
+ $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');
+
+ // 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();
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write comment to XML format.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pCellReference Cell reference
+ * @param Comment $pComment Comment
+ * @param array $pAuthors Array of authors
+ */
+ private function writeComment(XMLWriter $objWriter, $pCellReference, Comment $pComment, array $pAuthors): void
+ {
+ // 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();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write VML comments to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeVMLComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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');
+
+ // 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();
+
+ $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: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();
+
+ $objWriter->endElement();
+
+ // Loop through comments
+ foreach ($comments as $key => $value) {
+ $this->writeVMLComment($objWriter, $key, $value);
+ }
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write VML comment to XML format.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pCellReference Cell reference, eg: 'A1'
+ * @param Comment $pComment Comment
+ */
+ private function writeVMLComment(XMLWriter $objWriter, $pCellReference, Comment $pComment): void
+ {
+ // Metadata
+ [$column, $row] = Coordinate::coordinateFromString($pCellReference);
+ $column = Coordinate::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: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: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');
+
+ // div
+ $objWriter->startElement('div');
+ $objWriter->writeAttribute('style', 'text-align:left');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // x:ClientData
+ $objWriter->startElement('x:ClientData');
+ $objWriter->writeAttribute('ObjectType', 'Note');
+
+ // x:MoveWithCells
+ $objWriter->writeElement('x:MoveWithCells', '');
+
+ // x:SizeWithCells
+ $objWriter->writeElement('x:SizeWithCells', '');
+
+ // x:AutoFill
+ $objWriter->writeElement('x:AutoFill', 'False');
+
+ // x:Row
+ $objWriter->writeElement('x:Row', ($row - 1));
+
+ // x:Column
+ $objWriter->writeElement('x:Column', ($column - 1));
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php
new file mode 100644
index 0000000..2499d97
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php
@@ -0,0 +1,240 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\File;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
+use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
+
+class ContentTypes extends WriterPart
+{
+ /**
+ * Write content types to XML format.
+ *
+ * @param bool $includeCharts Flag indicating if we should include drawing details for charts
+ *
+ * @return string XML Output
+ */
+ public function writeContentTypes(Spreadsheet $spreadsheet, $includeCharts = false)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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');
+
+ // 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');
+
+ // XML
+ $this->writeDefaultContentType($objWriter, 'xml', 'application/xml');
+
+ // VML
+ $this->writeDefaultContentType($objWriter, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing');
+
+ // Workbook
+ if ($spreadsheet->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
+ // Better use Override, because we can use 'bin' also for xl\printerSettings\printerSettings1.bin
+ $this->writeOverrideContentType($objWriter, '/xl/vbaProject.bin', 'application/vnd.ms-office.vbaProject');
+ if ($spreadsheet->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');
+
+ $this->writeOverrideContentType($objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml');
+
+ $customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
+ if (!empty($customPropertyList)) {
+ $this->writeOverrideContentType($objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml');
+ }
+
+ // Worksheets
+ $sheetCount = $spreadsheet->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');
+
+ // Add worksheet relationship content types
+ $unparsedLoadedData = $spreadsheet->getUnparsedLoadedData();
+ $chart = 1;
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ $drawings = $spreadsheet->getSheet($i)->getDrawingCollection();
+ $drawingCount = count($drawings);
+ $chartCount = ($includeCharts) ? $spreadsheet->getSheet($i)->getChartCount() : 0;
+ $hasUnparsedDrawing = isset($unparsedLoadedData['sheets'][$spreadsheet->getSheet($i)->getCodeName()]['drawingOriginalIds']);
+
+ // We need a drawing relationship for the worksheet if we have either drawings or charts
+ if (($drawingCount > 0) || ($chartCount > 0) || $hasUnparsedDrawing) {
+ $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
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ if (count($spreadsheet->getSheet($i)->getComments()) > 0) {
+ $this->writeOverrideContentType($objWriter, '/xl/comments' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml');
+ }
+ }
+
+ // Add media content-types
+ $aMediaContentTypes = [];
+ $mediaCount = $this->getParentWriter()->getDrawingHashTable()->count();
+ for ($i = 0; $i < $mediaCount; ++$i) {
+ $extension = '';
+ $mimeType = '';
+
+ if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing) {
+ $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension());
+ $mimeType = $this->getImageMimeType($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath());
+ } elseif ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
+ $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType());
+ $extension = explode('/', $extension);
+ $extension = $extension[1];
+
+ $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType();
+ }
+
+ if (!isset($aMediaContentTypes[$extension])) {
+ $aMediaContentTypes[$extension] = $mimeType;
+
+ $this->writeDefaultContentType($objWriter, $extension, $mimeType);
+ }
+ }
+ if ($spreadsheet->hasRibbonBinObjects()) {
+ // Some additional objects in the ribbon ?
+ // we need to write "Extension" but not already write for media content
+ $tabRibbonTypes = array_diff($spreadsheet->getRibbonBinObjects('types'), array_keys($aMediaContentTypes));
+ foreach ($tabRibbonTypes as $aRibbonType) {
+ $mimeType = 'image/.' . $aRibbonType; //we wrote $mimeType like customUI Editor
+ $this->writeDefaultContentType($objWriter, $aRibbonType, $mimeType);
+ }
+ }
+ $sheetCount = $spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ if (count($spreadsheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
+ foreach ($spreadsheet->getSheet($i)->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())]);
+ }
+ }
+ }
+ }
+
+ // unparsed defaults
+ if (isset($unparsedLoadedData['default_content_types'])) {
+ foreach ($unparsedLoadedData['default_content_types'] as $extName => $contentType) {
+ $this->writeDefaultContentType($objWriter, $extName, $contentType);
+ }
+ }
+
+ // unparsed overrides
+ if (isset($unparsedLoadedData['override_content_types'])) {
+ foreach ($unparsedLoadedData['override_content_types'] as $partName => $overrideType) {
+ $this->writeOverrideContentType($objWriter, $partName, $overrideType);
+ }
+ }
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Get image mime type.
+ *
+ * @param string $pFile Filename
+ *
+ * @return string Mime Type
+ */
+ private function getImageMimeType($pFile)
+ {
+ if (File::fileExists($pFile)) {
+ $image = getimagesize($pFile);
+
+ return image_type_to_mime_type($image[2]);
+ }
+
+ throw new WriterException("File $pFile does not exist");
+ }
+
+ /**
+ * Write Default content type.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pPartname Part name
+ * @param string $pContentType Content type
+ */
+ private function writeDefaultContentType(XMLWriter $objWriter, $pPartname, $pContentType): void
+ {
+ if ($pPartname != '' && $pContentType != '') {
+ // Write content type
+ $objWriter->startElement('Default');
+ $objWriter->writeAttribute('Extension', $pPartname);
+ $objWriter->writeAttribute('ContentType', $pContentType);
+ $objWriter->endElement();
+ } else {
+ throw new WriterException('Invalid parameters passed.');
+ }
+ }
+
+ /**
+ * Write Override content type.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pPartname Part name
+ * @param string $pContentType Content type
+ */
+ private function writeOverrideContentType(XMLWriter $objWriter, $pPartname, $pContentType): void
+ {
+ if ($pPartname != '' && $pContentType != '') {
+ // Write content type
+ $objWriter->startElement('Override');
+ $objWriter->writeAttribute('PartName', $pPartname);
+ $objWriter->writeAttribute('ContentType', $pContentType);
+ $objWriter->endElement();
+ } else {
+ throw new WriterException('Invalid parameters passed.');
+ }
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php
new file mode 100644
index 0000000..43a8d2e
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+use PhpOffice\PhpSpreadsheet\DefinedName;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
+
+class DefinedNames
+{
+ private $objWriter;
+
+ private $spreadsheet;
+
+ public function __construct(XMLWriter $objWriter, Spreadsheet $spreadsheet)
+ {
+ $this->objWriter = $objWriter;
+ $this->spreadsheet = $spreadsheet;
+ }
+
+ public function write(): void
+ {
+ // Write defined names
+ $this->objWriter->startElement('definedNames');
+
+ // Named ranges
+ if (count($this->spreadsheet->getDefinedNames()) > 0) {
+ // Named ranges
+ $this->writeNamedRangesAndFormulae();
+ }
+
+ // Other defined names
+ $sheetCount = $this->spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ // NamedRange for autoFilter
+ $this->writeNamedRangeForAutofilter($this->spreadsheet->getSheet($i), $i);
+
+ // NamedRange for Print_Titles
+ $this->writeNamedRangeForPrintTitles($this->spreadsheet->getSheet($i), $i);
+
+ // NamedRange for Print_Area
+ $this->writeNamedRangeForPrintArea($this->spreadsheet->getSheet($i), $i);
+ }
+
+ $this->objWriter->endElement();
+ }
+
+ /**
+ * Write defined names.
+ */
+ private function writeNamedRangesAndFormulae(): void
+ {
+ // Loop named ranges
+ $definedNames = $this->spreadsheet->getDefinedNames();
+ foreach ($definedNames as $definedName) {
+ $this->writeDefinedName($definedName);
+ }
+ }
+
+ /**
+ * Write Defined Name for named range.
+ */
+ private function writeDefinedName(DefinedName $pDefinedName): void
+ {
+ // definedName for named range
+ $this->objWriter->startElement('definedName');
+ $this->objWriter->writeAttribute('name', $pDefinedName->getName());
+ if ($pDefinedName->getLocalOnly() && $pDefinedName->getScope() !== null) {
+ $this->objWriter->writeAttribute('localSheetId', $pDefinedName->getScope()->getParent()->getIndex($pDefinedName->getScope()));
+ }
+
+ $definedRange = $pDefinedName->getValue();
+ $splitCount = preg_match_all(
+ '/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
+ $definedRange,
+ $splitRanges,
+ PREG_OFFSET_CAPTURE
+ );
+
+ $lengths = array_map('strlen', array_column($splitRanges[0], 0));
+ $offsets = array_column($splitRanges[0], 1);
+
+ $worksheets = $splitRanges[2];
+ $columns = $splitRanges[6];
+ $rows = $splitRanges[7];
+
+ while ($splitCount > 0) {
+ --$splitCount;
+ $length = $lengths[$splitCount];
+ $offset = $offsets[$splitCount];
+ $worksheet = $worksheets[$splitCount][0];
+ $column = $columns[$splitCount][0];
+ $row = $rows[$splitCount][0];
+
+ $newRange = '';
+ if (empty($worksheet)) {
+ if (($offset === 0) || ($definedRange[$offset - 1] !== ':')) {
+ // We should have a worksheet
+ $worksheet = $pDefinedName->getWorksheet()->getTitle();
+ }
+ } else {
+ $worksheet = str_replace("''", "'", trim($worksheet, "'"));
+ }
+ if (!empty($worksheet)) {
+ $newRange = "'" . str_replace("'", "''", $worksheet) . "'!";
+ }
+
+ if (!empty($column)) {
+ $newRange .= $column;
+ }
+ if (!empty($row)) {
+ $newRange .= $row;
+ }
+
+ $definedRange = substr($definedRange, 0, $offset) . $newRange . substr($definedRange, $offset + $length);
+ }
+
+ if (substr($definedRange, 0, 1) === '=') {
+ $definedRange = substr($definedRange, 1);
+ }
+
+ $this->objWriter->writeRawData($definedRange);
+
+ $this->objWriter->endElement();
+ }
+
+ /**
+ * Write Defined Name for autoFilter.
+ */
+ private function writeNamedRangeForAutofilter(Worksheet $pSheet, int $pSheetId = 0): void
+ {
+ // NamedRange for autoFilter
+ $autoFilterRange = $pSheet->getAutoFilter()->getRange();
+ if (!empty($autoFilterRange)) {
+ $this->objWriter->startElement('definedName');
+ $this->objWriter->writeAttribute('name', '_xlnm._FilterDatabase');
+ $this->objWriter->writeAttribute('localSheetId', $pSheetId);
+ $this->objWriter->writeAttribute('hidden', '1');
+
+ // Create absolute coordinate and write as raw text
+ $range = Coordinate::splitRange($autoFilterRange);
+ $range = $range[0];
+ // Strip any worksheet ref so we can make the cell ref absolute
+ [$ws, $range[0]] = Worksheet::extractSheetTitle($range[0], true);
+
+ $range[0] = Coordinate::absoluteCoordinate($range[0]);
+ $range[1] = Coordinate::absoluteCoordinate($range[1]);
+ $range = implode(':', $range);
+
+ $this->objWriter->writeRawData('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . $range);
+
+ $this->objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write Defined Name for PrintTitles.
+ */
+ private function writeNamedRangeForPrintTitles(Worksheet $pSheet, int $pSheetId = 0): void
+ {
+ // NamedRange for PrintTitles
+ if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
+ $this->objWriter->startElement('definedName');
+ $this->objWriter->writeAttribute('name', '_xlnm.Print_Titles');
+ $this->objWriter->writeAttribute('localSheetId', $pSheetId);
+
+ // Setting string
+ $settingString = '';
+
+ // Columns to repeat
+ if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
+ $repeat = $pSheet->getPageSetup()->getColumnsToRepeatAtLeft();
+
+ $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
+ }
+
+ // Rows to repeat
+ if ($pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
+ if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
+ $settingString .= ',';
+ }
+
+ $repeat = $pSheet->getPageSetup()->getRowsToRepeatAtTop();
+
+ $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
+ }
+
+ $this->objWriter->writeRawData($settingString);
+
+ $this->objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write Defined Name for PrintTitles.
+ */
+ private function writeNamedRangeForPrintArea(Worksheet $pSheet, int $pSheetId = 0): void
+ {
+ // NamedRange for PrintArea
+ if ($pSheet->getPageSetup()->isPrintAreaSet()) {
+ $this->objWriter->startElement('definedName');
+ $this->objWriter->writeAttribute('name', '_xlnm.Print_Area');
+ $this->objWriter->writeAttribute('localSheetId', $pSheetId);
+
+ // Print area
+ $printArea = Coordinate::splitRange($pSheet->getPageSetup()->getPrintArea());
+
+ $chunks = [];
+ foreach ($printArea as $printAreaRect) {
+ $printAreaRect[0] = Coordinate::absoluteReference($printAreaRect[0]);
+ $printAreaRect[1] = Coordinate::absoluteReference($printAreaRect[1]);
+ $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect);
+ }
+
+ $this->objWriter->writeRawData(implode(',', $chunks));
+
+ $this->objWriter->endElement();
+ }
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
new file mode 100644
index 0000000..7125b70
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
@@ -0,0 +1,239 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+class DocProps extends WriterPart
+{
+ /**
+ * Write docProps/app.xml to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeDocPropsApp(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ // Application
+ $objWriter->writeElement('Application', 'Microsoft Excel');
+
+ // DocSecurity
+ $objWriter->writeElement('DocSecurity', '0');
+
+ // ScaleCrop
+ $objWriter->writeElement('ScaleCrop', 'false');
+
+ // HeadingPairs
+ $objWriter->startElement('HeadingPairs');
+
+ // 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:i4', $spreadsheet->getSheetCount());
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // TitlesOfParts
+ $objWriter->startElement('TitlesOfParts');
+
+ // Vector
+ $objWriter->startElement('vt:vector');
+ $objWriter->writeAttribute('size', $spreadsheet->getSheetCount());
+ $objWriter->writeAttribute('baseType', 'lpstr');
+
+ $sheetCount = $spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ $objWriter->writeElement('vt:lpstr', $spreadsheet->getSheet($i)->getTitle());
+ }
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // Company
+ $objWriter->writeElement('Company', $spreadsheet->getProperties()->getCompany());
+
+ // Company
+ $objWriter->writeElement('Manager', $spreadsheet->getProperties()->getManager());
+
+ // LinksUpToDate
+ $objWriter->writeElement('LinksUpToDate', 'false');
+
+ // SharedDoc
+ $objWriter->writeElement('SharedDoc', 'false');
+
+ // HyperlinksChanged
+ $objWriter->writeElement('HyperlinksChanged', 'false');
+
+ // AppVersion
+ $objWriter->writeElement('AppVersion', '12.0000');
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write docProps/core.xml to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeDocPropsCore(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ // dc:creator
+ $objWriter->writeElement('dc:creator', $spreadsheet->getProperties()->getCreator());
+
+ // cp:lastModifiedBy
+ $objWriter->writeElement('cp:lastModifiedBy', $spreadsheet->getProperties()->getLastModifiedBy());
+
+ // dcterms:created
+ $objWriter->startElement('dcterms:created');
+ $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
+ $objWriter->writeRawData(date(DATE_W3C, $spreadsheet->getProperties()->getCreated()));
+ $objWriter->endElement();
+
+ // dcterms:modified
+ $objWriter->startElement('dcterms:modified');
+ $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
+ $objWriter->writeRawData(date(DATE_W3C, $spreadsheet->getProperties()->getModified()));
+ $objWriter->endElement();
+
+ // dc:title
+ $objWriter->writeElement('dc:title', $spreadsheet->getProperties()->getTitle());
+
+ // dc:description
+ $objWriter->writeElement('dc:description', $spreadsheet->getProperties()->getDescription());
+
+ // dc:subject
+ $objWriter->writeElement('dc:subject', $spreadsheet->getProperties()->getSubject());
+
+ // cp:keywords
+ $objWriter->writeElement('cp:keywords', $spreadsheet->getProperties()->getKeywords());
+
+ // cp:category
+ $objWriter->writeElement('cp:category', $spreadsheet->getProperties()->getCategory());
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write docProps/custom.xml to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeDocPropsCustom(Spreadsheet $spreadsheet)
+ {
+ $customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
+ if (empty($customPropertyList)) {
+ return;
+ }
+
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ foreach ($customPropertyList as $key => $customProperty) {
+ $propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty);
+ $propertyType = $spreadsheet->getProperties()->getCustomPropertyType($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;
+ }
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
new file mode 100644
index 0000000..3f989df
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
@@ -0,0 +1,505 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
+use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
+use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
+
+class Drawing extends WriterPart
+{
+ /**
+ * Write drawings to XML format.
+ *
+ * @param bool $includeCharts Flag indicating if we should include drawing details for charts
+ *
+ * @return string XML Output
+ */
+ public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, $includeCharts = false)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ // Loop through images and write drawings
+ $i = 1;
+ $iterator = $pWorksheet->getDrawingCollection()->getIterator();
+ while ($iterator->valid()) {
+ /** @var BaseDrawing $pDrawing */
+ $pDrawing = $iterator->current();
+ $pRelationId = $i;
+ $hlinkClickId = $pDrawing->getHyperlink() === null ? null : ++$i;
+
+ $this->writeDrawing($objWriter, $pDrawing, $pRelationId, $hlinkClickId);
+
+ $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);
+ }
+ }
+ }
+
+ // unparsed AlternateContent
+ $unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
+ if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'])) {
+ foreach ($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
+ $objWriter->writeRaw($drawingAlternateContent);
+ }
+ }
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write drawings to XML format.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param int $pRelationId
+ */
+ public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $pRelationId = -1): void
+ {
+ $tl = $pChart->getTopLeftPosition();
+ $tl['colRow'] = Coordinate::coordinateFromString($tl['cell']);
+ $br = $pChart->getBottomRightPosition();
+ $br['colRow'] = Coordinate::coordinateFromString($br['cell']);
+
+ $objWriter->startElement('xdr:twoCellAnchor');
+
+ $objWriter->startElement('xdr:from');
+ $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($tl['colRow'][0]) - 1);
+ $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
+ $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1);
+ $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
+ $objWriter->endElement();
+ $objWriter->startElement('xdr:to');
+ $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($br['colRow'][0]) - 1);
+ $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
+ $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1);
+ $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\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.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param int $pRelationId
+ * @param null|int $hlinkClickId
+ */
+ public function writeDrawing(XMLWriter $objWriter, BaseDrawing $pDrawing, $pRelationId = -1, $hlinkClickId = null): void
+ {
+ if ($pRelationId >= 0) {
+ // xdr:oneCellAnchor
+ $objWriter->startElement('xdr:oneCellAnchor');
+ // Image location
+ $aCoordinates = Coordinate::coordinateFromString($pDrawing->getCoordinates());
+ $aCoordinates[0] = Coordinate::columnIndexFromString($aCoordinates[0]);
+
+ // xdr:from
+ $objWriter->startElement('xdr:from');
+ $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
+ $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetX()));
+ $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
+ $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetY()));
+ $objWriter->endElement();
+
+ // xdr:ext
+ $objWriter->startElement('xdr:ext');
+ $objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getWidth()));
+ $objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getHeight()));
+ $objWriter->endElement();
+
+ // xdr:pic
+ $objWriter->startElement('xdr:pic');
+
+ // 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());
+
+ //a:hlinkClick
+ $this->writeHyperLinkDrawing($objWriter, $hlinkClickId);
+
+ $objWriter->endElement();
+
+ // xdr:cNvPicPr
+ $objWriter->startElement('xdr:cNvPicPr');
+
+ // a:picLocks
+ $objWriter->startElement('a:picLocks');
+ $objWriter->writeAttribute('noChangeAspect', '1');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // 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:stretch
+ $objWriter->startElement('a:stretch');
+ $objWriter->writeElement('a:fillRect', null);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // xdr:spPr
+ $objWriter->startElement('xdr:spPr');
+
+ // a:xfrm
+ $objWriter->startElement('a:xfrm');
+ $objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getRotation()));
+ $objWriter->endElement();
+
+ // a:prstGeom
+ $objWriter->startElement('a:prstGeom');
+ $objWriter->writeAttribute('prst', 'rect');
+
+ // a:avLst
+ $objWriter->writeElement('a:avLst', null);
+
+ $objWriter->endElement();
+
+ if ($pDrawing->getShadow()->getVisible()) {
+ // a:effectLst
+ $objWriter->startElement('a:effectLst');
+
+ // a:outerShdw
+ $objWriter->startElement('a:outerShdw');
+ $objWriter->writeAttribute('blurRad', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius()));
+ $objWriter->writeAttribute('dist', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance()));
+ $objWriter->writeAttribute('dir', \PhpOffice\PhpSpreadsheet\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:alpha
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // xdr:clientData
+ $objWriter->writeElement('xdr:clientData', null);
+
+ $objWriter->endElement();
+ } else {
+ throw new WriterException('Invalid parameters passed.');
+ }
+ }
+
+ /**
+ * Write VML header/footer images to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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');
+
+ // 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();
+
+ $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:stroke
+ $objWriter->startElement('v:stroke');
+ $objWriter->writeAttribute('joinstyle', 'miter');
+ $objWriter->endElement();
+
+ // 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', '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', '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 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', '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', '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', 'sum @10 21600 0');
+ $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();
+
+ // o:lock
+ $objWriter->startElement('o:lock');
+ $objWriter->writeAttribute('v:ext', 'edit');
+ $objWriter->writeAttribute('aspectratio', 't');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // Loop through images
+ foreach ($images as $key => $value) {
+ $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
+ }
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write VML comment to XML format.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pReference Reference
+ * @param HeaderFooterDrawing $pImage Image
+ */
+ private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $pReference, HeaderFooterDrawing $pImage): void
+ {
+ // 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();
+
+ // 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();
+
+ // o:lock
+ $objWriter->startElement('o:lock');
+ $objWriter->writeAttribute('v:ext', 'edit');
+ $objWriter->writeAttribute('textRotation', 't');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Get an array of all drawings.
+ *
+ * @return \PhpOffice\PhpSpreadsheet\Worksheet\Drawing[] All drawings in PhpSpreadsheet
+ */
+ public function allDrawings(Spreadsheet $spreadsheet)
+ {
+ // Get an array of all drawings
+ $aDrawings = [];
+
+ // Loop through PhpSpreadsheet
+ $sheetCount = $spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ // Loop through images and add to array
+ $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
+ while ($iterator->valid()) {
+ $aDrawings[] = $iterator->current();
+
+ $iterator->next();
+ }
+ }
+
+ return $aDrawings;
+ }
+
+ /**
+ * @param null|int $hlinkClickId
+ */
+ private function writeHyperLinkDrawing(XMLWriter $objWriter, $hlinkClickId): void
+ {
+ if ($hlinkClickId === null) {
+ return;
+ }
+
+ $objWriter->startElement('a:hlinkClick');
+ $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
+ $objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
+ $objWriter->endElement();
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php
new file mode 100644
index 0000000..3d14f9a
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php
@@ -0,0 +1,451 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
+use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
+
+class Rels extends WriterPart
+{
+ /**
+ * Write relationships to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeRelationships(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // Relationships
+ $objWriter->startElement('Relationships');
+ $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
+
+ $customPropertyList = $spreadsheet->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/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 ($spreadsheet->hasRibbon()) {
+ $this->writeRelationShip(
+ $objWriter,
+ 5,
+ 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility',
+ $spreadsheet->getRibbonXMLData('target')
+ );
+ }
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write workbook relationships to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeWorkbookRelationships(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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 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'
+ );
+
+ // Relationships with sheets
+ $sheetCount = $spreadsheet->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 ($spreadsheet->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();
+
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write worksheet relationships to XML format.
+ *
+ * Numbering is as follows:
+ * rId1 - Drawings
+ * rId_hyperlink_x - Hyperlinks
+ *
+ * @param int $pWorksheetId
+ * @param bool $includeCharts Flag indicating if we should write charts
+ *
+ * @return string XML Output
+ */
+ public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, $pWorksheetId = 1, $includeCharts = false)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // Relationships
+ $objWriter->startElement('Relationships');
+ $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
+
+ // Write drawing relationships?
+ $drawingOriginalIds = [];
+ $unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
+ if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingOriginalIds'])) {
+ $drawingOriginalIds = $unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingOriginalIds'];
+ }
+
+ if ($includeCharts) {
+ $charts = $pWorksheet->getChartCollection();
+ } else {
+ $charts = [];
+ }
+
+ if (($pWorksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
+ $rId = 1;
+
+ // Use original $relPath to get original $rId.
+ // Take first. In future can be overwritten.
+ // (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeDrawings)
+ reset($drawingOriginalIds);
+ $relPath = key($drawingOriginalIds);
+ if (isset($drawingOriginalIds[$relPath])) {
+ $rId = (int) (substr($drawingOriginalIds[$relPath], 3));
+ }
+
+ // Generate new $relPath to write drawing relationship
+ $relPath = '../drawings/drawing' . $pWorksheetId . '.xml';
+ $this->writeRelationship(
+ $objWriter,
+ $rId,
+ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
+ $relPath
+ );
+ }
+
+ // 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;
+ }
+ }
+
+ // 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'
+ );
+ }
+
+ // 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'
+ );
+ }
+
+ $this->writeUnparsedRelationship($pWorksheet, $objWriter, 'ctrlProps', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp');
+ $this->writeUnparsedRelationship($pWorksheet, $objWriter, 'vmlDrawings', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing');
+ $this->writeUnparsedRelationship($pWorksheet, $objWriter, 'printerSettings', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings');
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+
+ private function writeUnparsedRelationship(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, XMLWriter $objWriter, $relationship, $type): void
+ {
+ $unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
+ if (!isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()][$relationship])) {
+ return;
+ }
+
+ foreach ($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()][$relationship] as $rId => $value) {
+ $this->writeRelationship(
+ $objWriter,
+ $rId,
+ $type,
+ $value['relFilePath']
+ );
+ }
+ }
+
+ /**
+ * Write drawing relationships to XML format.
+ *
+ * @param int &$chartRef Chart ID
+ * @param bool $includeCharts Flag indicating if we should write charts
+ *
+ * @return string XML Output
+ */
+ public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, &$chartRef, $includeCharts = false)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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 \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
+ || $iterator->current() instanceof MemoryDrawing
+ ) {
+ // Write relationship for image drawing
+ /** @var \PhpOffice\PhpSpreadsheet\Worksheet\Drawing $drawing */
+ $drawing = $iterator->current();
+ $this->writeRelationship(
+ $objWriter,
+ $i,
+ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
+ '../media/' . str_replace(' ', '', $drawing->getIndexedFilename())
+ );
+
+ $i = $this->writeDrawingHyperLink($objWriter, $drawing, $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'
+ );
+ }
+ }
+ }
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write header/footer drawing relationships to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // 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()
+ );
+ }
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write Override content type.
+ *
+ * @param 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
+ */
+ private function writeRelationship(XMLWriter $objWriter, $pId, $pType, $pTarget, $pTargetMode = ''): void
+ {
+ 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);
+ }
+
+ $objWriter->endElement();
+ } else {
+ throw new WriterException('Invalid parameters passed.');
+ }
+ }
+
+ /**
+ * @param $objWriter
+ * @param \PhpOffice\PhpSpreadsheet\Worksheet\Drawing $drawing
+ * @param $i
+ *
+ * @return int
+ */
+ private function writeDrawingHyperLink($objWriter, $drawing, $i)
+ {
+ if ($drawing->getHyperlink() === null) {
+ return $i;
+ }
+
+ ++$i;
+ $this->writeRelationship(
+ $objWriter,
+ $i,
+ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
+ $drawing->getHyperlink()->getUrl(),
+ $drawing->getHyperlink()->getTypeHyperlink()
+ );
+
+ return $i;
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php
new file mode 100644
index 0000000..66d9d77
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+class RelsRibbon extends WriterPart
+{
+ /**
+ * Write relationships for additional objects of custom UI (ribbon).
+ *
+ * @return string XML Output
+ */
+ public function writeRibbonRelationships(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // XML header
+ $objWriter->startDocument('1.0', 'UTF-8', 'yes');
+
+ // Relationships
+ $objWriter->startElement('Relationships');
+ $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
+ $localRels = $spreadsheet->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();
+ }
+ }
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php
new file mode 100644
index 0000000..4ffb558
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+class RelsVBA extends WriterPart
+{
+ /**
+ * Write relationships for a signed VBA Project.
+ *
+ * @return string XML Output
+ */
+ public function writeVBARelationships(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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();
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
new file mode 100644
index 0000000..310e073
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
@@ -0,0 +1,282 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Cell\DataType;
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\RichText\Run;
+use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
+
+class StringTable extends WriterPart
+{
+ /**
+ * Create worksheet stringtable.
+ *
+ * @param Worksheet $pSheet Worksheet
+ * @param string[] $pExistingTable Existing table to eventually merge with
+ *
+ * @return string[] String table for worksheet
+ */
+ public function createStringTable(Worksheet $pSheet, $pExistingTable = null)
+ {
+ // Create string lookup table
+ $aStringTable = [];
+ $cellCollection = null;
+ $aFlippedStringTable = null; // For faster lookup
+
+ // Is an existing table given?
+ if (($pExistingTable !== null) && is_array($pExistingTable)) {
+ $aStringTable = $pExistingTable;
+ }
+
+ // Fill index array
+ $aFlippedStringTable = $this->flipStringTable($aStringTable);
+
+ // Loop through cells
+ foreach ($pSheet->getCoordinates() as $coordinate) {
+ $cell = $pSheet->getCell($coordinate);
+ $cellValue = $cell->getValue();
+ if (
+ !is_object($cellValue) &&
+ ($cellValue !== null) &&
+ $cellValue !== '' &&
+ !isset($aFlippedStringTable[$cellValue]) &&
+ ($cell->getDataType() == DataType::TYPE_STRING || $cell->getDataType() == DataType::TYPE_STRING2 || $cell->getDataType() == DataType::TYPE_NULL)
+ ) {
+ $aStringTable[] = $cellValue;
+ $aFlippedStringTable[$cellValue] = true;
+ } elseif (
+ $cellValue instanceof RichText &&
+ ($cellValue !== null) &&
+ !isset($aFlippedStringTable[$cellValue->getHashCode()])
+ ) {
+ $aStringTable[] = $cellValue;
+ $aFlippedStringTable[$cellValue->getHashCode()] = true;
+ }
+ }
+
+ return $aStringTable;
+ }
+
+ /**
+ * Write string table to XML format.
+ *
+ * @param string[] $pStringTable
+ *
+ * @return string XML Output
+ */
+ public function writeStringTable(array $pStringTable)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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));
+
+ // Loop through string table
+ foreach ($pStringTable as $textElement) {
+ $objWriter->startElement('si');
+
+ if (!$textElement instanceof RichText) {
+ $textToWrite = StringHelper::controlCharacterPHP2OOXML($textElement);
+ $objWriter->startElement('t');
+ if ($textToWrite !== trim($textToWrite)) {
+ $objWriter->writeAttribute('xml:space', 'preserve');
+ }
+ $objWriter->writeRawData($textToWrite);
+ $objWriter->endElement();
+ } elseif ($textElement instanceof RichText) {
+ $this->writeRichText($objWriter, $textElement);
+ }
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write Rich Text.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param RichText $pRichText Rich text
+ * @param string $prefix Optional Namespace prefix
+ */
+ public function writeRichText(XMLWriter $objWriter, RichText $pRichText, $prefix = null): void
+ {
+ 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 Run) {
+ // rPr
+ $objWriter->startElement($prefix . 'rPr');
+
+ // 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();
+
+ // 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');
+ } elseif ($element->getFont()->getSubscript()) {
+ $objWriter->writeAttribute('val', 'subscript');
+ }
+ $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();
+
+ // 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();
+
+ $objWriter->endElement();
+ }
+
+ // t
+ $objWriter->startElement($prefix . 't');
+ $objWriter->writeAttribute('xml:space', 'preserve');
+ $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write Rich Text.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param RichText|string $pRichText text string or Rich text
+ * @param string $prefix Optional Namespace prefix
+ */
+ public function writeRichTextForCharts(XMLWriter $objWriter, $pRichText = null, $prefix = null): void
+ {
+ if (!$pRichText instanceof RichText) {
+ $textRun = $pRichText;
+ $pRichText = new 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');
+
+ // 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'));
+
+ // rFont
+ $objWriter->startElement($prefix . 'latin');
+ $objWriter->writeAttribute('typeface', $element->getFont()->getName());
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // t
+ $objWriter->startElement($prefix . 't');
+ $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Flip string table (for index searching).
+ *
+ * @param array $stringTable Stringtable
+ *
+ * @return array
+ */
+ public function flipStringTable(array $stringTable)
+ {
+ // Return value
+ $returnValue = [];
+
+ // Loop through stringtable and add flipped items to $returnValue
+ foreach ($stringTable as $key => $value) {
+ if (!$value instanceof RichText) {
+ $returnValue[$value] = $key;
+ } elseif ($value instanceof RichText) {
+ $returnValue[$value->getHashCode()] = $key;
+ }
+ }
+
+ return $returnValue;
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php
new file mode 100644
index 0000000..69d20a9
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php
@@ -0,0 +1,676 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Borders;
+use PhpOffice\PhpSpreadsheet\Style\Conditional;
+use PhpOffice\PhpSpreadsheet\Style\Fill;
+use PhpOffice\PhpSpreadsheet\Style\Font;
+use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
+use PhpOffice\PhpSpreadsheet\Style\Protection;
+
+class Style extends WriterPart
+{
+ /**
+ * Write styles to XML format.
+ *
+ * @return string XML Output
+ */
+ public function writeStyles(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ // 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);
+ }
+
+ $objWriter->endElement();
+
+ // 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));
+ }
+
+ $objWriter->endElement();
+
+ // 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));
+ }
+
+ $objWriter->endElement();
+
+ // 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));
+ }
+
+ $objWriter->endElement();
+
+ // 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();
+
+ $objWriter->endElement();
+
+ // cellXfs
+ $objWriter->startElement('cellXfs');
+ $objWriter->writeAttribute('count', count($spreadsheet->getCellXfCollection()));
+
+ // xf
+ foreach ($spreadsheet->getCellXfCollection() as $cellXf) {
+ $this->writeCellStyleXf($objWriter, $cellXf, $spreadsheet);
+ }
+
+ $objWriter->endElement();
+
+ // 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();
+
+ $objWriter->endElement();
+
+ // 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());
+ }
+
+ $objWriter->endElement();
+
+ // tableStyles
+ $objWriter->startElement('tableStyles');
+ $objWriter->writeAttribute('defaultTableStyle', 'TableStyleMedium9');
+ $objWriter->writeAttribute('defaultPivotStyle', 'PivotTableStyle1');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write Fill.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Fill $pFill Fill style
+ */
+ private function writeFill(XMLWriter $objWriter, Fill $pFill): void
+ {
+ // Check if this is a pattern type or gradient type
+ if (
+ $pFill->getFillType() === Fill::FILL_GRADIENT_LINEAR ||
+ $pFill->getFillType() === Fill::FILL_GRADIENT_PATH
+ ) {
+ // Gradient fill
+ $this->writeGradientFill($objWriter, $pFill);
+ } elseif ($pFill->getFillType() !== null) {
+ // Pattern fill
+ $this->writePatternFill($objWriter, $pFill);
+ }
+ }
+
+ /**
+ * Write Gradient Fill.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Fill $pFill Fill style
+ */
+ private function writeGradientFill(XMLWriter $objWriter, Fill $pFill): void
+ {
+ // fill
+ $objWriter->startElement('fill');
+
+ // gradientFill
+ $objWriter->startElement('gradientFill');
+ $objWriter->writeAttribute('type', $pFill->getFillType());
+ $objWriter->writeAttribute('degree', $pFill->getRotation());
+
+ // stop
+ $objWriter->startElement('stop');
+ $objWriter->writeAttribute('position', '0');
+
+ // color
+ $objWriter->startElement('color');
+ $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB());
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // stop
+ $objWriter->startElement('stop');
+ $objWriter->writeAttribute('position', '1');
+
+ // color
+ $objWriter->startElement('color');
+ $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB());
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Pattern Fill.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Fill $pFill Fill style
+ */
+ private function writePatternFill(XMLWriter $objWriter, Fill $pFill): void
+ {
+ // fill
+ $objWriter->startElement('fill');
+
+ // patternFill
+ $objWriter->startElement('patternFill');
+ $objWriter->writeAttribute('patternType', $pFill->getFillType());
+
+ if ($pFill->getFillType() !== Fill::FILL_NONE) {
+ // fgColor
+ if ($pFill->getStartColor()->getARGB()) {
+ $objWriter->startElement('fgColor');
+ $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB());
+ $objWriter->endElement();
+ }
+ }
+ if ($pFill->getFillType() !== Fill::FILL_NONE) {
+ // bgColor
+ if ($pFill->getEndColor()->getARGB()) {
+ $objWriter->startElement('bgColor');
+ $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB());
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Font.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param Font $pFont Font style
+ */
+ private function writeFont(XMLWriter $objWriter, Font $pFont): void
+ {
+ // font
+ $objWriter->startElement('font');
+ // Weird! The order of these elements actually makes a difference when opening Xlsx
+ // 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');
+ } elseif ($pFont->getSubscript() === true) {
+ $objWriter->writeAttribute('val', 'subscript');
+ }
+ $objWriter->endElement();
+ }
+
+ // Size
+ if ($pFont->getSize() !== null) {
+ $objWriter->startElement('sz');
+ $objWriter->writeAttribute('val', StringHelper::formatNumber($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 XMLWriter $objWriter XML Writer
+ * @param Borders $pBorders Borders style
+ */
+ private function writeBorder(XMLWriter $objWriter, Borders $pBorders): void
+ {
+ // Write border
+ $objWriter->startElement('border');
+ // Diagonal?
+ switch ($pBorders->getDiagonalDirection()) {
+ case Borders::DIAGONAL_UP:
+ $objWriter->writeAttribute('diagonalUp', 'true');
+ $objWriter->writeAttribute('diagonalDown', 'false');
+
+ break;
+ case Borders::DIAGONAL_DOWN:
+ $objWriter->writeAttribute('diagonalUp', 'false');
+ $objWriter->writeAttribute('diagonalDown', 'true');
+
+ break;
+ case 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 XMLWriter $objWriter XML Writer
+ * @param \PhpOffice\PhpSpreadsheet\Style\Style $pStyle Style
+ * @param Spreadsheet $spreadsheet Workbook
+ */
+ private function writeCellStyleXf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $pStyle, Spreadsheet $spreadsheet): void
+ {
+ // 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);
+ }
+
+ 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());
+ }
+
+ $objWriter->writeAttribute('fillId', (int) $this->getParentWriter()->getFillHashTable()->getIndexForHashCode($pStyle->getFill()->getHashCode()));
+ $objWriter->writeAttribute('borderId', (int) $this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($pStyle->getBorders()->getHashCode()));
+
+ // Apply styles?
+ $objWriter->writeAttribute('applyFont', ($spreadsheet->getDefaultStyle()->getFont()->getHashCode() != $pStyle->getFont()->getHashCode()) ? '1' : '0');
+ $objWriter->writeAttribute('applyNumberFormat', ($spreadsheet->getDefaultStyle()->getNumberFormat()->getHashCode() != $pStyle->getNumberFormat()->getHashCode()) ? '1' : '0');
+ $objWriter->writeAttribute('applyFill', ($spreadsheet->getDefaultStyle()->getFill()->getHashCode() != $pStyle->getFill()->getHashCode()) ? '1' : '0');
+ $objWriter->writeAttribute('applyBorder', ($spreadsheet->getDefaultStyle()->getBorders()->getHashCode() != $pStyle->getBorders()->getHashCode()) ? '1' : '0');
+ $objWriter->writeAttribute('applyAlignment', ($spreadsheet->getDefaultStyle()->getAlignment()->getHashCode() != $pStyle->getAlignment()->getHashCode()) ? '1' : '0');
+ if ($pStyle->getProtection()->getLocked() != Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
+ $objWriter->writeAttribute('applyProtection', 'true');
+ }
+
+ // alignment
+ $objWriter->startElement('alignment');
+ $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal());
+ $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical());
+
+ $textRotation = 0;
+ if ($pStyle->getAlignment()->getTextRotation() >= 0) {
+ $textRotation = $pStyle->getAlignment()->getTextRotation();
+ } elseif ($pStyle->getAlignment()->getTextRotation() < 0) {
+ $textRotation = 90 - $pStyle->getAlignment()->getTextRotation();
+ }
+ $objWriter->writeAttribute('textRotation', $textRotation);
+
+ $objWriter->writeAttribute('wrapText', ($pStyle->getAlignment()->getWrapText() ? 'true' : 'false'));
+ $objWriter->writeAttribute('shrinkToFit', ($pStyle->getAlignment()->getShrinkToFit() ? 'true' : 'false'));
+
+ if ($pStyle->getAlignment()->getIndent() > 0) {
+ $objWriter->writeAttribute('indent', $pStyle->getAlignment()->getIndent());
+ }
+ if ($pStyle->getAlignment()->getReadOrder() > 0) {
+ $objWriter->writeAttribute('readingOrder', $pStyle->getAlignment()->getReadOrder());
+ }
+ $objWriter->endElement();
+
+ // protection
+ if ($pStyle->getProtection()->getLocked() != Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
+ $objWriter->startElement('protection');
+ if ($pStyle->getProtection()->getLocked() != Protection::PROTECTION_INHERIT) {
+ $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
+ }
+ if ($pStyle->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
+ $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
+ }
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Cell Style Dxf.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param \PhpOffice\PhpSpreadsheet\Style\Style $pStyle Style
+ */
+ private function writeCellStyleDxf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $pStyle): void
+ {
+ // dxf
+ $objWriter->startElement('dxf');
+
+ // font
+ $this->writeFont($objWriter, $pStyle->getFont());
+
+ // numFmt
+ $this->writeNumFmt($objWriter, $pStyle->getNumberFormat());
+
+ // fill
+ $this->writeFill($objWriter, $pStyle->getFill());
+
+ // 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());
+ }
+
+ if ($pStyle->getAlignment()->getTextRotation() !== null) {
+ $textRotation = 0;
+ if ($pStyle->getAlignment()->getTextRotation() >= 0) {
+ $textRotation = $pStyle->getAlignment()->getTextRotation();
+ } elseif ($pStyle->getAlignment()->getTextRotation() < 0) {
+ $textRotation = 90 - $pStyle->getAlignment()->getTextRotation();
+ }
+ $objWriter->writeAttribute('textRotation', $textRotation);
+ }
+ $objWriter->endElement();
+
+ // border
+ $this->writeBorder($objWriter, $pStyle->getBorders());
+
+ // protection
+ if (($pStyle->getProtection()->getLocked() !== null) || ($pStyle->getProtection()->getHidden() !== null)) {
+ if (
+ $pStyle->getProtection()->getLocked() !== Protection::PROTECTION_INHERIT ||
+ $pStyle->getProtection()->getHidden() !== Protection::PROTECTION_INHERIT
+ ) {
+ $objWriter->startElement('protection');
+ if (
+ ($pStyle->getProtection()->getLocked() !== null) &&
+ ($pStyle->getProtection()->getLocked() !== Protection::PROTECTION_INHERIT)
+ ) {
+ $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
+ }
+ if (
+ ($pStyle->getProtection()->getHidden() !== null) &&
+ ($pStyle->getProtection()->getHidden() !== Protection::PROTECTION_INHERIT)
+ ) {
+ $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
+ }
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write BorderPr.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param string $pName Element name
+ * @param Border $pBorder Border style
+ */
+ private function writeBorderPr(XMLWriter $objWriter, $pName, Border $pBorder): void
+ {
+ // Write BorderPr
+ if ($pBorder->getBorderStyle() != Border::BORDER_NONE) {
+ $objWriter->startElement($pName);
+ $objWriter->writeAttribute('style', $pBorder->getBorderStyle());
+
+ // color
+ $objWriter->startElement('color');
+ $objWriter->writeAttribute('rgb', $pBorder->getColor()->getARGB());
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write NumberFormat.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param NumberFormat $pNumberFormat Number Format
+ * @param int $pId Number Format identifier
+ */
+ private function writeNumFmt(XMLWriter $objWriter, NumberFormat $pNumberFormat, $pId = 0): void
+ {
+ // Translate formatcode
+ $formatCode = $pNumberFormat->getFormatCode();
+
+ // numFmt
+ if ($formatCode !== null) {
+ $objWriter->startElement('numFmt');
+ $objWriter->writeAttribute('numFmtId', ($pId + 164));
+ $objWriter->writeAttribute('formatCode', $formatCode);
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Get an array of all styles.
+ *
+ * @return \PhpOffice\PhpSpreadsheet\Style\Style[] All styles in PhpSpreadsheet
+ */
+ public function allStyles(Spreadsheet $spreadsheet)
+ {
+ return $spreadsheet->getCellXfCollection();
+ }
+
+ /**
+ * Get an array of all conditional styles.
+ *
+ * @return Conditional[] All conditional styles in PhpSpreadsheet
+ */
+ public function allConditionalStyles(Spreadsheet $spreadsheet)
+ {
+ // Get an array of all styles
+ $aStyles = [];
+
+ $sheetCount = $spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ foreach ($spreadsheet->getSheet($i)->getConditionalStylesCollection() as $conditionalStyles) {
+ foreach ($conditionalStyles as $conditionalStyle) {
+ $aStyles[] = $conditionalStyle;
+ }
+ }
+ }
+
+ return $aStyles;
+ }
+
+ /**
+ * Get an array of all fills.
+ *
+ * @return Fill[] All fills in PhpSpreadsheet
+ */
+ public function allFills(Spreadsheet $spreadsheet)
+ {
+ // Get an array of unique fills
+ $aFills = [];
+
+ // Two first fills are predefined
+ $fill0 = new Fill();
+ $fill0->setFillType(Fill::FILL_NONE);
+ $aFills[] = $fill0;
+
+ $fill1 = new Fill();
+ $fill1->setFillType(Fill::FILL_PATTERN_GRAY125);
+ $aFills[] = $fill1;
+ // The remaining fills
+ $aStyles = $this->allStyles($spreadsheet);
+ /** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
+ foreach ($aStyles as $style) {
+ if (!isset($aFills[$style->getFill()->getHashCode()])) {
+ $aFills[$style->getFill()->getHashCode()] = $style->getFill();
+ }
+ }
+
+ return $aFills;
+ }
+
+ /**
+ * Get an array of all fonts.
+ *
+ * @return Font[] All fonts in PhpSpreadsheet
+ */
+ public function allFonts(Spreadsheet $spreadsheet)
+ {
+ // Get an array of unique fonts
+ $aFonts = [];
+ $aStyles = $this->allStyles($spreadsheet);
+
+ /** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
+ foreach ($aStyles as $style) {
+ if (!isset($aFonts[$style->getFont()->getHashCode()])) {
+ $aFonts[$style->getFont()->getHashCode()] = $style->getFont();
+ }
+ }
+
+ return $aFonts;
+ }
+
+ /**
+ * Get an array of all borders.
+ *
+ * @return Borders[] All borders in PhpSpreadsheet
+ */
+ public function allBorders(Spreadsheet $spreadsheet)
+ {
+ // Get an array of unique borders
+ $aBorders = [];
+ $aStyles = $this->allStyles($spreadsheet);
+
+ /** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
+ foreach ($aStyles as $style) {
+ if (!isset($aBorders[$style->getBorders()->getHashCode()])) {
+ $aBorders[$style->getBorders()->getHashCode()] = $style->getBorders();
+ }
+ }
+
+ return $aBorders;
+ }
+
+ /**
+ * Get an array of all number formats.
+ *
+ * @return NumberFormat[] All number formats in PhpSpreadsheet
+ */
+ public function allNumberFormats(Spreadsheet $spreadsheet)
+ {
+ // Get an array of unique number formats
+ $aNumFmts = [];
+ $aStyles = $this->allStyles($spreadsheet);
+
+ /** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
+ foreach ($aStyles as $style) {
+ if ($style->getNumberFormat()->getBuiltInFormatCode() === false && !isset($aNumFmts[$style->getNumberFormat()->getHashCode()])) {
+ $aNumFmts[$style->getNumberFormat()->getHashCode()] = $style->getNumberFormat();
+ }
+ }
+
+ return $aNumFmts;
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php
new file mode 100644
index 0000000..b06ef41
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php
@@ -0,0 +1,837 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
+class Theme extends WriterPart
+{
+ /**
+ * Map of Major fonts to write.
+ *
+ * @var array of string
+ */
+ private static $majorFonts = [
+ '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.
+ *
+ * @var array of string
+ */
+ private static $minorFonts = [
+ '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.
+ *
+ * @var array of string
+ */
+ private static $colourScheme = [
+ '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.
+ *
+ * @return string XML Output
+ */
+ public function writeTheme(Spreadsheet $spreadsheet)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(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:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '0');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:tint
+ $objWriter->startElement('a:tint');
+ $objWriter->writeAttribute('val', '50000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '300000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '35000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:tint
+ $objWriter->startElement('a:tint');
+ $objWriter->writeAttribute('val', '37000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '300000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '100000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:tint
+ $objWriter->startElement('a:tint');
+ $objWriter->writeAttribute('val', '15000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '350000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:lin
+ $objWriter->startElement('a:lin');
+ $objWriter->writeAttribute('ang', '16200000');
+ $objWriter->writeAttribute('scaled', '1');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gradFill
+ $objWriter->startElement('a:gradFill');
+ $objWriter->writeAttribute('rotWithShape', '1');
+
+ // a:gsLst
+ $objWriter->startElement('a:gsLst');
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '0');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:shade
+ $objWriter->startElement('a:shade');
+ $objWriter->writeAttribute('val', '51000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '130000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '80000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:shade
+ $objWriter->startElement('a:shade');
+ $objWriter->writeAttribute('val', '93000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '130000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '100000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:shade
+ $objWriter->startElement('a:shade');
+ $objWriter->writeAttribute('val', '94000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '135000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:lin
+ $objWriter->startElement('a:lin');
+ $objWriter->writeAttribute('ang', '16200000');
+ $objWriter->writeAttribute('scaled', '0');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // 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:solidFill
+ $objWriter->startElement('a:solidFill');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:shade
+ $objWriter->startElement('a:shade');
+ $objWriter->writeAttribute('val', '95000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '105000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:prstDash
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', 'solid');
+ $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:solidFill
+ $objWriter->startElement('a:solidFill');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:prstDash
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', 'solid');
+ $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:solidFill
+ $objWriter->startElement('a:solidFill');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:prstDash
+ $objWriter->startElement('a:prstDash');
+ $objWriter->writeAttribute('val', 'solid');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:effectStyleLst
+ $objWriter->startElement('a:effectStyleLst');
+
+ // a:effectStyle
+ $objWriter->startElement('a:effectStyle');
+
+ // 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:srgbClr
+ $objWriter->startElement('a:srgbClr');
+ $objWriter->writeAttribute('val', '000000');
+
+ // a:alpha
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', '38000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:effectStyle
+ $objWriter->startElement('a:effectStyle');
+
+ // 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:srgbClr
+ $objWriter->startElement('a:srgbClr');
+ $objWriter->writeAttribute('val', '000000');
+
+ // a:alpha
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', '35000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:effectStyle
+ $objWriter->startElement('a:effectStyle');
+
+ // 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:srgbClr
+ $objWriter->startElement('a:srgbClr');
+ $objWriter->writeAttribute('val', '000000');
+
+ // a:alpha
+ $objWriter->startElement('a:alpha');
+ $objWriter->writeAttribute('val', '35000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:scene3d
+ $objWriter->startElement('a:scene3d');
+
+ // 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();
+
+ $objWriter->endElement();
+
+ // 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();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:sp3d
+ $objWriter->startElement('a:sp3d');
+
+ // a:bevelT
+ $objWriter->startElement('a:bevelT');
+ $objWriter->writeAttribute('w', '63500');
+ $objWriter->writeAttribute('h', '25400');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:bgFillStyleLst
+ $objWriter->startElement('a:bgFillStyleLst');
+
+ // 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:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '0');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:tint
+ $objWriter->startElement('a:tint');
+ $objWriter->writeAttribute('val', '40000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '350000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '40000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // 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:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '350000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '100000');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:shade
+ $objWriter->startElement('a:shade');
+ $objWriter->writeAttribute('val', '20000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '255000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // 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();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gradFill
+ $objWriter->startElement('a:gradFill');
+ $objWriter->writeAttribute('rotWithShape', '1');
+
+ // a:gsLst
+ $objWriter->startElement('a:gsLst');
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '0');
+
+ // a:schemeClr
+ $objWriter->startElement('a:schemeClr');
+ $objWriter->writeAttribute('val', 'phClr');
+
+ // a:tint
+ $objWriter->startElement('a:tint');
+ $objWriter->writeAttribute('val', '80000');
+ $objWriter->endElement();
+
+ // a:satMod
+ $objWriter->startElement('a:satMod');
+ $objWriter->writeAttribute('val', '300000');
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // a:gs
+ $objWriter->startElement('a:gs');
+ $objWriter->writeAttribute('pos', '100000');
+
+ // 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();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ // 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();
+
+ $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 XMLWriter $objWriter
+ * @param string $latinFont
+ * @param array of string $fontSet
+ *
+ * @return string XML Output
+ */
+ 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 XMLWriter $objWriter
+ *
+ * @return string XML Output
+ */
+ 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/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php
new file mode 100644
index 0000000..12cd159
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php
@@ -0,0 +1,225 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Shared\Date;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx\DefinedNames as DefinedNamesWriter;
+
+class Workbook extends WriterPart
+{
+ /**
+ * Write workbook to XML format.
+ *
+ * @param bool $recalcRequired Indicate whether formulas should be recalculated before writing
+ *
+ * @return string XML Output
+ */
+ public function writeWorkbook(Spreadsheet $spreadsheet, $recalcRequired = false)
+ {
+ // Create XML writer
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
+ }
+
+ // 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');
+
+ // fileVersion
+ $this->writeFileVersion($objWriter);
+
+ // workbookPr
+ $this->writeWorkbookPr($objWriter);
+
+ // workbookProtection
+ $this->writeWorkbookProtection($objWriter, $spreadsheet);
+
+ // bookViews
+ if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
+ $this->writeBookViews($objWriter, $spreadsheet);
+ }
+
+ // sheets
+ $this->writeSheets($objWriter, $spreadsheet);
+
+ // definedNames
+ (new DefinedNamesWriter($objWriter, $spreadsheet))->write();
+
+ // calcPr
+ $this->writeCalcPr($objWriter, $recalcRequired);
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write file version.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeFileVersion(XMLWriter $objWriter): void
+ {
+ $objWriter->startElement('fileVersion');
+ $objWriter->writeAttribute('appName', 'xl');
+ $objWriter->writeAttribute('lastEdited', '4');
+ $objWriter->writeAttribute('lowestEdited', '4');
+ $objWriter->writeAttribute('rupBuild', '4505');
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write WorkbookPr.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeWorkbookPr(XMLWriter $objWriter): void
+ {
+ $objWriter->startElement('workbookPr');
+
+ if (Date::getExcelCalendar() === Date::CALENDAR_MAC_1904) {
+ $objWriter->writeAttribute('date1904', '1');
+ }
+
+ $objWriter->writeAttribute('codeName', 'ThisWorkbook');
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write BookViews.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeBookViews(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
+ {
+ // bookViews
+ $objWriter->startElement('bookViews');
+
+ // workbookView
+ $objWriter->startElement('workbookView');
+
+ $objWriter->writeAttribute('activeTab', $spreadsheet->getActiveSheetIndex());
+ $objWriter->writeAttribute('autoFilterDateGrouping', ($spreadsheet->getAutoFilterDateGrouping() ? 'true' : 'false'));
+ $objWriter->writeAttribute('firstSheet', $spreadsheet->getFirstSheetIndex());
+ $objWriter->writeAttribute('minimized', ($spreadsheet->getMinimized() ? 'true' : 'false'));
+ $objWriter->writeAttribute('showHorizontalScroll', ($spreadsheet->getShowHorizontalScroll() ? 'true' : 'false'));
+ $objWriter->writeAttribute('showSheetTabs', ($spreadsheet->getShowSheetTabs() ? 'true' : 'false'));
+ $objWriter->writeAttribute('showVerticalScroll', ($spreadsheet->getShowVerticalScroll() ? 'true' : 'false'));
+ $objWriter->writeAttribute('tabRatio', $spreadsheet->getTabRatio());
+ $objWriter->writeAttribute('visibility', $spreadsheet->getVisibility());
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write WorkbookProtection.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeWorkbookProtection(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
+ {
+ if ($spreadsheet->getSecurity()->isSecurityEnabled()) {
+ $objWriter->startElement('workbookProtection');
+ $objWriter->writeAttribute('lockRevision', ($spreadsheet->getSecurity()->getLockRevision() ? 'true' : 'false'));
+ $objWriter->writeAttribute('lockStructure', ($spreadsheet->getSecurity()->getLockStructure() ? 'true' : 'false'));
+ $objWriter->writeAttribute('lockWindows', ($spreadsheet->getSecurity()->getLockWindows() ? 'true' : 'false'));
+
+ if ($spreadsheet->getSecurity()->getRevisionsPassword() != '') {
+ $objWriter->writeAttribute('revisionsPassword', $spreadsheet->getSecurity()->getRevisionsPassword());
+ }
+
+ if ($spreadsheet->getSecurity()->getWorkbookPassword() != '') {
+ $objWriter->writeAttribute('workbookPassword', $spreadsheet->getSecurity()->getWorkbookPassword());
+ }
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write calcPr.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param bool $recalcRequired Indicate whether formulas should be recalculated before writing
+ */
+ private function writeCalcPr(XMLWriter $objWriter, $recalcRequired = true): void
+ {
+ $objWriter->startElement('calcPr');
+
+ // 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('forceFullCalc', ($recalcRequired) ? 0 : 1);
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write sheets.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ */
+ private function writeSheets(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
+ {
+ // Write sheets
+ $objWriter->startElement('sheets');
+ $sheetCount = $spreadsheet->getSheetCount();
+ for ($i = 0; $i < $sheetCount; ++$i) {
+ // sheet
+ $this->writeSheet(
+ $objWriter,
+ $spreadsheet->getSheet($i)->getTitle(),
+ ($i + 1),
+ ($i + 1 + 3),
+ $spreadsheet->getSheet($i)->getSheetState()
+ );
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write sheet.
+ *
+ * @param 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)
+ */
+ private function writeSheet(XMLWriter $objWriter, $pSheetname, $pSheetId = 1, $pRelId = 1, $sheetState = 'visible'): void
+ {
+ 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 WriterException('Invalid parameters passed.');
+ }
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
new file mode 100644
index 0000000..2b89709
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
@@ -0,0 +1,1282 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Cell\Cell;
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
+use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Style\Conditional;
+use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
+use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
+use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
+use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as PhpspreadsheetWorksheet;
+
+class Worksheet extends WriterPart
+{
+ /**
+ * Write worksheet to XML format.
+ *
+ * @param string[] $pStringTable
+ * @param bool $includeCharts Flag indicating if we should write charts
+ *
+ * @return string XML Output
+ */
+ public function writeWorksheet(PhpspreadsheetWorksheet $pSheet, $pStringTable = null, $includeCharts = false)
+ {
+ // Create XML writer
+ $objWriter = null;
+ if ($this->getParentWriter()->getUseDiskCaching()) {
+ $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
+ } else {
+ $objWriter = new XMLWriter(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');
+
+ $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
+ $objWriter->writeAttribute('xmlns:x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main');
+ $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
+ $objWriter->writeAttribute('mc:Ignorable', 'x14ac');
+ $objWriter->writeAttribute('xmlns:x14ac', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac');
+
+ // 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);
+
+ // AlternateContent
+ $this->writeAlternateContent($objWriter, $pSheet);
+
+ $objWriter->endElement();
+
+ // Return
+ return $objWriter->getData();
+ }
+
+ /**
+ * Write SheetPr.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeSheetPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // sheetPr
+ $objWriter->startElement('sheetPr');
+ if ($pSheet->getParent()->hasMacros()) {
+ //if the workbook have macros, we need to have codeName for the sheet
+ if (!$pSheet->hasCodeName()) {
+ $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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeDimension(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // dimension
+ $objWriter->startElement('dimension');
+ $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension());
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write SheetViews.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeSheetViews(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // sheetViews
+ $objWriter->startElement('sheetViews');
+
+ // Sheet selected?
+ $sheetSelected = false;
+ if ($this->getParentWriter()->getSpreadsheet()->getIndex($pSheet) == $this->getParentWriter()->getSpreadsheet()->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());
+ }
+
+ // Show zeros (Excel also writes this attribute only if set to false)
+ if ($pSheet->getSheetView()->getShowZeros() === false) {
+ $objWriter->writeAttribute('showZeros', 0);
+ }
+
+ // View Layout Type
+ if ($pSheet->getSheetView()->getView() !== 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();
+ $sqref = $pSheet->getSelectedCells();
+
+ // Pane
+ $pane = '';
+ if ($pSheet->getFreezePane()) {
+ [$xSplit, $ySplit] = Coordinate::coordinateFromString($pSheet->getFreezePane());
+ $xSplit = Coordinate::columnIndexFromString($xSplit);
+ --$xSplit;
+ --$ySplit;
+
+ $topLeftCell = $pSheet->getTopLeftCell();
+
+ // pane
+ $pane = 'topRight';
+ $objWriter->startElement('pane');
+ if ($xSplit > 0) {
+ $objWriter->writeAttribute('xSplit', $xSplit);
+ }
+ if ($ySplit > 0) {
+ $objWriter->writeAttribute('ySplit', $ySplit);
+ $pane = ($xSplit > 0) ? 'bottomRight' : 'bottomLeft';
+ }
+ $objWriter->writeAttribute('topLeftCell', $topLeftCell);
+ $objWriter->writeAttribute('activePane', $pane);
+ $objWriter->writeAttribute('state', 'frozen');
+ $objWriter->endElement();
+
+ if (($xSplit > 0) && ($ySplit > 0)) {
+ // 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
+ // 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', $sqref);
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write SheetFormatPr.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // sheetFormatPr
+ $objWriter->startElement('sheetFormatPr');
+
+ // Default row height
+ if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) {
+ $objWriter->writeAttribute('customHeight', 'true');
+ $objWriter->writeAttribute('defaultRowHeight', StringHelper::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', StringHelper::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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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', Coordinate::columnIndexFromString($colDimension->getColumnIndex()));
+ $objWriter->writeAttribute('max', Coordinate::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', StringHelper::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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeSheetProtection(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // sheetProtection
+ $objWriter->startElement('sheetProtection');
+
+ $protection = $pSheet->getProtection();
+
+ if ($protection->getAlgorithm()) {
+ $objWriter->writeAttribute('algorithmName', $protection->getAlgorithm());
+ $objWriter->writeAttribute('hashValue', $protection->getPassword());
+ $objWriter->writeAttribute('saltValue', $protection->getSalt());
+ $objWriter->writeAttribute('spinCount', $protection->getSpinCount());
+ } elseif ($protection->getPassword() !== '') {
+ $objWriter->writeAttribute('password', $protection->getPassword());
+ }
+
+ $objWriter->writeAttribute('sheet', ($protection->getSheet() ? 'true' : 'false'));
+ $objWriter->writeAttribute('objects', ($protection->getObjects() ? 'true' : 'false'));
+ $objWriter->writeAttribute('scenarios', ($protection->getScenarios() ? 'true' : 'false'));
+ $objWriter->writeAttribute('formatCells', ($protection->getFormatCells() ? 'true' : 'false'));
+ $objWriter->writeAttribute('formatColumns', ($protection->getFormatColumns() ? 'true' : 'false'));
+ $objWriter->writeAttribute('formatRows', ($protection->getFormatRows() ? 'true' : 'false'));
+ $objWriter->writeAttribute('insertColumns', ($protection->getInsertColumns() ? 'true' : 'false'));
+ $objWriter->writeAttribute('insertRows', ($protection->getInsertRows() ? 'true' : 'false'));
+ $objWriter->writeAttribute('insertHyperlinks', ($protection->getInsertHyperlinks() ? 'true' : 'false'));
+ $objWriter->writeAttribute('deleteColumns', ($protection->getDeleteColumns() ? 'true' : 'false'));
+ $objWriter->writeAttribute('deleteRows', ($protection->getDeleteRows() ? 'true' : 'false'));
+ $objWriter->writeAttribute('selectLockedCells', ($protection->getSelectLockedCells() ? 'true' : 'false'));
+ $objWriter->writeAttribute('sort', ($protection->getSort() ? 'true' : 'false'));
+ $objWriter->writeAttribute('autoFilter', ($protection->getAutoFilter() ? 'true' : 'false'));
+ $objWriter->writeAttribute('pivotTables', ($protection->getPivotTables() ? 'true' : 'false'));
+ $objWriter->writeAttribute('selectUnlockedCells', ($protection->getSelectUnlockedCells() ? 'true' : 'false'));
+ $objWriter->endElement();
+ }
+
+ private static function writeAttributeIf(XMLWriter $objWriter, $condition, string $attr, string $val): void
+ {
+ if ($condition) {
+ $objWriter->writeAttribute($attr, $val);
+ }
+ }
+
+ private static function writeElementIf(XMLWriter $objWriter, $condition, string $attr, string $val): void
+ {
+ if ($condition) {
+ $objWriter->writeElement($attr, $val);
+ }
+ }
+
+ private static function writeOtherCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void
+ {
+ if (
+ $conditional->getConditionType() == Conditional::CONDITION_CELLIS
+ || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
+ || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION
+ ) {
+ foreach ($conditional->getConditions() as $formula) {
+ // Formula
+ $objWriter->writeElement('formula', Xlfn::addXlfn($formula));
+ }
+ } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) {
+ // formula copied from ms xlsx xml source file
+ $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))=0');
+ } elseif ($conditional->getConditionType() == Conditional::CONDITION_NOTCONTAINSBLANKS) {
+ // formula copied from ms xlsx xml source file
+ $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))>0');
+ }
+ }
+
+ private static function writeTextCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void
+ {
+ $txt = $conditional->getText();
+ if ($txt !== null) {
+ $objWriter->writeAttribute('text', $txt);
+ if ($conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT) {
+ $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $txt . '",' . $cellCoordinate . ')))');
+ } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH) {
+ $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($txt) . ')="' . $txt . '"');
+ } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH) {
+ $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($txt) . ')="' . $txt . '"');
+ } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS) {
+ $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $txt . '",' . $cellCoordinate . '))');
+ }
+ }
+ }
+
+ /**
+ * Write ConditionalFormatting.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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() != 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++);
+
+ self::writeAttributeif(
+ $objWriter,
+ ($conditional->getConditionType() == Conditional::CONDITION_CELLIS || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT)
+ && $conditional->getOperatorType() != Conditional::OPERATOR_NONE,
+ 'operator',
+ $conditional->getOperatorType()
+ );
+
+ self::writeAttributeIf($objWriter, $conditional->getStopIfTrue(), 'stopIfTrue', '1');
+
+ if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT) {
+ self::writeTextCondElements($objWriter, $conditional, $cellCoordinate);
+ } else {
+ self::writeOtherCondElements($objWriter, $conditional, $cellCoordinate);
+ }
+
+ $objWriter->endElement();
+
+ $objWriter->endElement();
+ }
+ }
+ }
+ }
+
+ /**
+ * Write DataValidations.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // Datavalidation collection
+ $dataValidationCollection = $pSheet->getDataValidationCollection();
+
+ // Write data validations?
+ if (!empty($dataValidationCollection)) {
+ $dataValidationCollection = Coordinate::mergeRangesInCollection($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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeHyperlinks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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->writeAttribute('display', $hyperlink->getTooltip());
+ }
+
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write ProtectedRanges.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeProtectedRanges(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeMergeCells(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writePrintOptions(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writePageMargins(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // pageMargins
+ $objWriter->startElement('pageMargins');
+ $objWriter->writeAttribute('left', StringHelper::formatNumber($pSheet->getPageMargins()->getLeft()));
+ $objWriter->writeAttribute('right', StringHelper::formatNumber($pSheet->getPageMargins()->getRight()));
+ $objWriter->writeAttribute('top', StringHelper::formatNumber($pSheet->getPageMargins()->getTop()));
+ $objWriter->writeAttribute('bottom', StringHelper::formatNumber($pSheet->getPageMargins()->getBottom()));
+ $objWriter->writeAttribute('header', StringHelper::formatNumber($pSheet->getPageMargins()->getHeader()));
+ $objWriter->writeAttribute('footer', StringHelper::formatNumber($pSheet->getPageMargins()->getFooter()));
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write AutoFilter.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeAutoFilter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ $autoFilterRange = $pSheet->getAutoFilter()->getRange();
+ if (!empty($autoFilterRange)) {
+ // autoFilter
+ $objWriter->startElement('autoFilter');
+
+ // Strip any worksheet reference from the filter coordinates
+ $range = Coordinate::splitRange($autoFilterRange);
+ $range = $range[0];
+ // Strip any worksheet ref
+ [$ws, $range[0]] = PhpspreadsheetWorksheet::extractSheetTitle($range[0], true);
+ $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() == Column::AUTOFILTER_COLUMN_JOIN_AND) {
+ $objWriter->writeAttribute('and', 1);
+ }
+
+ foreach ($rules as $rule) {
+ if (
+ ($column->getFilterType() === Column::AUTOFILTER_FILTERTYPE_FILTER) &&
+ ($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_EQUAL) &&
+ ($rule->getValue() === '')
+ ) {
+ // Filter rule for Blanks
+ $objWriter->writeAttribute('blank', 1);
+ } elseif ($rule->getRuleType() === 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() === Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
+ // Top 10 Filter Rule
+ $objWriter->writeAttribute('val', $rule->getValue());
+ $objWriter->writeAttribute('percent', (($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0'));
+ $objWriter->writeAttribute('top', (($rule->getGrouping() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1' : '0'));
+ } else {
+ // Filter, DateGroupItem or CustomFilter
+ $objWriter->startElement($rule->getRuleType());
+
+ if ($rule->getOperator() !== Rule::AUTOFILTER_COLUMN_RULE_EQUAL) {
+ $objWriter->writeAttribute('operator', $rule->getOperator());
+ }
+ if ($rule->getRuleType() === 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writePageSetup(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // pageSetup
+ $objWriter->startElement('pageSetup');
+ $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize());
+ $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation());
+
+ if ($pSheet->getPageSetup()->getScale() !== null) {
+ $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale());
+ }
+ if ($pSheet->getPageSetup()->getFitToHeight() !== null) {
+ $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight());
+ } else {
+ $objWriter->writeAttribute('fitToHeight', '0');
+ }
+ if ($pSheet->getPageSetup()->getFitToWidth() !== null) {
+ $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth());
+ } else {
+ $objWriter->writeAttribute('fitToWidth', '0');
+ }
+ if ($pSheet->getPageSetup()->getFirstPageNumber() !== null) {
+ $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber());
+ $objWriter->writeAttribute('useFirstPageNumber', '1');
+ }
+ $objWriter->writeAttribute('pageOrder', $pSheet->getPageSetup()->getPageOrder());
+
+ $getUnparsedLoadedData = $pSheet->getParent()->getUnparsedLoadedData();
+ if (isset($getUnparsedLoadedData['sheets'][$pSheet->getCodeName()]['pageSetupRelId'])) {
+ $objWriter->writeAttribute('r:id', $getUnparsedLoadedData['sheets'][$pSheet->getCodeName()]['pageSetupRelId']);
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Header / Footer.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeHeaderFooter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeBreaks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // Get row and column breaks
+ $aRowBreaks = [];
+ $aColumnBreaks = [];
+ foreach ($pSheet->getBreaks() as $cell => $breakType) {
+ if ($breakType == PhpspreadsheetWorksheet::BREAK_ROW) {
+ $aRowBreaks[] = $cell;
+ } elseif ($breakType == PhpspreadsheetWorksheet::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 = Coordinate::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 = Coordinate::coordinateFromString($cell);
+
+ $objWriter->startElement('brk');
+ $objWriter->writeAttribute('id', Coordinate::columnIndexFromString($coords[0]) - 1);
+ $objWriter->writeAttribute('man', '1');
+ $objWriter->endElement();
+ }
+
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * Write SheetData.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ * @param string[] $pStringTable String table
+ */
+ private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable): void
+ {
+ // Flipped stringtable, for faster index searching
+ $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
+
+ // sheetData
+ $objWriter->startElement('sheetData');
+
+ // Get column count
+ $colCount = Coordinate::columnIndexFromString($pSheet->getHighestColumn());
+
+ // Highest row number
+ $highestRow = $pSheet->getHighestRow();
+
+ // Loop through cells
+ $cellsByRow = [];
+ foreach ($pSheet->getCoordinates() as $coordinate) {
+ $cellAddress = Coordinate::coordinateFromString($coordinate);
+ $cellsByRow[$cellAddress[1]][] = $coordinate;
+ }
+
+ $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', StringHelper::formatNumber($rowDimension->getRowHeight()));
+ }
+
+ // Row visibility
+ if (!$rowDimension->getVisible() === true) {
+ $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, $aFlippedStringTable);
+ }
+ }
+
+ // End row
+ $objWriter->endElement();
+ }
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * @param RichText|string $cellValue
+ */
+ private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, $cellValue): void
+ {
+ $objWriter->writeAttribute('t', $mappedType);
+ if (!$cellValue instanceof RichText) {
+ $objWriter->writeElement('t', StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
+ } elseif ($cellValue instanceof RichText) {
+ $objWriter->startElement('is');
+ $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue);
+ $objWriter->endElement();
+ }
+ }
+
+ /**
+ * @param RichText|string $cellValue
+ * @param string[] $pFlippedStringTable
+ */
+ private function writeCellString(XMLWriter $objWriter, string $mappedType, $cellValue, array $pFlippedStringTable): void
+ {
+ $objWriter->writeAttribute('t', $mappedType);
+ if (!$cellValue instanceof RichText) {
+ self::writeElementIf($objWriter, isset($pFlippedStringTable[$cellValue]), 'v', $pFlippedStringTable[$cellValue]);
+ } else {
+ $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
+ }
+ }
+
+ /**
+ * @param float|int $cellValue
+ */
+ private function writeCellNumeric(XMLWriter $objWriter, $cellValue): void
+ {
+ //force a decimal to be written if the type is float
+ if (is_float($cellValue)) {
+ // force point as decimal separator in case current locale uses comma
+ $cellValue = str_replace(',', '.', (string) $cellValue);
+ if (strpos($cellValue, '.') === false) {
+ $cellValue = $cellValue . '.0';
+ }
+ }
+ $objWriter->writeElement('v', $cellValue);
+ }
+
+ private function writeCellBoolean(XMLWriter $objWriter, string $mappedType, bool $cellValue): void
+ {
+ $objWriter->writeAttribute('t', $mappedType);
+ $objWriter->writeElement('v', $cellValue ? '1' : '0');
+ }
+
+ private function writeCellError(XMLWriter $objWriter, string $mappedType, string $cellValue, string $formulaerr = '#NULL!'): void
+ {
+ $objWriter->writeAttribute('t', $mappedType);
+ $cellIsFormula = substr($cellValue, 0, 1) === '=';
+ self::writeElementIf($objWriter, $cellIsFormula, 'f', Xlfn::addXlfnStripEquals($cellValue));
+ $objWriter->writeElement('v', $cellIsFormula ? $formulaerr : $cellValue);
+ }
+
+ private function writeCellFormula(XMLWriter $objWriter, string $cellValue, Cell $pCell): void
+ {
+ $calculatedValue = $this->getParentWriter()->getPreCalculateFormulas() ? $pCell->getCalculatedValue() : $cellValue;
+ if (is_string($calculatedValue)) {
+ if (\PhpOffice\PhpSpreadsheet\Calculation\Functions::isError($calculatedValue)) {
+ $this->writeCellError($objWriter, 'e', $cellValue, $calculatedValue);
+
+ return;
+ }
+ $objWriter->writeAttribute('t', 'str');
+ } elseif (is_bool($calculatedValue)) {
+ $objWriter->writeAttribute('t', 'b');
+ }
+ // array values are not yet supported
+ //$attributes = $pCell->getFormulaAttributes();
+ //if (($attributes['t'] ?? null) === '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', Xlfn::addXlfnStripEquals($cellValue));
+ //}
+ $objWriter->writeElement('f', Xlfn::addXlfnStripEquals($cellValue));
+ self::writeElementIf(
+ $objWriter,
+ $this->getParentWriter()->getOffice2003Compatibility() === false,
+ 'v',
+ ($this->getParentWriter()->getPreCalculateFormulas() && !is_array($calculatedValue) && substr($calculatedValue, 0, 1) !== '#')
+ ? StringHelper::formatNumber($calculatedValue) : '0'
+ );
+ }
+
+ /**
+ * Write Cell.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ * @param string $pCellAddress Cell Address
+ * @param string[] $pFlippedStringTable String table (flipped), for faster index searching
+ */
+ private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, string $pCellAddress, array $pFlippedStringTable): void
+ {
+ // Cell
+ $pCell = $pSheet->getCell($pCellAddress);
+ $objWriter->startElement('c');
+ $objWriter->writeAttribute('r', $pCellAddress);
+
+ // Sheet styles
+ $xfi = $pCell->getXfIndex();
+ self::writeAttributeIf($objWriter, $xfi, 's', $xfi);
+
+ // If cell value is supplied, write cell value
+ $cellValue = $pCell->getValue();
+ if (is_object($cellValue) || $cellValue !== '') {
+ // Map type
+ $mappedType = $pCell->getDataType();
+
+ // Write data depending on its type
+ switch (strtolower($mappedType)) {
+ case 'inlinestr': // Inline string
+ $this->writeCellInlineStr($objWriter, $mappedType, $cellValue);
+
+ break;
+ case 's': // String
+ $this->writeCellString($objWriter, $mappedType, $cellValue, $pFlippedStringTable);
+
+ break;
+ case 'f': // Formula
+ $this->writeCellFormula($objWriter, $cellValue, $pCell);
+
+ break;
+ case 'n': // Numeric
+ $this->writeCellNumeric($objWriter, $cellValue);
+
+ break;
+ case 'b': // Boolean
+ $this->writeCellBoolean($objWriter, $mappedType, $cellValue);
+
+ break;
+ case 'e': // Error
+ $this->writeCellError($objWriter, $mappedType, $cellValue);
+ }
+ }
+
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write Drawings.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ * @param bool $includeCharts Flag indicating if we should include drawing details for charts
+ */
+ private function writeDrawings(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, $includeCharts = false): void
+ {
+ $unparsedLoadedData = $pSheet->getParent()->getUnparsedLoadedData();
+ $hasUnparsedDrawing = isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds']);
+ $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0;
+ if ($chartCount == 0 && $pSheet->getDrawingCollection()->count() == 0 && !$hasUnparsedDrawing) {
+ return;
+ }
+
+ // If sheet contains drawings, add the relationships
+ $objWriter->startElement('drawing');
+
+ $rId = 'rId1';
+ if (isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'])) {
+ $drawingOriginalIds = $unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'];
+ // take first. In future can be overriten
+ // (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels::writeWorksheetRelationships)
+ $rId = reset($drawingOriginalIds);
+ }
+
+ $objWriter->writeAttribute('r:id', $rId);
+ $objWriter->endElement();
+ }
+
+ /**
+ * Write LegacyDrawing.
+ *
+ * @param XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeLegacyDrawing(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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 XMLWriter $objWriter XML Writer
+ * @param PhpspreadsheetWorksheet $pSheet Worksheet
+ */
+ private function writeLegacyDrawingHF(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ // 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();
+ }
+ }
+
+ private function writeAlternateContent(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
+ {
+ if (empty($pSheet->getParent()->getUnparsedLoadedData()['sheets'][$pSheet->getCodeName()]['AlternateContents'])) {
+ return;
+ }
+
+ foreach ($pSheet->getParent()->getUnparsedLoadedData()['sheets'][$pSheet->getCodeName()]['AlternateContents'] as $alternateContent) {
+ $objWriter->writeRaw($alternateContent);
+ }
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php
new file mode 100644
index 0000000..803662f
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+abstract class WriterPart
+{
+ /**
+ * Parent Xlsx object.
+ *
+ * @var Xlsx
+ */
+ private $parentWriter;
+
+ /**
+ * Get parent Xlsx object.
+ *
+ * @return Xlsx
+ */
+ public function getParentWriter()
+ {
+ return $this->parentWriter;
+ }
+
+ /**
+ * Set parent Xlsx object.
+ */
+ public function __construct(Xlsx $pWriter)
+ {
+ $this->parentWriter = $pWriter;
+ }
+}
diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php
new file mode 100644
index 0000000..9c56ff4
--- /dev/null
+++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php
@@ -0,0 +1,159 @@
+<?php
+
+namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
+class Xlfn
+{
+ const XLFNREGEXP = '/(?<!_xlfn[.])\\b('
+ // functions added with Excel 2010
+ . 'beta[.]dist'
+ . '|beta[.]inv'
+ . '|binom[.]dist'
+ . '|binom[.]inv'
+ . '|chisq[.]dist'
+ . '|chisq[.]dist[.]rt'
+ . '|chisq[.]inv'
+ . '|chisq[.]inv[.]rt'
+ . '|chisq[.]test'
+ . '|confidence[.]norm'
+ . '|confidence[.]t'
+ . '|covariance[.]p'
+ . '|covariance[.]s'
+ . '|erf[.]precise'
+ . '|erfc[.]precise'
+ . '|expon[.]dist'
+ . '|f[.]dist'
+ . '|f[.]dist[.]rt'
+ . '|f[.]inv'
+ . '|f[.]inv[.]rt'
+ . '|f[.]test'
+ . '|gamma[.]dist'
+ . '|gamma[.]inv'
+ . '|gammaln[.]precise'
+ . '|lognorm[.]dist'
+ . '|lognorm[.]inv'
+ . '|mode[.]mult'
+ . '|mode[.]sngl'
+ . '|negbinom[.]dist'
+ . '|networkdays[.]intl'
+ . '|norm[.]dist'
+ . '|norm[.]inv'
+ . '|norm[.]s[.]dist'
+ . '|norm[.]s[.]inv'
+ . '|percentile[.]exc'
+ . '|percentile[.]inc'
+ . '|percentrank[.]exc'
+ . '|percentrank[.]inc'
+ . '|poisson[.]dist'
+ . '|quartile[.]exc'
+ . '|quartile[.]inc'
+ . '|rank[.]avg'
+ . '|rank[.]eq'
+ . '|stdev[.]p'
+ . '|stdev[.]s'
+ . '|t[.]dist'
+ . '|t[.]dist[.]2t'
+ . '|t[.]dist[.]rt'
+ . '|t[.]inv'
+ . '|t[.]inv[.]2t'
+ . '|t[.]test'
+ . '|var[.]p'
+ . '|var[.]s'
+ . '|weibull[.]dist'
+ . '|z[.]test'
+ // functions added with Excel 2013
+ . '|acot'
+ . '|acoth'
+ . '|arabic'
+ . '|averageifs'
+ . '|binom[.]dist[.]range'
+ . '|bitand'
+ . '|bitlshift'
+ . '|bitor'
+ . '|bitrshift'
+ . '|bitxor'
+ . '|ceiling[.]math'
+ . '|combina'
+ . '|cot'
+ . '|coth'
+ . '|csc'
+ . '|csch'
+ . '|days'
+ . '|dbcs'
+ . '|decimal'
+ . '|encodeurl'
+ . '|filterxml'
+ . '|floor[.]math'
+ . '|formulatext'
+ . '|gamma'
+ . '|gauss'
+ . '|ifna'
+ . '|imcosh'
+ . '|imcot'
+ . '|imcsc'
+ . '|imcsch'
+ . '|imsec'
+ . '|imsech'
+ . '|imsinh'
+ . '|imtan'
+ . '|isformula'
+ . '|iso[.]ceiling'
+ . '|isoweeknum'
+ . '|munit'
+ . '|numbervalue'
+ . '|pduration'
+ . '|permutationa'
+ . '|phi'
+ . '|rri'
+ . '|sec'
+ . '|sech'
+ . '|sheet'
+ . '|sheets'
+ . '|skew[.]p'
+ . '|unichar'
+ . '|unicode'
+ . '|webservice'
+ . '|xor'
+ // functions added with Excel 2016
+ . '|forecast[.]et2'
+ . '|forecast[.]ets[.]confint'
+ . '|forecast[.]ets[.]seasonality'
+ . '|forecast[.]ets[.]stat'
+ . '|forecast[.]linear'
+ . '|switch'
+ // functions added with Excel 2019
+ . '|concat'
+ . '|countifs'
+ . '|ifs'
+ . '|maxifs'
+ . '|minifs'
+ . '|sumifs'
+ . '|textjoin'
+ // functions added with Excel 365
+ . '|filter'
+ . '|randarray'
+ . '|sequence'
+ . '|sort'
+ . '|sortby'
+ . '|unique'
+ . '|xlookup'
+ . '|xmatch'
+ . ')(?=\\s*[(])/i';
+
+ /**
+ * Prefix function name in string with _xlfn. where required.
+ */
+ public static function addXlfn(string $funcstring): string
+ {
+ return preg_replace(self::XLFNREGEXP, '_xlfn.$1', $funcstring);
+ }
+
+ /**
+ * Prefix function name in string with _xlfn. where required.
+ * Leading character, expected to be equals sign, is stripped.
+ */
+ public static function addXlfnStripEquals(string $funcstring): string
+ {
+ return self::addXlfn(substr($funcstring, 1));
+ }
+}