Skip to content

Commit

Permalink
Support Border for Charts (#3462)
Browse files Browse the repository at this point in the history
* Support Border for Charts

All chart linestyles will be supported for Chart Border. Also add fill color for Chart. Also 'nofill' for Axis (allows suppressing of vertical axis line). These are demonstrated in sample 32_readwriteChartLine5, and a new unit test member is added. This addresses some vague problems added to issue #1797 over 8 months after it was closed; there is still at least one problem, much more complicated than the 2 being addressed in this PR.

* Handle Legend Borders in Same Way as Chart Borders

Consistency is good, and the implementation of Chart Borders offers more possibilities than the implementation of Legend Borders had. Since Legend Borders hasn't made it to a release yet, there is no need for deprecations.
  • Loading branch information
oleibman committed Mar 20, 2023
1 parent 025e905 commit dafd78b
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 34 deletions.
2 changes: 1 addition & 1 deletion samples/Chart/33_Chart_create_stock.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
$legend->getBorderColor()->setColorProperties('ffc000');
$legend->getBorderLines()->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
$legend->getFillColor()->setColorProperties('cccccc');
$legendText = new AxisText();
$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB);
Expand Down
15 changes: 15 additions & 0 deletions src/PhpSpreadsheet/Chart/Axis.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public function __construct()
Properties::FORMAT_CODE_DATE_ISO8601,
];

/** @var bool */
private $noFill = false;

/**
* Get Series Data Type.
*
Expand Down Expand Up @@ -318,4 +321,16 @@ public function setAxisText(?AxisText $axisText): self

return $this;
}

public function setNoFill(bool $noFill): self
{
$this->noFill = $noFill;

return $this;
}

public function getNoFill(): bool
{
return $this->noFill;
}
}
25 changes: 25 additions & 0 deletions src/PhpSpreadsheet/Chart/Chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ class Chart
/** @var bool */
private $roundedCorners = false;

/** @var GridLines */
private $borderLines;

/** @var ChartColor */
private $fillColor;

/**
* Create a new Chart.
* majorGridlines and minorGridlines are deprecated, moved to Axis.
Expand All @@ -176,6 +182,8 @@ public function __construct($name, ?Title $title = null, ?Legend $legend = null,
if ($minorGridlines !== null) {
$this->yAxis->setMinorGridlines($minorGridlines);
}
$this->fillColor = new ChartColor();
$this->borderLines = new GridLines();
}

/**
Expand Down Expand Up @@ -786,4 +794,21 @@ public function setRoundedCorners(?bool $roundedCorners): self

return $this;
}

public function getBorderLines(): GridLines
{
return $this->borderLines;
}

public function setBorderLines(GridLines $borderLines): self
{
$this->borderLines = $borderLines;

return $this;
}

public function getFillColor(): ChartColor
{
return $this->fillColor;
}
}
23 changes: 15 additions & 8 deletions src/PhpSpreadsheet/Chart/Legend.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class Legend
*/
private $layout;

/** @var ChartColor */
private $borderColor;
/** @var GridLines */
private $borderLines;

/** @var ChartColor */
private $fillColor;
Expand All @@ -69,15 +69,10 @@ public function __construct($position = self::POSITION_RIGHT, ?Layout $layout =
$this->setPosition($position);
$this->layout = $layout;
$this->setOverlay($overlay);
$this->borderColor = new ChartColor();
$this->borderLines = new GridLines();
$this->fillColor = new ChartColor();
}

public function getBorderColor(): ChartColor
{
return $this->borderColor;
}

public function getFillColor(): ChartColor
{
return $this->fillColor;
Expand Down Expand Up @@ -181,4 +176,16 @@ public function setLegendText(?AxisText $legendText): self

return $this;
}

public function getBorderLines(): GridLines
{
return $this->borderLines;
}

public function setBorderLines(GridLines $borderLines): self
{
$this->borderLines = $borderLines;

return $this;
}
}
36 changes: 29 additions & 7 deletions src/PhpSpreadsheet/Reader/Xlsx/Chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,25 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
$yAxis = new Axis();
$autoTitleDeleted = null;
$chartNoFill = false;
$chartBorderLines = null;
$chartFillColor = null;
$gradientArray = [];
$gradientLin = null;
$roundedCorners = false;
foreach ($chartElementsC as $chartElementKey => $chartElement) {
switch ($chartElementKey) {
case 'spPr':
$possibleNoFill = $chartElementsC->spPr->children($this->aNamespace);
if (isset($possibleNoFill->noFill)) {
$children = $chartElementsC->spPr->children($this->aNamespace);
if (isset($children->noFill)) {
$chartNoFill = true;
}
if (isset($children->solidFill)) {
$chartFillColor = $this->readColor($children->solidFill);
}
if (isset($children->ln)) {
$chartBorderLines = new GridLines();
$this->readLineStyle($chartElementsC, $chartBorderLines);
}

break;
case 'roundedCorners':
Expand Down Expand Up @@ -158,6 +167,9 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
$axisColorArray = $this->readColor($sppr->solidFill);
$xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']);
}
if (isset($chartDetail->spPr->ln->noFill)) {
$xAxis->setNoFill(true);
}
}
if (isset($chartDetail->majorGridlines)) {
$majorGridlines = new GridLines();
Expand Down Expand Up @@ -228,6 +240,9 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
$axisColorArray = $this->readColor($sppr->solidFill);
$whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']);
}
if (isset($sppr->ln->noFill)) {
$whichAxis->setNoFill(true);
}
}
if ($whichAxis !== null && isset($chartDetail->majorGridlines)) {
$majorGridlines = new GridLines();
Expand Down Expand Up @@ -351,7 +366,7 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
$legendPos = 'r';
$legendLayout = null;
$legendOverlay = false;
$legendBorderColor = null;
$legendBorderLines = null;
$legendFillColor = null;
$legendText = null;
$addLegendText = false;
Expand All @@ -375,8 +390,9 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
if (isset($children->solidFill)) {
$legendFillColor = $this->readColor($children->solidFill);
}
if (isset($children->ln->solidFill)) {
$legendBorderColor = $this->readColor($children->ln->solidFill);
if (isset($children->ln)) {
$legendBorderLines = new GridLines();
$this->readLineStyle($chartDetails, $legendBorderLines);
}

break;
Expand All @@ -401,8 +417,8 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
if ($legendFillColor !== null) {
$legend->getFillColor()->setColorPropertiesArray($legendFillColor);
}
if ($legendBorderColor !== null) {
$legend->getBorderColor()->setColorPropertiesArray($legendBorderColor);
if ($legendBorderLines !== null) {
$legend->setBorderLines($legendBorderLines);
}
if ($addLegendText) {
$legend->setLegendText($legendText);
Expand All @@ -417,6 +433,12 @@ public function readChart(SimpleXMLElement $chartElements, $chartName)
if ($chartNoFill) {
$chart->setNoFill(true);
}
if ($chartFillColor !== null) {
$chart->getFillColor()->setColorPropertiesArray($chartFillColor);
}
if ($chartBorderLines !== null) {
$chart->setBorderLines($chartBorderLines);
}
$chart->setRoundedCorners($roundedCorners);
if (is_bool($autoTitleDeleted)) {
$chart->setAutoTitleDeleted($autoTitleDeleted);
Expand Down
35 changes: 19 additions & 16 deletions src/PhpSpreadsheet/Writer/Xlsx/Chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,20 @@ public function writeChart(\PhpOffice\PhpSpreadsheet\Chart\Chart $chart, $calcul
$objWriter->endElement();

$objWriter->endElement(); // c:chart

$objWriter->startElement('c:spPr');
if ($chart->getNoFill()) {
$objWriter->startElement('c:spPr');
$objWriter->startElement('a:noFill');
$objWriter->endElement(); // a:noFill
$objWriter->endElement(); // c:spPr
}
$fillColor = $chart->getFillColor();
if ($fillColor->isUsable()) {
$this->writeColor($objWriter, $fillColor);
}
$borderLines = $chart->getBorderLines();
$this->writeLineStyles($objWriter, $borderLines);
$this->writeEffects($objWriter, $borderLines);
$objWriter->endElement(); // c:spPr

$this->writePrintSettings($objWriter);

Expand Down Expand Up @@ -201,20 +209,15 @@ private function writeLegend(XMLWriter $objWriter, ?Legend $legend = null): void
$objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0');
$objWriter->endElement();

$objWriter->startElement('c:spPr');
$fillColor = $legend->getFillColor();
$borderColor = $legend->getBorderColor();
if ($fillColor->isUsable() || $borderColor->isUsable()) {
$objWriter->startElement('c:spPr');
if ($fillColor->isUsable()) {
$this->writeColor($objWriter, $fillColor);
}
if ($borderColor->isUsable()) {
$objWriter->startElement('a:ln');
$this->writeColor($objWriter, $borderColor);
$objWriter->endElement(); // a:ln
}
$objWriter->endElement(); // c:spPr
if ($fillColor->isUsable()) {
$this->writeColor($objWriter, $fillColor);
}
$borderLines = $legend->getBorderLines();
$this->writeLineStyles($objWriter, $borderLines);
$this->writeEffects($objWriter, $borderLines);
$objWriter->endElement(); // c:spPr

$legendText = $legend->getLegendText();
$objWriter->startElement('c:txPr');
Expand Down Expand Up @@ -654,7 +657,7 @@ private function writeCategoryAxis(XMLWriter $objWriter, ?Title $xAxisLabel, $id

$objWriter->startElement('c:spPr');
$this->writeColor($objWriter, $yAxis->getFillColorObject());
$this->writeLineStyles($objWriter, $yAxis);
$this->writeLineStyles($objWriter, $yAxis, $yAxis->getNoFill());
$this->writeEffects($objWriter, $yAxis);
$objWriter->endElement(); // spPr

Expand Down Expand Up @@ -880,7 +883,7 @@ private function writeValueAxis(XMLWriter $objWriter, ?Title $yAxisLabel, $group

$objWriter->startElement('c:spPr');
$this->writeColor($objWriter, $xAxis->getFillColorObject());
$this->writeLineStyles($objWriter, $xAxis);
$this->writeLineStyles($objWriter, $xAxis, $xAxis->getNoFill());
$this->writeEffects($objWriter, $xAxis);
$objWriter->endElement(); //end spPr

Expand Down
54 changes: 54 additions & 0 deletions tests/PhpSpreadsheetTests/Chart/ChartBorderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Chart;

use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;

class ChartBorderTest extends AbstractFunctional
{
private const DIRECTORY = 'samples' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;

public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}

public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}

public function testChartBorder(): void
{
$file = self::DIRECTORY . '32readwriteLineChart5.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();
$charts = $sheet->getChartCollection();
self::assertCount(1, $charts);
$chart = $charts[0];
self::assertNotNull($chart);
self::assertSame('ffffff', $chart->getFillColor()->getValue());
self::assertSame('srgbClr', $chart->getFillColor()->getType());
self::assertSame('d9d9d9', $chart->getBorderLines()->getLineColorProperty('value'));
self::assertSame('srgbClr', $chart->getBorderLines()->getLineColorProperty('type'));
self::assertEqualsWithDelta(9360 / Properties::POINTS_WIDTH_MULTIPLIER, $chart->getBorderLines()->getLineStyleProperty('width'), 1.0E-8);
self::assertTrue($chart->getChartAxisY()->getNoFill());
self::assertFalse($chart->getChartAxisX()->getNoFill());

$reloadedSpreadsheet->disconnectWorksheets();
}
}
4 changes: 2 additions & 2 deletions tests/PhpSpreadsheetTests/Chart/LegendColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public function testLegend(): void
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
$legend->getBorderColor()->setColorProperties('ffc000');
$legend->getBorderLines()->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB);
$legend->getFillColor()->setColorProperties('cccccc');
$legendText = new AxisText();
$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB);
Expand Down Expand Up @@ -146,7 +146,7 @@ public function testLegend(): void
if ($legend2 === null) {
self::fail('Unexpected null legend');
} else {
self::assertSame('ffc000', $legend2->getBorderColor()->getValue());
self::assertSame('ffc000', $legend2->getBorderLines()->getLineColorProperty('value'));
self::assertSame('cccccc', $legend2->getFillColor()->getValue());
$legendText2 = $legend2->getLegendText();
if ($legendText2 === null) {
Expand Down

0 comments on commit dafd78b

Please sign in to comment.