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:
parent
d0ff3d9ca7
commit
5608e05eda
|
|
@ -1110,31 +1110,6 @@ parameters:
|
|||
count: 1
|
||||
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\\(\\)\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -346,17 +346,17 @@ class Axis extends Properties
|
|||
* @param int $shadowPresets
|
||||
* @param string $colorValue
|
||||
* @param string $colorType
|
||||
* @param string $colorAlpha
|
||||
* @param float $blur
|
||||
* @param int $angle
|
||||
* @param float $distance
|
||||
* @param null|int|string $colorAlpha
|
||||
* @param null|float $blur
|
||||
* @param null|int $angle
|
||||
* @param null|float $distance
|
||||
*/
|
||||
public function setShadowProperties($shadowPresets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
|
||||
{
|
||||
$this->setShadowPresetsProperties((int) $shadowPresets)
|
||||
->setShadowColor(
|
||||
$colorValue ?? $this->shadowProperties['color']['value'],
|
||||
$colorAlpha ?? (int) $this->shadowProperties['color']['alpha'],
|
||||
(int) ($colorAlpha ?? $this->shadowProperties['color']['alpha']),
|
||||
$colorType ?? $this->shadowProperties['color']['type']
|
||||
)
|
||||
->setShadowBlur($blur)
|
||||
|
|
@ -412,9 +412,9 @@ class Axis extends Properties
|
|||
/**
|
||||
* Set Shadow Color.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $alphaType
|
||||
* @param null|string $color
|
||||
* @param null|int $alpha
|
||||
* @param null|string $alphaType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
|
@ -428,7 +428,7 @@ class Axis extends Properties
|
|||
/**
|
||||
* Set Shadow Blur.
|
||||
*
|
||||
* @param float $blur
|
||||
* @param null|float $blur
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
|
@ -444,7 +444,7 @@ class Axis extends Properties
|
|||
/**
|
||||
* Set Shadow Angle.
|
||||
*
|
||||
* @param int $angle
|
||||
* @param null|int $angle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
|
@ -460,7 +460,7 @@ class Axis extends Properties
|
|||
/**
|
||||
* Set Shadow Distance.
|
||||
*
|
||||
* @param float $distance
|
||||
* @param null|float $distance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
|
@ -489,9 +489,9 @@ class Axis extends Properties
|
|||
* Set Glow Properties.
|
||||
*
|
||||
* @param float $size
|
||||
* @param string $colorValue
|
||||
* @param int $colorAlpha
|
||||
* @param string $colorType
|
||||
* @param null|string $colorValue
|
||||
* @param null|int $colorAlpha
|
||||
* @param null|string $colorType
|
||||
*/
|
||||
public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void
|
||||
{
|
||||
|
|
@ -508,7 +508,7 @@ class Axis extends Properties
|
|||
*
|
||||
* @param array|string $property
|
||||
*
|
||||
* @return string
|
||||
* @return null|string
|
||||
*/
|
||||
public function getGlowProperty($property)
|
||||
{
|
||||
|
|
@ -555,7 +555,7 @@ class Axis extends Properties
|
|||
public function setSoftEdges($size): void
|
||||
{
|
||||
if ($size !== null) {
|
||||
$softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
||||
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ abstract class Properties
|
|||
const SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21;
|
||||
const SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22;
|
||||
const SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23;
|
||||
const POINTS_WIDTH_MULTIPLIER = 12700;
|
||||
|
||||
/**
|
||||
* @param float $width
|
||||
|
|
@ -118,7 +119,7 @@ abstract class Properties
|
|||
*/
|
||||
protected function getExcelPointsWidth($width)
|
||||
{
|
||||
return $width * 12700;
|
||||
return $width * self::POINTS_WIDTH_MULTIPLIER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,7 +134,7 @@ abstract class Properties
|
|||
|
||||
protected function getTrueAlpha($alpha)
|
||||
{
|
||||
return (string) 100 - $alpha . '000';
|
||||
return (string) (100 - $alpha) . '000';
|
||||
}
|
||||
|
||||
protected function setColorProperties($color, $alpha, $colorType)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@
|
|||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
|
|
@ -67,6 +69,8 @@ class Chart
|
|||
$dispBlanksAs = $plotVisOnly = null;
|
||||
$plotArea = null;
|
||||
$rotX = $rotY = $rAngAx = $perspective = null;
|
||||
$xAxis = new Axis();
|
||||
$yAxis = new Axis();
|
||||
foreach ($chartElementsC as $chartElementKey => $chartElement) {
|
||||
switch ($chartElementKey) {
|
||||
case 'chart':
|
||||
|
|
@ -93,6 +97,7 @@ class Chart
|
|||
if (isset($chartDetail->title)) {
|
||||
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||
}
|
||||
$this->readEffects($chartDetail, $xAxis);
|
||||
|
||||
break;
|
||||
case 'dateAx':
|
||||
|
|
@ -102,6 +107,7 @@ class Chart
|
|||
|
||||
break;
|
||||
case 'valAx':
|
||||
$whichAxis = null;
|
||||
if (isset($chartDetail->title, $chartDetail->axPos)) {
|
||||
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
|
||||
|
|
@ -110,15 +116,18 @@ class Chart
|
|||
case 't':
|
||||
case 'b':
|
||||
$XaxisLabel = $axisLabel;
|
||||
$whichAxis = $xAxis;
|
||||
|
||||
break;
|
||||
case 'r':
|
||||
case 'l':
|
||||
$YaxisLabel = $axisLabel;
|
||||
$whichAxis = $yAxis;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->readEffects($chartDetail, $whichAxis);
|
||||
|
||||
break;
|
||||
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)) {
|
||||
$chart->setRotX($rotX);
|
||||
}
|
||||
|
|
@ -345,9 +354,8 @@ class Chart
|
|||
if (is_countable($ln->noFill) && count($ln->noFill) === 1) {
|
||||
$noFill = true;
|
||||
}
|
||||
$sf = $children->solidFill->schemeClr;
|
||||
if ($sf) {
|
||||
$schemeClr = self::getAttribute($sf, 'val', 'string');
|
||||
if (isset($children->solidFill)) {
|
||||
$this->readColor($children->solidFill, $srgbClr, $schemeClr);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -357,8 +365,8 @@ class Chart
|
|||
$pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null;
|
||||
if (count($seriesDetail->spPr) === 1) {
|
||||
$ln = $seriesDetail->spPr->children($this->aNamespace);
|
||||
if (count($ln->solidFill) === 1) {
|
||||
$srgbClr = self::getAttribute($ln->solidFill->srgbClr, 'val', 'string');
|
||||
if (isset($ln->solidFill)) {
|
||||
$this->readColor($ln->solidFill, $srgbClr, $schemeClr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +611,8 @@ class Chart
|
|||
$defaultLatin = null;
|
||||
$defaultEastAsian = null;
|
||||
$defaultComplexScript = null;
|
||||
$defaultColor = null;
|
||||
$defaultSrgbColor = '';
|
||||
$defaultSchemeColor = '';
|
||||
if (isset($titleDetailPart->pPr->defRPr)) {
|
||||
/** @var ?int */
|
||||
$defaultFontSize = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer');
|
||||
|
|
@ -632,9 +641,8 @@ class Chart
|
|||
/** @var ?string */
|
||||
$defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string');
|
||||
}
|
||||
if (isset($titleDetailPart->pPr->defRPr->solidFill->srgbClr)) {
|
||||
/** @var ?string */
|
||||
$defaultColor = self::getAttribute($titleDetailPart->pPr->defRPr->solidFill->srgbClr, 'val', 'string');
|
||||
if (isset($titleDetailPart->pPr->defRPr->solidFill)) {
|
||||
$this->readColor($titleDetailPart->pPr->defRPr->solidFill, $defaultSrgbColor, $defaultSchemeClr);
|
||||
}
|
||||
}
|
||||
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
|
||||
|
|
@ -660,7 +668,8 @@ class Chart
|
|||
$latinName = null;
|
||||
$eastAsian = null;
|
||||
$complexScript = null;
|
||||
$fontColor = null;
|
||||
$fontSrgbClr = '';
|
||||
$fontSchemeClr = '';
|
||||
$uSchemeClr = null;
|
||||
if (isset($titleDetailElement->rPr)) {
|
||||
// not used now, not sure it ever was, grandfathering
|
||||
|
|
@ -686,10 +695,9 @@ class Chart
|
|||
|
||||
// not used now, not sure it ever was, grandfathering
|
||||
/** @var ?string */
|
||||
$fontColor = self::getAttribute($titleDetailElement->rPr, 'color', 'string');
|
||||
if (isset($titleDetailElement->rPr->solidFill->srgbClr)) {
|
||||
/** @var ?string */
|
||||
$fontColor = self::getAttribute($titleDetailElement->rPr->solidFill->srgbClr, 'val', 'string');
|
||||
$fontSrgbClr = self::getAttribute($titleDetailElement->rPr, 'color', 'string');
|
||||
if (isset($titleDetailElement->rPr->solidFill)) {
|
||||
$this->readColor($titleDetailElement->rPr->solidFill, $fontSrgbClr, $fontSchemeClr);
|
||||
}
|
||||
|
||||
/** @var ?bool */
|
||||
|
|
@ -742,11 +750,17 @@ class Chart
|
|||
$fontFound = true;
|
||||
}
|
||||
|
||||
$fontColor = $fontColor ?? $defaultColor;
|
||||
if ($fontColor !== null) {
|
||||
$objText->getFont()->setColor(new Color($fontColor));
|
||||
$fontSrgbClr = $fontSrgbClr ?? $defaultSrgbColor;
|
||||
if (!empty($fontSrgbClr)) {
|
||||
$objText->getFont()->setColor(new Color($fontSrgbClr));
|
||||
$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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ class StringHelper
|
|||
/**
|
||||
* 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 $length Maximum number of characters in substring
|
||||
*
|
||||
|
|
@ -478,7 +478,7 @@ class StringHelper
|
|||
*/
|
||||
public static function substring($textValue, $offset, $length = 0)
|
||||
{
|
||||
return mb_substr($textValue, $offset, $length, 'UTF-8');
|
||||
return mb_substr($textValue ?? '', $offset, $length, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class Font extends Supervisor
|
|||
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
|
||||
*/
|
||||
|
|
@ -39,6 +39,9 @@ class Font extends Supervisor
|
|||
|
||||
/** @var string */
|
||||
private $uSchemeClr = '';
|
||||
|
||||
/** @var string */
|
||||
private $uSrgbClr = '';
|
||||
// end of chart title items
|
||||
|
||||
/**
|
||||
|
|
@ -603,6 +606,30 @@ class Font extends Supervisor
|
|||
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.
|
||||
*
|
||||
|
|
@ -731,15 +758,18 @@ class Font extends Supervisor
|
|||
$this->underline .
|
||||
($this->strikethrough ? 't' : 'f') .
|
||||
$this->color->getHashCode() .
|
||||
'*' .
|
||||
$this->latin .
|
||||
'*' .
|
||||
$this->eastAsian .
|
||||
'*' .
|
||||
$this->complexScript .
|
||||
$this->strikeType .
|
||||
$this->uSchemeClr .
|
||||
(string) $this->baseLine .
|
||||
implode(
|
||||
'*',
|
||||
[
|
||||
$this->latin,
|
||||
$this->eastAsian,
|
||||
$this->complexScript,
|
||||
$this->strikeType,
|
||||
$this->uSchemeClr,
|
||||
$this->uSrgbClr,
|
||||
(string) $this->baseLine,
|
||||
]
|
||||
) .
|
||||
__CLASS__
|
||||
);
|
||||
}
|
||||
|
|
@ -762,6 +792,7 @@ class Font extends Supervisor
|
|||
$this->exportArray2($exportedArray, 'superscript', $this->getSuperscript());
|
||||
$this->exportArray2($exportedArray, 'underline', $this->getUnderline());
|
||||
$this->exportArray2($exportedArray, 'uSchemeClr', $this->getUSchemeClr());
|
||||
$this->exportArray2($exportedArray, 'uSrgbClr', $this->getUSrgbClr());
|
||||
|
||||
return $exportedArray;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -497,6 +497,27 @@ class Chart extends WriterPart
|
|||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels'));
|
||||
$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') {
|
||||
$objWriter->startElement('c:crossAx');
|
||||
$objWriter->writeAttribute('val', $id2);
|
||||
|
|
@ -909,9 +930,9 @@ class Chart extends WriterPart
|
|||
$objWriter->startElement('a:glow');
|
||||
$objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size'));
|
||||
$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->writeAttribute('val', $xAxis->getGlowProperty(['color', 'alpha']));
|
||||
$objWriter->writeAttribute('val', (string) $xAxis->getGlowProperty(['color', 'alpha']));
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue