Additional Support for Chart DataSeriesValues (#2906)

* Additional Support for Chart DataSeriesValues

Fix #2863. DataSeriesValues now extends Properties, allowing it to share code in common with Axis and Gridlines. This causes some minor breakages; in particular line width is now initialized to null instead of Excel's default value, and is specified in points, as the user would expect from Excel, rather than the value stored in Xml.

This change:
- adds support for 1 or 2 marker colors.
- adds support for `smoothLine` to DataSeriesValues.
- will determine `catAx` or `valAx` for Axis based on what is read from the Xml when available, rather than guessing based on format. (Another minor break.)
- reads `formatCode` and `sourceLinked` for Axis.
- correct 2 uses of `$plotSeriesRef` to `$plotSeriesIndex` in Writer/Xlsx/Chart.
- pushes coverage over 90% for Chart (88.70% overall).

* Update Change Log

I had updated previously but forgot to stage the member.

* Adopt Some Suggestions

Incorporate some changes suggested by @bridgeplayr.

* Use ChartColor for DSV Fill And Font Text

DataSeriesValues Fill could be a scalar or an array, so I saved it till last.

* Some Final Cleanup

No code changes.

Illustrate even more of the new features in existing sample files.

Deprecate *_ARGB in Properties/ChartColors in favor of *_RGB, because it uses only 6 hex digits. The alpha value is stored separately.
This commit is contained in:
oleibman 2022-06-29 17:52:09 -07:00 committed by GitHub
parent b5b83abc0e
commit 5d5e550342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1279 additions and 385 deletions

View File

@ -49,7 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772) - 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) - 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) - 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) [Issue #2219](https://github.com/PHPOffice/PhpSpreadsheet/issues/2219) [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) [PR #2856](https://github.com/PHPOffice/PhpSpreadsheet/pull/2856) [PR #2865](https://github.com/PHPOffice/PhpSpreadsheet/pull/2865) [PR #2872](https://github.com/PHPOffice/PhpSpreadsheet/pull/2872) [PR #2879](https://github.com/PHPOffice/PhpSpreadsheet/pull/2879) - 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) [Issue #2219](https://github.com/PHPOffice/PhpSpreadsheet/issues/2219) [Issue #2863](https://github.com/PHPOffice/PhpSpreadsheet/issues/2863) [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) [PR #2856](https://github.com/PHPOffice/PhpSpreadsheet/pull/2856) [PR #2865](https://github.com/PHPOffice/PhpSpreadsheet/pull/2865) [PR #2872](https://github.com/PHPOffice/PhpSpreadsheet/pull/2872) [PR #2879](https://github.com/PHPOffice/PhpSpreadsheet/pull/2879) [PR #2898](https://github.com/PHPOffice/PhpSpreadsheet/pull/2898) [PR #2906](https://github.com/PHPOffice/PhpSpreadsheet/pull/2906)
- Calculating Engine regexp for Column/Row references when there are multiple quoted worksheet references in the formula [Issue #2874](https://github.com/PHPOffice/PhpSpreadsheet/issues/2874) [PR #2899](https://github.com/PHPOffice/PhpSpreadsheet/pull/2899) - Calculating Engine regexp for Column/Row references when there are multiple quoted worksheet references in the formula [Issue #2874](https://github.com/PHPOffice/PhpSpreadsheet/issues/2874) [PR #2899](https://github.com/PHPOffice/PhpSpreadsheet/pull/2899)
## 1.23.0 - 2022-04-24 ## 1.23.0 - 2022-04-24

View File

@ -4055,16 +4055,6 @@ parameters:
count: 1 count: 1
path: src/PhpSpreadsheet/Writer/Xlsx.php path: src/PhpSpreadsheet/Writer/Xlsx.php
-
message: "#^Cannot call method getDataValues\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
-
message: "#^Cannot call method getFillColor\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
- -
message: "#^Parameter \\#1 \\$plotSeriesValues of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeBubbles\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|null, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false given\\.$#" message: "#^Parameter \\#1 \\$plotSeriesValues of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeBubbles\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|null, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false given\\.$#"
count: 1 count: 1
@ -4087,7 +4077,7 @@ parameters:
- -
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#" message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
count: 42 count: 41
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
- -

View File

@ -0,0 +1,183 @@
<?php
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../Header.php';
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Custom colors for dataSeries (gray, blue, red, orange)
$colors = [
'cccccc', '00abb8', 'b8292f', 'eb8500',
];
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels1 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues1 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
// Custom colors
$dataSeriesValues1 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4, [], null, $colors),
];
// Build the dataseries
$series1 = new DataSeries(
DataSeries::TYPE_BARCHART, // plotType
null, // plotGrouping (Pie charts don't have any grouping)
range(0, count($dataSeriesValues1) - 1), // plotOrder
$dataSeriesLabels1, // plotLabel
$xAxisTickValues1, // plotCategory
$dataSeriesValues1 // plotValues
);
// Set up a layout object for the Pie chart
$layout1 = new Layout();
$layout1->setShowVal(true);
$layout1->setShowPercent(true);
// Set the series in the plot area
$plotArea1 = new PlotArea($layout1, [$series1]);
// Set the chart legend
$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
$title1 = new Title('Test Bar Chart');
// Create the chart
$chart1 = new Chart(
'chart1', // name
$title1, // title
$legend1, // legend
$plotArea1, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
null // yAxisLabel - Pie charts don't have a Y-Axis
);
// Set the position where the chart should appear in the worksheet
$chart1->setTopLeftPosition('A7');
$chart1->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart1);
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels2 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues2 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
// Custom colors
$dataSeriesValues2 = [
$dataSeriesValues2Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
];
$dataSeriesValues2Element->setFillColor($colors);
// Build the dataseries
$series2 = new DataSeries(
DataSeries::TYPE_DONUTCHART, // plotType
null, // plotGrouping (Donut charts don't have any grouping)
range(0, count($dataSeriesValues2) - 1), // plotOrder
$dataSeriesLabels2, // plotLabel
$xAxisTickValues2, // plotCategory
$dataSeriesValues2 // plotValues
);
// Set up a layout object for the Pie chart
$layout2 = new Layout();
$layout2->setShowVal(true);
$layout2->setShowCatName(true);
// Set the series in the plot area
$plotArea2 = new PlotArea($layout2, [$series2]);
$title2 = new Title('Test Donut Chart');
// Create the chart
$chart2 = new Chart(
'chart2', // name
$title2, // title
null, // legend
$plotArea2, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
null // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis
);
// Set the position where the chart should appear in the worksheet
$chart2->setTopLeftPosition('I7');
$chart2->setBottomRightPosition('P20');
// Add the chart to the worksheet
$worksheet->addChart($chart2);
// Save Excel 2007 file
$filename = $helper->getFilename(__FILE__);
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->setIncludeCharts(true);
$callStartTime = microtime(true);
$writer->save($filename);
$helper->logWrite($writer, $filename, $callStartTime);

View File

@ -5,6 +5,7 @@ use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title; use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
@ -35,6 +36,7 @@ $dataSeriesLabels = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
]; ];
$dataSeriesLabels[0]->setFillColor('FF0000');
// Set the X-Axis Labels // Set the X-Axis Labels
// Datatype // Datatype
// Cell reference for data // Cell reference for data
@ -57,7 +59,7 @@ $dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4), new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
]; ];
$dataSeriesValues[2]->setLineWidth(60000); $dataSeriesValues[2]->setLineWidth(60000 / Properties::POINTS_WIDTH_MULTIPLIER);
// Build the dataseries // Build the dataseries
$series = new DataSeries( $series = new DataSeries(

View File

@ -2,6 +2,7 @@
use PhpOffice\PhpSpreadsheet\Chart\Axis; use PhpOffice\PhpSpreadsheet\Chart\Axis;
use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
@ -64,11 +65,76 @@ $dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4), new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4), new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4),
]; ];
// series 1
// marker details
$dataSeriesValues[0]
->setPointMarker('diamond')
->setPointSize(5)
->getMarkerFillColor()
->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
$dataSeriesValues[0]
->getMarkerBorderColor()
->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
// line details - smooth line, connected
$dataSeriesValues[0]
->setScatterLines(true)
->setSmoothLine(true)
->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type
$dataSeriesValues[0]->setLineStyleProperties(
2.5, // width in points
Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound
Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash
Properties::LINE_STYLE_CAP_SQUARE, // cap
Properties::LINE_STYLE_JOIN_MITER, // join
Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type
Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index
Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type
Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index
);
// series 2 - straight line - no special effects, connected, straight line
$dataSeriesValues[1] // square fill
->setPointMarker('square')
->setPointSize(6)
->getMarkerBorderColor()
->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME);
$dataSeriesValues[1] // square border
->getMarkerFillColor()
->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
$dataSeriesValues[1]
->setScatterLines(true)
->setSmoothLine(false)
->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB);
$dataSeriesValues[1]->setLineWidth(2.0);
// series 3 - markers, no line
$dataSeriesValues[2] // triangle fill
//->setPointMarker('triangle') // let Excel choose shape
->setPointSize(7)
->getMarkerFillColor()
->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
$dataSeriesValues[2] // triangle border
->getMarkerBorderColor()
->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME);
$dataSeriesValues[2]->setScatterLines(false); // points not connected
// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers // Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers
$xAxis = new Axis(); $xAxis = new Axis();
//$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE ); //$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE );
$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); $xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true);
$yAxis = new Axis();
$yAxis->setLineStyleProperties(
2.5, // width in points
Properties::LINE_STYLE_COMPOUND_SIMPLE,
Properties::LINE_STYLE_DASH_DASH_DOT,
Properties::LINE_STYLE_CAP_FLAT,
Properties::LINE_STYLE_JOIN_BEVEL
);
$yAxis->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
// Build the dataseries // Build the dataseries
$series = new DataSeries( $series = new DataSeries(
DataSeries::TYPE_SCATTERCHART, // plotType DataSeries::TYPE_SCATTERCHART, // plotType
@ -79,8 +145,7 @@ $series = new DataSeries(
$dataSeriesValues, // plotValues $dataSeriesValues, // plotValues
null, // plotDirection null, // plotDirection
false, // smooth line false, // smooth line
//DataSeries::STYLE_LINEMARKER // plotStyle DataSeries::STYLE_SMOOTHMARKER // plotStyle
DataSeries::STYLE_MARKER // plotStyle
); );
// Set the series in the plot area // Set the series in the plot area
@ -103,6 +168,7 @@ $chart = new Chart(
$yAxisLabel, // yAxisLabel $yAxisLabel, // yAxisLabel
// added xAxis for correct date display // added xAxis for correct date display
$xAxis, // xAxis $xAxis, // xAxis
$yAxis, // yAxis
); );
// Set the position where the chart should appear in the worksheet // Set the position where the chart should appear in the worksheet

Binary file not shown.

View File

