Namespacing Part 3 - Charts (#2852)
* Namespacing Part 3 - Charts Charts still need some work, but they are now in good enough shape that the code that reads them can handle namespacing properly. Rather than a set of static routines, Reader/Xlsx/Chart needs to be changed to a regular object, with the relevant namespaces passed in the constructor. I am still looking for a test spreadsheet with non-standard namespacing for a full-blown test, but, in the meantime, the existing tests and samples will suffice. When I find a test case, I will certainly add it. The resulting code is actually simpler than it had been because of the elimination of the need for a NamespacesMeta variable in all the function signatures. Because of that, enough errors disappeared from Phpstan that I decided to just finish that job - its baseline file now dips below 5,000 lines. * Update Change Log Need to document many chart changes.
This commit is contained in:
parent
13e1b9a939
commit
9e4ff929b4
|
|
@ -9,13 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
### Added
|
||||
|
||||
- Add point size option for scatter charts
|
||||
- Add point size option for scatter charts [Issue #2298](https://github.com/PHPOffice/PhpSpreadsheet/issues/2298) [PR #2801](https://github.com/PHPOffice/PhpSpreadsheet/pull/2801)
|
||||
- Basic support for Xlsx reading/writing Chart Sheets [PR #2830](https://github.com/PHPOffice/PhpSpreadsheet/pull/2830)
|
||||
|
||||
Note that a ChartSheet is still only written as a normal Worksheet containing a single chart, not as an actual ChartSheet.
|
||||
|
||||
- Added Worksheet visibility in Ods Reader [PR #2851](https://github.com/PHPOffice/PhpSpreadsheet/pull/2851) and Gnumeric Reader [PR #2853](https://github.com/PHPOffice/PhpSpreadsheet/pull/2853)
|
||||
- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850)
|
||||
- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792)
|
||||
- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
@ -36,6 +38,10 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
- Xls Reader resolving absolute named ranges to relative ranges [Issue #2826](https://github.com/PHPOffice/PhpSpreadsheet/issues/2826) [PR #2827](https://github.com/PHPOffice/PhpSpreadsheet/pull/2827)
|
||||
- Null value handling in the Excel Math/Trig PRODUCT() function [Issue #2833](https://github.com/PHPOffice/PhpSpreadsheet/issues/2833) [PR #2834](https://github.com/PHPOffice/PhpSpreadsheet/pull/2834)
|
||||
- Invalid Print Area defined in Xlsx corrupts internal storage of print area [Issue #2848](https://github.com/PHPOffice/PhpSpreadsheet/issues/2848) [PR #2849](https://github.com/PHPOffice/PhpSpreadsheet/pull/2849)
|
||||
- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772)
|
||||
- Copy from Xls(x) to Html/Pdf loses drawings [PR #2788](https://github.com/PHPOffice/PhpSpreadsheet/pull/2788)
|
||||
- Html Reader converting cell containing 0 to null string [Issue #2810](https://github.com/PHPOffice/PhpSpreadsheet/issues/2810) [PR #2813](https://github.com/PHPOffice/PhpSpreadsheet/pull/2813)
|
||||
- Many fixes for Charts, especially, but not limited to, Scatter, Bubble, and Surface charts. [Issue #2762](https://github.com/PHPOffice/PhpSpreadsheet/issues/2762) [Issue #2299](https://github.com/PHPOffice/PhpSpreadsheet/issues/2299) [Issue #2700](https://github.com/PHPOffice/PhpSpreadsheet/issues/2700) [Issue #2817](https://github.com/PHPOffice/PhpSpreadsheet/issues/2817) [Issue #2763](https://github.com/PHPOffice/PhpSpreadsheet/issues/2763) [PR #2828](https://github.com/PHPOffice/PhpSpreadsheet/pull/2828) [PR #2841](https://github.com/PHPOffice/PhpSpreadsheet/pull/2841) [PR #2846](https://github.com/PHPOffice/PhpSpreadsheet/pull/2846) [PR #2852](https://github.com/PHPOffice/PhpSpreadsheet/pull/2852)
|
||||
|
||||
## 1.23.0 - 2022-04-24
|
||||
|
||||
|
|
|
|||
|
|
@ -2515,136 +2515,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$chartDetail with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$plotType with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$seriesDetail with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has parameter \\$dataType with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has parameter \\$seriesValueSet with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has parameter \\$dataType with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has parameter \\$seriesValueSet with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has parameter \\$chartDetail with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartTitle\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:parseRichText\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readChartAttributes\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readChartAttributes\\(\\) has parameter \\$chartDetail with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$position of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend constructor expects string, bool\\|float\\|int\\|string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$overlay of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend constructor expects bool, bool\\|float\\|int\\|string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$plotOrder of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeries constructor expects array\\<int\\>, array\\<int\\|string, bool\\|float\\|int\\|string\\|null\\> given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$pointCount of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues constructor expects int, null given\\.$#"
|
||||
count: 4
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#6 \\$displayBlanksAs of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart constructor expects string, bool\\|float\\|int\\|string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#7 \\$plotDirection of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeries constructor expects string\\|null, bool\\|float\\|int\\|string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\ColumnAndRowAttributes\\:\\:isFilteredColumn\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -1645,7 +1645,8 @@ class Xlsx extends BaseReader
|
|||
if ($this->includeCharts) {
|
||||
$chartEntryRef = ltrim((string) $contentType['PartName'], '/');
|
||||
$chartElements = $this->loadZip($chartEntryRef);
|
||||
$objChart = Chart::readChart($chartElements, basename($chartEntryRef, '.xml'));
|
||||
$chartReader = new Chart();
|
||||
$objChart = $chartReader->readChart($chartElements, basename($chartEntryRef, '.xml'));
|
||||
if (isset($charts[$chartEntryRef])) {
|
||||
$chartPositionRef = $charts[$chartEntryRef]['sheet'] . '!' . $charts[$chartEntryRef]['id'];
|
||||
if (isset($chartDetails[$chartPositionRef])) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,18 @@ use SimpleXMLElement;
|
|||
|
||||
class Chart
|
||||
{
|
||||
/** @var string */
|
||||
private $cNamespace;
|
||||
|
||||
/** @var string */
|
||||
private $aNamespace;
|
||||
|
||||
public function __construct(string $cNamespace = Namespaces::CHART, string $aNamespace = Namespaces::DRAWINGML)
|
||||
{
|
||||
$this->cNamespace = $cNamespace;
|
||||
$this->aNamespace = $aNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $format
|
||||
|
|
@ -47,10 +59,9 @@ class Chart
|
|||
*
|
||||
* @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;
|
||||
|
|
@ -60,7 +71,7 @@ class Chart
|
|||
switch ($chartElementKey) {
|
||||
case 'chart':
|
||||
foreach ($chartElement as $chartDetailsKey => $chartDetails) {
|
||||
$chartDetailsC = $chartDetails->children($namespacesChartMeta['c']);
|
||||
$chartDetailsC = $chartDetails->children($this->cNamespace);
|
||||
switch ($chartDetailsKey) {
|
||||
case 'view3D':
|
||||
$rotX = self::getAttribute($chartDetails->rotX, 'val', 'integer');
|
||||
|
|
@ -75,24 +86,24 @@ class Chart
|
|||
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
|
||||
switch ($chartDetailKey) {
|
||||
case 'layout':
|
||||
$plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
|
||||
$plotAreaLayout = $this->chartLayoutDetails($chartDetail);
|
||||
|
||||
break;
|
||||
case 'catAx':
|
||||
if (isset($chartDetail->title)) {
|
||||
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
|
||||
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'dateAx':
|
||||
if (isset($chartDetail->title)) {
|
||||
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
|
||||
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'valAx':
|
||||
if (isset($chartDetail->title, $chartDetail->axPos)) {
|
||||
$axisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
|
||||
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
|
||||
|
||||
switch ($axPos) {
|
||||
|
|
@ -113,70 +124,72 @@ class Chart
|
|||
case 'barChart':
|
||||
case 'bar3DChart':
|
||||
$barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string');
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer->setPlotDirection($barDirection);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotDirection("$barDirection");
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'lineChart':
|
||||
case 'line3DChart':
|
||||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'areaChart':
|
||||
case 'area3DChart':
|
||||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'doughnutChart':
|
||||
case 'pieChart':
|
||||
case 'pie3DChart':
|
||||
$explosion = isset($chartDetail->ser->explosion);
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer->setPlotStyle($explosion);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotStyle("$explosion");
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'scatterChart':
|
||||
/** @var string */
|
||||
$scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string');
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotStyle($scatterStyle);
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'bubbleChart':
|
||||
$bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer');
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer->setPlotStyle($bubbleScale);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotStyle("$bubbleScale");
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'radarChart':
|
||||
/** @var string */
|
||||
$radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string');
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotStyle($radarStyle);
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'surfaceChart':
|
||||
case 'surface3DChart':
|
||||
$wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean');
|
||||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotSer->setPlotStyle($wireFrame);
|
||||
$plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotSer->setPlotStyle("$wireFrame");
|
||||
$plotSeries[] = $plotSer;
|
||||
$plotAttributes = self::readChartAttributes($chartDetail);
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'stockChart':
|
||||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
|
||||
$plotAttributes = self::readChartAttributes($plotAreaLayout);
|
||||
$plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey);
|
||||
$plotAttributes = $this->readChartAttributes($plotAreaLayout);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -185,7 +198,7 @@ class Chart
|
|||
$plotAreaLayout = new Layout();
|
||||
}
|
||||
$plotArea = new PlotArea($plotAreaLayout, $plotSeries);
|
||||
self::setChartAttributes($plotAreaLayout, $plotAttributes);
|
||||
$this->setChartAttributes($plotAreaLayout, $plotAttributes);
|
||||
|
||||
break;
|
||||
case 'plotVisOnly':
|
||||
|
|
@ -197,7 +210,7 @@ class Chart
|
|||
|
||||
break;
|
||||
case 'title':
|
||||
$title = self::chartTitle($chartDetails, $namespacesChartMeta);
|
||||
$title = $this->chartTitle($chartDetails);
|
||||
|
||||
break;
|
||||
case 'legend':
|
||||
|
|
@ -215,19 +228,19 @@ class Chart
|
|||
|
||||
break;
|
||||
case 'layout':
|
||||
$legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
|
||||
$legendLayout = $this->chartLayoutDetails($chartDetail);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$legend = new Legend($legendPos, $legendLayout, $legendOverlay);
|
||||
$legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$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);
|
||||
if (is_int($rotX)) {
|
||||
$chart->setRotX($rotX);
|
||||
}
|
||||
|
|
@ -244,25 +257,25 @@ class Chart
|
|||
return $chart;
|
||||
}
|
||||
|
||||
private static function chartTitle(SimpleXMLElement $titleDetails, array $namespacesChartMeta)
|
||||
private function chartTitle(SimpleXMLElement $titleDetails): Title
|
||||
{
|
||||
$caption = [];
|
||||
$titleLayout = null;
|
||||
foreach ($titleDetails as $titleDetailKey => $chartDetail) {
|
||||
switch ($titleDetailKey) {
|
||||
case 'tx':
|
||||
$titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']);
|
||||
$titleDetails = $chartDetail->rich->children($this->aNamespace);
|
||||
foreach ($titleDetails as $titleKey => $titleDetail) {
|
||||
switch ($titleKey) {
|
||||
case 'p':
|
||||
$titleDetailPart = $titleDetail->children($namespacesChartMeta['a']);
|
||||
$caption[] = self::parseRichText($titleDetailPart);
|
||||
$titleDetailPart = $titleDetail->children($this->aNamespace);
|
||||
$caption[] = $this->parseRichText($titleDetailPart);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'layout':
|
||||
$titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
|
||||
$titleLayout = $this->chartLayoutDetails($chartDetail);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -271,12 +284,12 @@ class Chart
|
|||
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;
|
||||
}
|
||||
|
|
@ -288,13 +301,13 @@ class Chart
|
|||
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 = [];
|
||||
|
||||
$seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']);
|
||||
$seriesDetailSet = $chartDetail->children($this->cNamespace);
|
||||
foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) {
|
||||
switch ($seriesDetailKey) {
|
||||
case 'grouping':
|
||||
|
|
@ -322,11 +335,11 @@ class Chart
|
|||
|
||||
break;
|
||||
case 'tx':
|
||||
$seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
|
||||
$seriesLabel[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);
|
||||
|
||||
break;
|
||||
case 'spPr':
|
||||
$children = $seriesDetail->children($namespacesChartMeta['a']);
|
||||
$children = $seriesDetail->children($this->aNamespace);
|
||||
$ln = $children->ln;
|
||||
$lineWidth = self::getAttribute($ln, 'w', 'string');
|
||||
if (is_countable($ln->noFill) && count($ln->noFill) === 1) {
|
||||
|
|
@ -343,9 +356,9 @@ class Chart
|
|||
$pointSize = self::getAttribute($seriesDetail->size, 'val', 'string');
|
||||
$pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null;
|
||||
if (count($seriesDetail->spPr) === 1) {
|
||||
$ln = $seriesDetail->spPr->children($namespacesChartMeta['a']);
|
||||
$ln = $seriesDetail->spPr->children($this->aNamespace);
|
||||
if (count($ln->solidFill) === 1) {
|
||||
$srgbClr = self::getattribute($ln->solidFill->srgbClr, 'val', 'string');
|
||||
$srgbClr = self::getAttribute($ln->solidFill->srgbClr, 'val', 'string');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,19 +368,19 @@ class Chart
|
|||
|
||||
break;
|
||||
case 'cat':
|
||||
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
|
||||
$seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);
|
||||
|
||||
break;
|
||||
case 'val':
|
||||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize");
|
||||
|
||||
break;
|
||||
case 'xVal':
|
||||
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||
$seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize");
|
||||
|
||||
break;
|
||||
case 'yVal':
|
||||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize");
|
||||
|
||||
break;
|
||||
case 'bubble3D':
|
||||
|
|
@ -423,17 +436,21 @@ class Chart
|
|||
}
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
|
||||
}
|
||||
|
||||
private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null)
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null)
|
||||
{
|
||||
if (isset($seriesDetail->strRef)) {
|
||||
$seriesSource = (string) $seriesDetail->strRef->f;
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize");
|
||||
|
||||
if (isset($seriesDetail->strRef->strCache)) {
|
||||
$seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');
|
||||
$seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's');
|
||||
$seriesValues
|
||||
->setFormatCode($seriesData['formatCode'])
|
||||
->setDataValues($seriesData['dataValues']);
|
||||
|
|
@ -442,9 +459,9 @@ class Chart
|
|||
return $seriesValues;
|
||||
} elseif (isset($seriesDetail->numRef)) {
|
||||
$seriesSource = (string) $seriesDetail->numRef->f;
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize");
|
||||
if (isset($seriesDetail->numRef->numCache)) {
|
||||
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
|
||||
$seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace));
|
||||
$seriesValues
|
||||
->setFormatCode($seriesData['formatCode'])
|
||||
->setDataValues($seriesData['dataValues']);
|
||||
|
|
@ -453,10 +470,10 @@ class Chart
|
|||
return $seriesValues;
|
||||
} elseif (isset($seriesDetail->multiLvlStrRef)) {
|
||||
$seriesSource = (string) $seriesDetail->multiLvlStrRef->f;
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize");
|
||||
|
||||
if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) {
|
||||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's');
|
||||
$seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's');
|
||||
$seriesValues
|
||||
->setFormatCode($seriesData['formatCode'])
|
||||
->setDataValues($seriesData['dataValues']);
|
||||
|
|
@ -465,10 +482,10 @@ class Chart
|
|||
return $seriesValues;
|
||||
} elseif (isset($seriesDetail->multiLvlNumRef)) {
|
||||
$seriesSource = (string) $seriesDetail->multiLvlNumRef->f;
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize");
|
||||
|
||||
if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) {
|
||||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's');
|
||||
$seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's');
|
||||
$seriesValues
|
||||
->setFormatCode($seriesData['formatCode'])
|
||||
->setDataValues($seriesData['dataValues']);
|
||||
|
|
@ -480,7 +497,7 @@ class Chart
|
|||
return null;
|
||||
}
|
||||
|
||||
private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n')
|
||||
private function chartDataSeriesValues(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array
|
||||
{
|
||||
$seriesVal = [];
|
||||
$formatCode = '';
|
||||
|
|
@ -500,7 +517,7 @@ class Chart
|
|||
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer');
|
||||
if ($dataType == 's') {
|
||||
$seriesVal[$pointVal] = (string) $seriesValue->v;
|
||||
} elseif ($seriesValue->v === ExcelError::NA()) {
|
||||
} elseif ((string) $seriesValue->v === ExcelError::NA()) {
|
||||
$seriesVal[$pointVal] = null;
|
||||
} else {
|
||||
$seriesVal[$pointVal] = (float) $seriesValue->v;
|
||||
|
|
@ -517,7 +534,7 @@ class Chart
|
|||
];
|
||||
}
|
||||
|
||||
private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n')
|
||||
private function chartDataSeriesValuesMultiLevel(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array
|
||||
{
|
||||
$seriesVal = [];
|
||||
$formatCode = '';
|
||||
|
|
@ -538,7 +555,7 @@ class Chart
|
|||
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer');
|
||||
if ($dataType == 's') {
|
||||
$seriesVal[$pointVal][] = (string) $seriesValue->v;
|
||||
} elseif ($seriesValue->v === ExcelError::NA()) {
|
||||
} elseif ((string) $seriesValue->v === ExcelError::NA()) {
|
||||
$seriesVal[$pointVal] = null;
|
||||
} else {
|
||||
$seriesVal[$pointVal][] = (float) $seriesValue->v;
|
||||
|
|
@ -556,7 +573,7 @@ class Chart
|
|||
];
|
||||
}
|
||||
|
||||
private static function parseRichText(SimpleXMLElement $titleDetailPart)
|
||||
private function parseRichText(SimpleXMLElement $titleDetailPart): RichText
|
||||
{
|
||||
$value = new RichText();
|
||||
$objText = null;
|
||||
|
|
@ -773,7 +790,10 @@ class Chart
|
|||
return $value;
|
||||
}
|
||||
|
||||
private static function readChartAttributes($chartDetail)
|
||||
/**
|
||||
* @param null|Layout|SimpleXMLElement $chartDetail
|
||||
*/
|
||||
private function readChartAttributes($chartDetail): array
|
||||
{
|
||||
$plotAttributes = [];
|
||||
if (isset($chartDetail->dLbls)) {
|
||||
|
|
@ -806,7 +826,7 @@ class Chart
|
|||
/**
|
||||
* @param mixed $plotAttributes
|
||||
*/
|
||||
private static function setChartAttributes(Layout $plotArea, $plotAttributes): void
|
||||
private function setChartAttributes(Layout $plotArea, $plotAttributes): void
|
||||
{
|
||||
foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) {
|
||||
switch ($plotAttributeKey) {
|
||||
|
|
|
|||
|
|
@ -963,7 +963,7 @@ class Chart extends WriterPart
|
|||
|
||||
if ($id1 !== '0') {
|
||||
$objWriter->startElement('c:crossAx');
|
||||
$objWriter->writeAttribute('val', $id2);
|
||||
$objWriter->writeAttribute('val', $id1);
|
||||
$objWriter->endElement();
|
||||
|
||||
if ($xAxis->getAxisOptionsProperty('horizontal_crosses_value') !== null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue