Add Support to Chart/Axis for Glow/SoftEdges (#2865)

* Add Support to Chart/Axis for Glow/SoftEdges

Chart is very under-covered in unit tests. I was hoping to just add some tests and be done with it, but that just won't suffice - many code changes are required. Adding Glow properties for Axis turned out to be a real mixed bag - no support in Xlsx/Reader at all, support in Xlsx/Writer ... for the X-axis only. So we'll just inch forward in many stages.

This change does not address other Axis properties (Fill, Shadow, Line, LineStyle, and maybe others, and their sub-properties). On my to-do list.

GridLines, and maybe other Chart objects, also should support these properties. This change does not address those. On my to-do list.

No support is added for spreadsheet formats other than Xlsx.

* Refactoring

This should make the code easier to follow, and I hope it will also be extensible to other object types (e.g. GridLines).

* More Refactoring

Make scheme/srgb easier to handle.

* Fix Typo

In a very rarely used function.
This commit is contained in:
oleibman 2022-06-03 16:47:03 -07:00 committed by GitHub
parent d0ff3d9ca7
commit 5608e05eda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 437 additions and 75 deletions

View File

@ -1110,31 +1110,6 @@ parameters:
count: 1 count: 1
path: src/PhpSpreadsheet/Cell/Coordinate.php path: src/PhpSpreadsheet/Cell/Coordinate.php
-
message: "#^Parameter \\#1 \\$textValue of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:substring\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Cell/DataType.php
-
message: "#^Parameter \\#1 \\$angle of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\:\\:setShadowAngle\\(\\) expects int, int\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Axis.php
-
message: "#^Parameter \\#1 \\$blur of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\:\\:setShadowBlur\\(\\) expects float, float\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Axis.php
-
message: "#^Parameter \\#1 \\$distance of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\:\\:setShadowDistance\\(\\) expects float, float\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Axis.php
-
message: "#^Parameter \\#2 \\$alpha of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\:\\:setShadowColor\\(\\) expects int, int\\|string given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Axis.php
- -
message: "#^Call to an undefined method object\\:\\:render\\(\\)\\.$#" message: "#^Call to an undefined method object\\:\\:render\\(\\)\\.$#"
count: 1 count: 1

View File

@ -346,17 +346,17 @@ class Axis extends Properties
* @param int $shadowPresets * @param int $shadowPresets
* @param string $colorValue * @param string $colorValue
* @param string $colorType * @param string $colorType
* @param string $colorAlpha * @param null|int|string $colorAlpha
* @param float $blur * @param null|float $blur
* @param int $angle * @param null|int $angle
* @param float $distance * @param null|float $distance
*/ */
public function setShadowProperties($shadowPresets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void public function setShadowProperties($shadowPresets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
{ {
$this->setShadowPresetsProperties((int) $shadowPresets) $this->setShadowPresetsProperties((int) $shadowPresets)
->setShadowColor( ->setShadowColor(
$colorValue ?? $this->shadowProperties['color']['value'], $colorValue ?? $this->shadowProperties['color']['value'],
$colorAlpha ?? (int) $this->shadowProperties['color']['alpha'], (int) ($colorAlpha ?? $this->shadowProperties['color']['alpha']),
$colorType ?? $this->shadowProperties['color']['type'] $colorType ?? $this->shadowProperties['color']['type']
) )
->setShadowBlur($blur) ->setShadowBlur($blur)
@ -412,9 +412,9 @@ class Axis extends Properties
/** /**
* Set Shadow Color. * Set Shadow Color.
* *
* @param string $color * @param null|string $color
* @param int $alpha * @param null|int $alpha
* @param string $alphaType * @param null|string $alphaType
* *
* @return $this * @return $this
*/ */
@ -428,7 +428,7 @@ class Axis extends Properties
/** /**
* Set Shadow Blur. * Set Shadow Blur.
* *
* @param float $blur * @param null|float $blur
* *
* @return $this * @return $this
*/ */
@ -444,7 +444,7 @@ class Axis extends Properties
/** /**
* Set Shadow Angle. * Set Shadow Angle.
* *
* @param int $angle * @param null|int $angle
* *
* @return $this * @return $this
*/ */
@ -460,7 +460,7 @@ class Axis extends Properties
/** /**
* Set Shadow Distance. * Set Shadow Distance.
* *
* @param float $distance * @param null|float $distance
* *
* @return $this * @return $this
*/ */
@ -489,9 +489,9 @@ class Axis extends Properties
* Set Glow Properties. * Set Glow Properties.
* *
* @param float $size * @param float $size
* @param string $colorValue * @param null|string $colorValue
* @param int $colorAlpha * @param null|int $colorAlpha
* @param string $colorType * @param null|string $colorType
*/ */
public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void
{ {
@ -508,7 +508,7 @@ class Axis extends Properties
* *
* @param array|string $property * @param array|string $property
* *
* @return string * @return null|string
*/ */
public function getGlowProperty($property) public function getGlowProperty($property)
{ {
@ -555,7 +555,7 @@ class Axis extends Properties
public function setSoftEdges($size): void public function setSoftEdges($size): void
{ {
if ($size !== null) { if ($size !== null) {
$softEdges['size'] = (string) $this->getExcelPointsWidth($size); $this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
} }
} }

View File

@ -110,6 +110,7 @@ abstract class Properties
const SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21; const SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21;
const SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22; const SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22;
const SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23; const SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23;
const POINTS_WIDTH_MULTIPLIER = 12700;
/** /**
* @param float $width * @param float $width
@ -118,7 +119,7 @@ abstract class Properties
*/ */
protected function getExcelPointsWidth($width) protected function getExcelPointsWidth($width)
{ {
return $width * 12700; return $width * self::POINTS_WIDTH_MULTIPLIER;
} }
/** /**
@ -133,7 +134,7 @@ abstract class Properties
protected function getTrueAlpha($alpha) protected function getTrueAlpha($alpha)
{ {
return (string) 100 - $alpha . '000'; return (string) (100 - $alpha) . '000';
} }
protected function setColorProperties($color, $alpha, $colorType) protected function setColorProperties($color, $alpha, $colorType)

View File

@ -3,11 +3,13 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx; namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Chart\Axis;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Layout; use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\Legend;
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\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Style\Color;
@ -67,6 +69,8 @@ class Chart
$dispBlanksAs = $plotVisOnly = null; $dispBlanksAs = $plotVisOnly = null;
$plotArea = null; $plotArea = null;
$rotX = $rotY = $rAngAx = $perspective = null; $rotX = $rotY = $rAngAx = $perspective = null;
$xAxis = new Axis();
$yAxis = new Axis();
foreach ($chartElementsC as $chartElementKey => $chartElement) { foreach ($chartElementsC as $chartElementKey => $chartElement) {
switch ($chartElementKey) { switch ($chartElementKey) {
case 'chart': case 'chart':
@ -93,6 +97,7 @@ class Chart
if (isset($chartDetail->title)) { if (isset($chartDetail->title)) {
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
} }
$this->readEffects($chartDetail, $xAxis);
break; break;
case 'dateAx': case 'dateAx':
@ -102,6 +107,7 @@ class Chart
break; break;
case 'valAx': case 'valAx':
$whichAxis = null;
if (isset($chartDetail->title, $chartDetail->axPos)) { if (isset($chartDetail->title, $chartDetail->axPos)) {
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); $axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string'); $axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
@ -110,15 +116,18 @@ class Chart
case 't': case 't':
case 'b': case 'b':
$XaxisLabel = $axisLabel; $XaxisLabel = $axisLabel;
$whichAxis = $xAxis;
break; break;
case 'r': case 'r':
case 'l': case 'l':
$YaxisLabel = $axisLabel; $YaxisLabel = $axisLabel;
$whichAxis = $yAxis;
break; break;
} }
} }
$this->readEffects($chartDetail, $whichAxis);
break; break;
case 'barChart': case 'barChart':
@ -240,7 +249,7 @@ class Chart
} }
} }
} }
$chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel); $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel, $xAxis, $yAxis);
if (is_int($rotX)) { if (is_int($rotX)) {
$chart->setRotX($rotX); $chart->setRotX($rotX);
} }
@ -345,9 +354,8 @@ class Chart
if (is_countable($ln->noFill) && count($ln->noFill) === 1) { if (is_countable($ln->noFill) && count($ln->noFill) === 1) {
$noFill = true; $noFill = true;
} }
$sf = $children->solidFill->schemeClr; if (isset($children->solidFill)) {
if ($sf) { $this->readColor($children->solidFill, $srgbClr, $schemeClr);
$schemeClr = self::getAttribute($sf, 'val', 'string');
} }
break; break;
@ -357,8 +365,8 @@ class Chart
$pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null; $pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null;
if (count($seriesDetail->spPr) === 1) { if (count($seriesDetail->spPr) === 1) {
$ln = $seriesDetail->spPr->children($this->aNamespace); $ln = $seriesDetail->spPr->children($this->aNamespace);
if (count($ln->solidFill) === 1) { if (isset($ln->solidFill)) {
$srgbClr = self::getAttribute($ln->solidFill->srgbClr, 'val', 'string'); $this->readColor($ln->solidFill, $srgbClr, $schemeClr);
} }
} }
@ -603,7 +611,8 @@ class Chart
$defaultLatin = null; $defaultLatin = null;
$defaultEastAsian = null; $defaultEastAsian = null;
$defaultComplexScript = null; $defaultComplexScript = null;
$defaultColor = null; $defaultSrgbColor = '';
$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');
@ -632,9 +641,8 @@ class Chart
/** @var ?string */ /** @var ?string */
$defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); $defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string');
} }
if (isset($titleDetailPart->pPr->defRPr->solidFill->srgbClr)) { if (isset($titleDetailPart->pPr->defRPr->solidFill)) {
/** @var ?string */ $this->readColor($titleDetailPart->pPr->defRPr->solidFill, $defaultSrgbColor, $defaultSchemeClr);
$defaultColor = self::getAttribute($titleDetailPart->pPr->defRPr->solidFill->srgbClr, 'val', 'string');
} }
} }
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) { foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
@ -660,7 +668,8 @@ class Chart
$latinName = null; $latinName = null;
$eastAsian = null; $eastAsian = null;
$complexScript = null; $complexScript = null;
$fontColor = null; $fontSrgbClr = '';
$fontSchemeClr = '';
$uSchemeClr = null; $uSchemeClr = 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
@ -686,10 +695,9 @@ class Chart
// not used now, not sure it ever was, grandfathering // not used now, not sure it ever was, grandfathering
/** @var ?string */ /** @var ?string */
$fontColor = self::getAttribute($titleDetailElement->rPr, 'color', 'string'); $fontSrgbClr = self::getAttribute($titleDetailElement->rPr, 'color', 'string');
if (isset($titleDetailElement->rPr->solidFill->srgbClr)) { if (isset($titleDetailElement->rPr->solidFill)) {
/** @var ?string */ $this->readColor($titleDetailElement->rPr->solidFill, $fontSrgbClr, $fontSchemeClr);
$fontColor = self::getAttribute($titleDetailElement->rPr->solidFill->srgbClr, 'val', 'string');
} }
/** @var ?bool */ /** @var ?bool */
@ -742,11 +750,17 @@ class Chart
$fontFound = true; $fontFound = true;
} }
$fontColor = $fontColor ?? $defaultColor; $fontSrgbClr = $fontSrgbClr ?? $defaultSrgbColor;
if ($fontColor !== null) { if (!empty($fontSrgbClr)) {
$objText->getFont()->setColor(new Color($fontColor)); $objText->getFont()->setColor(new Color($fontSrgbClr));
$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) {
@ -877,4 +891,56 @@ class Chart
} }
} }
} }
/**
* @param null|Axis $chartObject may be extended to include other types
*/
private function readEffects(SimpleXMLElement $chartDetail, $chartObject): void
{
if (!isset($chartObject, $chartDetail->spPr)) {
return;
}
$sppr = $chartDetail->spPr->children($this->aNamespace);
if (isset($sppr->effectLst->glow)) {
$axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / Properties::POINTS_WIDTH_MULTIPLIER;
if ($axisGlowSize != 0.0) {
$srgbClr = $schemeClr = '';
$colorArray = $this->readColor($sppr->effectLst->glow, $srgbClr, $schemeClr);
$chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']);
}
}
if (isset($sppr->effectLst->softEdge)) {
$chartObject->setSoftEdges((float) self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string') / Properties::POINTS_WIDTH_MULTIPLIER);
}
}
private function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr, ?string &$schemeClr): array
{
$result = [
'type' => null,
'value' => null,
'alpha' => null,
];
if (isset($colorXml->srgbClr)) {
$result['type'] = Properties::EXCEL_COLOR_TYPE_ARGB;
$result['value'] = $srgbClr = self::getAttribute($colorXml->srgbClr, 'val', 'string');
if (isset($colorXml->srgbClr->alpha)) {
$alpha = (int) self::getAttribute($colorXml->srgbClr->alpha, 'val', 'string');
$alpha = 100 - (int) ($alpha / 1000);
$result['alpha'] = $alpha;
}
} elseif (isset($colorXml->schemeClr)) {
$result['type'] = Properties::EXCEL_COLOR_TYPE_SCHEME;
$result['value'] = $schemeClr = self::getAttribute($colorXml->schemeClr, 'val', 'string');
if (isset($colorXml->schemeClr->alpha)) {
$alpha = (int) self::getAttribute($colorXml->schemeClr->alpha, 'val', 'string');
$alpha = 100 - (int) ($alpha / 1000);
$result['alpha'] = $alpha;
}
}
return $result;
}
} }

View File

@ -470,7 +470,7 @@ class StringHelper
/** /**
* Get a substring of a UTF-8 encoded string. * Get a substring of a UTF-8 encoded string.
* *
* @param string $textValue UTF-8 encoded string * @param null|string $textValue UTF-8 encoded string
* @param int $offset Start offset * @param int $offset Start offset
* @param int $length Maximum number of characters in substring * @param int $length Maximum number of characters in substring
* *
@ -478,7 +478,7 @@ class StringHelper
*/ */
public static function substring($textValue, $offset, $length = 0) public static function substring($textValue, $offset, $length = 0)
{ {
return mb_substr($textValue, $offset, $length, 'UTF-8'); return mb_substr($textValue ?? '', $offset, $length, 'UTF-8');
} }
/** /**

View File

@ -19,7 +19,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
*/ */
@ -39,6 +39,9 @@ class Font extends Supervisor
/** @var string */ /** @var string */
private $uSchemeClr = ''; private $uSchemeClr = '';
/** @var string */
private $uSrgbClr = '';
// end of chart title items // end of chart title items
/** /**
@ -603,6 +606,30 @@ class Font extends Supervisor
return $this; return $this;
} }
public function getUSrgbClr(): string
{
if ($this->isSupervisor) {
return $this->getSharedComponent()->getUSrgbClr();
}
return $this->uSrgbClr;
}
public function setUSrgbClr(string $uSrgbClr): self
{
if (!$this->isSupervisor) {
$this->uSrgbClr = $uSrgbClr;
} else {
// should never be true
// @codeCoverageIgnoreStart
$styleArray = $this->getStyleArray(['uSrgbClr' => $uSrgbClr]);
$this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
// @codeCoverageIgnoreEnd
}
return $this;
}
/** /**
* Get Underline. * Get Underline.
* *
@ -731,15 +758,18 @@ class Font extends Supervisor
$this->underline . $this->underline .
($this->strikethrough ? 't' : 'f') . ($this->strikethrough ? 't' : 'f') .
$this->color->getHashCode() . $this->color->getHashCode() .
'*' . implode(
$this->latin . '*',
'*' . [
$this->eastAsian . $this->latin,
'*' . $this->eastAsian,
$this->complexScript . $this->complexScript,
$this->strikeType . $this->strikeType,
$this->uSchemeClr . $this->uSchemeClr,
(string) $this->baseLine . $this->uSrgbClr,
(string) $this->baseLine,
]
) .
__CLASS__ __CLASS__
); );
} }
@ -762,6 +792,7 @@ class Font extends Supervisor
$this->exportArray2($exportedArray, 'superscript', $this->getSuperscript()); $this->exportArray2($exportedArray, 'superscript', $this->getSuperscript());
$this->exportArray2($exportedArray, 'underline', $this->getUnderline()); $this->exportArray2($exportedArray, 'underline', $this->getUnderline());
$this->exportArray2($exportedArray, 'uSchemeClr', $this->getUSchemeClr()); $this->exportArray2($exportedArray, 'uSchemeClr', $this->getUSchemeClr());
$this->exportArray2($exportedArray, 'uSrgbClr', $this->getUSrgbClr());
return $exportedArray; return $exportedArray;
} }

View File

@ -497,6 +497,27 @@ class Chart extends WriterPart
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels')); $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels'));
$objWriter->endElement(); $objWriter->endElement();
$objWriter->startElement('c:spPr');
$objWriter->startElement('a:effectLst');
if ($yAxis->getGlowProperty('size') !== null) {
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $yAxis->getGlowProperty('size'));
$objWriter->startElement("a:{$yAxis->getGlowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', (string) $yAxis->getGlowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', (string) $yAxis->getGlowProperty(['color', 'alpha']));
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}
if ($yAxis->getSoftEdgesSize() !== null) {
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', $yAxis->getSoftEdgesSize());
$objWriter->endElement(); //end softEdge
}
$objWriter->endElement(); // effectLst
$objWriter->endElement(); // spPr
if ($id2 !== '0') { if ($id2 !== '0') {
$objWriter->startElement('c:crossAx'); $objWriter->startElement('c:crossAx');
$objWriter->writeAttribute('val', $id2); $objWriter->writeAttribute('val', $id2);
@ -909,9 +930,9 @@ class Chart extends WriterPart
$objWriter->startElement('a:glow'); $objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size')); $objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size'));
$objWriter->startElement("a:{$xAxis->getGlowProperty(['color', 'type'])}"); $objWriter->startElement("a:{$xAxis->getGlowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'value'])); $objWriter->writeAttribute('val', (string) $xAxis->getGlowProperty(['color', 'value']));
$objWriter->startElement('a:alpha'); $objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $xAxis->getGlowProperty(['color', 'alpha'])); $objWriter->writeAttribute('val', (string) $xAxis->getGlowProperty(['color', 'alpha']));
$objWriter->endElement(); $objWriter->endElement();
$objWriter->endElement(); $objWriter->endElement();
$objWriter->endElement(); $objWriter->endElement();

View File

@ -0,0 +1,268 @@
<?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\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
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 AxisGlowTest extends AbstractFunctional
{
public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}
public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}
public function testGlowY(): 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(
DataSeries::TYPE_AREACHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
// 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
);
$yAxis = $chart->getChartAxisY();
$xAxis = $chart->getChartAxisX();
$yAxis->setGlowProperties(10, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
$expectedSize = 127000.0;
$expectedGlowColor = [
'type' => 'srgbClr',
'value' => 'FFFF00',
'alpha' => '70000',
];
$yAxis->setSoftEdges(2.5);
$xAxis->setSoftEdges(5);
$expectedSoftEdgesY = '31750';
$expectedSoftEdgesX = '63500';
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
self::assertEquals($expectedSoftEdgesY, $yAxis->getSoftEdgesSize());
self::assertEquals($expectedSoftEdgesX, $xAxis->getSoftEdgesSize());
// 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);
/** @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);
$yAxis2 = $chart2->getChartAxisY();
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
self::assertEquals($expectedSoftEdgesY, $yAxis2->getSoftEdgesSize());
$xAxis2 = $chart2->getChartAxisX();
self::assertNull($xAxis2->getGlowProperty('size'));
$reloadedSpreadsheet->disconnectWorksheets();
}
public function testGlowX(): 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(
DataSeries::TYPE_AREACHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
// 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
);
$yAxis = $chart->getChartAxisX(); // deliberate
$yAxis->setGlowProperties(20, 'accent1', 20, Properties::EXCEL_COLOR_TYPE_SCHEME);
$expectedSize = 254000.0;
$expectedGlowColor = [
'type' => 'schemeClr',
'value' => 'accent1',
'alpha' => '80000',
];
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
// 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);
/** @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);
$yAxis2 = $chart2->getChartAxisX(); // deliberate
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
$xAxis2 = $chart2->getChartAxisY(); // deliberate
self::assertNull($xAxis2->getGlowProperty('size'));
$reloadedSpreadsheet->disconnectWorksheets();
}
}