@ -27,6 +27,9 @@ class Axis extends Properties
'numeric' => null, 'numeric' => null,
]; ];
/** @var string */
private $axisType = '';
/** /**
* Axis Options. * Axis Options.
* *
@ -62,11 +65,11 @@ class Axis extends Properties
* *
* @param mixed $format_code * @param mixed $format_code
*/ */
public function setAxisNumberProperties($format_code, ?bool $numeric = null): void public function setAxisNumberProperties($format_code, ?bool $numeric = null, int $sourceLinked = 0): void
{ {
$format = (string) $format_code; $format = (string) $format_code;
$this->axisNumber['format'] = $format; $this->axisNumber['format'] = $format;
$this->axisNumber['source_linked'] = 0; $this->axisNumber['source_linked'] = $sourceLinked;
if (is_bool($numeric)) { if (is_bool($numeric)) {
$this->axisNumber['numeric'] = $numeric; $this->axisNumber['numeric'] = $numeric;
} elseif (in_array($format, self::NUMERIC_FORMAT, true)) { } elseif (in_array($format, self::NUMERIC_FORMAT, true)) {
@ -156,6 +159,22 @@ class Axis extends Properties
$this->axisOptions['orientation'] = (string) $orientation; $this->axisOptions['orientation'] = (string) $orientation;
} }
public function getAxisType(): string
{
return $this->axisType;
}
public function setAxisType(string $type): self
{
if ($type === 'catAx' || $type === 'valAx') {
$this->axisType = $type;
} else {
$this->axisType = '';
}
return $this;
}
/** /**
* Set Fill Property. * Set Fill Property.
* *

View File

@ -6,6 +6,8 @@ class ChartColor
{ {
const EXCEL_COLOR_TYPE_STANDARD = 'prstClr'; const EXCEL_COLOR_TYPE_STANDARD = 'prstClr';
const EXCEL_COLOR_TYPE_SCHEME = 'schemeClr'; const EXCEL_COLOR_TYPE_SCHEME = 'schemeClr';
const EXCEL_COLOR_TYPE_RGB = 'srgbClr';
/** @deprecated 1.24 use EXCEL_COLOR_TYPE_RGB instead */
const EXCEL_COLOR_TYPE_ARGB = 'srgbClr'; const EXCEL_COLOR_TYPE_ARGB = 'srgbClr';
const EXCEL_COLOR_TYPES = [ const EXCEL_COLOR_TYPES = [
self::EXCEL_COLOR_TYPE_ARGB, self::EXCEL_COLOR_TYPE_ARGB,
@ -22,6 +24,18 @@ class ChartColor
/** @var ?int */ /** @var ?int */
private $alpha; private $alpha;
/**
* @param string|string[] $value
*/
public function __construct($value = '', ?int $alpha = null, ?string $type = null)
{
if (is_array($value)) {
$this->setColorPropertiesArray($value);
} else {
$this->setColorProperties($value, $alpha, $type);
}
}
public function getValue(): string public function getValue(): string
{ {
return $this->value; return $this->value;
@ -61,10 +75,21 @@ class ChartColor
/** /**
* @param null|float|int|string $alpha * @param null|float|int|string $alpha
*/ */
public function setColorProperties(?string $color, $alpha, ?string $type): self public function setColorProperties(?string $color, $alpha = null, ?string $type = null): self
{ {
if (empty($type) && !empty($color)) {
if (substr($color, 0, 1) === '*') {
$type = 'schemeClr';
$color = substr($color, 1);
} elseif (substr($color, 0, 1) === '/') {
$type = 'prstClr';
$color = substr($color, 1);
} elseif (preg_match('/^[0-9A-Fa-f]{6}$/', $color) === 1) {
$type = 'srgbClr';
}
}
if ($color !== null) { if ($color !== null) {
$this->setValue($color); $this->setValue("$color");
} }
if ($type !== null) { if ($type !== null) {
$this->setType($type); $this->setType($type);
@ -80,21 +105,16 @@ class ChartColor
public function setColorPropertiesArray(array $color): self public function setColorPropertiesArray(array $color): self
{ {
if (array_key_exists('value', $color) && is_string($color['value'])) { return $this->setColorProperties(
$this->setValue($color['value']); $color['value'] ?? '',
} $color['alpha'] ?? null,
if (array_key_exists('type', $color) && is_string($color['type'])) { $color['type'] ?? null
$this->setType($color['type']); );
} }
if (array_key_exists('alpha', $color)) {
if ($color['alpha'] === null) {
$this->setAlpha(null);
} elseif (is_numeric($color['alpha'])) {
$this->setAlpha((int) $color['alpha']);
}
}
return $this; public function isUsable(): bool
{
return $this->type !== '' && $this->value !== '';
} }
/** /**

View File

@ -257,8 +257,6 @@ class DataSeries
$keys = array_keys($this->plotLabel); $keys = array_keys($this->plotLabel);
if (in_array($index, $keys)) { if (in_array($index, $keys)) {
return $this->plotLabel[$index]; return $this->plotLabel[$index];
} elseif (isset($keys[$index])) {
return $this->plotLabel[$keys[$index]];
} }
return false; return false;
@ -339,8 +337,6 @@ class DataSeries
$keys = array_keys($this->plotValues); $keys = array_keys($this->plotValues);
if (in_array($index, $keys)) { if (in_array($index, $keys)) {
return $this->plotValues[$index]; return $this->plotValues[$index];
} elseif (isset($keys[$index])) {
return $this->plotValues[$keys[$index]];
} }
return false; return false;

View File

@ -7,7 +7,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class DataSeriesValues class DataSeriesValues extends Properties
{ {
const DATASERIES_TYPE_STRING = 'String'; const DATASERIES_TYPE_STRING = 'String';
const DATASERIES_TYPE_NUMBER = 'Number'; const DATASERIES_TYPE_NUMBER = 'Number';
@ -45,6 +45,12 @@ class DataSeriesValues
*/ */
private $pointMarker; private $pointMarker;
/** @var ChartColor */
private $markerFillColor;
/** @var ChartColor */
private $markerBorderColor;
/** /**
* Series Point Size. * Series Point Size.
* *
@ -69,23 +75,10 @@ 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 null|string|string[] * @var null|ChartColor|ChartColor[]
*/ */
private $fillColor; private $fillColor;
/** @var string */
private $schemeClr = '';
/** @var string */
private $prstClr = '';
/**
* Line Width.
*
* @var int
*/
private $lineWidth = 12700;
/** @var bool */ /** @var bool */
private $scatterLines = true; private $scatterLines = true;
@ -101,18 +94,23 @@ class DataSeriesValues
* @param int $pointCount * @param int $pointCount
* @param mixed $dataValues * @param mixed $dataValues
* @param null|mixed $marker * @param null|mixed $marker
* @param null|string|string[] $fillColor * @param null|ChartColor|ChartColor[]|string|string[] $fillColor
* @param string $pointSize * @param string $pointSize
*/ */
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null, $pointSize = '3') public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null, $pointSize = '3')
{ {
parent::__construct();
$this->markerFillColor = new ChartColor();
$this->markerBorderColor = new ChartColor();
$this->setDataType($dataType); $this->setDataType($dataType);
$this->dataSource = $dataSource; $this->dataSource = $dataSource;
$this->formatCode = $formatCode; $this->formatCode = $formatCode;
$this->pointCount = $pointCount; $this->pointCount = $pointCount;
$this->dataValues = $dataValues; $this->dataValues = $dataValues;
$this->pointMarker = $marker; $this->pointMarker = $marker;
$this->fillColor = $fillColor; if ($fillColor !== null) {
$this->setFillColor($fillColor);
}
if (is_numeric($pointSize)) { if (is_numeric($pointSize)) {
$this->pointSize = (int) $pointSize; $this->pointSize = (int) $pointSize;
} }
@ -198,6 +196,16 @@ class DataSeriesValues
return $this; return $this;
} }
public function getMarkerFillColor(): ChartColor
{
return $this->markerFillColor;
}
public function getMarkerBorderColor(): ChartColor
{
return $this->markerBorderColor;
}
/** /**
* Get Point Size. * Get Point Size.
*/ */
@ -252,37 +260,96 @@ class DataSeriesValues
return $this->pointCount; return $this->pointCount;
} }
/**
* Get fill color object.
*
* @return null|ChartColor|ChartColor[]
*/
public function getFillColorObject()
{
return $this->fillColor;
}
private function stringToChartColor(string $fillString): ChartColor
{
$value = $type = '';
if (substr($fillString, 0, 1) === '*') {
$type = 'schemeClr';
$value = substr($fillString, 1);
} elseif (substr($fillString, 0, 1) === '/') {
$type = 'prstClr';
$value = substr($fillString, 1);
} elseif ($fillString !== '') {
$type = 'srgbClr';
$value = $fillString;
$this->validateColor($value);
}
return new ChartColor($value, null, $type);
}
private function chartColorToString(ChartColor $chartColor): string
{
$type = (string) $chartColor->getColorProperty('type');
$value = (string) $chartColor->getColorProperty('value');
if ($type === '' || $value === '') {
return '';
}
if ($type === 'schemeClr') {
return "*$value";
}
if ($type === 'prstClr') {
return "/$value";
}
return $value;
}
/** /**
* Get fill color. * Get fill color.
* *
* @return null|string|string[] HEX color or array with HEX colors * @return string|string[] HEX color or array with HEX colors
*/ */
public function getFillColor() public function getFillColor()
{ {
return $this->fillColor; if ($this->fillColor === null) {
return '';
}
if (is_array($this->fillColor)) {
$array = [];
foreach ($this->fillColor as $chartColor) {
$array[] = self::chartColorToString($chartColor);
}
return $array;
}
return self::chartColorToString($this->fillColor);
} }
/** /**
* Set fill color for series. * Set fill color for series.
* *
* @param string|string[] $color HEX color or array with HEX colors * @param ChartColor|ChartColor[]|string|string[] $color HEX color or array with HEX colors
* *
* @return DataSeriesValues * @return DataSeriesValues
*/ */
public function setFillColor($color) public function setFillColor($color)
{ {
if (is_array($color)) { if (is_array($color)) {
foreach ($color as $colorValue) { $this->fillColor = [];
if (substr($colorValue, 0, 1) !== '*' && substr($colorValue, 0, 1) !== '/') { foreach ($color as $fillString) {
$this->validateColor($colorValue); if ($fillString instanceof ChartColor) {
$this->fillColor[] = $fillString;
} else {
$this->fillColor[] = self::stringToChartColor($fillString);
} }
} }
} else { } elseif ($color instanceof ChartColor) {
if (substr($color, 0, 1) !== '*' && substr($color, 0, 1) !== '/') { $this->fillColor = $color;
$this->validateColor("$color"); } elseif (is_string($color)) {
} $this->fillColor = self::stringToChartColor($color);
} }
$this->fillColor = $color;
return $this; return $this;
} }
@ -306,24 +373,23 @@ class DataSeriesValues
/** /**
* Get line width for series. * Get line width for series.
* *
* @return int * @return null|float|int
*/ */
public function getLineWidth() public function getLineWidth()
{ {
return $this->lineWidth; return $this->lineStyleProperties['width'];
} }
/** /**
* Set line width for the series. * Set line width for the series.
* *
* @param int $width * @param null|float|int $width
* *
* @return $this * @return $this
*/ */
public function setLineWidth($width) public function setLineWidth($width)
{ {
$minWidth = 12700; $this->lineStyleProperties['width'] = $width;
$this->lineWidth = max($minWidth, $width);
return $this; return $this;
} }
@ -466,26 +532,33 @@ class DataSeriesValues
return $this; return $this;
} }
public function getSchemeClr(): string /**
* Smooth Line.
*
* @var bool
*/
private $smoothLine;
/**
* Get Smooth Line.
*
* @return bool
*/
public function getSmoothLine()
{ {
return $this->schemeClr; return $this->smoothLine;
} }
public function setSchemeClr(string $schemeClr): self /**
* Set Smooth Line.
*
* @param bool $smoothLine
*
* @return $this
*/
public function setSmoothLine($smoothLine)
{ {
$this->schemeClr = $schemeClr; $this->smoothLine = $smoothLine;
return $this;
}
public function getPrstClr(): string
{
return $this->prstClr;
}
public function setPrstClr(string $prstClr): self
{
$this->prstClr = $prstClr;
return $this; return $this;
} }

View File

@ -59,6 +59,8 @@ abstract class Properties
const LINE_STYLE_COMPOUND_TRIPLE = 'tri'; const LINE_STYLE_COMPOUND_TRIPLE = 'tri';
const LINE_STYLE_DASH_SOLID = 'solid'; const LINE_STYLE_DASH_SOLID = 'solid';
const LINE_STYLE_DASH_ROUND_DOT = 'sysDot'; const LINE_STYLE_DASH_ROUND_DOT = 'sysDot';
const LINE_STYLE_DASH_SQUARE_DOT = 'sysDash';
/** @deprecated 1.24 use LINE_STYLE_DASH_SQUARE_DOT instead */
const LINE_STYLE_DASH_SQUERE_DOT = 'sysDash'; const LINE_STYLE_DASH_SQUERE_DOT = 'sysDash';
const LINE_STYPE_DASH_DASH = 'dash'; const LINE_STYPE_DASH_DASH = 'dash';
const LINE_STYLE_DASH_DASH_DOT = 'dashDot'; const LINE_STYLE_DASH_DASH_DOT = 'dashDot';
@ -68,7 +70,7 @@ abstract class Properties
const LINE_STYLE_CAP_SQUARE = 'sq'; const LINE_STYLE_CAP_SQUARE = 'sq';
const LINE_STYLE_CAP_ROUND = 'rnd'; const LINE_STYLE_CAP_ROUND = 'rnd';
const LINE_STYLE_CAP_FLAT = 'flat'; const LINE_STYLE_CAP_FLAT = 'flat';
const LINE_STYLE_JOIN_ROUND = 'bevel'; const LINE_STYLE_JOIN_ROUND = 'round';
const LINE_STYLE_JOIN_MITER = 'miter'; const LINE_STYLE_JOIN_MITER = 'miter';
const LINE_STYLE_JOIN_BEVEL = 'bevel'; const LINE_STYLE_JOIN_BEVEL = 'bevel';
const LINE_STYLE_ARROW_TYPE_NOARROW = null; const LINE_STYLE_ARROW_TYPE_NOARROW = null;
@ -643,30 +645,6 @@ abstract class Properties
return $this; return $this;
} }
/**
* Set Shadow Color.
*
* @param string $color
* @param int $alpha
* @param string $colorType
*
* @return $this
*/
protected function setShadowColor($color, $alpha, $colorType)
{
if ($color !== null) {
$this->shadowProperties['color']['value'] = (string) $color;
}
if ($alpha !== null) {
$this->shadowProperties['color']['alpha'] = (int) $alpha;
}
if ($colorType !== null) {
$this->shadowProperties['color']['type'] = (string) $colorType;
}
return $this;
}
/** /**
* Set Shadow Blur. * Set Shadow Blur.
* *
@ -766,6 +744,12 @@ abstract class Properties
], ],
]; ];
public function copyLineStyles(self $otherProperties): void
{
$this->lineStyleProperties = $otherProperties->lineStyleProperties;
$this->lineColor = $otherProperties->lineColor;
}
public function getLineColor(): ChartColor public function getLineColor(): ChartColor
{ {
return $this->lineColor; return $this->lineColor;

View File

@ -14,7 +14,6 @@ use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties; use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title; use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Font; use PhpOffice\PhpSpreadsheet\Style\Font;
use SimpleXMLElement; use SimpleXMLElement;
@ -90,6 +89,7 @@ class Chart
case 'plotArea': case 'plotArea':
$plotAreaLayout = $XaxisLabel = $YaxisLabel = null; $plotAreaLayout = $XaxisLabel = $YaxisLabel = null;
$plotSeries = $plotAttributes = []; $plotSeries = $plotAttributes = [];
$catAxRead = false;
foreach ($chartDetails as $chartDetailKey => $chartDetail) { foreach ($chartDetails as $chartDetailKey => $chartDetail) {
switch ($chartDetailKey) { switch ($chartDetailKey) {
case 'layout': case 'layout':
@ -97,9 +97,11 @@ class Chart
break; break;
case 'catAx': case 'catAx':
$catAxRead = true;
if (isset($chartDetail->title)) { if (isset($chartDetail->title)) {
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
} }
$xAxis->setAxisType('catAx');
$this->readEffects($chartDetail, $xAxis); $this->readEffects($chartDetail, $xAxis);
if (isset($chartDetail->spPr)) { if (isset($chartDetail->spPr)) {
$sppr = $chartDetail->spPr->children($this->aNamespace); $sppr = $chartDetail->spPr->children($this->aNamespace);
@ -122,16 +124,22 @@ class Chart
$axPos = null; $axPos = null;
if (isset($chartDetail->axPos)) { if (isset($chartDetail->axPos)) {
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string'); $axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
}
if ($catAxRead) {
$whichAxis = $yAxis;
$yAxis->setAxisType($chartDetailKey);
} elseif (!empty($axPos)) {
switch ($axPos) { switch ($axPos) {
case 't': case 't':
case 'b': case 'b':
$whichAxis = $xAxis; $whichAxis = $xAxis;
$xAxis->setAxisType($chartDetailKey);
break; break;
case 'r': case 'r':
case 'l': case 'l':
$whichAxis = $yAxis; $whichAxis = $yAxis;
$yAxis->setAxisType($chartDetailKey);
break; break;
} }
@ -373,14 +381,14 @@ class Chart
case 'ser': case 'ser':
$marker = null; $marker = null;
$seriesIndex = ''; $seriesIndex = '';
$srgbClr = null; $fillColor = null;
$lineWidth = null;
$pointSize = null; $pointSize = null;
$noFill = false; $noFill = false;
$schemeClr = '';
$prstClr = '';
$bubble3D = false; $bubble3D = false;
$dPtColors = []; $dPtColors = [];
$markerFillColor = null;
$markerBorderColor = null;
$lineStyle = null;
foreach ($seriesDetails as $seriesKey => $seriesDetail) { foreach ($seriesDetails as $seriesKey => $seriesDetail) {
switch ($seriesKey) { switch ($seriesKey) {
case 'idx': case 'idx':
@ -399,12 +407,16 @@ class Chart
case 'spPr': case 'spPr':
$children = $seriesDetail->children($this->aNamespace); $children = $seriesDetail->children($this->aNamespace);
$ln = $children->ln; $ln = $children->ln;
$lineWidth = self::getAttribute($ln, 'w', 'string'); if (isset($children->ln)) {
if (is_countable($ln->noFill) && count($ln->noFill) === 1) { $ln = $children->ln;
$noFill = true; if (is_countable($ln->noFill) && count($ln->noFill) === 1) {
$noFill = true;
}
$lineStyle = new GridLines();
$this->readLineStyle($seriesDetails, $lineStyle);
} }
if (isset($children->solidFill)) { if (isset($children->solidFill)) {
$this->readColor($children->solidFill, $srgbClr, $schemeClr, $prstClr); $fillColor = new ChartColor($this->readColor($children->solidFill));
} }
break; break;
@ -414,13 +426,7 @@ class Chart
$children = $seriesDetail->spPr->children($this->aNamespace); $children = $seriesDetail->spPr->children($this->aNamespace);
if (isset($children->solidFill)) { if (isset($children->solidFill)) {
$arrayColors = $this->readColor($children->solidFill); $arrayColors = $this->readColor($children->solidFill);
if ($arrayColors['type'] === 'srgbClr') { $dptColors[$dptIdx] = new ChartColor($arrayColors);
$dptColors[$dptIdx] = $arrayColors['value'];
} elseif ($arrayColors['type'] === 'prstClr') {
$dptColors[$dptIdx] = '/' . $arrayColors['value'];
} else {
$dptColors[$dptIdx] = '*' . $arrayColors['value'];
}
} }
} }
@ -429,10 +435,13 @@ class Chart
$marker = self::getAttribute($seriesDetail->symbol, 'val', 'string'); $marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');
$pointSize = self::getAttribute($seriesDetail->size, 'val', 'string'); $pointSize = self::getAttribute($seriesDetail->size, 'val', 'string');
$pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null; $pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null;
if (count($seriesDetail->spPr) === 1) { if (isset($seriesDetail->spPr)) {
$ln = $seriesDetail->spPr->children($this->aNamespace); $children = $seriesDetail->spPr->children($this->aNamespace);
if (isset($ln->solidFill)) { if (isset($children->solidFill)) {
$this->readColor($ln->solidFill, $srgbClr, $schemeClr, $prstClr); $markerFillColor = $this->readColor($children->solidFill);
}
if (isset($children->ln->solidFill)) {
$markerBorderColor = $this->readColor($children->ln->solidFill);
} }
} }
@ -446,19 +455,19 @@ class Chart
break; break;
case 'val': case 'val':
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; break;
case 'xVal': case 'xVal':
$seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; break;
case 'yVal': case 'yVal':
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; break;
case 'bubbleSize': case 'bubbleSize':
$seriesBubbles[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); $seriesBubbles[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; break;
case 'bubble3D': case 'bubble3D':
@ -478,36 +487,15 @@ class Chart
$seriesValues[$seriesIndex]->setScatterLines(false); $seriesValues[$seriesIndex]->setScatterLines(false);
} }
} }
if (is_numeric($lineWidth)) { if ($lineStyle !== null) {
if (isset($seriesLabel[$seriesIndex])) { if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->setLineWidth((int) $lineWidth); $seriesLabel[$seriesIndex]->copyLineStyles($lineStyle);
} }
if (isset($seriesCategory[$seriesIndex])) { if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->setLineWidth((int) $lineWidth); $seriesCategory[$seriesIndex]->copyLineStyles($lineStyle);
} }
if (isset($seriesValues[$seriesIndex])) { if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->setLineWidth((int) $lineWidth); $seriesValues[$seriesIndex]->copyLineStyles($lineStyle);
}
}
if ($schemeClr) {
if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->setSchemeClr($schemeClr);
}
if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->setSchemeClr($schemeClr);
}
if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->setSchemeClr($schemeClr);
}
} elseif ($prstClr) {
if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->setPrstClr($prstClr);
}
if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->setPrstClr($prstClr);
}
if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->setPrstClr($prstClr);
} }
} }
if ($bubble3D) { if ($bubble3D) {
@ -532,6 +520,39 @@ class Chart
$seriesValues[$seriesIndex]->setFillColor($dptColors); $seriesValues[$seriesIndex]->setFillColor($dptColors);
} }
} }
if ($markerFillColor !== null) {
if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor);
}
if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor);
}
if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor);
}
}
if ($markerBorderColor !== null) {
if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor);
}
if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor);
}
if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor);
}
}
if ($smoothLine) {
if (isset($seriesLabel[$seriesIndex])) {
$seriesLabel[$seriesIndex]->setSmoothLine(true);
}
if (isset($seriesCategory[$seriesIndex])) {
$seriesCategory[$seriesIndex]->setSmoothLine(true);
}
if (isset($seriesValues[$seriesIndex])) {
$seriesValues[$seriesIndex]->setSmoothLine(true);
}
}
} }
} }
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
@ -544,11 +565,11 @@ class Chart
/** /**
* @return mixed * @return mixed
*/ */
private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null) private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?ChartColor $fillColor = 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, 0, null, $marker, $srgbClr, "$pointSize"); $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");
if (isset($seriesDetail->strRef->strCache)) { if (isset($seriesDetail->strRef->strCache)) {
$seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's'); $seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's');
@ -560,7 +581,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, 0, null, $marker, $srgbClr, "$pointSize"); $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");
if (isset($seriesDetail->numRef->numCache)) { if (isset($seriesDetail->numRef->numCache)) {
$seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace)); $seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace));
$seriesValues $seriesValues
@ -571,7 +592,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, 0, null, $marker, $srgbClr, "$pointSize"); $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");
if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) { if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) {
$seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's'); $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's');
@ -583,7 +604,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, 0, null, $marker, $srgbClr, "$pointSize"); $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");
if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) { if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) {
$seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's'); $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's');
@ -698,8 +719,7 @@ class Chart
$defaultLatin = null; $defaultLatin = null;
$defaultEastAsian = null; $defaultEastAsian = null;
$defaultComplexScript = null; $defaultComplexScript = null;
$defaultSrgbColor = ''; $defaultFontColor = null;
$defaultSchemeColor = '';
if (isset($titleDetailPart->pPr->defRPr)) { if (isset($titleDetailPart->pPr->defRPr)) {
/** @var ?int */ /** @var ?int */
$defaultFontSize = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer'); $defaultFontSize = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer');
@ -729,7 +749,7 @@ class Chart
$defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); $defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string');
} }
if (isset($titleDetailPart->pPr->defRPr->solidFill)) { if (isset($titleDetailPart->pPr->defRPr->solidFill)) {
$this->readColor($titleDetailPart->pPr->defRPr->solidFill, $defaultSrgbColor, $defaultSchemeClr); $defaultFontColor = $this->readColor($titleDetailPart->pPr->defRPr->solidFill);
} }
} }
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) { foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
@ -755,8 +775,7 @@ class Chart
$latinName = null; $latinName = null;
$eastAsian = null; $eastAsian = null;
$complexScript = null; $complexScript = null;
$fontSrgbClr = ''; $fontColor = null;
$fontSchemeClr = '';
$underlineColor = null; $underlineColor = null;
if (isset($titleDetailElement->rPr)) { if (isset($titleDetailElement->rPr)) {
// not used now, not sure it ever was, grandfathering // not used now, not sure it ever was, grandfathering
@ -781,10 +800,8 @@ class Chart
$fontSize = self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'); $fontSize = self::getAttribute($titleDetailElement->rPr, 'sz', 'integer');
// not used now, not sure it ever was, grandfathering // not used now, not sure it ever was, grandfathering
/** @var ?string */
$fontSrgbClr = self::getAttribute($titleDetailElement->rPr, 'color', 'string');
if (isset($titleDetailElement->rPr->solidFill)) { if (isset($titleDetailElement->rPr->solidFill)) {
$this->readColor($titleDetailElement->rPr->solidFill, $fontSrgbClr, $fontSchemeClr); $fontColor = $this->readColor($titleDetailElement->rPr->solidFill);
} }
/** @var ?bool */ /** @var ?bool */
@ -834,19 +851,15 @@ class Chart
if (is_int($fontSize)) { if (is_int($fontSize)) {
$objText->getFont()->setSize(floor($fontSize / 100)); $objText->getFont()->setSize(floor($fontSize / 100));
$fontFound = true; $fontFound = true;
} else {
$objText->getFont()->setSize(null, true);
} }
$fontSrgbClr = $fontSrgbClr ?? $defaultSrgbColor; $fontColor = $fontColor ?? $defaultFontColor;
if (!empty($fontSrgbClr)) { if (!empty($fontColor)) {
$objText->getFont()->setColor(new Color($fontSrgbClr)); $objText->getFont()->setChartColor($fontColor);
$fontFound = true; $fontFound = true;
} }
// need to think about what to do here
//$fontSchemeClr = $fontSchemeClr ?? $defaultSchemeColor;
//if (!empty($fontSchemeClr)) {
// $objText->getFont()->setColor(new Color($fontSrgbClr));
// $fontFound = true;
//}
$bold = $bold ?? $defaultBold; $bold = $bold ?? $defaultBold;
if ($bold !== null) { if ($bold !== null) {
@ -1059,7 +1072,7 @@ class Chart
'innerShdw', 'innerShdw',
]; ];
private function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr = null, ?string &$schemeClr = null, ?string &$prstClr = null): array private function readColor(SimpleXMLElement $colorXml): array
{ {
$result = [ $result = [
'type' => null, 'type' => null,
@ -1070,13 +1083,6 @@ class Chart
if (isset($colorXml->$type)) { if (isset($colorXml->$type)) {
$result['type'] = $type; $result['type'] = $type;
$result['value'] = self::getAttribute($colorXml->$type, 'val', 'string'); $result['value'] = self::getAttribute($colorXml->$type, 'val', 'string');
if ($type === Properties::EXCEL_COLOR_TYPE_ARGB) {
$srgbClr = $result['value'];
} elseif ($type === Properties::EXCEL_COLOR_TYPE_SCHEME) {
$schemeClr = $result['value'];
} elseif ($type === Properties::EXCEL_COLOR_TYPE_STANDARD) {
$prstClr = $result['value'];
}
if (isset($colorXml->$type->alpha)) { if (isset($colorXml->$type->alpha)) {
/** @var string */ /** @var string */
$alpha = self::getAttribute($colorXml->$type->alpha, 'val', 'string'); $alpha = self::getAttribute($colorXml->$type->alpha, 'val', 'string');
@ -1092,10 +1098,7 @@ class Chart
return $result; return $result;
} }
/** private function readLineStyle(SimpleXMLElement $chartDetail, ?Properties $chartObject): void
* @param null|GridLines $chartObject may be extended to include other types
*/
private function readLineStyle(SimpleXMLElement $chartDetail, $chartObject): void
{ {
if (!isset($chartObject, $chartDetail->spPr)) { if (!isset($chartObject, $chartDetail->spPr)) {
return; return;
@ -1164,6 +1167,13 @@ class Chart
if (!isset($whichAxis)) { if (!isset($whichAxis)) {
return; return;
} }
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)) { if (isset($chartDetail->crossBetween)) {
$whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string')); $whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string'));
} }

View File

@ -21,7 +21,7 @@ class Font extends Supervisor
protected $name = 'Calibri'; protected $name = 'Calibri';
/** /**
* The following 6 are used only for chart titles, I think. * The following 7 are used only for chart titles, I think.
* *
*@var string *@var string
*/ */
@ -41,6 +41,9 @@ class Font extends Supervisor
/** @var ?ChartColor */ /** @var ?ChartColor */
private $underlineColor; private $underlineColor;
/** @var ?ChartColor */
private $chartColor;
// end of chart title items // end of chart title items
/** /**
@ -371,7 +374,7 @@ class Font extends Supervisor
* *
* @return $this * @return $this
*/ */
public function setSize($sizeInPoints) public function setSize($sizeInPoints, bool $nullOk = false)
{ {
if (is_string($sizeInPoints) || is_int($sizeInPoints)) { if (is_string($sizeInPoints) || is_int($sizeInPoints)) {
$sizeInPoints = (float) $sizeInPoints; // $pValue = 0 if given string is not numeric $sizeInPoints = (float) $sizeInPoints; // $pValue = 0 if given string is not numeric
@ -380,7 +383,9 @@ class Font extends Supervisor
// Size must be a positive floating point number // Size must be a positive floating point number
// ECMA-376-1:2016, part 1, chapter 18.4.11 sz (Font Size), p. 1536 // ECMA-376-1:2016, part 1, chapter 18.4.11 sz (Font Size), p. 1536
if (!is_float($sizeInPoints) || !($sizeInPoints > 0)) { if (!is_float($sizeInPoints) || !($sizeInPoints > 0)) {
$sizeInPoints = 10.0; if (!$nullOk || $sizeInPoints !== null) {
$sizeInPoints = 10.0;
}
} }
if ($this->isSupervisor) { if ($this->isSupervisor) {
@ -593,8 +598,7 @@ class Font extends Supervisor
public function setUnderlineColor(array $colorArray): self public function setUnderlineColor(array $colorArray): self
{ {
if (!$this->isSupervisor) { if (!$this->isSupervisor) {
$this->underlineColor = new ChartColor(); $this->underlineColor = new ChartColor($colorArray);
$this->underlineColor->setColorPropertiesArray($colorArray);
} else { } else {
// should never be true // should never be true
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
@ -606,6 +610,30 @@ class Font extends Supervisor
return $this; return $this;
} }
public function getChartColor(): ?ChartColor
{
if ($this->isSupervisor) {
return $this->getSharedComponent()->getChartColor();
}
return $this->chartColor;
}
public function setChartColor(array $colorArray): self
{
if (!$this->isSupervisor) {
$this->chartColor = new ChartColor($colorArray);
} else {
// should never be true
// @codeCoverageIgnoreStart
$styleArray = $this->getStyleArray(['chartColor' => $colorArray]);
$this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
// @codeCoverageIgnoreEnd
}
return $this;
}
/** /**
* Get Underline. * Get Underline.
* *
@ -713,6 +741,18 @@ class Font extends Supervisor
return $this; return $this;
} }
private function hashChartColor(?ChartColor $underlineColor): string
{
if ($this->underlineColor === null) {
return '';
}
return
$this->underlineColor->getValue()
. $this->underlineColor->getType()
. (string) $this->underlineColor->getAlpha();
}
/** /**
* Get hash code. * Get hash code.
* *
@ -723,14 +763,6 @@ class Font extends Supervisor
if ($this->isSupervisor) { if ($this->isSupervisor) {
return $this->getSharedComponent()->getHashCode(); return $this->getSharedComponent()->getHashCode();
} }
if ($this->underlineColor === null) {
$underlineColor = '';
} else {
$underlineColor =
$this->underlineColor->getValue()
. $this->underlineColor->getType()
. (string) $this->underlineColor->getAlpha();
}
return md5( return md5(
$this->name . $this->name .
@ -749,7 +781,8 @@ class Font extends Supervisor
$this->eastAsian, $this->eastAsian,
$this->complexScript, $this->complexScript,
$this->strikeType, $this->strikeType,
$underlineColor, $this->hashChartColor($this->chartColor),
$this->hashChartColor($this->underlineColor),
(string) $this->baseLine, (string) $this->baseLine,
] ]
) . ) .
@ -762,6 +795,7 @@ class Font extends Supervisor
$exportedArray = []; $exportedArray = [];
$this->exportArray2($exportedArray, 'baseLine', $this->getBaseLine()); $this->exportArray2($exportedArray, 'baseLine', $this->getBaseLine());
$this->exportArray2($exportedArray, 'bold', $this->getBold()); $this->exportArray2($exportedArray, 'bold', $this->getBold());
$this->exportArray2($exportedArray, 'chartColor', $this->getChartColor());
$this->exportArray2($exportedArray, 'color', $this->getColor()); $this->exportArray2($exportedArray, 'color', $this->getColor());
$this->exportArray2($exportedArray, 'complexScript', $this->getComplexScript()); $this->exportArray2($exportedArray, 'complexScript', $this->getComplexScript());
$this->exportArray2($exportedArray, 'eastAsian', $this->getEastAsian()); $this->exportArray2($exportedArray, 'eastAsian', $this->getEastAsian());

View File

@ -419,7 +419,9 @@ class Chart extends WriterPart
{ {
// N.B. writeCategoryAxis may be invoked with the last parameter($yAxis) using $xAxis for ScatterChart, etc // N.B. writeCategoryAxis may be invoked with the last parameter($yAxis) using $xAxis for ScatterChart, etc
// In that case, xAxis is NOT a category. // In that case, xAxis is NOT a category.
if ($yAxis->getAxisIsNumericFormat()) { if ($yAxis->getAxisType() !== '') {
$objWriter->startElement('c:' . $yAxis->getAxisType());
} elseif ($yAxis->getAxisIsNumericFormat()) {
$objWriter->startElement('c:valAx'); $objWriter->startElement('c:valAx');
} else { } else {
$objWriter->startElement('c:catAx'); $objWriter->startElement('c:catAx');
@ -469,10 +471,6 @@ class Chart extends WriterPart
$objWriter->endElement(); $objWriter->endElement();
$objWriter->startElement('a:p'); $objWriter->startElement('a:p');
$objWriter->startElement('a:pPr');
$objWriter->startElement('a:defRPr');
$objWriter->endElement();
$objWriter->endElement();
$caption = $xAxisLabel->getCaption(); $caption = $xAxisLabel->getCaption();
if (is_array($caption)) { if (is_array($caption)) {
@ -622,7 +620,7 @@ class Chart extends WriterPart
$objWriter->startElement('c:majorGridlines'); $objWriter->startElement('c:majorGridlines');
$objWriter->startElement('c:spPr'); $objWriter->startElement('c:spPr');
$this->writeGridlinesLn($objWriter, $majorGridlines); $this->writeLineStyles($objWriter, $majorGridlines);
$objWriter->startElement('a:effectLst'); $objWriter->startElement('a:effectLst');
$this->writeGlow($objWriter, $majorGridlines); $this->writeGlow($objWriter, $majorGridlines);
@ -637,7 +635,7 @@ class Chart extends WriterPart
$objWriter->startElement('c:minorGridlines'); $objWriter->startElement('c:minorGridlines');
$objWriter->startElement('c:spPr'); $objWriter->startElement('c:spPr');
$this->writeGridlinesLn($objWriter, $minorGridlines); $this->writeLineStyles($objWriter, $minorGridlines);
$objWriter->startElement('a:effectLst'); $objWriter->startElement('a:effectLst');
$this->writeGlow($objWriter, $minorGridlines); $this->writeGlow($objWriter, $minorGridlines);
@ -661,10 +659,6 @@ class Chart extends WriterPart
$objWriter->endElement(); $objWriter->endElement();
$objWriter->startElement('a:p'); $objWriter->startElement('a:p');
$objWriter->startElement('a:pPr');
$objWriter->startElement('a:defRPr');
$objWriter->endElement();
$objWriter->endElement();
$caption = $yAxisLabel->getCaption(); $caption = $yAxisLabel->getCaption();
if (is_array($caption)) { if (is_array($caption)) {
@ -715,7 +709,7 @@ class Chart extends WriterPart
$this->writeColor($objWriter, $xAxis->getFillColorObject()); $this->writeColor($objWriter, $xAxis->getFillColorObject());
$this->writeGridlinesLn($objWriter, $xAxis); $this->writeLineStyles($objWriter, $xAxis);
$objWriter->startElement('a:effectLst'); $objWriter->startElement('a:effectLst');
$this->writeGlow($objWriter, $xAxis); $this->writeGlow($objWriter, $xAxis);
@ -849,40 +843,27 @@ class Chart extends WriterPart
/** /**
* Method writing plot series values. * Method writing plot series values.
*
* @param int $val value for idx (default: 3)
* @param string $fillColor hex color (default: FF9900)
*/ */
private function writePlotSeriesValuesElement(XMLWriter $objWriter, $val = 3, $fillColor = 'FF9900'): void private function writePlotSeriesValuesElement(XMLWriter $objWriter, int $val, ?ChartColor $fillColor): void
{ {
if ($fillColor === '') { if ($fillColor === null || !$fillColor->isUsable()) {
return; return;
} }
$objWriter->startElement('c:dPt'); $objWriter->startElement('c:dPt');
$objWriter->startElement('c:idx'); $objWriter->startElement('c:idx');
$objWriter->writeAttribute('val', $val); $objWriter->writeAttribute('val', $val);
$objWriter->endElement(); $objWriter->endElement(); // c:idx
$objWriter->startElement('c:bubble3D'); $objWriter->startElement('c:bubble3D');
$objWriter->writeAttribute('val', 0); $objWriter->writeAttribute('val', 0);
$objWriter->endElement(); $objWriter->endElement(); // c:bubble3D
$objWriter->startElement('c:spPr'); $objWriter->startElement('c:spPr');
$objWriter->startElement('a:solidFill'); $this->writeColor($objWriter, $fillColor);
if (substr($fillColor, 0, 1) === '*') { $objWriter->endElement(); // c:spPr
$objWriter->startElement('a:schemeClr');
$objWriter->writeAttribute('val', substr($fillColor, 1)); $objWriter->endElement(); // c:dPt
} elseif (substr($fillColor, 0, 1) === '/') {
$objWriter->startElement('a:prstClr');
$objWriter->writeAttribute('val', substr($fillColor, 1));
} else {
$objWriter->startElement('a:srgbClr');
$objWriter->writeAttribute('val', $fillColor);
}
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
} }
/** /**
@ -934,20 +915,6 @@ class Chart extends WriterPart
foreach ($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) { foreach ($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) {
$objWriter->startElement('c:ser'); $objWriter->startElement('c:ser');
$plotLabel = $plotGroup->getPlotLabelByIndex($plotSeriesIdx);
if ($plotLabel && $groupType !== DataSeries::TYPE_LINECHART) {
$fillColor = $plotLabel->getFillColor();
if ($fillColor !== null && !is_array($fillColor)) {
$objWriter->startElement('c:spPr');
$objWriter->startElement('a:solidFill');
$objWriter->startElement('a:srgbClr');
$objWriter->writeAttribute('val', $fillColor);
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}
}
$objWriter->startElement('c:idx'); $objWriter->startElement('c:idx');
$objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesIdx); $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesIdx);
$objWriter->endElement(); $objWriter->endElement();
@ -956,22 +923,35 @@ class Chart extends WriterPart
$objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesRef); $objWriter->writeAttribute('val', $this->seriesIndex + $plotSeriesRef);
$objWriter->endElement(); $objWriter->endElement();
// Values $plotLabel = $plotGroup->getPlotLabelByIndex($plotSeriesIdx);
$plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesRef); $labelFill = null;
if ($plotLabel && $groupType === DataSeries::TYPE_LINECHART) {
$labelFill = $plotLabel->getFillColorObject();
$labelFill = ($labelFill instanceof ChartColor) ? $labelFill : null;
}
if ($plotLabel && $groupType !== DataSeries::TYPE_LINECHART) {
$fillColor = $plotLabel->getFillColorObject();
if ($fillColor !== null && !is_array($fillColor) && $fillColor->isUsable()) {
$objWriter->startElement('c:spPr');
$this->writeColor($objWriter, $fillColor);
$objWriter->endElement(); // c:spPr
}
}
if (($groupType == DataSeries::TYPE_PIECHART) || ($groupType == DataSeries::TYPE_PIECHART_3D) || ($groupType == DataSeries::TYPE_DONUTCHART)) { // Values
$fillColorValues = $plotSeriesValues->getFillColor(); $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesIdx);
if ($plotSeriesValues !== false && in_array($groupType, self::CUSTOM_COLOR_TYPES, true)) {
$fillColorValues = $plotSeriesValues->getFillColorObject();
if ($fillColorValues !== null && is_array($fillColorValues)) { if ($fillColorValues !== null && is_array($fillColorValues)) {
foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) { foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) {
$this->writePlotSeriesValuesElement($objWriter, $dataKey, $fillColorValues[$dataKey] ?? ''); $this->writePlotSeriesValuesElement($objWriter, $dataKey, $fillColorValues[$dataKey] ?? null);
} }
} else {
$this->writePlotSeriesValuesElement($objWriter);
} }
} }
// Labels // Labels
$plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesRef); $plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesIdx);
if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) { if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) {
$objWriter->startElement('c:tx'); $objWriter->startElement('c:tx');
$objWriter->startElement('c:strRef'); $objWriter->startElement('c:strRef');
@ -982,77 +962,54 @@ class Chart extends WriterPart
// Formatting for the points // Formatting for the points
if ( if (
$groupType == DataSeries::TYPE_LINECHART $plotSeriesValues !== false
|| $groupType == DataSeries::TYPE_STOCKCHART
|| ($groupType === DataSeries::TYPE_SCATTERCHART && $plotSeriesValues !== false && !$plotSeriesValues->getScatterLines())
|| ($plotSeriesValues !== false && ($plotSeriesValues->getSchemeClr() || $plotSeriesValues->getPrstClr()))
) { ) {
$plotLineWidth = 12700;
if ($plotSeriesValues) {
$plotLineWidth = $plotSeriesValues->getLineWidth();
}
$objWriter->startElement('c:spPr'); $objWriter->startElement('c:spPr');
$schemeClr = $typeClr = ''; $fillObject = $labelFill ?? $plotSeriesValues->getFillColorObject();
if ($plotLabel) { $callLineStyles = true;
$schemeClr = $plotLabel->getSchemeClr(); if ($fillObject instanceof ChartColor && $fillObject->isUsable()) {
if ($schemeClr) { if ($groupType === DataSeries::TYPE_LINECHART) {
$typeClr = 'schemeClr'; $objWriter->startElement('a:ln');
} else { $callLineStyles = false;
$schemeClr = $plotLabel->getPrstClr(); }
if ($schemeClr) { $this->writeColor($objWriter, $fillObject);
$typeClr = 'prstClr'; if (!$callLineStyles) {
} $objWriter->endElement(); // a:ln
} }
} }
if ($schemeClr) { $nofill = $groupType == DataSeries::TYPE_STOCKCHART || ($groupType === DataSeries::TYPE_SCATTERCHART && !$plotSeriesValues->getScatterLines());
$objWriter->startElement('a:solidFill'); if ($callLineStyles) {
$objWriter->startElement("a:$typeClr"); $this->writeLineStyles($objWriter, $plotSeriesValues, $nofill);
$objWriter->writeAttribute('val', $schemeClr);
$objWriter->endElement();
$objWriter->endElement();
} }
$objWriter->startElement('a:ln'); $objWriter->endElement(); // c:spPr
$objWriter->writeAttribute('w', $plotLineWidth);
if ($groupType == DataSeries::TYPE_STOCKCHART || $groupType === DataSeries::TYPE_SCATTERCHART) {
$objWriter->startElement('a:noFill');
$objWriter->endElement();
} elseif ($plotLabel) {
$fillColor = $plotLabel->getFillColor();
if (is_string($fillColor)) {
$objWriter->startElement('a:solidFill');
$objWriter->startElement('a:srgbClr');
$objWriter->writeAttribute('val', $fillColor);
$objWriter->endElement();
$objWriter->endElement();
}
}
$objWriter->endElement();
$objWriter->endElement();
} }
if ($plotSeriesValues) { if ($plotSeriesValues) {
$plotSeriesMarker = $plotSeriesValues->getPointMarker(); $plotSeriesMarker = $plotSeriesValues->getPointMarker();
if ($plotSeriesMarker) { $markerFillColor = $plotSeriesValues->getMarkerFillColor();
$fillUsed = $markerFillColor->IsUsable();
$markerBorderColor = $plotSeriesValues->getMarkerBorderColor();
$borderUsed = $markerBorderColor->isUsable();
if ($plotSeriesMarker || $fillUsed || $borderUsed) {
$objWriter->startElement('c:marker'); $objWriter->startElement('c:marker');
$objWriter->startElement('c:symbol'); $objWriter->startElement('c:symbol');
$objWriter->writeAttribute('val', $plotSeriesMarker); if ($plotSeriesMarker) {
$objWriter->writeAttribute('val', $plotSeriesMarker);
}
$objWriter->endElement(); $objWriter->endElement();
if ($plotSeriesMarker !== 'none') { if ($plotSeriesMarker !== 'none') {
$objWriter->startElement('c:size'); $objWriter->startElement('c:size');
$objWriter->writeAttribute('val', (string) $plotSeriesValues->getPointSize()); $objWriter->writeAttribute('val', (string) $plotSeriesValues->getPointSize());
$objWriter->endElement(); $objWriter->endElement(); // c:size
$fillColor = $plotSeriesValues->getFillColor(); $objWriter->startElement('c:spPr');
if (is_string($fillColor) && $fillColor !== '') { $this->writeColor($objWriter, $markerFillColor);
$objWriter->startElement('c:spPr'); if ($borderUsed) {
$objWriter->startElement('a:solidFill'); $objWriter->startElement('a:ln');
$objWriter->startElement('a:srgbClr'); $this->writeColor($objWriter, $markerBorderColor);
$objWriter->writeAttribute('val', $fillColor); $objWriter->endElement(); // a:ln
$objWriter->endElement(); // srgbClr
$objWriter->endElement(); // solidFill
$objWriter->endElement(); // spPr
} }
$objWriter->endElement(); // spPr
} }
$objWriter->endElement(); $objWriter->endElement();
@ -1066,7 +1023,7 @@ class Chart extends WriterPart
} }
// Category Labels // Category Labels
$plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesRef); $plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesIdx);
if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) { if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) {
$catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries(); $catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries();
@ -1112,7 +1069,7 @@ class Chart extends WriterPart
$objWriter->endElement(); $objWriter->endElement();
if ($groupType === DataSeries::TYPE_SCATTERCHART && $plotGroup->getPlotStyle() === 'smoothMarker') { if ($groupType === DataSeries::TYPE_SCATTERCHART && $plotGroup->getPlotStyle() === 'smoothMarker') {
$objWriter->startElement('c:smooth'); $objWriter->startElement('c:smooth');
$objWriter->writeAttribute('val', '1'); $objWriter->writeAttribute('val', $plotSeriesValues->getSmoothLine() ? '1' : '0');
$objWriter->endElement(); $objWriter->endElement();
} }
} }
@ -1268,6 +1225,14 @@ class Chart extends WriterPart
} }
} }
private const CUSTOM_COLOR_TYPES = [
DataSeries::TYPE_BARCHART,
DataSeries::TYPE_BARCHART_3D,
DataSeries::TYPE_PIECHART,
DataSeries::TYPE_PIECHART_3D,
DataSeries::TYPE_DONUTCHART,
];
/** /**
* Write Bubble Chart Details. * Write Bubble Chart Details.
*/ */
@ -1384,8 +1349,8 @@ class Chart extends WriterPart
$objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
$objWriter->startElement('mc:Choice'); $objWriter->startElement('mc:Choice');
$objWriter->writeAttribute('xmlns:c14', 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart');
$objWriter->writeAttribute('Requires', 'c14'); $objWriter->writeAttribute('Requires', 'c14');
$objWriter->writeAttribute('xmlns:c14', 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart');
$objWriter->startElement('c14:style'); $objWriter->startElement('c14:style');
$objWriter->writeAttribute('val', '102'); $objWriter->writeAttribute('val', '102');
@ -1509,12 +1474,7 @@ class Chart extends WriterPart
$objWriter->endElement(); //end softEdge $objWriter->endElement(); //end softEdge
} }
/** private function writeLineStyles(XMLWriter $objWriter, Properties $gridlines, bool $noFill = false): void
* Write Line Style for Gridlines.
*
* @param Axis|GridLines $gridlines
*/
private function writeGridlinesLn(XMLWriter $objWriter, $gridlines): void
{ {
$objWriter->startElement('a:ln'); $objWriter->startElement('a:ln');
$widthTemp = $gridlines->getLineStyleProperty('width'); $widthTemp = $gridlines->getLineStyleProperty('width');
@ -1523,7 +1483,12 @@ class Chart extends WriterPart
} }
$this->writeNotEmpty($objWriter, 'cap', $gridlines->getLineStyleProperty('cap')); $this->writeNotEmpty($objWriter, 'cap', $gridlines->getLineStyleProperty('cap'));
$this->writeNotEmpty($objWriter, 'cmpd', $gridlines->getLineStyleProperty('compound')); $this->writeNotEmpty($objWriter, 'cmpd', $gridlines->getLineStyleProperty('compound'));
$this->writeColor($objWriter, $gridlines->getLineColor()); if ($noFill) {
$objWriter->startElement('a:noFill');
$objWriter->endElement();
} else {
$this->writeColor($objWriter, $gridlines->getLineColor());
}
$dash = $gridlines->getLineStyleProperty('dash'); $dash = $gridlines->getLineStyleProperty('dash');
if (!empty($dash)) { if (!empty($dash)) {
@ -1544,16 +1509,16 @@ class Chart extends WriterPart
if ($gridlines->getLineStyleProperty(['arrow', 'head', 'type'])) { if ($gridlines->getLineStyleProperty(['arrow', 'head', 'type'])) {
$objWriter->startElement('a:headEnd'); $objWriter->startElement('a:headEnd');
$objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'head', 'type'])); $objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'head', 'type']));
$this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('head', 'w')); $this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowWidth('head'));
$this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('head', 'len')); $this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowLength('head'));
$objWriter->endElement(); $objWriter->endElement();
} }
if ($gridlines->getLineStyleProperty(['arrow', 'end', 'type'])) { if ($gridlines->getLineStyleProperty(['arrow', 'end', 'type'])) {
$objWriter->startElement('a:tailEnd'); $objWriter->startElement('a:tailEnd');
$objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'end', 'type'])); $objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'end', 'type']));
$this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('end', 'w')); $this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowWidth('end'));
$this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('end', 'len')); $this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowLength('end'));
$objWriter->endElement(); $objWriter->endElement();
} }
$objWriter->endElement(); //end ln $objWriter->endElement(); //end ln

View File

@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\RichText\Run; use PhpOffice\PhpSpreadsheet\RichText\Run;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper; use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
@ -198,7 +199,7 @@ class StringTable extends WriterPart
* @param RichText|string $richText text string or Rich text * @param RichText|string $richText text string or Rich text
* @param string $prefix Optional Namespace prefix * @param string $prefix Optional Namespace prefix
*/ */
public function writeRichTextForCharts(XMLWriter $objWriter, $richText = null, $prefix = null): void public function writeRichTextForCharts(XMLWriter $objWriter, $richText = null, $prefix = ''): void
{ {
if (!$richText instanceof RichText) { if (!$richText instanceof RichText) {
$textRun = $richText; $textRun = $richText;
@ -207,7 +208,7 @@ class StringTable extends WriterPart
$run->setFont(null); $run->setFont(null);
} }
if ($prefix !== null) { if ($prefix !== '') {
$prefix .= ':'; $prefix .= ':';
} }
@ -249,27 +250,10 @@ class StringTable extends WriterPart
} }
// Color // Color
$objWriter->startElement($prefix . 'solidFill'); $this->writeChartTextColor($objWriter, $element->getFont()->getChartColor(), $prefix);
$objWriter->startElement($prefix . 'srgbClr');
$objWriter->writeAttribute('val', $element->getFont()->getColor()->getRGB());
$objWriter->endElement(); // srgbClr
$objWriter->endElement(); // solidFill
// Underscore Color // Underscore Color
$underlineColor = $element->getFont()->getUnderlineColor(); $this->writeChartTextColor($objWriter, $element->getFont()->getUnderlineColor(), $prefix, 'uFill');
if ($underlineColor !== null) {
$type = $underlineColor->getType();
$value = $underlineColor->getValue();
if (!empty($type) && !empty($value)) {
$objWriter->startElement($prefix . 'uFill');
$objWriter->startElement($prefix . 'solidFill');
$objWriter->startElement($prefix . $type);
$objWriter->writeAttribute('val', $value);
$objWriter->endElement(); // schemeClr
$objWriter->endElement(); // solidFill
$objWriter->endElement(); // uFill
}
}
// fontName // fontName
if ($element->getFont()->getLatin()) { if ($element->getFont()->getLatin()) {
@ -300,6 +284,33 @@ class StringTable extends WriterPart
} }
} }
private function writeChartTextColor(XMLWriter $objWriter, ?ChartColor $underlineColor, string $prefix, ?string $openTag = ''): void
{
if ($underlineColor !== null) {
$type = $underlineColor->getType();
$value = $underlineColor->getValue();
if (!empty($type) && !empty($value)) {
if ($openTag !== '') {
$objWriter->startElement($prefix . $openTag);
}
$objWriter->startElement($prefix . 'solidFill');
$objWriter->startElement($prefix . $type);
$objWriter->writeAttribute('val', $value);
$alpha = $underlineColor->getAlpha();
if (is_numeric($alpha)) {
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', ChartColor::alphaToXml((int) $alpha));
$objWriter->endElement();
}
$objWriter->endElement(); // srgbClr/schemeClr/prstClr
$objWriter->endElement(); // solidFill
if ($openTag !== '') {
$objWriter->endElement(); // uFill
}
}
}
}
/** /**
* Flip string table (for index searching). * Flip string table (for index searching).
* *

View File

@ -119,6 +119,7 @@ class AxisGlowTest extends AbstractFunctional
$xAxis->setSoftEdges($softEdgesX); $xAxis->setSoftEdges($softEdgesX);
self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size')); self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color')); self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
self::assertSame($expectedGlowColor['value'], $yAxis->getGlowProperty(['color', 'value']));
self::assertEquals($softEdgesY, $yAxis->getSoftEdgesSize()); self::assertEquals($softEdgesY, $yAxis->getSoftEdgesSize());
self::assertEquals($softEdgesX, $xAxis->getSoftEdgesSize()); self::assertEquals($softEdgesX, $xAxis->getSoftEdgesSize());

View File

@ -0,0 +1,162 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
// based on 33_Chart_create_bar_custom_colors.php
class BarChartCustomColorsTest extends AbstractFunctional
{
public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}
public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}
public function testBarchartColor(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Custom colors for dataSeries (gray, blue, red, orange)
$colors = [
'cccccc',
'*accent1', // use schemeClr, was '00abb8',
'/green', // use prstClr, was 'b8292f',
'eb8500',
];
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels1 = [
new DataSeriesValues(
DataSeriesValues::DATASERIES_TYPE_STRING,
'Worksheet!$C$1',
null,
1
), // 2011
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues1 = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
// Custom Colors
$dataSeriesValues1Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4);
$dataSeriesValues1Element->setFillColor($colors);
$dataSeriesValues1 = [$dataSeriesValues1Element];
// Build the dataseries
$series1 = new DataSeries(
DataSeries::TYPE_PIECHART, // plotType
null, // plotGrouping (Pie charts don't have any grouping)
range(0, count($dataSeriesValues1) - 1), // plotOrder
$dataSeriesLabels1, // plotLabel
$xAxisTickValues1, // plotCategory
$dataSeriesValues1 // plotValues
);
// Set up a layout object for the Pie chart
$layout1 = new Layout();
$layout1->setShowVal(true);
$layout1->setShowPercent(true);
// Set the series in the plot area
$plotArea1 = new PlotArea($layout1, [$series1]);
// Set the chart legend
$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
$title1 = new Title('Test Pie Chart');
// Create the chart
$chart1 = new Chart(
'chart1', // name
$title1, // title
$legend1, // legend
$plotArea1, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
null // no Y-Axis for Pie Chart
);
// Set the position where the chart should appear in the worksheet
$chart1->setTopLeftPosition('A7');
$chart1->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart1);
/** @var callable */
$callableReader = [$this, 'readCharts'];
/** @var callable */
$callableWriter = [$this, 'writeCharts'];
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
$spreadsheet->disconnectWorksheets();
$sheet = $reloadedSpreadsheet->getActiveSheet();
$charts2 = $sheet->getChartCollection();
self::assertCount(1, $charts2);
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$plotArea2 = $chart2->getPlotArea();
$dataSeries2 = $plotArea2->getPlotGroup();
self::assertCount(1, $dataSeries2);
$plotValues = $dataSeries2[0]->getPlotValues();
self::assertCount(1, $plotValues);
$fillColors = $plotValues[0]->getFillColor();
self::assertSame($colors, $fillColors);
$writer = new XlsxWriter($reloadedSpreadsheet);
$writer->setIncludeCharts(true);
$writerChart = new XlsxWriter\Chart($writer);
$data = $writerChart->writeChart($chart2);
self::assertSame(1, substr_count($data, '<a:srgbClr val="cccccc"/>'));
self::assertSame(1, substr_count($data, '<a:schemeClr val="accent1"/>'));
self::assertSame(1, substr_count($data, '<a:prstClr val="green"/>'));
self::assertSame(1, substr_count($data, '<a:srgbClr val="eb8500"/>'));
self::assertSame(4, substr_count($data, '<c:dPt>'));
$reloadedSpreadsheet->disconnectWorksheets();
}
}

View File

@ -58,7 +58,10 @@ class Charts32ColoredAxisLabelTest extends AbstractFunctional
self::assertInstanceOf(Run::class, $run); self::assertInstanceOf(Run::class, $run);
$font = $run->getFont(); $font = $run->getFont();
self::assertInstanceOf(Font::class, $font); self::assertInstanceOf(Font::class, $font);
self::assertSame('00B050', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('00B050', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$yAxisLabel = $chart->getYAxisLabel(); $yAxisLabel = $chart->getYAxisLabel();
$captionArray = $yAxisLabel->getCaption(); $captionArray = $yAxisLabel->getCaption();
@ -73,7 +76,10 @@ class Charts32ColoredAxisLabelTest extends AbstractFunctional
self::assertInstanceOf(Run::class, $run); self::assertInstanceOf(Run::class, $run);
$font = $run->getFont(); $font = $run->getFont();
self::assertInstanceOf(Font::class, $font); self::assertInstanceOf(Font::class, $font);
self::assertSame('FF0000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('FF0000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$reloadedSpreadsheet->disconnectWorksheets(); $reloadedSpreadsheet->disconnectWorksheets();
} }

View File

@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Chart; namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader; use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\RichText\Run; use PhpOffice\PhpSpreadsheet\RichText\Run;
@ -65,7 +66,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('none', $font->getUnderline()); self::assertSame('none', $font->getUnderline());
self::assertSame('000000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('000000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$plotArea = $chart->getPlotArea(); $plotArea = $chart->getPlotArea();
$plotSeries = $plotArea->getPlotGroup(); $plotSeries = $plotArea->getPlotGroup();
@ -75,19 +79,22 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertCount(3, $plotValues); self::assertCount(3, $plotValues);
$values = $plotValues[0]; $values = $plotValues[0];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[1]; $values = $plotValues[1];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[2]; $values = $plotValues[2];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(7, $values->getPointSize()); self::assertSame(7, $values->getPointSize());
self::assertSame('FFFF00', $values->getFillColor()); // Had been testing for Fill Color, but we actually
// meant to test for marker color, which is now distinct.
self::assertSame('FFFF00', $values->getMarkerFillColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerFillColor()->getType());
$reloadedSpreadsheet->disconnectWorksheets(); $reloadedSpreadsheet->disconnectWorksheets();
} }
@ -135,7 +142,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('none', $font->getUnderline()); self::assertSame('none', $font->getUnderline());
self::assertSame('000000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('000000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$run = $elements[1]; $run = $elements[1];
self::assertInstanceOf(Run::class, $run); self::assertInstanceOf(Run::class, $run);
@ -149,7 +159,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('single', $font->getUnderline()); self::assertSame('single', $font->getUnderline());
self::assertSame('00B0F0', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('00B0F0', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$run = $elements[2]; $run = $elements[2];
self::assertInstanceOf(Run::class, $run); self::assertInstanceOf(Run::class, $run);
@ -163,7 +176,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('none', $font->getUnderline()); self::assertSame('none', $font->getUnderline());
self::assertSame('000000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('000000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$plotArea = $chart->getPlotArea(); $plotArea = $chart->getPlotArea();
$plotSeries = $plotArea->getPlotGroup(); $plotSeries = $plotArea->getPlotGroup();
@ -173,19 +189,22 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertCount(3, $plotValues); self::assertCount(3, $plotValues);
$values = $plotValues[0]; $values = $plotValues[0];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[1]; $values = $plotValues[1];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[2]; $values = $plotValues[2];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(7, $values->getPointSize()); self::assertSame(7, $values->getPointSize());
self::assertSame('FFFF00', $values->getFillColor()); // Had been testing for Fill Color, but we actually
// meant to test for marker color, which is now distinct.
self::assertSame('FFFF00', $values->getMarkerFillColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerFillColor()->getType());
$reloadedSpreadsheet->disconnectWorksheets(); $reloadedSpreadsheet->disconnectWorksheets();
} }
@ -232,7 +251,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('none', $font->getUnderline()); self::assertSame('none', $font->getUnderline());
self::assertSame('000000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('000000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
$plotArea = $chart->getPlotArea(); $plotArea = $chart->getPlotArea();
$plotSeries = $plotArea->getPlotGroup(); $plotSeries = $plotArea->getPlotGroup();
@ -242,17 +264,19 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertCount(3, $plotValues); self::assertCount(3, $plotValues);
$values = $plotValues[0]; $values = $plotValues[0];
self::assertTrue($values->getScatterLines()); self::assertTrue($values->getScatterLines());
self::assertSame(12700, $values->getLineWidth()); // the default value of 1 point is no longer written out
// when not explicitly specified.
self::assertNull($values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[1]; $values = $plotValues[1];
self::assertTrue($values->getScatterLines()); self::assertTrue($values->getScatterLines());
self::assertSame(12700, $values->getLineWidth()); self::assertNull($values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[2]; $values = $plotValues[2];
self::assertTrue($values->getScatterLines()); self::assertTrue($values->getScatterLines());
self::assertSame(12700, $values->getLineWidth()); self::assertNull($values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
@ -303,7 +327,10 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertFalse($font->getSubscript()); self::assertFalse($font->getSubscript());
self::assertFalse($font->getStrikethrough()); self::assertFalse($font->getStrikethrough());
self::assertSame('none', $font->getUnderline()); self::assertSame('none', $font->getUnderline());
self::assertSame('000000', $font->getColor()->getRGB()); $chartColor = $font->getChartColor();
self::assertNotNull($chartColor);
self::assertSame('000000', $chartColor->getValue());
self::assertSame('srgbClr', $chartColor->getType());
} }
$plotArea = $chart->getPlotArea(); $plotArea = $chart->getPlotArea();
@ -314,19 +341,97 @@ class Charts32ScatterTest extends AbstractFunctional
self::assertCount(3, $plotValues); self::assertCount(3, $plotValues);
$values = $plotValues[0]; $values = $plotValues[0];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[1]; $values = $plotValues[1];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(3, $values->getPointSize()); self::assertSame(3, $values->getPointSize());
self::assertSame('', $values->getFillColor()); self::assertSame('', $values->getFillColor());
$values = $plotValues[2]; $values = $plotValues[2];
self::assertFalse($values->getScatterLines()); self::assertFalse($values->getScatterLines());
self::assertSame(28575, $values->getLineWidth()); self::assertSame(28575 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame(7, $values->getPointSize()); self::assertSame(7, $values->getPointSize());
self::assertSame('FFFF00', $values->getFillColor()); // Had been testing for Fill Color, but we actually
// meant to test for marker color, which is now distinct.
self::assertSame('FFFF00', $values->getMarkerFillColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerFillColor()->getType());
$reloadedSpreadsheet->disconnectWorksheets();
}
public function testScatter8(): void
{
$file = self::DIRECTORY . '32readwriteScatterChart8.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('Worksheet', $sheet->getTitle());
$charts = $sheet->getChartCollection();
self::assertCount(1, $charts);
$chart = $charts[0];
self::assertNotNull($chart);
$plotArea = $chart->getPlotArea();
$plotSeries = $plotArea->getPlotGroup();
self::assertCount(1, $plotSeries);
$dataSeries = $plotSeries[0];
$plotValues = $dataSeries->getPlotValues();
self::assertCount(3, $plotValues);
$values = $plotValues[0];
self::assertSame(31750 / Properties::POINTS_WIDTH_MULTIPLIER, $values->getLineWidth());
self::assertSame('sq', $values->getLineStyleProperty('cap'));
self::assertSame('tri', $values->getLineStyleProperty('compound'));
self::assertSame('sysDash', $values->getLineStyleProperty('dash'));
self::assertSame('miter', $values->getLineStyleProperty('join'));
self::assertSame('arrow', $values->getLineStyleProperty(['arrow', 'head', 'type']));
self::assertSame('med', $values->getLineStyleProperty(['arrow', 'head', 'w']));
self::assertSame('sm', $values->getLineStyleProperty(['arrow', 'head', 'len']));
self::assertSame('triangle', $values->getLineStyleProperty(['arrow', 'end', 'type']));
self::assertSame('med', $values->getLineStyleProperty(['arrow', 'end', 'w']));
self::assertSame('lg', $values->getLineStyleProperty(['arrow', 'end', 'len']));
self::assertSame('accent1', $values->getLineColorProperty('value'));
self::assertSame('schemeClr', $values->getLineColorProperty('type'));
self::assertSame(40, $values->getLineColorProperty('alpha'));
self::assertSame('', $values->getFillColor());
self::assertSame(7, $values->getPointSize());
self::assertSame('diamond', $values->getPointMarker());
self::assertSame('0070C0', $values->getMarkerFillColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerFillColor()->getType());
self::assertSame('002060', $values->getMarkerBorderColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerBorderColor()->getType());
$values = $plotValues[1];
self::assertSame(7, $values->getPointSize());
self::assertSame('square', $values->getPointMarker());
self::assertSame('accent6', $values->getMarkerFillColor()->getValue());
self::assertSame('schemeClr', $values->getMarkerFillColor()->getType());
self::assertSame(3, $values->getMarkerFillColor()->getAlpha());
self::assertSame('0FF000', $values->getMarkerBorderColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerBorderColor()->getType());
self::assertNull($values->getMarkerBorderColor()->getAlpha());
$values = $plotValues[2];
self::assertSame(7, $values->getPointSize());
self::assertSame('triangle', $values->getPointMarker());
self::assertSame('FFFF00', $values->getMarkerFillColor()->getValue());
self::assertSame('srgbClr', $values->getMarkerFillColor()->getType());
self::assertNull($values->getMarkerFillColor()->getAlpha());
self::assertSame('accent4', $values->getMarkerBorderColor()->getValue());
self::assertSame('schemeClr', $values->getMarkerBorderColor()->getType());
$reloadedSpreadsheet->disconnectWorksheets(); $reloadedSpreadsheet->disconnectWorksheets();
} }

View File

@ -84,12 +84,16 @@ class Charts32XmlTest extends TestCase
$chart = $charts[0]; $chart = $charts[0];
self::assertNotNull($chart); self::assertNotNull($chart);
$xAxis = $chart->getChartAxisX(); $xAxis = $chart->getChartAxisX();
$yAxis = $chart->getChartAxisY();
self::assertSame(Properties::FORMAT_CODE_GENERAL, $xAxis->getAxisNumberFormat()); self::assertSame(Properties::FORMAT_CODE_GENERAL, $xAxis->getAxisNumberFormat());
if (is_bool($numeric)) { if (is_bool($numeric)) {
$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, true); $xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, true);
} }
$yAxis = $chart->getChartAxisY(); self::assertSame('valAx', $yAxis->getAxisType());
self::assertSame('valAx', $xAxis->getAxisType());
self::assertSame(Properties::FORMAT_CODE_GENERAL, $yAxis->getAxisNumberFormat()); self::assertSame(Properties::FORMAT_CODE_GENERAL, $yAxis->getAxisNumberFormat());
$xAxis->setAxisType('');
$yAxis->setAxisType('');
if (is_bool($numeric)) { if (is_bool($numeric)) {
$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, $numeric); $xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, $numeric);
$yAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, $numeric); $yAxis->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL, $numeric);
@ -119,6 +123,34 @@ class Charts32XmlTest extends TestCase
]; ];
} }
public function testCatAxValAxFromRead(): void
{
$file = self::DIRECTORY . '32readwriteScatterChart1.xlsx';
$reader = new XlsxReader();
$reader->setIncludeCharts(true);
$spreadsheet = $reader->load($file);
$sheet = $spreadsheet->getActiveSheet();
$charts = $sheet->getChartCollection();
self::assertCount(1, $charts);
$chart = $charts[0];
self::assertNotNull($chart);
$xAxis = $chart->getChartAxisX();
$yAxis = $chart->getChartAxisY();
self::assertSame(Properties::FORMAT_CODE_GENERAL, $xAxis->getAxisNumberFormat());
self::assertSame('valAx', $yAxis->getAxisType());
self::assertSame('valAx', $xAxis->getAxisType());
self::assertSame(Properties::FORMAT_CODE_GENERAL, $yAxis->getAxisNumberFormat());
$writer = new XlsxWriter($spreadsheet);
$writer->setIncludeCharts(true);
$writerChart = new XlsxWriter\Chart($writer);
$data = $writerChart->writeChart($chart);
$spreadsheet->disconnectWorksheets();
self::assertSame(0, substr_count($data, '<c:catAx>'));
self::assertSame(2, substr_count($data, '<c:valAx>'));
}
public function testAreaPrstClr(): void public function testAreaPrstClr(): void
{ {
$file = self::DIRECTORY . '32readwriteAreaChart4.xlsx'; $file = self::DIRECTORY . '32readwriteAreaChart4.xlsx';

View File

@ -0,0 +1,32 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PHPUnit\Framework\TestCase;
class ColorTest extends TestCase
{
public function testDefaultTypes(): void
{
$color = new ChartColor('800000');
self::assertSame('srgbClr', $color->getType());
self::assertSame('800000', $color->getValue());
$color->setColorProperties('*accent1');
self::assertSame('schemeClr', $color->getType());
self::assertSame('accent1', $color->getValue());
$color->setColorProperties('/red');
self::assertSame('prstClr', $color->getType());
self::assertSame('red', $color->getValue());
}
public function testDataSeriesValues(): void
{
$dsv = new DataSeriesValues();
$dsv->setFillColor([new ChartColor(), new ChartColor()]);
self::assertSame(['', ''], $dsv->getFillColor());
$dsv->setFillColor('cccccc');
self::assertSame('cccccc', $dsv->getFillColor());
}
}

View File

@ -0,0 +1,172 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class DataSeriesValues2Test extends AbstractFunctional
{
public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}
public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}
public function testDataSeriesValues(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
];
// Build the dataseries
$series = new DataSeries(
null, // plotType
null, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
self::assertEmpty($series->getPlotType());
self::assertEmpty($series->getPlotGrouping());
self::assertFalse($series->getSmoothLine());
$series->setPlotType(DataSeries::TYPE_AREACHART);
$series->setPlotGrouping(DataSeries::GROUPING_PERCENT_STACKED);
$series->setSmoothLine(true);
self::assertSame(DataSeries::TYPE_AREACHART, $series->getPlotType());
self::assertSame(DataSeries::GROUPING_PERCENT_STACKED, $series->getPlotGrouping());
self::assertTrue($series->getSmoothLine());
// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
$title = new Title('Test %age-Stacked Area Chart');
$yAxisLabel = new Title('Value ($k)');
// Create the chart
$chart = new Chart(
'chart1', // name
$title, // title
$legend, // legend
$plotArea, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
$yAxisLabel // yAxisLabel
);
// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A7');
$chart->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart);
self::assertSame(1, $chart->getPlotArea()->getPlotGroupCount());
$plotValues = $chart->getPlotArea()->getPlotGroup()[0]->getPlotValues();
self::assertCount(3, $plotValues);
self::assertSame([], $plotValues[1]->getDataValues());
self::assertNull($plotValues[1]->getDataValue());
/** @var callable */
$callableReader = [$this, 'readCharts'];
/** @var callable */
$callableWriter = [$this, 'writeCharts'];
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
$spreadsheet->disconnectWorksheets();
$sheet = $reloadedSpreadsheet->getActiveSheet();
$charts2 = $sheet->getChartCollection();
self::assertCount(1, $charts2);
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$plotValues2 = $chart2->getPlotArea()->getPlotGroup()[0]->getPlotValues();
self::assertCount(3, $plotValues2);
self::assertSame([15.0, 73.0, 61.0, 32.0], $plotValues2[1]->getDataValues());
self::assertSame([15.0, 73.0, 61.0, 32.0], $plotValues2[1]->getDataValue());
$labels2 = $chart->getPlotArea()->getPlotGroup()[0]->getPlotLabels();
self::assertCount(3, $labels2);
self::assertSame(2010, $labels2[0]->getDataValue());
$dataSeries = $chart->getPlotArea()->getPlotGroup()[0];
self::assertFalse($dataSeries->getPlotValuesByIndex(99));
self::assertNotFalse($dataSeries->getPlotValuesByIndex(0));
self::assertSame([12, 56, 52, 30], $dataSeries->getPlotValuesByIndex(0)->getDataValues());
self::assertSame(DataSeries::TYPE_AREACHART, $dataSeries->getPlotType());
self::assertSame(DataSeries::GROUPING_PERCENT_STACKED, $dataSeries->getPlotGrouping());
self::assertTrue($dataSeries->getSmoothLine());
$reloadedSpreadsheet->disconnectWorksheets();
}
public function testSomeProperties(): void
{
$dataSeriesValues = new DataSeriesValues();
self::assertNull($dataSeriesValues->getDataSource());
self::assertEmpty($dataSeriesValues->getPointMarker());
self::assertSame(3, $dataSeriesValues->getPointSize());
$dataSeriesValues->setDataSource('Worksheet!$B$1')
->setPointMarker('square')
->setPointSize(6);
self::assertSame('Worksheet!$B$1', $dataSeriesValues->getDataSource());
self::assertSame('square', $dataSeriesValues->getPointMarker());
self::assertSame(6, $dataSeriesValues->getPointSize());
}
}

