Some Fixes for Scatter Charts (#2828)
* Some Fixes for Scatter Charts Chart issues have been pouring in recently. This is a partial response to issue #2762. It implements "no joins" for scatter charts, as well as having the reader and writer handle "point size", "line width", and "color" for markers. A new boolean property `scatterLines`, with setter and getter, is added to DataSeriesValues to handle joins (default is true which means scatter plot points *are* joined by lines). Some, but not yet all, default font properties for the chart title are handled (color and, surprisingly, font name present challenges). With these changes, sample 32readwriteScatterChart1.xlsx now looks closer to its source. There are still some differences (x-axis changes), but I think this change is already large enough. I can work on the other problems later. The code for reading charts has not yet been converted to be namespace aware. Having a tiny island of aware code in a sea of unaware makes no sense to me, so some of the new code is likewise unaware. I hope to be able to get to it eventually, but, among other considerations, it is difficult to generate suitable test cases. * Add Formal Tests Essentially the same as the corresponding Samples, but with formal assertions. * Clean Up Some Code in Reader/Xlsx/Chart Having added code to support default font attributes as well as element-specific font attributes for chart captions, there was duplicated code between the default and specific sections. I hope that this PR makes the code easier to follow. * Add Support for Font Name and Color to XLSX Chart Titles XML layout for these in new files differs from what program was expecting. Not sure if program expectations were wrong, or if this is a change to Excel since initial development. * Minor Improvement Handle theoretical case where Chart title has text but no font information. * Support Bezier Curve and Scaling of X-Axis on Scatter Plot For Bezier, need to specify `<c:smooth>` tag in addition to already supplied `<c:scatterStyle val="smoothMarker">` For X-Axis, scatter needs to supply both X and y axis as `<c:valAx>` rather than `<c:catAx>` for X.
This commit is contained in:
parent
4df236a688
commit
9aa1708468
|
|
@ -1215,26 +1215,6 @@ parameters:
|
||||||
count: 2
|
count: 2
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeries.php
|
path: src/PhpSpreadsheet/Chart/DataSeries.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\:\\:refresh\\(\\) has parameter \\$flatten with no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeriesValues.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\:\\:\\$dataSource \\(string\\) does not accept string\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeriesValues.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\:\\:\\$dataTypeValues has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeriesValues.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\:\\:\\$fillColor \\(array\\<string\\>\\|string\\) does not accept array\\<string\\>\\|string\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeriesValues.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$angle of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setShadowAngle\\(\\) expects int, int\\|null given\\.$#"
|
message: "#^Parameter \\#1 \\$angle of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setShadowAngle\\(\\) expects int, int\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -2560,56 +2540,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method getFont\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\RichText\\\\Run\\|null\\.$#"
|
|
||||||
count: 12
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setBold\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setColor\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setItalic\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setName\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setSize\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setStrikethrough\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setSubscript\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setSuperscript\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method setUnderline\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
|
||||||
count: 3
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has no return type specified\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has no return type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -2635,11 +2565,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$marker with no 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\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -2715,21 +2640,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readColor\\(\\) has no return type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readColor\\(\\) has parameter \\$background with no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readColor\\(\\) has parameter \\$color 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\\.$#"
|
message: "#^Parameter \\#1 \\$position of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend constructor expects string, bool\\|float\\|int\\|string\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -4997,7 +4907,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method getBold\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
message: "#^Cannot call method getBold\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
@ -5007,12 +4917,12 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method getItalic\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
message: "#^Cannot call method getItalic\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method getName\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
message: "#^Cannot call method getName\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
@ -5022,7 +4932,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method getStrikethrough\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
message: "#^Cannot call method getStrikethrough\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
@ -5037,7 +4947,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method getUnderline\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
message: "#^Cannot call method getUnderline\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -12,7 +12,7 @@ class DataSeriesValues
|
||||||
const DATASERIES_TYPE_STRING = 'String';
|
const DATASERIES_TYPE_STRING = 'String';
|
||||||
const DATASERIES_TYPE_NUMBER = 'Number';
|
const DATASERIES_TYPE_NUMBER = 'Number';
|
||||||
|
|
||||||
private static $dataTypeValues = [
|
private const DATA_TYPE_VALUES = [
|
||||||
self::DATASERIES_TYPE_STRING,
|
self::DATASERIES_TYPE_STRING,
|
||||||
self::DATASERIES_TYPE_NUMBER,
|
self::DATASERIES_TYPE_NUMBER,
|
||||||
];
|
];
|
||||||
|
|
@ -27,7 +27,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Series Data Source.
|
* Series Data Source.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var ?string
|
||||||
*/
|
*/
|
||||||
private $dataSource;
|
private $dataSource;
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Fill color (can be array with colors if dataseries have custom colors).
|
* Fill color (can be array with colors if dataseries have custom colors).
|
||||||
*
|
*
|
||||||
* @var string|string[]
|
* @var null|string|string[]
|
||||||
*/
|
*/
|
||||||
private $fillColor;
|
private $fillColor;
|
||||||
|
|
||||||
|
|
@ -80,6 +80,9 @@ class DataSeriesValues
|
||||||
*/
|
*/
|
||||||
private $lineWidth = 12700;
|
private $lineWidth = 12700;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $scatterLines = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DataSeriesValues object.
|
* Create a new DataSeriesValues object.
|
||||||
*
|
*
|
||||||
|
|
@ -90,8 +93,9 @@ class DataSeriesValues
|
||||||
* @param mixed $dataValues
|
* @param mixed $dataValues
|
||||||
* @param null|mixed $marker
|
* @param null|mixed $marker
|
||||||
* @param null|string|string[] $fillColor
|
* @param null|string|string[] $fillColor
|
||||||
|
* @param string $pointSize
|
||||||
*/
|
*/
|
||||||
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null)
|
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null, $pointSize = '3')
|
||||||
{
|
{
|
||||||
$this->setDataType($dataType);
|
$this->setDataType($dataType);
|
||||||
$this->dataSource = $dataSource;
|
$this->dataSource = $dataSource;
|
||||||
|
|
@ -100,6 +104,9 @@ class DataSeriesValues
|
||||||
$this->dataValues = $dataValues;
|
$this->dataValues = $dataValues;
|
||||||
$this->pointMarker = $marker;
|
$this->pointMarker = $marker;
|
||||||
$this->fillColor = $fillColor;
|
$this->fillColor = $fillColor;
|
||||||
|
if (is_numeric($pointSize)) {
|
||||||
|
$this->pointSize = (int) $pointSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -126,7 +133,7 @@ class DataSeriesValues
|
||||||
*/
|
*/
|
||||||
public function setDataType($dataType)
|
public function setDataType($dataType)
|
||||||
{
|
{
|
||||||
if (!in_array($dataType, self::$dataTypeValues)) {
|
if (!in_array($dataType, self::DATA_TYPE_VALUES)) {
|
||||||
throw new Exception('Invalid datatype for chart data series values');
|
throw new Exception('Invalid datatype for chart data series values');
|
||||||
}
|
}
|
||||||
$this->dataType = $dataType;
|
$this->dataType = $dataType;
|
||||||
|
|
@ -137,7 +144,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Get Series Data Source (formula).
|
* Get Series Data Source (formula).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return ?string
|
||||||
*/
|
*/
|
||||||
public function getDataSource()
|
public function getDataSource()
|
||||||
{
|
{
|
||||||
|
|
@ -147,7 +154,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Set Series Data Source (formula).
|
* Set Series Data Source (formula).
|
||||||
*
|
*
|
||||||
* @param string $dataSource
|
* @param ?string $dataSource
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
|
|
@ -239,7 +246,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Get fill color.
|
* Get fill color.
|
||||||
*
|
*
|
||||||
* @return string|string[] HEX color or array with HEX colors
|
* @return null|string|string[] HEX color or array with HEX colors
|
||||||
*/
|
*/
|
||||||
public function getFillColor()
|
public function getFillColor()
|
||||||
{
|
{
|
||||||
|
|
@ -249,7 +256,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Set fill color for series.
|
* Set fill color for series.
|
||||||
*
|
*
|
||||||
* @param string|string[] $color HEX color or array with HEX colors
|
* @param null|string|string[] $color HEX color or array with HEX colors
|
||||||
*
|
*
|
||||||
* @return DataSeriesValues
|
* @return DataSeriesValues
|
||||||
*/
|
*/
|
||||||
|
|
@ -260,7 +267,7 @@ class DataSeriesValues
|
||||||
$this->validateColor($colorValue);
|
$this->validateColor($colorValue);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->validateColor($color);
|
$this->validateColor("$color");
|
||||||
}
|
}
|
||||||
$this->fillColor = $color;
|
$this->fillColor = $color;
|
||||||
|
|
||||||
|
|
@ -379,7 +386,7 @@ class DataSeriesValues
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function refresh(Worksheet $worksheet, $flatten = true): void
|
public function refresh(Worksheet $worksheet, bool $flatten = true): void
|
||||||
{
|
{
|
||||||
if ($this->dataSource !== null) {
|
if ($this->dataSource !== null) {
|
||||||
$calcEngine = Calculation::getInstance($worksheet->getParent());
|
$calcEngine = Calculation::getInstance($worksheet->getParent());
|
||||||
|
|
@ -421,4 +428,16 @@ class DataSeriesValues
|
||||||
$this->pointCount = count($this->dataValues);
|
$this->pointCount = count($this->dataValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getScatterLines(): bool
|
||||||
|
{
|
||||||
|
return $this->scatterLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setScatterLines(bool $scatterLines): self
|
||||||
|
{
|
||||||
|
$this->scatterLines = $scatterLines;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class Chart
|
||||||
private static function getAttribute(SimpleXMLElement $component, $name, $format)
|
private static function getAttribute(SimpleXMLElement $component, $name, $format)
|
||||||
{
|
{
|
||||||
$attributes = $component->attributes();
|
$attributes = $component->attributes();
|
||||||
if (isset($attributes[$name])) {
|
if (@isset($attributes[$name])) {
|
||||||
if ($format == 'string') {
|
if ($format == 'string') {
|
||||||
return (string) $attributes[$name];
|
return (string) $attributes[$name];
|
||||||
} elseif ($format == 'integer') {
|
} elseif ($format == 'integer') {
|
||||||
|
|
@ -42,15 +42,6 @@ class Chart
|
||||||
return null;
|
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 string $chartName
|
* @param string $chartName
|
||||||
*
|
*
|
||||||
|
|
@ -293,6 +284,10 @@ class Chart
|
||||||
case 'ser':
|
case 'ser':
|
||||||
$marker = null;
|
$marker = null;
|
||||||
$seriesIndex = '';
|
$seriesIndex = '';
|
||||||
|
$srgbClr = null;
|
||||||
|
$lineWidth = null;
|
||||||
|
$pointSize = null;
|
||||||
|
$noFill = false;
|
||||||
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
||||||
switch ($seriesKey) {
|
switch ($seriesKey) {
|
||||||
case 'idx':
|
case 'idx':
|
||||||
|
|
@ -307,9 +302,25 @@ class Chart
|
||||||
case 'tx':
|
case 'tx':
|
||||||
$seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
|
$seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'spPr':
|
||||||
|
$ln = $seriesDetail->children($namespacesChartMeta['a'])->ln;
|
||||||
|
$lineWidth = self::getAttribute($ln, 'w', 'string');
|
||||||
|
if (is_countable($ln->noFill) && count($ln->noFill) === 1) {
|
||||||
|
$noFill = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'marker':
|
case 'marker':
|
||||||
$marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');
|
$marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');
|
||||||
|
$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']);
|
||||||
|
if (count($ln->solidFill) === 1) {
|
||||||
|
$srgbClr = self::getattribute($ln->solidFill->srgbClr, 'val', 'string');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'smooth':
|
case 'smooth':
|
||||||
|
|
@ -321,30 +332,52 @@ class Chart
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'val':
|
case 'val':
|
||||||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
|
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'xVal':
|
case 'xVal':
|
||||||
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
|
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'yVal':
|
case 'yVal':
|
||||||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
|
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($noFill) {
|
||||||
|
if (isset($seriesLabel[$seriesIndex])) {
|
||||||
|
$seriesLabel[$seriesIndex]->setScatterLines(false);
|
||||||
|
}
|
||||||
|
if (isset($seriesCategory[$seriesIndex])) {
|
||||||
|
$seriesCategory[$seriesIndex]->setScatterLines(false);
|
||||||
|
}
|
||||||
|
if (isset($seriesValues[$seriesIndex])) {
|
||||||
|
$seriesValues[$seriesIndex]->setScatterLines(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_numeric($lineWidth)) {
|
||||||
|
if (isset($seriesLabel[$seriesIndex])) {
|
||||||
|
$seriesLabel[$seriesIndex]->setLineWidth((int) $lineWidth);
|
||||||
|
}
|
||||||
|
if (isset($seriesCategory[$seriesIndex])) {
|
||||||
|
$seriesCategory[$seriesIndex]->setLineWidth((int) $lineWidth);
|
||||||
|
}
|
||||||
|
if (isset($seriesValues[$seriesIndex])) {
|
||||||
|
$seriesValues[$seriesIndex]->setLineWidth((int) $lineWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
|
return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null)
|
private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null)
|
||||||
{
|
{
|
||||||
if (isset($seriesDetail->strRef)) {
|
if (isset($seriesDetail->strRef)) {
|
||||||
$seriesSource = (string) $seriesDetail->strRef->f;
|
$seriesSource = (string) $seriesDetail->strRef->f;
|
||||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker);
|
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||||
|
|
||||||
if (isset($seriesDetail->strRef->strCache)) {
|
if (isset($seriesDetail->strRef->strCache)) {
|
||||||
$seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');
|
$seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');
|
||||||
|
|
@ -356,7 +389,7 @@ class Chart
|
||||||
return $seriesValues;
|
return $seriesValues;
|
||||||
} elseif (isset($seriesDetail->numRef)) {
|
} elseif (isset($seriesDetail->numRef)) {
|
||||||
$seriesSource = (string) $seriesDetail->numRef->f;
|
$seriesSource = (string) $seriesDetail->numRef->f;
|
||||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, null, null, $marker);
|
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||||
if (isset($seriesDetail->numRef->numCache)) {
|
if (isset($seriesDetail->numRef->numCache)) {
|
||||||
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
|
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
|
||||||
$seriesValues
|
$seriesValues
|
||||||
|
|
@ -367,7 +400,7 @@ class Chart
|
||||||
return $seriesValues;
|
return $seriesValues;
|
||||||
} elseif (isset($seriesDetail->multiLvlStrRef)) {
|
} elseif (isset($seriesDetail->multiLvlStrRef)) {
|
||||||
$seriesSource = (string) $seriesDetail->multiLvlStrRef->f;
|
$seriesSource = (string) $seriesDetail->multiLvlStrRef->f;
|
||||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker);
|
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||||
|
|
||||||
if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) {
|
if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) {
|
||||||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's');
|
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's');
|
||||||
|
|
@ -379,7 +412,7 @@ class Chart
|
||||||
return $seriesValues;
|
return $seriesValues;
|
||||||
} elseif (isset($seriesDetail->multiLvlNumRef)) {
|
} elseif (isset($seriesDetail->multiLvlNumRef)) {
|
||||||
$seriesSource = (string) $seriesDetail->multiLvlNumRef->f;
|
$seriesSource = (string) $seriesDetail->multiLvlNumRef->f;
|
||||||
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker);
|
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize");
|
||||||
|
|
||||||
if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) {
|
if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) {
|
||||||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's');
|
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's');
|
||||||
|
|
@ -474,36 +507,113 @@ class Chart
|
||||||
{
|
{
|
||||||
$value = new RichText();
|
$value = new RichText();
|
||||||
$objText = null;
|
$objText = null;
|
||||||
|
$defaultFontSize = null;
|
||||||
|
$defaultBold = null;
|
||||||
|
$defaultItalic = null;
|
||||||
|
$defaultUnderscore = null;
|
||||||
|
$defaultStrikethrough = null;
|
||||||
|
$defaultBaseline = null;
|
||||||
|
$defaultFontName = null;
|
||||||
|
$defaultColor = 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->pPr->defRPr->latin)) {
|
||||||
|
/** @var ?string */
|
||||||
|
$defaultFontName = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string');
|
||||||
|
}
|
||||||
|
if (isset($titleDetailPart->pPr->defRPr->solidFill->srgbClr)) {
|
||||||
|
/** @var ?string */
|
||||||
|
$defaultColor = self::getAttribute($titleDetailPart->pPr->defRPr->solidFill->srgbClr, 'val', 'string');
|
||||||
|
}
|
||||||
|
}
|
||||||
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
|
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
|
||||||
if (isset($titleDetailElement->t)) {
|
if (isset($titleDetailElement->t)) {
|
||||||
$objText = $value->createTextRun((string) $titleDetailElement->t);
|
$objText = $value->createTextRun((string) $titleDetailElement->t);
|
||||||
}
|
}
|
||||||
|
if ($objText === null || $objText->getFont() === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$fontSize = null;
|
||||||
|
$bold = null;
|
||||||
|
$italic = null;
|
||||||
|
$underscore = null;
|
||||||
|
$strikethrough = null;
|
||||||
|
$baseline = null;
|
||||||
|
$fontName = null;
|
||||||
|
$fontColor = null;
|
||||||
if (isset($titleDetailElement->rPr)) {
|
if (isset($titleDetailElement->rPr)) {
|
||||||
|
// not used now, not sure it ever was, grandfathering
|
||||||
if (isset($titleDetailElement->rPr->rFont['val'])) {
|
if (isset($titleDetailElement->rPr->rFont['val'])) {
|
||||||
$objText->getFont()->setName((string) $titleDetailElement->rPr->rFont['val']);
|
$fontName = (string) $titleDetailElement->rPr->rFont['val'];
|
||||||
|
}
|
||||||
|
if (isset($titleDetailElement->rPr->latin)) {
|
||||||
|
/** @var ?string */
|
||||||
|
$fontName = self::getAttribute($titleDetailElement->rPr->latin, 'typeface', 'string');
|
||||||
|
}
|
||||||
|
/** @var ?int */
|
||||||
|
$fontSize = self::getAttribute($titleDetailElement->rPr, 'sz', 'integer');
|
||||||
|
|
||||||
|
// not used now, not sure it ever was, grandfathering
|
||||||
|
/** @var ?string */
|
||||||
|
$fontColor = self::getAttribute($titleDetailElement->rPr, 'color', 'string');
|
||||||
|
if (isset($titleDetailElement->rPr->solidFill->srgbClr)) {
|
||||||
|
/** @var ?string */
|
||||||
|
$fontColor = self::getAttribute($titleDetailElement->rPr->solidFill->srgbClr, 'val', 'string');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'));
|
/** @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');
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
|
$strikethrough = self::getAttribute($titleDetailElement->rPr, 's', 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fontName = $fontName ?? $defaultFontName;
|
||||||
|
if ($fontName !== null) {
|
||||||
|
$objText->getFont()->setName($fontName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fontSize = $fontSize ?? $defaultFontSize;
|
||||||
if (is_int($fontSize)) {
|
if (is_int($fontSize)) {
|
||||||
$objText->getFont()->setSize(floor($fontSize / 100));
|
$objText->getFont()->setSize(floor($fontSize / 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
$fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string'));
|
$fontColor = $fontColor ?? $defaultColor;
|
||||||
if ($fontColor !== null) {
|
if ($fontColor !== null) {
|
||||||
$objText->getFont()->setColor(new Color(self::readColor($fontColor)));
|
$objText->getFont()->setColor(new Color($fontColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
$bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean');
|
$bold = $bold ?? $defaultBold;
|
||||||
if ($bold !== null) {
|
if ($bold !== null) {
|
||||||
$objText->getFont()->setBold($bold);
|
$objText->getFont()->setBold($bold);
|
||||||
}
|
}
|
||||||
|
|
||||||
$italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean');
|
$italic = $italic ?? $defaultItalic;
|
||||||
if ($italic !== null) {
|
if ($italic !== null) {
|
||||||
$objText->getFont()->setItalic($italic);
|
$objText->getFont()->setItalic($italic);
|
||||||
}
|
}
|
||||||
|
|
||||||
$baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer');
|
$baseline = $baseline ?? $defaultBaseline;
|
||||||
if ($baseline !== null) {
|
if ($baseline !== null) {
|
||||||
if ($baseline > 0) {
|
if ($baseline > 0) {
|
||||||
$objText->getFont()->setSuperscript(true);
|
$objText->getFont()->setSuperscript(true);
|
||||||
|
|
@ -512,7 +622,7 @@ class Chart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$underscore = (self::getAttribute($titleDetailElement->rPr, 'u', 'string'));
|
$underscore = $underscore ?? $defaultUnderscore;
|
||||||
if ($underscore !== null) {
|
if ($underscore !== null) {
|
||||||
if ($underscore == 'sng') {
|
if ($underscore == 'sng') {
|
||||||
$objText->getFont()->setUnderline(Font::UNDERLINE_SINGLE);
|
$objText->getFont()->setUnderline(Font::UNDERLINE_SINGLE);
|
||||||
|
|
@ -523,7 +633,7 @@ class Chart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string'));
|
$strikethrough = $strikethrough ?? $defaultStrikethrough;
|
||||||
if ($strikethrough !== null) {
|
if ($strikethrough !== null) {
|
||||||
if ($strikethrough == 'noStrike') {
|
if ($strikethrough == 'noStrike') {
|
||||||
$objText->getFont()->setStrikethrough(false);
|
$objText->getFont()->setStrikethrough(false);
|
||||||
|
|
@ -532,7 +642,6 @@ class Chart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ class Chart extends WriterPart
|
||||||
if ($chartType === DataSeries::TYPE_BUBBLECHART) {
|
if ($chartType === DataSeries::TYPE_BUBBLECHART) {
|
||||||
$this->writeValueAxis($objWriter, $xAxisLabel, $chartType, $id1, $id2, $catIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines);
|
$this->writeValueAxis($objWriter, $xAxisLabel, $chartType, $id1, $id2, $catIsMultiLevelSeries, $xAxis, $majorGridlines, $minorGridlines);
|
||||||
} else {
|
} else {
|
||||||
$this->writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $catIsMultiLevelSeries, $xAxis);
|
$this->writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $catIsMultiLevelSeries, $xAxis, ($chartType === DataSeries::TYPE_SCATTERCHART) ? 'c:valAx' : 'c:catAx');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->writeValueAxis($objWriter, $yAxisLabel, $chartType, $id1, $id2, $valIsMultiLevelSeries, $yAxis, $majorGridlines, $minorGridlines);
|
$this->writeValueAxis($objWriter, $yAxisLabel, $chartType, $id1, $id2, $valIsMultiLevelSeries, $yAxis, $majorGridlines, $minorGridlines);
|
||||||
|
|
@ -367,9 +367,9 @@ class Chart extends WriterPart
|
||||||
* @param string $id2
|
* @param string $id2
|
||||||
* @param bool $isMultiLevelSeries
|
* @param bool $isMultiLevelSeries
|
||||||
*/
|
*/
|
||||||
private function writeCategoryAxis(XMLWriter $objWriter, ?Title $xAxisLabel, $id1, $id2, $isMultiLevelSeries, Axis $yAxis): void
|
private function writeCategoryAxis(XMLWriter $objWriter, ?Title $xAxisLabel, $id1, $id2, $isMultiLevelSeries, Axis $yAxis, string $element = 'c:catAx'): void
|
||||||
{
|
{
|
||||||
$objWriter->startElement('c:catAx');
|
$objWriter->startElement($element);
|
||||||
|
|
||||||
if ($id1 > 0) {
|
if ($id1 > 0) {
|
||||||
$objWriter->startElement('c:axId');
|
$objWriter->startElement('c:axId');
|
||||||
|
|
@ -1016,7 +1016,7 @@ class Chart extends WriterPart
|
||||||
* @param bool $valIsMultiLevelSeries Is value set a multi-series set
|
* @param bool $valIsMultiLevelSeries Is value set a multi-series set
|
||||||
* @param string $plotGroupingType Type of grouping for multi-series values
|
* @param string $plotGroupingType Type of grouping for multi-series values
|
||||||
*/
|
*/
|
||||||
private function writePlotGroup(?DataSeries $plotGroup, $groupType, XMLWriter $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries, &$plotGroupingType): void
|
private function writePlotGroup(?DataSeries $plotGroup, string $groupType, XMLWriter $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries, &$plotGroupingType): void
|
||||||
{
|
{
|
||||||
if ($plotGroup === null) {
|
if ($plotGroup === null) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1104,7 +1104,7 @@ class Chart extends WriterPart
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting for the points
|
// Formatting for the points
|
||||||
if (($groupType == DataSeries::TYPE_LINECHART) || ($groupType == DataSeries::TYPE_STOCKCHART)) {
|
if (($groupType == DataSeries::TYPE_LINECHART) || ($groupType == DataSeries::TYPE_STOCKCHART || ($groupType === DataSeries::TYPE_SCATTERCHART && $plotSeriesValues !== false && !$plotSeriesValues->getScatterLines()))) {
|
||||||
$plotLineWidth = 12700;
|
$plotLineWidth = 12700;
|
||||||
if ($plotSeriesValues) {
|
if ($plotSeriesValues) {
|
||||||
$plotLineWidth = $plotSeriesValues->getLineWidth();
|
$plotLineWidth = $plotSeriesValues->getLineWidth();
|
||||||
|
|
@ -1113,7 +1113,7 @@ class Chart extends WriterPart
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
$objWriter->startElement('a:ln');
|
$objWriter->startElement('a:ln');
|
||||||
$objWriter->writeAttribute('w', $plotLineWidth);
|
$objWriter->writeAttribute('w', $plotLineWidth);
|
||||||
if ($groupType == DataSeries::TYPE_STOCKCHART) {
|
if ($groupType == DataSeries::TYPE_STOCKCHART || $groupType === DataSeries::TYPE_SCATTERCHART) {
|
||||||
$objWriter->startElement('a:noFill');
|
$objWriter->startElement('a:noFill');
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
} elseif ($plotLabel) {
|
} elseif ($plotLabel) {
|
||||||
|
|
@ -1142,6 +1142,16 @@ class Chart extends WriterPart
|
||||||
$objWriter->startElement('c:size');
|
$objWriter->startElement('c:size');
|
||||||
$objWriter->writeAttribute('val', (string) $plotSeriesValues->getPointSize());
|
$objWriter->writeAttribute('val', (string) $plotSeriesValues->getPointSize());
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
$fillColor = $plotSeriesValues->getFillColor();
|
||||||
|
if (is_string($fillColor) && $fillColor !== '') {
|
||||||
|
$objWriter->startElement('c:spPr');
|
||||||
|
$objWriter->startElement('a:solidFill');
|
||||||
|
$objWriter->startElement('a:srgbClr');
|
||||||
|
$objWriter->writeAttribute('val', $fillColor);
|
||||||
|
$objWriter->endElement(); // srgbClr
|
||||||
|
$objWriter->endElement(); // solidFill
|
||||||
|
$objWriter->endElement(); // spPr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
@ -1192,6 +1202,11 @@ class Chart extends WriterPart
|
||||||
|
|
||||||
$this->writePlotSeriesValues($plotSeriesValues, $objWriter, $groupType, 'num');
|
$this->writePlotSeriesValues($plotSeriesValues, $objWriter, $groupType, 'num');
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
if ($groupType === DataSeries::TYPE_SCATTERCHART && $plotGroup->getPlotStyle() === 'smoothMarker') {
|
||||||
|
$objWriter->startElement('c:smooth');
|
||||||
|
$objWriter->writeAttribute('val', '1');
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($groupType === DataSeries::TYPE_BUBBLECHART) {
|
if ($groupType === DataSeries::TYPE_BUBBLECHART) {
|
||||||
|
|
|
||||||
|
|
@ -215,9 +215,13 @@ class StringTable extends WriterPart
|
||||||
foreach ($elements as $element) {
|
foreach ($elements as $element) {
|
||||||
// r
|
// r
|
||||||
$objWriter->startElement($prefix . 'r');
|
$objWriter->startElement($prefix . 'r');
|
||||||
|
if ($element->getFont() !== null) {
|
||||||
// rPr
|
// rPr
|
||||||
$objWriter->startElement($prefix . 'rPr');
|
$objWriter->startElement($prefix . 'rPr');
|
||||||
|
$size = $element->getFont()->getSize();
|
||||||
|
if (is_numeric($size)) {
|
||||||
|
$objWriter->writeAttribute('sz', (string) (int) ($size * 100));
|
||||||
|
}
|
||||||
|
|
||||||
// Bold
|
// Bold
|
||||||
$objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0));
|
$objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0));
|
||||||
|
|
@ -239,12 +243,20 @@ class StringTable extends WriterPart
|
||||||
// Strikethrough
|
// Strikethrough
|
||||||
$objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike'));
|
$objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike'));
|
||||||
|
|
||||||
// rFont
|
// Color
|
||||||
|
$objWriter->startElement($prefix . 'solidFill');
|
||||||
|
$objWriter->startElement($prefix . 'srgbClr');
|
||||||
|
$objWriter->writeAttribute('val', $element->getFont()->getColor()->getRGB());
|
||||||
|
$objWriter->endElement(); // srgbClr
|
||||||
|
$objWriter->endElement(); // solidFill
|
||||||
|
|
||||||
|
// fontName
|
||||||
$objWriter->startElement($prefix . 'latin');
|
$objWriter->startElement($prefix . 'latin');
|
||||||
$objWriter->writeAttribute('typeface', $element->getFont()->getName());
|
$objWriter->writeAttribute('typeface', $element->getFont()->getName());
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
// t
|
// t
|
||||||
$objWriter->startElement($prefix . 't');
|
$objWriter->startElement($prefix . 't');
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,13 @@ abstract class AbstractFunctional extends TestCase
|
||||||
*
|
*
|
||||||
* @return Spreadsheet
|
* @return Spreadsheet
|
||||||
*/
|
*/
|
||||||
protected function writeAndReload(Spreadsheet $spreadsheet, $format, ?callable $readerCustomizer = null)
|
protected function writeAndReload(Spreadsheet $spreadsheet, $format, ?callable $readerCustomizer = null, ?callable $writerCustomizer = null)
|
||||||
{
|
{
|
||||||
$filename = File::temporaryFilename();
|
$filename = File::temporaryFilename();
|
||||||
$writer = IOFactory::createWriter($spreadsheet, $format);
|
$writer = IOFactory::createWriter($spreadsheet, $format);
|
||||||
|
if ($writerCustomizer) {
|
||||||
|
$writerCustomizer($writer);
|
||||||
|
}
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
|
|
||||||
$reader = IOFactory::createReader($format);
|
$reader = IOFactory::createReader($format);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,261 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
|
use PhpOffice\PhpSpreadsheet\RichText\Run;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||||
|
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||||
|
|
||||||
|
class Charts32ScatterTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
private const DIRECTORY = 'samples' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
public function readCharts(XlsxReader $reader): void
|
||||||
|
{
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeCharts(XlsxWriter $writer): void
|
||||||
|
{
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testScatter1(): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . '32readwriteScatterChart1.xlsx';
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame(1, $sheet->getChartCount());
|
||||||
|
/** @var callable */
|
||||||
|
$callableReader = [$this, 'readCharts'];
|
||||||
|
/** @var callable */
|
||||||
|
$callableWriter = [$this, 'writeCharts'];
|
||||||
|
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Charts', $sheet->getTitle());
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
$title = $chart->getTitle();
|
||||||
|
$captionArray = $title->getCaption();
|
||||||
|
self::assertIsArray($captionArray);
|
||||||
|
self::assertCount(1, $captionArray);
|
||||||
|
$caption = $captionArray[0];
|
||||||
|
self::assertInstanceOf(RichText::class, $caption);
|
||||||
|
self::assertSame('Scatter - No Join and Markers', $caption->getPlainText());
|
||||||
|
$elements = $caption->getRichTextElements();
|
||||||
|
self::assertCount(1, $elements);
|
||||||
|
$run = $elements[0];
|
||||||
|
self::assertInstanceOf(Run::class, $run);
|
||||||
|
$font = $run->getFont();
|
||||||
|
self::assertInstanceOf(Font::class, $font);
|
||||||
|
self::assertSame('Calibri', $font->getName());
|
||||||
|
self::assertEquals(12, $font->getSize());
|
||||||
|
self::assertTrue($font->getBold());
|
||||||
|
self::assertFalse($font->getItalic());
|
||||||
|
self::assertFalse($font->getSuperscript());
|
||||||
|
self::assertFalse($font->getSubscript());
|
||||||
|
self::assertFalse($font->getStrikethrough());
|
||||||
|
self::assertSame('none', $font->getUnderline());
|
||||||
|
self::assertSame('000000', $font->getColor()->getRGB());
|
||||||
|
|
||||||
|
$plotArea = $chart->getPlotArea();
|
||||||
|
$plotSeries = $plotArea->getPlotGroup();
|
||||||
|
self::assertCount(1, $plotSeries);
|
||||||
|
$dataSeries = $plotSeries[0];
|
||||||
|
$plotValues = $dataSeries->getPlotValues();
|
||||||
|
self::assertCount(3, $plotValues);
|
||||||
|
$values = $plotValues[0];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[1];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[2];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(7, $values->getPointSize());
|
||||||
|
self::assertSame('FFFF00', $values->getFillColor());
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testScatter6(): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . '32readwriteScatterChart6.xlsx';
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame(1, $sheet->getChartCount());
|
||||||
|
/** @var callable */
|
||||||
|
$callableReader = [$this, 'readCharts'];
|
||||||
|
/** @var callable */
|
||||||
|
$callableWriter = [$this, 'writeCharts'];
|
||||||
|
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Charts', $sheet->getTitle());
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
$title = $chart->getTitle();
|
||||||
|
$captionArray = $title->getCaption();
|
||||||
|
self::assertIsArray($captionArray);
|
||||||
|
self::assertCount(1, $captionArray);
|
||||||
|
$caption = $captionArray[0];
|
||||||
|
self::assertInstanceOf(RichText::class, $caption);
|
||||||
|
self::assertSame('Scatter - Rich Text Title No Join and Markers', $caption->getPlainText());
|
||||||
|
$elements = $caption->getRichTextElements();
|
||||||
|
self::assertCount(3, $elements);
|
||||||
|
|
||||||
|
$run = $elements[0];
|
||||||
|
self::assertInstanceOf(Run::class, $run);
|
||||||
|
$font = $run->getFont();
|
||||||
|
self::assertInstanceOf(Font::class, $font);
|
||||||
|
self::assertSame('Calibri', $font->getName());
|
||||||
|
self::assertEquals(12, $font->getSize());
|
||||||
|
self::assertTrue($font->getBold());
|
||||||
|
self::assertFalse($font->getItalic());
|
||||||
|
self::assertFalse($font->getSuperscript());
|
||||||
|
self::assertFalse($font->getSubscript());
|
||||||
|
self::assertFalse($font->getStrikethrough());
|
||||||
|
self::assertSame('none', $font->getUnderline());
|
||||||
|
self::assertSame('000000', $font->getColor()->getRGB());
|
||||||
|
|
||||||
|
$run = $elements[1];
|
||||||
|
self::assertInstanceOf(Run::class, $run);
|
||||||
|
$font = $run->getFont();
|
||||||
|
self::assertInstanceOf(Font::class, $font);
|
||||||
|
self::assertSame('Courier New', $font->getName());
|
||||||
|
self::assertEquals(10, $font->getSize());
|
||||||
|
self::assertFalse($font->getBold());
|
||||||
|
self::assertFalse($font->getItalic());
|
||||||
|
self::assertFalse($font->getSuperscript());
|
||||||
|
self::assertFalse($font->getSubscript());
|
||||||
|
self::assertFalse($font->getStrikethrough());
|
||||||
|
self::assertSame('single', $font->getUnderline());
|
||||||
|
self::assertSame('00B0F0', $font->getColor()->getRGB());
|
||||||
|
|
||||||
|
$run = $elements[2];
|
||||||
|
self::assertInstanceOf(Run::class, $run);
|
||||||
|
$font = $run->getFont();
|
||||||
|
self::assertInstanceOf(Font::class, $font);
|
||||||
|
self::assertSame('Calibri', $font->getName());
|
||||||
|
self::assertEquals(12, $font->getSize());
|
||||||
|
self::assertTrue($font->getBold());
|
||||||
|
self::assertFalse($font->getItalic());
|
||||||
|
self::assertFalse($font->getSuperscript());
|
||||||
|
self::assertFalse($font->getSubscript());
|
||||||
|
self::assertFalse($font->getStrikethrough());
|
||||||
|
self::assertSame('none', $font->getUnderline());
|
||||||
|
self::assertSame('000000', $font->getColor()->getRGB());
|
||||||
|
|
||||||
|
$plotArea = $chart->getPlotArea();
|
||||||
|
$plotSeries = $plotArea->getPlotGroup();
|
||||||
|
self::assertCount(1, $plotSeries);
|
||||||
|
$dataSeries = $plotSeries[0];
|
||||||
|
$plotValues = $dataSeries->getPlotValues();
|
||||||
|
self::assertCount(3, $plotValues);
|
||||||
|
$values = $plotValues[0];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[1];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[2];
|
||||||
|
self::assertFalse($values->getScatterLines());
|
||||||
|
self::assertSame(28575, $values->getLineWidth());
|
||||||
|
self::assertSame(7, $values->getPointSize());
|
||||||
|
self::assertSame('FFFF00', $values->getFillColor());
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testScatter3(): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . '32readwriteScatterChart3.xlsx';
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame(1, $sheet->getChartCount());
|
||||||
|
/** @var callable */
|
||||||
|
$callableReader = [$this, 'readCharts'];
|
||||||
|
/** @var callable */
|
||||||
|
$callableWriter = [$this, 'writeCharts'];
|
||||||
|
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Charts', $sheet->getTitle());
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
$title = $chart->getTitle();
|
||||||
|
$captionArray = $title->getCaption();
|
||||||
|
self::assertIsArray($captionArray);
|
||||||
|
self::assertCount(1, $captionArray);
|
||||||
|
$caption = $captionArray[0];
|
||||||
|
self::assertInstanceOf(RichText::class, $caption);
|
||||||
|
self::assertSame('Scatter - Join Straight Lines and Markers', $caption->getPlainText());
|
||||||
|
$elements = $caption->getRichTextElements();
|
||||||
|
self::assertCount(1, $elements);
|
||||||
|
$run = $elements[0];
|
||||||
|
self::assertInstanceOf(Run::class, $run);
|
||||||
|
$font = $run->getFont();
|
||||||
|
self::assertInstanceOf(Font::class, $font);
|
||||||
|
self::assertSame('Calibri', $font->getName());
|
||||||
|
self::assertEquals(12, $font->getSize());
|
||||||
|
self::assertTrue($font->getBold());
|
||||||
|
self::assertFalse($font->getItalic());
|
||||||
|
self::assertFalse($font->getSuperscript());
|
||||||
|
self::assertFalse($font->getSubscript());
|
||||||
|
self::assertFalse($font->getStrikethrough());
|
||||||
|
self::assertSame('none', $font->getUnderline());
|
||||||
|
self::assertSame('000000', $font->getColor()->getRGB());
|
||||||
|
|
||||||
|
$plotArea = $chart->getPlotArea();
|
||||||
|
$plotSeries = $plotArea->getPlotGroup();
|
||||||
|
self::assertCount(1, $plotSeries);
|
||||||
|
$dataSeries = $plotSeries[0];
|
||||||
|
$plotValues = $dataSeries->getPlotValues();
|
||||||
|
self::assertCount(3, $plotValues);
|
||||||
|
$values = $plotValues[0];
|
||||||
|
self::assertTrue($values->getScatterLines());
|
||||||
|
self::assertSame(12700, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[1];
|
||||||
|
self::assertTrue($values->getScatterLines());
|
||||||
|
self::assertSame(12700, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
$values = $plotValues[2];
|
||||||
|
self::assertTrue($values->getScatterLines());
|
||||||
|
self::assertSame(12700, $values->getLineWidth());
|
||||||
|
self::assertSame(3, $values->getPointSize());
|
||||||
|
self::assertSame('', $values->getFillColor());
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class Charts32XmlTest extends TestCase
|
||||||
|
{
|
||||||
|
// These tests can only be performed by examining xml.
|
||||||
|
private const DIRECTORY = 'samples' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $outputFileName = '';
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
if ($this->outputFileName !== '') {
|
||||||
|
unlink($this->outputFileName);
|
||||||
|
$this->outputFileName = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerScatterCharts
|
||||||
|
*/
|
||||||
|
public function testBezierCount(int $expectedCount, string $inputFile): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . $inputFile;
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
|
||||||
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
$this->outputFileName = File::temporaryFilename();
|
||||||
|
$writer->save($this->outputFileName);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= $this->outputFileName;
|
||||||
|
$file .= '#xl/charts/chart2.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected tags
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertSame(1, substr_count($data, '<c:scatterStyle val='));
|
||||||
|
self::assertSame($expectedCount ? 1 : 0, substr_count($data, '<c:scatterStyle val="smoothMarker"/>'));
|
||||||
|
self::assertSame($expectedCount, substr_count($data, '<c:smooth val="1"/>'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerScatterCharts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'no line' => [0, '32readwriteScatterChart1.xlsx'],
|
||||||
|
'smooth line (Bezier)' => [3, '32readwriteScatterChart2.xlsx'],
|
||||||
|
'straight line' => [0, '32readwriteScatterChart3.xlsx'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAreaPercentageNoCat(): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . '32readwriteAreaPercentageChart1.xlsx';
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
|
||||||
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
$this->outputFileName = File::temporaryFilename();
|
||||||
|
$writer->save($this->outputFileName);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= $this->outputFileName;
|
||||||
|
$file .= '#xl/charts/chart1.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected tags
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertSame(0, substr_count($data, '<c:cat>'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue