See Release Notes
Long Term Support Release
<?php namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;< use PhpOffice\PhpSpreadsheet\Calculation\Functions;> use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; > use PhpOffice\PhpSpreadsheet\Chart\Axis; > use PhpOffice\PhpSpreadsheet\Chart\ChartColor;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\Properties as ChartProperties;use PhpOffice\PhpSpreadsheet\Chart\Title;> use PhpOffice\PhpSpreadsheet\Chart\TrendLine; use PhpOffice\PhpSpreadsheet\RichText\RichText; > use PhpOffice\PhpSpreadsheet\Reader\Xlsx;< use PhpOffice\PhpSpreadsheet\Style\Color;use PhpOffice\PhpSpreadsheet\Style\Font; use SimpleXMLElement; class Chart {> /** @var string */ /** > private $cNamespace; * @param SimpleXMLElement $component > * @param string $name > /** @var string */ * @param string $format > private $aNamespace; * > * @return null|bool|float|int|string > public function __construct(string $cNamespace = Namespaces::CHART, string $aNamespace = Namespaces::DRAWINGML) */ > { private static function getAttribute(SimpleXMLElement $component, $name, $format) > $this->cNamespace = $cNamespace; { > $this->aNamespace = $aNamespace; $attributes = $component->attributes(); > } if (isset($attributes[$name])) { >< * @param SimpleXMLElement $component< if (isset($attributes[$name])) {> if (@isset($attributes[$name])) {} elseif ($format == 'integer') { return (int) $attributes[$name]; } elseif ($format == 'boolean') {< return (bool) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true;> $value = (string) $attributes[$name]; > > return $value === 'true' || $value === '1';} return (float) $attributes[$name]; } return null; }< private static function readColor($color, $background = false) < { < if (isset($color['rgb'])) { < return (string) $color['rgb']; < } elseif (isset($color['indexed'])) { < return Color::indexedColor($color['indexed'] - 7, $background)->getARGB(); < } < } </**< * @param SimpleXMLElement $chartElements* @param string $chartName * * @return \PhpOffice\PhpSpreadsheet\Chart\Chart */< public static function readChart(SimpleXMLElement $chartElements, $chartName)> public function readChart(SimpleXMLElement $chartElements, $chartName){< $namespacesChartMeta = $chartElements->getNamespaces(true); < $chartElementsC = $chartElements->children($namespacesChartMeta['c']);> $chartElementsC = $chartElements->children($this->cNamespace);$XaxisLabel = $YaxisLabel = $legend = $title = null; $dispBlanksAs = $plotVisOnly = null;<> $plotArea = null; > $rotX = $rotY = $rAngAx = $perspective = null; > $xAxis = new Axis(); > $yAxis = new Axis(); > $autoTitleDeleted = null; > $chartNoFill = false; > $gradientArray = []; > $gradientLin = null; > $roundedCorners = false;foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) {> case 'spPr': case 'chart': > $possibleNoFill = $chartElementsC->spPr->children($this->aNamespace); foreach ($chartElement as $chartDetailsKey => $chartDetails) { > if (isset($possibleNoFill->noFill)) { $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); > $chartNoFill = true; switch ($chartDetailsKey) { > } case 'plotArea': > $plotAreaLayout = $XaxisLable = $YaxisLable = null; > break; $plotSeries = $plotAttributes = []; > case 'roundedCorners': foreach ($chartDetails as $chartDetailKey => $chartDetail) { > /** @var bool */ switch ($chartDetailKey) { > $roundedCorners = self::getAttribute($chartElementsC->roundedCorners, 'val', 'boolean'); case 'layout': > $plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); > break;< $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']);> $chartDetails = Xlsx::testSimpleXml($chartDetails);break;> case 'autoTitleDeleted': case 'catAx': > /** @var bool */ if (isset($chartDetail->title)) { > $autoTitleDeleted = self::getAttribute($chartElementsC->chart->autoTitleDeleted, 'val', 'boolean'); $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); > } > break; > case 'view3D': break; > $rotX = self::getAttribute($chartDetails->rotX, 'val', 'integer'); case 'dateAx': > $rotY = self::getAttribute($chartDetails->rotY, 'val', 'integer'); if (isset($chartDetail->title)) { > $rAngAx = self::getAttribute($chartDetails->rAngAx, 'val', 'integer'); $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); > $perspective = self::getAttribute($chartDetails->perspective, 'val', 'integer'); } > > break;< $plotAreaLayout = $XaxisLable = $YaxisLable = null;> $plotAreaLayout = $XaxisLabel = $YaxisLabel = null;case 'valAx':> $catAxRead = false; if (isset($chartDetail->title)) { > $plotNoFill = false;$YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);> $chartDetail = Xlsx::testSimpleXml($chartDetail);}> case 'spPr': > $possibleNoFill = $chartDetails->spPr->children($this->aNamespace); break; > if (isset($possibleNoFill->noFill)) { case 'barChart': > $plotNoFill = true; case 'bar3DChart': > } $barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string'); > if (isset($possibleNoFill->gradFill->gsLst)) { $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > foreach ($possibleNoFill->gradFill->gsLst->gs as $gradient) { $plotSer->setPlotDirection($barDirection); > $gradient = Xlsx::testSimpleXml($gradient); $plotSeries[] = $plotSer; > /** @var float */ $plotAttributes = self::readChartAttributes($chartDetail); > $pos = self::getAttribute($gradient, 'pos', 'float'); > $gradientArray[] = [ break; > $pos / ChartProperties::PERCENTAGE_MULTIPLIER, case 'lineChart': > new ChartColor($this->readColor($gradient)), case 'line3DChart': > ]; $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > } $plotAttributes = self::readChartAttributes($chartDetail); > } > if (isset($possibleNoFill->gradFill->lin)) { break; > $gradientLin = ChartProperties::XmlToAngle((string) self::getAttribute($possibleNoFill->gradFill->lin, 'ang', 'string')); case 'areaChart': > } case 'area3DChart': > $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > break;< $plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);> $plotAreaLayout = $this->chartLayoutDetails($chartDetail);< case 'catAx':> case Axis::AXIS_TYPE_CATEGORY: > case Axis::AXIS_TYPE_DATE: > $catAxRead = true;< $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);> $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));case 'doughnutChart':> $xAxis->setAxisType($chartDetailKey); case 'pieChart': > $this->readEffects($chartDetail, $xAxis); case 'pie3DChart': > if (isset($chartDetail->spPr)) { $explosion = isset($chartDetail->ser->explosion); > $sppr = $chartDetail->spPr->children($this->aNamespace); $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > if (isset($sppr->solidFill)) { $plotSer->setPlotStyle($explosion); > $axisColorArray = $this->readColor($sppr->solidFill); $plotSeries[] = $plotSer; > $xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); $plotAttributes = self::readChartAttributes($chartDetail); > } > } break; > if (isset($chartDetail->majorGridlines)) { case 'scatterChart': > $majorGridlines = new GridLines(); $scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string'); > if (isset($chartDetail->majorGridlines->spPr)) { $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $this->readEffects($chartDetail->majorGridlines, $majorGridlines); $plotSer->setPlotStyle($scatterStyle); > $this->readLineStyle($chartDetail->majorGridlines, $majorGridlines); $plotSeries[] = $plotSer; > } $plotAttributes = self::readChartAttributes($chartDetail); > $xAxis->setMajorGridlines($majorGridlines); > } break; > if (isset($chartDetail->minorGridlines)) { case 'bubbleChart': > $minorGridlines = new GridLines(); $bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer'); > $minorGridlines->activateObject(); $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > if (isset($chartDetail->minorGridlines->spPr)) { $plotSer->setPlotStyle($bubbleScale); > $this->readEffects($chartDetail->minorGridlines, $minorGridlines); $plotSeries[] = $plotSer; > $this->readLineStyle($chartDetail->minorGridlines, $minorGridlines); $plotAttributes = self::readChartAttributes($chartDetail); > } > $xAxis->setMinorGridlines($minorGridlines); break; > } case 'radarChart': > $this->setAxisProperties($chartDetail, $xAxis); $radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string'); > $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > break; $plotSer->setPlotStyle($radarStyle); > case Axis::AXIS_TYPE_VALUE: $plotSeries[] = $plotSer; > $whichAxis = null; $plotAttributes = self::readChartAttributes($chartDetail); > $axPos = null; > if (isset($chartDetail->axPos)) { break; > $axPos = self::getAttribute($chartDetail->axPos, 'val', 'string'); case 'surfaceChart': > } case 'surface3DChart': > if ($catAxRead) { $wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean'); > $whichAxis = $yAxis; $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $yAxis->setAxisType($chartDetailKey); $plotSer->setPlotStyle($wireFrame); > } elseif (!empty($axPos)) { $plotSeries[] = $plotSer; > switch ($axPos) { $plotAttributes = self::readChartAttributes($chartDetail); > case 't': > case 'b': break; > $whichAxis = $xAxis; case 'stockChart': > $xAxis->setAxisType($chartDetailKey); $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $plotAttributes = self::readChartAttributes($plotAreaLayout); > break; > case 'r': break; > case 'l': } > $whichAxis = $yAxis; } > $yAxis->setAxisType($chartDetailKey);< case 'dateAx': < if (isset($chartDetail->title)) { < $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);$plotArea = new PlotArea($plotAreaLayout, $plotSeries);> } self::setChartAttributes($plotAreaLayout, $plotAttributes); > if (isset($chartDetail->title)) { > $axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); break; > case 'plotVisOnly': > switch ($axPos) { $plotVisOnly = self::getAttribute($chartDetails, 'val', 'string'); > case 't': > case 'b': break; > $XaxisLabel = $axisLabel;< case 'valAx': < if (isset($chartDetail->title)) { < $YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);> case 'r': > case 'l': > $YaxisLabel = $axisLabel; > > break; > } > } > $this->readEffects($chartDetail, $whichAxis); > if ($whichAxis !== null && isset($chartDetail->spPr)) { > $sppr = $chartDetail->spPr->children($this->aNamespace); > if (isset($sppr->solidFill)) { > $axisColorArray = $this->readColor($sppr->solidFill); > $whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); > } > } > if ($whichAxis !== null && isset($chartDetail->majorGridlines)) { > $majorGridlines = new GridLines(); > if (isset($chartDetail->majorGridlines->spPr)) { > $this->readEffects($chartDetail->majorGridlines, $majorGridlines); > $this->readLineStyle($chartDetail->majorGridlines, $majorGridlines); > } > $whichAxis->setMajorGridlines($majorGridlines); > } > if ($whichAxis !== null && isset($chartDetail->minorGridlines)) { > $minorGridlines = new GridLines(); > $minorGridlines->activateObject(); > if (isset($chartDetail->minorGridlines->spPr)) { > $this->readEffects($chartDetail->minorGridlines, $minorGridlines); > $this->readLineStyle($chartDetail->minorGridlines, $minorGridlines);break;> $whichAxis->setMinorGridlines($minorGridlines); case 'title': > } $title = self::chartTitle($chartDetails, $namespacesChartMeta); > $this->setAxisProperties($chartDetail, $whichAxis);< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotDirection($barDirection);> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotDirection("$barDirection");< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($chartDetail);> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($chartDetail);> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);< $explosion = isset($chartDetail->ser->explosion); < $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($explosion);> $explosion = self::getAttribute($chartDetail->ser->explosion, 'val', 'string'); > $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$explosion");< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);break;> /** @var string */< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($bubbleScale);> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$bubbleScale");< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);$legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);> /** @var string */< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($wireFrame);> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$wireFrame");< $plotAttributes = self::readChartAttributes($chartDetail);> $plotAttributes = $this->readChartAttributes($chartDetail);< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($plotAreaLayout);> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);< self::setChartAttributes($plotAreaLayout, $plotAttributes);> $this->setChartAttributes($plotAreaLayout, $plotAttributes); > if ($plotNoFill) { > $plotArea->setNoFill(true); > } > if (!empty($gradientArray)) { > $plotArea->setGradientFillProperties($gradientArray, $gradientLin); > }< $title = self::chartTitle($chartDetails, $namespacesChartMeta);> $title = $this->chartTitle($chartDetails);}> $chartDetail = Xlsx::testSimpleXml($chartDetail);< $legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);> $legendLayout = $this->chartLayoutDetails($chartDetail);< $legend = new Legend($legendPos, $legendLayout, $legendOverlay);> $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay);< $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, $dispBlanksAs, $XaxisLabel, $YaxisLabel);> $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel, $xAxis, $yAxis); > if ($chartNoFill) { > $chart->setNoFill(true); > } > $chart->setRoundedCorners($roundedCorners); > if (is_bool($autoTitleDeleted)) { > $chart->setAutoTitleDeleted($autoTitleDeleted); > } > if (is_int($rotX)) { > $chart->setRotX($rotX); > } > if (is_int($rotY)) { > $chart->setRotY($rotY); > } > if (is_int($rAngAx)) { > $chart->setRAngAx($rAngAx); > } > if (is_int($perspective)) { > $chart->setPerspective($perspective); > }return $chart; }< private static function chartTitle(SimpleXMLElement $titleDetails, array $namespacesChartMeta)> private function chartTitle(SimpleXMLElement $titleDetails): Title{ $caption = []; $titleLayout = null; foreach ($titleDetails as $titleDetailKey => $chartDetail) {> $chartDetail = Xlsx::testSimpleXml($chartDetail);switch ($titleDetailKey) { case 'tx':< $titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']);> if (isset($chartDetail->rich)) { > $titleDetails = $chartDetail->rich->children($this->aNamespace);foreach ($titleDetails as $titleKey => $titleDetail) {> $titleDetail = Xlsx::testSimpleXml($titleDetail);switch ($titleKey) { case 'p':< $titleDetailPart = $titleDetail->children($namespacesChartMeta['a']); < $caption[] = self::parseRichText($titleDetailPart);> $titleDetailPart = $titleDetail->children($this->aNamespace); > $caption[] = $this->parseRichText($titleDetailPart); > } > } > } elseif (isset($chartDetail->strRef->strCache)) { > foreach ($chartDetail->strRef->strCache->pt as $pt) { > if (isset($pt->v)) { > $caption[] = (string) $pt->v; > }} } break; case 'layout':< $titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);> $titleLayout = $this->chartLayoutDetails($chartDetail);break; } } return new Title($caption, $titleLayout); }< private static function chartLayoutDetails($chartDetail, $namespacesChartMeta)> private function chartLayoutDetails(SimpleXMLElement $chartDetail): ?Layout{ if (!isset($chartDetail->manualLayout)) { return null; }< $details = $chartDetail->manualLayout->children($namespacesChartMeta['c']);> $details = $chartDetail->manualLayout->children($this->cNamespace);if ($details === null) { return null; } $layout = []; foreach ($details as $detailKey => $detail) {> $detail = Xlsx::testSimpleXml($detail);$layout[$detailKey] = self::getAttribute($detail, 'val', 'string'); } return new Layout($layout); }< private static function chartDataSeries($chartDetail, $namespacesChartMeta, $plotType)> private function chartDataSeries(SimpleXMLElement $chartDetail, string $plotType): DataSeries{ $multiSeriesType = null; $smoothLine = false;< $seriesLabel = $seriesCategory = $seriesValues = $plotOrder = [];> $seriesLabel = $seriesCategory = $seriesValues = $plotOrder = $seriesBubbles = [];< $seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']);> $seriesDetailSet = $chartDetail->children($this->cNamespace);foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) { switch ($seriesDetailKey) { case 'grouping': $multiSeriesType = self::getAttribute($chartDetail->grouping, 'val', 'string'); break; case 'ser': $marker = null; $seriesIndex = '';> $fillColor = null; foreach ($seriesDetails as $seriesKey => $seriesDetail) { > $pointSize = null; switch ($seriesKey) { > $noFill = false; case 'idx': > $bubble3D = false; $seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer'); > $dptColors = []; > $markerFillColor = null; break; > $markerBorderColor = null; case 'order': > $lineStyle = null; $seriesOrder = self::getAttribute($seriesDetail, 'val', 'integer'); > $labelLayout = null; $plotOrder[$seriesIndex] = $seriesOrder; > $trendLines = [];> $seriesDetail = Xlsx::testSimpleXml($seriesDetail);break; case 'tx':< $seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);> $seriesLabel[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail); > > break; > case 'spPr': > $children = $seriesDetail->children($this->aNamespace); > if (isset($children->ln)) { > $ln = $children->ln; > if (is_countable($ln->noFill) && count($ln->noFill) === 1) { > $noFill = true; > } > $lineStyle = new GridLines(); > $this->readLineStyle($seriesDetails, $lineStyle); > } > if (isset($children->effectLst)) { > if ($lineStyle === null) { > $lineStyle = new GridLines(); > } > $this->readEffects($seriesDetails, $lineStyle); > } > if (isset($children->solidFill)) { > $fillColor = new ChartColor($this->readColor($children->solidFill)); > } > > break; > case 'dPt': > $dptIdx = (int) self::getAttribute($seriesDetail->idx, 'val', 'string'); > if (isset($seriesDetail->spPr)) { > $children = $seriesDetail->spPr->children($this->aNamespace); > if (isset($children->solidFill)) { > $arrayColors = $this->readColor($children->solidFill); > $dptColors[$dptIdx] = new ChartColor($arrayColors); > } > } > > break; > case 'trendline': > $trendLine = new TrendLine(); > $this->readLineStyle($seriesDetail, $trendLine); > /** @var ?string */ > $trendLineType = self::getAttribute($seriesDetail->trendlineType, 'val', 'string'); > /** @var ?bool */ > $dispRSqr = self::getAttribute($seriesDetail->dispRSqr, 'val', 'boolean'); > /** @var ?bool */ > $dispEq = self::getAttribute($seriesDetail->dispEq, 'val', 'boolean'); > /** @var ?int */ > $order = self::getAttribute($seriesDetail->order, 'val', 'integer'); > /** @var ?int */ > $period = self::getAttribute($seriesDetail->period, 'val', 'integer'); > /** @var ?float */ > $forward = self::getAttribute($seriesDetail->forward, 'val', 'float'); > /** @var ?float */ > $backward = self::getAttribute($seriesDetail->backward, 'val', 'float'); > /** @var ?float */ > $intercept = self::getAttribute($seriesDetail->intercept, 'val', 'float'); > /** @var ?string */ > $name = (string) $seriesDetail->name; > $trendLine->setTrendLineProperties( > $trendLineType, > $order, > $period, > $dispRSqr, > $dispEq, > $backward, > $forward, > $intercept, > $name > ); > $trendLines[] = $trendLine;break; case 'marker': $marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');> $pointSize = self::getAttribute($seriesDetail->size, 'val', 'string'); > $pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null; break; > if (isset($seriesDetail->spPr)) { case 'smooth': > $children = $seriesDetail->spPr->children($this->aNamespace); $smoothLine = self::getAttribute($seriesDetail, 'val', 'boolean'); > if (isset($children->solidFill)) { > $markerFillColor = $this->readColor($children->solidFill); break; > } case 'cat': > if (isset($children->ln->solidFill)) { $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); > $markerBorderColor = $this->readColor($children->ln->solidFill); > } break; > }< $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);> $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);< $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);> $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");break; case 'xVal':< $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);> $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");break; case 'yVal':< $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);> $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");break;> case 'bubbleSize': } > $seriesBubbles[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize"); } > } > break; } > case 'bubble3D': > $bubble3D = self::getAttribute($seriesDetail, 'val', 'boolean'); return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); > } > break; > case 'dLbls': private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null) > $labelLayout = new Layout($this->readChartAttributes($seriesDetails)); { > if (isset($seriesDetail->strRef)) { > break; $seriesSource = (string) $seriesDetail->strRef->f; > } $seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's'); > } > if ($labelLayout) { return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > if (isset($seriesLabel[$seriesIndex])) { } elseif (isset($seriesDetail->numRef)) { > $seriesLabel[$seriesIndex]->setLabelLayout($labelLayout); $seriesSource = (string) $seriesDetail->numRef->f; > } $seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c'])); > if (isset($seriesCategory[$seriesIndex])) { > $seriesCategory[$seriesIndex]->setLabelLayout($labelLayout); return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > } } elseif (isset($seriesDetail->multiLvlStrRef)) { > if (isset($seriesValues[$seriesIndex])) { $seriesSource = (string) $seriesDetail->multiLvlStrRef->f; > $seriesValues[$seriesIndex]->setLabelLayout($labelLayout); $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); > } $seriesData['pointCount'] = count($seriesData['dataValues']); > } > if ($noFill) { return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > if (isset($seriesLabel[$seriesIndex])) { } elseif (isset($seriesDetail->multiLvlNumRef)) { > $seriesLabel[$seriesIndex]->setScatterLines(false); $seriesSource = (string) $seriesDetail->multiLvlNumRef->f; > } $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); > if (isset($seriesCategory[$seriesIndex])) { $seriesData['pointCount'] = count($seriesData['dataValues']); > $seriesCategory[$seriesIndex]->setScatterLines(false); > } return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > if (isset($seriesValues[$seriesIndex])) { } > $seriesValues[$seriesIndex]->setScatterLines(false); > } return null; > } } > if ($lineStyle !== null) { > if (isset($seriesLabel[$seriesIndex])) { private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n') > $seriesLabel[$seriesIndex]->copyLineStyles($lineStyle); { > } $seriesVal = []; > if (isset($seriesCategory[$seriesIndex])) { $formatCode = ''; > $seriesCategory[$seriesIndex]->copyLineStyles($lineStyle); $pointCount = 0; > } > if (isset($seriesValues[$seriesIndex])) { foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) { > $seriesValues[$seriesIndex]->copyLineStyles($lineStyle); switch ($seriesValueIdx) { > } case 'ptCount': > } $pointCount = self::getAttribute($seriesValue, 'val', 'integer'); > if ($bubble3D) { > if (isset($seriesLabel[$seriesIndex])) { break; > $seriesLabel[$seriesIndex]->setBubble3D($bubble3D); case 'formatCode': > } $formatCode = (string) $seriesValue; > if (isset($seriesCategory[$seriesIndex])) { > $seriesCategory[$seriesIndex]->setBubble3D($bubble3D); break; > } case 'pt': > if (isset($seriesValues[$seriesIndex])) { $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); > $seriesValues[$seriesIndex]->setBubble3D($bubble3D);if ($dataType == 's') {> if (!empty($dptColors)) { $seriesVal[$pointVal] = (string) $seriesValue->v; > if (isset($seriesLabel[$seriesIndex])) { } elseif ($seriesValue->v === Functions::NA()) { > $seriesLabel[$seriesIndex]->setFillColor($dptColors);$seriesVal[$pointVal] = null;> if (isset($seriesCategory[$seriesIndex])) { } else { > $seriesCategory[$seriesIndex]->setFillColor($dptColors);$seriesVal[$pointVal] = (float) $seriesValue->v;> if (isset($seriesValues[$seriesIndex])) { } > $seriesValues[$seriesIndex]->setFillColor($dptColors); > } break; > } } > if ($markerFillColor !== null) { } > if (isset($seriesLabel[$seriesIndex])) { > $seriesLabel[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); return [ > } 'formatCode' => $formatCode, > if (isset($seriesCategory[$seriesIndex])) { 'pointCount' => $pointCount, > $seriesCategory[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); 'dataValues' => $seriesVal, > } ]; > if (isset($seriesValues[$seriesIndex])) { } > $seriesValues[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); > } private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n') > } { > if ($markerBorderColor !== null) { $seriesVal = []; > if (isset($seriesLabel[$seriesIndex])) { $formatCode = ''; > $seriesLabel[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); $pointCount = 0; > } > if (isset($seriesCategory[$seriesIndex])) { foreach ($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) { > $seriesCategory[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); foreach ($seriesLevel as $seriesValueIdx => $seriesValue) { > } switch ($seriesValueIdx) { > if (isset($seriesValues[$seriesIndex])) { case 'ptCount': > $seriesValues[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); $pointCount = self::getAttribute($seriesValue, 'val', 'integer'); > } > } break; > if ($smoothLine) { case 'formatCode': > if (isset($seriesLabel[$seriesIndex])) { $formatCode = (string) $seriesValue; > $seriesLabel[$seriesIndex]->setSmoothLine(true); > } break; > if (isset($seriesCategory[$seriesIndex])) { case 'pt': > $seriesCategory[$seriesIndex]->setSmoothLine(true); $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); > } if ($dataType == 's') { > if (isset($seriesValues[$seriesIndex])) { $seriesVal[$pointVal][] = (string) $seriesValue->v; > $seriesValues[$seriesIndex]->setSmoothLine(true); } elseif ($seriesValue->v === Functions::NA()) { > } $seriesVal[$pointVal] = null; > } } else { > if (!empty($trendLines)) { $seriesVal[$pointVal][] = (float) $seriesValue->v; > if (isset($seriesLabel[$seriesIndex])) { } > $seriesLabel[$seriesIndex]->setTrendLines($trendLines); > } break; > if (isset($seriesCategory[$seriesIndex])) { } > $seriesCategory[$seriesIndex]->setTrendLines($trendLines); } > } } > if (isset($seriesValues[$seriesIndex])) { > $seriesValues[$seriesIndex]->setTrendLines($trendLines); return [ > } 'formatCode' => $formatCode, > } 'pointCount' => $pointCount, > } 'dataValues' => $seriesVal, > } ]; > /** @phpstan-ignore-next-line */ } > $series = new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); > $series->setPlotBubbleSizes($seriesBubbles);< return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);> return $series;< private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null)> /** > * @return mixed > */ > private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?ChartColor $fillColor = null, ?string $pointSize = null)< $seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);> if (isset($seriesDetail->strRef->strCache)) { > $seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > } > > return $seriesValues;< $seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize"); > if (isset($seriesDetail->numRef->numCache)) { > $seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace)); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > }< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);> return $seriesValues;< $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); < $seriesData['pointCount'] = count($seriesData['dataValues']);> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);> if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) { > $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > } > > return $seriesValues;< $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); < $seriesData['pointCount'] = count($seriesData['dataValues']);> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);> if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) { > $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > } > > return $seriesValues; > } > > if (isset($seriesDetail->v)) { > return new DataSeriesValues( > DataSeriesValues::DATASERIES_TYPE_STRING, > null, > null, > 1, > [(string) $seriesDetail->v] > );< private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n')> private function chartDataSeriesValues(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array$fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'));> $seriesValue = Xlsx::testSimpleXml($seriesValue);< } elseif ($seriesValue->v === Functions::NA()) {> } elseif ((string) $seriesValue->v === ExcelError::NA()) {< private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n')> private function chartDataSeriesValuesMultiLevel(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array< } elseif ($seriesValue->v === Functions::NA()) {> } elseif ((string) $seriesValue->v === ExcelError::NA()) {< private static function parseRichText(SimpleXMLElement $titleDetailPart)> private function parseRichText(SimpleXMLElement $titleDetailPart): RichText< $objText = null;> $defaultFontSize = null; > $defaultBold = null; > $defaultItalic = null; > $defaultUnderscore = null; > $defaultStrikethrough = null; > $defaultBaseline = null; > $defaultFontName = null; > $defaultLatin = null; > $defaultEastAsian = null; > $defaultComplexScript = null; > $defaultFontColor = null; > if (isset($titleDetailPart->pPr->defRPr)) { > /** @var ?int */ > $defaultFontSize = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer'); > /** @var ?bool */ > $defaultBold = self::getAttribute($titleDetailPart->pPr->defRPr, 'b', 'boolean'); > /** @var ?bool */ > $defaultItalic = self::getAttribute($titleDetailPart->pPr->defRPr, 'i', 'boolean'); > /** @var ?string */ > $defaultUnderscore = self::getAttribute($titleDetailPart->pPr->defRPr, 'u', 'string'); > /** @var ?string */ > $defaultStrikethrough = self::getAttribute($titleDetailPart->pPr->defRPr, 'strike', 'string'); > /** @var ?int */ > $defaultBaseline = self::getAttribute($titleDetailPart->pPr->defRPr, 'baseline', 'integer'); > if (isset($titleDetailPart->defRPr->rFont['val'])) { > $defaultFontName = (string) $titleDetailPart->defRPr->rFont['val']; > } > if (isset($titleDetailPart->pPr->defRPr->latin)) { > /** @var ?string */ > $defaultLatin = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->ea)) { > /** @var ?string */ > $defaultEastAsian = self::getAttribute($titleDetailPart->pPr->defRPr->ea, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->cs)) { > /** @var ?string */ > $defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->solidFill)) { > $defaultFontColor = $this->readColor($titleDetailPart->pPr->defRPr->solidFill); > } > }< if (isset($titleDetailElement->t)) { < $objText = $value->createTextRun((string) $titleDetailElement->t);> if ( > (string) $titleDetailElementKey !== 'r' > || !isset($titleDetailElement->t) > ) { > continue;}> $objText = $value->createTextRun((string) $titleDetailElement->t); > if ($objText->getFont() === null) { $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean'); > // @codeCoverageIgnoreStart if ($bold !== null) { > continue; $objText->getFont()->setBold($bold); > // @codeCoverageIgnoreEnd } > } > $fontSize = null; $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean'); > $bold = null; if ($italic !== null) { > $italic = null; $objText->getFont()->setItalic($italic); > $underscore = null; } > $strikethrough = null; > $baseline = null; $baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer'); > $fontName = null; if ($baseline !== null) { > $latinName = null; if ($baseline > 0) { > $eastAsian = null; $objText->getFont()->setSuperscript(true); > $complexScript = null; } elseif ($baseline < 0) { > $fontColor = null; $objText->getFont()->setSubscript(true); > $underlineColor = null;}> // not used now, not sure it ever was, grandfathering< $objText->getFont()->setName((string) $titleDetailElement->rPr->rFont['val']);> // @codeCoverageIgnoreStart > $fontName = (string) $titleDetailElement->rPr->rFont['val']; > // @codeCoverageIgnoreEnd > } > if (isset($titleDetailElement->rPr->latin)) { > /** @var ?string */ > $latinName = self::getAttribute($titleDetailElement->rPr->latin, 'typeface', 'string'); > } > if (isset($titleDetailElement->rPr->ea)) { > /** @var ?string */ > $eastAsian = self::getAttribute($titleDetailElement->rPr->ea, 'typeface', 'string'); > } > if (isset($titleDetailElement->rPr->cs)) { > /** @var ?string */ > $complexScript = self::getAttribute($titleDetailElement->rPr->cs, 'typeface', 'string'); > } > /** @var ?int */ > $fontSize = self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'); > > // not used now, not sure it ever was, grandfathering > if (isset($titleDetailElement->rPr->solidFill)) { > $fontColor = $this->readColor($titleDetailElement->rPr->solidFill); > } > > /** @var ?bool */ > $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean'); > > /** @var ?bool */ > $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean'); > > /** @var ?int */ > $baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer'); > > /** @var ?string */ > $underscore = self::getAttribute($titleDetailElement->rPr, 'u', 'string'); > if (isset($titleDetailElement->rPr->uFill->solidFill)) { > $underlineColor = $this->readColor($titleDetailElement->rPr->uFill->solidFill); > } > > /** @var ?string */ > $strikethrough = self::getAttribute($titleDetailElement->rPr, 'strike', 'string'); > } > > $fontFound = false; > $latinName = $latinName ?? $defaultLatin; > if ($latinName !== null) { > $objText->getFont()->setLatin($latinName); > $fontFound = true; > } > $eastAsian = $eastAsian ?? $defaultEastAsian; > if ($eastAsian !== null) { > $objText->getFont()->setEastAsian($eastAsian); > $fontFound = true; > } > $complexScript = $complexScript ?? $defaultComplexScript; > if ($complexScript !== null) { > $objText->getFont()->setComplexScript($complexScript); > $fontFound = true; > } > $fontName = $fontName ?? $defaultFontName; > if ($fontName !== null) { > // @codeCoverageIgnoreStart > $objText->getFont()->setName($fontName); > $fontFound = true; > // @codeCoverageIgnoreEnd< $fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer')); < if ($fontSize !== null) {> $fontSize = $fontSize ?? $defaultFontSize; > if (is_int($fontSize)) {if ($underscore !== null) {> $fontFound = true; if ($underscore == 'sng') { > } else { $objText->getFont()->setUnderline(Font::UNDERLINE_SINGLE); > $objText->getFont()->setSize(null, true);< $fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string')); < if ($fontColor !== null) { < $objText->getFont()->setColor(new Color(self::readColor($fontColor)));> $fontColor = $fontColor ?? $defaultFontColor; > if (!empty($fontColor)) { > $objText->getFont()->setChartColor($fontColor); > $fontFound = true;< $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean');> $bold = $bold ?? $defaultBold;}> $fontFound = true;< $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean');> $italic = $italic ?? $defaultItalic;> $fontFound = true;< $baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer');> $baseline = $baseline ?? $defaultBaseline;if ($strikethrough !== null) {> $objText->getFont()->setBaseLine($baseline);if ($strikethrough == 'noStrike') {> $fontFound = true;< $underscore = (self::getAttribute($titleDetailElement->rPr, 'u', 'string'));> $underscore = $underscore ?? $defaultUnderscore;} else {> } elseif ($underscore !== '') { $objText->getFont()->setStrikethrough(true); > $objText->getFont()->setUnderline($underscore);}> $fontFound = true; } > if ($underlineColor) { } > $objText->getFont()->setUnderlineColor($underlineColor); } > }< $strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string'));> $strikethrough = $strikethrough ?? $defaultStrikethrough;return $value;> $objText->getFont()->setStrikeType($strikethrough);}> $fontFound = true;> if ($fontFound === false) { private static function readChartAttributes($chartDetail) > $objText->setFont(null);< private static function readChartAttributes($chartDetail)> /** > * @param ?SimpleXMLElement $chartDetail > */ > private function readChartAttributes($chartDetail): array$plotAttributes = []; if (isset($chartDetail->dLbls)) {< if (isset($chartDetail->dLbls->howLegendKey)) {> if (isset($chartDetail->dLbls->dLblPos)) { > $plotAttributes['dLblPos'] = self::getAttribute($chartDetail->dLbls->dLblPos, 'val', 'string'); > } > if (isset($chartDetail->dLbls->numFmt)) { > $plotAttributes['numFmtCode'] = self::getAttribute($chartDetail->dLbls->numFmt, 'formatCode', 'string'); > $plotAttributes['numFmtLinked'] = self::getAttribute($chartDetail->dLbls->numFmt, 'sourceLinked', 'boolean'); > } > if (isset($chartDetail->dLbls->showLegendKey)) {$plotAttributes['showLegendKey'] = self::getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string'); } if (isset($chartDetail->dLbls->showVal)) { $plotAttributes['showVal'] = self::getAttribute($chartDetail->dLbls->showVal, 'val', 'string'); } if (isset($chartDetail->dLbls->showCatName)) { $plotAttributes['showCatName'] = self::getAttribute($chartDetail->dLbls->showCatName, 'val', 'string'); } if (isset($chartDetail->dLbls->showSerName)) { $plotAttributes['showSerName'] = self::getAttribute($chartDetail->dLbls->showSerName, 'val', 'string'); } if (isset($chartDetail->dLbls->showPercent)) { $plotAttributes['showPercent'] = self::getAttribute($chartDetail->dLbls->showPercent, 'val', 'string'); } if (isset($chartDetail->dLbls->showBubbleSize)) { $plotAttributes['showBubbleSize'] = self::getAttribute($chartDetail->dLbls->showBubbleSize, 'val', 'string'); } if (isset($chartDetail->dLbls->showLeaderLines)) { $plotAttributes['showLeaderLines'] = self::getAttribute($chartDetail->dLbls->showLeaderLines, 'val', 'string'); }> if (isset($chartDetail->dLbls->spPr)) { } > $sppr = $chartDetail->dLbls->spPr->children($this->aNamespace); > if (isset($sppr->solidFill)) { return $plotAttributes; > $plotAttributes['labelFillColor'] = new ChartColor($this->readColor($sppr->solidFill)); } > } > if (isset($sppr->ln->solidFill)) { /** > $plotAttributes['labelBorderColor'] = new ChartColor($this->readColor($sppr->ln->solidFill)); * @param Layout $plotArea > } * @param mixed $plotAttributes > } */ > if (isset($chartDetail->dLbls->txPr)) { private static function setChartAttributes(Layout $plotArea, $plotAttributes) > $txpr = $chartDetail->dLbls->txPr->children($this->aNamespace); { > if (isset($txpr->p->pPr->defRPr->solidFill)) { foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) { > $plotAttributes['labelFontColor'] = new ChartColor($this->readColor($txpr->p->pPr->defRPr->solidFill)); switch ($plotAttributeKey) { > } case 'showLegendKey': > }< * @param Layout $plotArea< private static function setChartAttributes(Layout $plotArea, $plotAttributes)> private function setChartAttributes(Layout $plotArea, $plotAttributes): voidbreak; case 'showVal': $plotArea->setShowVal($plotAttributeValue); break; case 'showCatName': $plotArea->setShowCatName($plotAttributeValue); break; case 'showSerName': $plotArea->setShowSerName($plotAttributeValue); break; case 'showPercent': $plotArea->setShowPercent($plotAttributeValue); break; case 'showBubbleSize': $plotArea->setShowBubbleSize($plotAttributeValue); break; case 'showLeaderLines': $plotArea->setShowLeaderLines($plotAttributeValue); break;> } } > } } > } } > } > private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void > { > if (!isset($chartObject, $chartDetail->spPr)) { > return; > } > $sppr = $chartDetail->spPr->children($this->aNamespace); > > if (isset($sppr->effectLst->glow)) { > $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; > if ($axisGlowSize != 0.0) { > $colorArray = $this->readColor($sppr->effectLst->glow); > $chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']); > } > } > > if (isset($sppr->effectLst->softEdge)) { > /** @var string */ > $softEdgeSize = self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string'); > if (is_numeric($softEdgeSize)) { > $chartObject->setSoftEdges((float) ChartProperties::xmlToPoints($softEdgeSize)); > } > } > > $type = ''; > foreach (self::SHADOW_TYPES as $shadowType) { > if (isset($sppr->effectLst->$shadowType)) { > $type = $shadowType; > > break; > } > } > if ($type !== '') { > /** @var string */ > $blur = self::getAttribute($sppr->effectLst->$type, 'blurRad', 'string'); > $blur = is_numeric($blur) ? ChartProperties::xmlToPoints($blur) : null; > /** @var string */ > $dist = self::getAttribute($sppr->effectLst->$type, 'dist', 'string'); > $dist = is_numeric($dist) ? ChartProperties::xmlToPoints($dist) : null; > /** @var string */ > $direction = self::getAttribute($sppr->effectLst->$type, 'dir', 'string'); > $direction = is_numeric($direction) ? ChartProperties::xmlToAngle($direction) : null; > $algn = self::getAttribute($sppr->effectLst->$type, 'algn', 'string'); > $rot = self::getAttribute($sppr->effectLst->$type, 'rotWithShape', 'string'); > $size = []; > foreach (['sx', 'sy'] as $sizeType) { > $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); > if (is_numeric($sizeValue)) { > $size[$sizeType] = ChartProperties::xmlToTenthOfPercent((string) $sizeValue); > } else { > $size[$sizeType] = null; > } > } > foreach (['kx', 'ky'] as $sizeType) { > $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); > if (is_numeric($sizeValue)) { > $size[$sizeType] = ChartProperties::xmlToAngle((string) $sizeValue); > } else { > $size[$sizeType] = null; > } > } > $colorArray = $this->readColor($sppr->effectLst->$type); > $chartObject > ->setShadowProperty('effect', $type) > ->setShadowProperty('blur', $blur) > ->setShadowProperty('direction', $direction) > ->setShadowProperty('distance', $dist) > ->setShadowProperty('algn', $algn) > ->setShadowProperty('rotWithShape', $rot) > ->setShadowProperty('size', $size) > ->setShadowProperty('color', $colorArray); > } > } > > private const SHADOW_TYPES = [ > 'outerShdw', > 'innerShdw', > ]; > > private function readColor(SimpleXMLElement $colorXml): array > { > $result = [ > 'type' => null, > 'value' => null, > 'alpha' => null, > 'brightness' => null, > ]; > foreach (ChartColor::EXCEL_COLOR_TYPES as $type) { > if (isset($colorXml->$type)) { > $result['type'] = $type; > $result['value'] = self::getAttribute($colorXml->$type, 'val', 'string'); > if (isset($colorXml->$type->alpha)) { > /** @var string */ > $alpha = self::getAttribute($colorXml->$type->alpha, 'val', 'string'); > if (is_numeric($alpha)) { > $result['alpha'] = ChartColor::alphaFromXml($alpha); > } > } > if (isset($colorXml->$type->lumMod)) { > /** @var string */ > $brightness = self::getAttribute($colorXml->$type->lumMod, 'val', 'string'); > if (is_numeric($brightness)) { > $result['brightness'] = ChartColor::alphaFromXml($brightness); > } > } > > break; > } > } > > return $result; > } > > private function readLineStyle(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void > { > if (!isset($chartObject, $chartDetail->spPr)) { > return; > } > $sppr = $chartDetail->spPr->children($this->aNamespace); > > if (!isset($sppr->ln)) { > return; > } > $lineWidth = null; > /** @var string */ > $lineWidthTemp = self::getAttribute($sppr->ln, 'w', 'string'); > if (is_numeric($lineWidthTemp)) { > $lineWidth = ChartProperties::xmlToPoints($lineWidthTemp); > } > /** @var string */ > $compoundType = self::getAttribute($sppr->ln, 'cmpd', 'string'); > /** @var string */ > $dashType = self::getAttribute($sppr->ln->prstDash, 'val', 'string'); > /** @var string */ > $capType = self::getAttribute($sppr->ln, 'cap', 'string'); > if (isset($sppr->ln->miter)) { > $joinType = ChartProperties::LINE_STYLE_JOIN_MITER; > } elseif (isset($sppr->ln->bevel)) { > $joinType = ChartProperties::LINE_STYLE_JOIN_BEVEL; > } else { > $joinType = ''; > } > $headArrowSize = ''; > $endArrowSize = ''; > /** @var string */ > $headArrowType = self::getAttribute($sppr->ln->headEnd, 'type', 'string'); > /** @var string */ > $headArrowWidth = self::getAttribute($sppr->ln->headEnd, 'w', 'string'); > /** @var string */ > $headArrowLength = self::getAttribute($sppr->ln->headEnd, 'len', 'string'); > /** @var string */ > $endArrowType = self::getAttribute($sppr->ln->tailEnd, 'type', 'string'); > /** @var string */ > $endArrowWidth = self::getAttribute($sppr->ln->tailEnd, 'w', 'string'); > /** @var string */ > $endArrowLength = self::getAttribute($sppr->ln->tailEnd, 'len', 'string'); > $chartObject->setLineStyleProperties( > $lineWidth, > $compoundType, > $dashType, > $capType, > $joinType, > $headArrowType, > $headArrowSize, > $endArrowType, > $endArrowSize, > $headArrowWidth, > $headArrowLength, > $endArrowWidth, > $endArrowLength > ); > $colorArray = $this->readColor($sppr->ln->solidFill); > $chartObject->getLineColor()->setColorPropertiesArray($colorArray); > } > > private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAxis): void > { > if (!isset($whichAxis)) { > return; > } > if (isset($chartDetail->delete)) { > $whichAxis->setAxisOption('hidden', (string) self::getAttribute($chartDetail->delete, 'val', 'string')); > } > if (isset($chartDetail->numFmt)) { > $whichAxis->setAxisNumberProperties( > (string) self::getAttribute($chartDetail->numFmt, 'formatCode', 'string'), > null, > (int) self::getAttribute($chartDetail->numFmt, 'sourceLinked', 'int') > ); > } > if (isset($chartDetail->crossBetween)) { > $whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string')); > } > if (isset($chartDetail->majorTickMark)) { > $whichAxis->setAxisOption('major_tick_mark', (string) self::getAttribute($chartDetail->majorTickMark, 'val', 'string')); > } > if (isset($chartDetail->minorTickMark)) { > $whichAxis->setAxisOption('minor_tick_mark', (string) self::getAttribute($chartDetail->minorTickMark, 'val', 'string')); > } > if (isset($chartDetail->tickLblPos)) { > $whichAxis->setAxisOption('axis_labels', (string) self::getAttribute($chartDetail->tickLblPos, 'val', 'string')); > } > if (isset($chartDetail->crosses)) { > $whichAxis->setAxisOption('horizontal_crosses', (string) self::getAttribute($chartDetail->crosses, 'val', 'string')); > } > if (isset($chartDetail->crossesAt)) { > $whichAxis->setAxisOption('horizontal_crosses_value', (string) self::getAttribute($chartDetail->crossesAt, 'val', 'string')); > } > if (isset($chartDetail->scaling->orientation)) { > $whichAxis->setAxisOption('orientation', (string) self::getAttribute($chartDetail->scaling->orientation, 'val', 'string')); > } > if (isset($chartDetail->scaling->max)) { > $whichAxis->setAxisOption('maximum', (string) self::getAttribute($chartDetail->scaling->max, 'val', 'string')); > } > if (isset($chartDetail->scaling->min)) { > $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); > } > if (isset($chartDetail->scaling->min)) { > $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); > } > if (isset($chartDetail->majorUnit)) { > $whichAxis->setAxisOption('major_unit', (string) self::getAttribute($chartDetail->majorUnit, 'val', 'string')); > } > if (isset($chartDetail->minorUnit)) { > $whichAxis->setAxisOption('minor_unit', (string) self::getAttribute($chartDetail->minorUnit, 'val', 'string')); > } > if (isset($chartDetail->baseTimeUnit)) { > $whichAxis->setAxisOption('baseTimeUnit', (string) self::getAttribute($chartDetail->baseTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->majorTimeUnit)) { > $whichAxis->setAxisOption('majorTimeUnit', (string) self::getAttribute($chartDetail->majorTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->minorTimeUnit)) { > $whichAxis->setAxisOption('minorTimeUnit', (string) self::getAttribute($chartDetail->minorTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->txPr)) { > $children = $chartDetail->txPr->children($this->aNamespace); > if (isset($children->bodyPr)) { > /** @var string */ > $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); > if (is_numeric($textRotation)) { > $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); > }