View File

@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Chart; namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Exception;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -51,13 +52,14 @@ class DataSeriesValuesTest extends TestCase
public function testGetLineWidth(): void public function testGetLineWidth(): void
{ {
$testInstance = new DataSeriesValues(); $testInstance = new DataSeriesValues();
self::assertEquals(12700, $testInstance->getLineWidth(), 'should have default'); // default has changed to null from 1 point (12700)
self::assertNull($testInstance->getLineWidth(), 'should have default');
$testInstance->setLineWidth(40000); $testInstance->setLineWidth(40000 / Properties::POINTS_WIDTH_MULTIPLIER);
self::assertEquals(40000, $testInstance->getLineWidth()); self::assertEquals(40000 / Properties::POINTS_WIDTH_MULTIPLIER, $testInstance->getLineWidth());
$testInstance->setLineWidth(1); $testInstance->setLineWidth(1);
self::assertEquals(12700, $testInstance->getLineWidth(), 'should enforce minimum width'); self::assertEquals(12700 / Properties::POINTS_WIDTH_MULTIPLIER, $testInstance->getLineWidth(), 'should enforce minimum width');
} }
public function testFillColorCorrectInput(): void public function testFillColorCorrectInput(): void

View File

@ -1,6 +1,6 @@
<?php <?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx; namespace PhpOffice\PhpSpreadsheetTests\Chart;
use DOMDocument; use DOMDocument;
use DOMNode; use DOMNode;
@ -108,7 +108,7 @@ class Issue589Test extends TestCase
if ($actualXml === false) { if ($actualXml === false) {
self::fail('Failure saving the spPr element as xml string!'); self::fail('Failure saving the spPr element as xml string!');
} else { } else {
self::assertXmlStringEqualsXmlString('<c:spPr><a:ln w="12700"><a:solidFill><a:srgbClr val="98B954"/></a:solidFill></a:ln></c:spPr>', $actualXml); self::assertXmlStringEqualsXmlString('<c:spPr><a:ln><a:solidFill><a:srgbClr val="98B954"/></a:solidFill></a:ln></c:spPr>', $actualXml);
} }
} }
} }
@ -153,7 +153,7 @@ class Issue589Test extends TestCase
if ($actualXml === false) { if ($actualXml === false) {
self::fail('Failure saving the spPr element as xml string!'); self::fail('Failure saving the spPr element as xml string!');
} else { } else {
self::assertXmlStringEqualsXmlString('<c:spPr><a:ln w="12700"></a:ln></c:spPr>', $actualXml); self::assertXmlStringEqualsXmlString('<c:spPr><a:ln/></c:spPr>', $actualXml);
} }
} }
} }

View File

@ -123,6 +123,35 @@ class ShadowPresetsTest extends TestCase
} }
} }
public function testPreset0(): void
{
$axis = new Axis();
$axis->setShadowProperties(0);
$expectedShadow = [
'presets' => Properties::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
'ky' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $axis->getShadowProperty($key), $key);
}
}
public function testOutOfRangePresets(): void public function testOutOfRangePresets(): void
{ {
$axis = new Axis(); $axis = new Axis();