diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5c1f074e..1491a665 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1170,46 +1170,6 @@ parameters: count: 2 path: src/PhpSpreadsheet/Chart/DataSeries.php - - - message: "#^Parameter \\#1 \\$color of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Parameter \\#2 \\$alpha of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects int, int\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Parameter \\#3 \\$colorType of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$glowProperties has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$lineProperties has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$objectState has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$shadowProperties has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$softEdges has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/GridLines.php - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend\\:\\:\\$layout \\(PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\|null\\.$#" count: 1 @@ -4385,11 +4345,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - message: "#^Else branch is unreachable because previous condition is always true\\.$#" - 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\\.$#" count: 1 @@ -4400,16 +4355,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - - message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, float given\\.$#" count: 6 @@ -4425,11 +4370,6 @@ parameters: count: 42 path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, string\\|null given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - message: "#^Parameter \\#6 \\$yAxis of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeCategoryAxis\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\|null given\\.$#" count: 1 @@ -4450,11 +4390,6 @@ parameters: count: 2 path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - message: "#^Part \\$xAxis\\-\\>getShadowProperty\\(\\['color', 'type'\\]\\) \\(array\\|int\\|string\\|null\\) of encapsed string cannot be cast to string\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:\\$calculateCellValues has no type specified\\.$#" count: 1 diff --git a/src/PhpSpreadsheet/Chart/Axis.php b/src/PhpSpreadsheet/Chart/Axis.php index 69607216..09a4febc 100644 --- a/src/PhpSpreadsheet/Chart/Axis.php +++ b/src/PhpSpreadsheet/Chart/Axis.php @@ -50,70 +50,6 @@ class Axis extends Properties 'alpha' => 0, ]; - /** - * Line Properties. - * - * @var mixed[] - */ - private $lineProperties = [ - 'type' => self::EXCEL_COLOR_TYPE_ARGB, - 'value' => null, - 'alpha' => 0, - ]; - - /** - * Line Style Properties. - * - * @var mixed[] - */ - private $lineStyleProperties = [ - 'width' => '9525', - 'compound' => self::LINE_STYLE_COMPOUND_SIMPLE, - 'dash' => self::LINE_STYLE_DASH_SOLID, - 'cap' => self::LINE_STYLE_CAP_FLAT, - 'join' => self::LINE_STYLE_JOIN_BEVEL, - 'arrow' => [ - 'head' => [ - 'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, - 'size' => self::LINE_STYLE_ARROW_SIZE_5, - ], - 'end' => [ - 'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, - 'size' => self::LINE_STYLE_ARROW_SIZE_8, - ], - ], - ]; - - /** - * Shadow Properties. - * - * @var mixed[] - */ - private $shadowProperties = Properties::PRESETS_OPTIONS[0]; - - /** - * Glow Properties. - * - * @var mixed[] - */ - private $glowProperties = [ - 'size' => null, - 'color' => [ - 'type' => self::EXCEL_COLOR_TYPE_STANDARD, - 'value' => 'black', - 'alpha' => 40, - ], - ]; - - /** - * Soft Edge Properties. - * - * @var mixed[] - */ - private $softEdges = [ - 'size' => null, - ]; - private const NUMERIC_FORMAT = [ Properties::FORMAT_CODE_NUMBER, Properties::FORMAT_CODE_DATE, @@ -161,33 +97,39 @@ class Axis extends Properties return (bool) $this->axisNumber['numeric']; } + public function setAxisOption(string $key, ?string $value): void + { + if (!empty($value)) { + $this->axisOptions[$key] = $value; + } + } + /** * Set Axis Options Properties. - * - * @param string $axisLabels - * @param string $horizontalCrossesValue - * @param string $horizontalCrosses - * @param string $axisOrientation - * @param string $majorTmt - * @param string $minorTmt - * @param string $minimum - * @param string $maximum - * @param string $majorUnit - * @param string $minorUnit */ - public function setAxisOptionsProperties($axisLabels, $horizontalCrossesValue = null, $horizontalCrosses = null, $axisOrientation = null, $majorTmt = null, $minorTmt = null, $minimum = null, $maximum = null, $majorUnit = null, $minorUnit = null): void - { - $this->axisOptions['axis_labels'] = (string) $axisLabels; - ($horizontalCrossesValue !== null) ? $this->axisOptions['horizontal_crosses_value'] = (string) $horizontalCrossesValue : null; - ($horizontalCrosses !== null) ? $this->axisOptions['horizontal_crosses'] = (string) $horizontalCrosses : null; - ($axisOrientation !== null) ? $this->axisOptions['orientation'] = (string) $axisOrientation : null; - ($majorTmt !== null) ? $this->axisOptions['major_tick_mark'] = (string) $majorTmt : null; - ($minorTmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minorTmt : null; - ($minorTmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minorTmt : null; - ($minimum !== null) ? $this->axisOptions['minimum'] = (string) $minimum : null; - ($maximum !== null) ? $this->axisOptions['maximum'] = (string) $maximum : null; - ($majorUnit !== null) ? $this->axisOptions['major_unit'] = (string) $majorUnit : null; - ($minorUnit !== null) ? $this->axisOptions['minor_unit'] = (string) $minorUnit : null; + public function setAxisOptionsProperties( + string $axisLabels, + ?string $horizontalCrossesValue = null, + ?string $horizontalCrosses = null, + ?string $axisOrientation = null, + ?string $majorTmt = null, + ?string $minorTmt = null, + ?string $minimum = null, + ?string $maximum = null, + ?string $majorUnit = null, + ?string $minorUnit = null + ): void { + $this->axisOptions['axis_labels'] = $axisLabels; + $this->setAxisOption('horizontal_crosses_value', $horizontalCrossesValue); + $this->setAxisOption('horizontal_crosses', $horizontalCrosses); + $this->setAxisOption('orientation', $axisOrientation); + $this->setAxisOption('major_tick_mark', $majorTmt); + $this->setAxisOption('minor_tick_mark', $minorTmt); + $this->setAxisOption('minor_tick_mark', $minorTmt); + $this->setAxisOption('minimum', $minimum); + $this->setAxisOption('maximum', $maximum); + $this->setAxisOption('major_unit', $majorUnit); + $this->setAxisOption('minor_unit', $minorUnit); } /** @@ -195,7 +137,7 @@ class Axis extends Properties * * @param string $property * - * @return string + * @return ?string */ public function getAxisOptionsProperty($property) { @@ -215,27 +157,15 @@ class Axis extends Properties /** * Set Fill Property. * - * @param string $color - * @param int $alpha - * @param string $AlphaType + * @param ?string $color + * @param ?int $alpha + * @param ?string $AlphaType */ - public function setFillParameters($color, $alpha = 0, $AlphaType = self::EXCEL_COLOR_TYPE_ARGB): void + public function setFillParameters($color, $alpha = null, $AlphaType = self::EXCEL_COLOR_TYPE_ARGB): void { $this->fillProperties = $this->setColorProperties($color, $alpha, $AlphaType); } - /** - * Set Line Property. - * - * @param string $color - * @param int $alpha - * @param string $alphaType - */ - public function setLineParameters($color, $alpha = 0, $alphaType = self::EXCEL_COLOR_TYPE_ARGB): void - { - $this->lineProperties = $this->setColorProperties($color, $alpha, $alphaType); - } - /** * Get Fill Property. * @@ -245,323 +175,33 @@ class Axis extends Properties */ public function getFillProperty($property) { - return $this->fillProperties[$property]; + return (string) $this->fillProperties[$property]; } /** - * Get Line Property. + * Get Line Color Property. * - * @param string $property + * @param string $propertyName * - * @return string + * @return null|int|string */ - public function getLineProperty($property) + public function getLineProperty($propertyName) { - return $this->lineProperties[$property]; + return $this->lineProperties['color'][$propertyName]; } - /** - * Set Line Style Properties. - * - * @param float $lineWidth - * @param string $compoundType - * @param string $dashType - * @param string $capType - * @param string $joinType - * @param string $headArrowType - * @param string $headArrowSize - * @param string $endArrowType - * @param string $endArrowSize - */ - public function setLineStyleProperties($lineWidth = null, $compoundType = null, $dashType = null, $capType = null, $joinType = null, $headArrowType = null, $headArrowSize = null, $endArrowType = null, $endArrowSize = null): void - { - ($lineWidth !== null) ? $this->lineStyleProperties['width'] = $this->getExcelPointsWidth((float) $lineWidth) : null; - ($compoundType !== null) ? $this->lineStyleProperties['compound'] = (string) $compoundType : null; - ($dashType !== null) ? $this->lineStyleProperties['dash'] = (string) $dashType : null; - ($capType !== null) ? $this->lineStyleProperties['cap'] = (string) $capType : null; - ($joinType !== null) ? $this->lineStyleProperties['join'] = (string) $joinType : null; - ($headArrowType !== null) ? $this->lineStyleProperties['arrow']['head']['type'] = (string) $headArrowType : null; - ($headArrowSize !== null) ? $this->lineStyleProperties['arrow']['head']['size'] = (string) $headArrowSize : null; - ($endArrowType !== null) ? $this->lineStyleProperties['arrow']['end']['type'] = (string) $endArrowType : null; - ($endArrowSize !== null) ? $this->lineStyleProperties['arrow']['end']['size'] = (string) $endArrowSize : null; - } + /** @var string */ + private $crossBetween = ''; // 'between' or 'midCat' might be better - /** - * Get Line Style Property. - * - * @param array|string $elements - * - * @return string - */ - public function getLineStyleProperty($elements) + public function setCrossBetween(string $crossBetween): self { - return $this->getArrayElementsValue($this->lineStyleProperties, $elements); - } - - /** - * Get Line Style Arrow Excel Width. - * - * @param string $arrow - * - * @return string - */ - public function getLineStyleArrowWidth($arrow) - { - return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'w'); - } - - /** - * Get Line Style Arrow Excel Length. - * - * @param string $arrow - * - * @return string - */ - public function getLineStyleArrowLength($arrow) - { - return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'len'); - } - - /** - * @param mixed $value - */ - public function setShadowProperty(string $propertyName, $value): self - { - if ($propertyName === 'color' && is_array($value)) { - $this->setShadowColor($value['value'], $value['alpha'], $value['type']); - } else { - $this->shadowProperties[$propertyName] = $value; - } + $this->crossBetween = $crossBetween; return $this; } - /** - * Set Shadow Properties. - * - * @param int $shadowPresets - * @param string $colorValue - * @param string $colorType - * @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 + public function getCrossBetween(): string { - $this->setShadowPresetsProperties((int) $shadowPresets) - ->setShadowColor( - $colorValue ?? $this->shadowProperties['color']['value'], - (int) ($colorAlpha ?? $this->shadowProperties['color']['alpha']), - $colorType ?? $this->shadowProperties['color']['type'] - ) - ->setShadowBlur($blur) - ->setShadowAngle($angle) - ->setShadowDistance($distance); - } - - /** - * Set Shadow Color. - * - * @param int $presets - * - * @return $this - */ - private function setShadowPresetsProperties($presets) - { - $this->shadowProperties['presets'] = $presets; - $this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets)); - - return $this; - } - - private const SHADOW_ARRAY_KEYS = ['size', 'color']; - - /** - * Set Shadow Properties from Mapped Values. - * - * @param mixed $reference - * - * @return $this - */ - private function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null) - { - $base_reference = $reference; - foreach ($propertiesMap as $property_key => $property_val) { - if (is_array($property_val)) { - if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) { - $reference = &$this->shadowProperties[$property_key]; - $this->setShadowPropertiesMapValues($property_val, $reference); - } - } else { - if ($base_reference === null) { - $this->shadowProperties[$property_key] = $property_val; - } else { - $reference[$property_key] = $property_val; - } - } - } - - return $this; - } - - /** - * Set Shadow Color. - * - * @param null|string $color - * @param null|int $alpha - * @param null|string $alphaType - * - * @return $this - */ - private function setShadowColor($color, $alpha, $alphaType) - { - $this->shadowProperties['color'] = $this->setColorProperties($color, $alpha, $alphaType); - - return $this; - } - - /** - * Set Shadow Blur. - * - * @param null|float $blur - * - * @return $this - */ - private function setShadowBlur($blur) - { - if ($blur !== null) { - $this->shadowProperties['blur'] = $blur; - } - - return $this; - } - - /** - * Set Shadow Angle. - * - * @param null|float|int $angle - * - * @return $this - */ - private function setShadowAngle($angle) - { - if (is_numeric($angle)) { - $this->shadowProperties['direction'] = $angle; - } - - return $this; - } - - /** - * Set Shadow Distance. - * - * @param null|float $distance - * - * @return $this - */ - private function setShadowDistance($distance) - { - if ($distance !== null) { - $this->shadowProperties['distance'] = $distance; - } - - return $this; - } - - /** - * Get Shadow Property. - * - * @param string|string[] $elements - * - * @return null|array|int|string - */ - public function getShadowProperty($elements) - { - return $this->getArrayElementsValue($this->shadowProperties, $elements); - } - - /** - * Set Glow Properties. - * - * @param float $size - * @param null|string $colorValue - * @param null|int $colorAlpha - * @param null|string $colorType - */ - public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void - { - $this->setGlowSize($size) - ->setGlowColor( - $colorValue ?? $this->glowProperties['color']['value'], - $colorAlpha ?? (int) $this->glowProperties['color']['alpha'], - $colorType ?? $this->glowProperties['color']['type'] - ); - } - - /** - * Get Glow Property. - * - * @param array|string $property - * - * @return null|string - */ - public function getGlowProperty($property) - { - return $this->getArrayElementsValue($this->glowProperties, $property); - } - - /** - * Set Glow Color. - * - * @param float $size - * - * @return $this - */ - private function setGlowSize($size) - { - if ($size !== null) { - $this->glowProperties['size'] = $size; - } - - return $this; - } - - /** - * Set Glow Color. - * - * @param string $color - * @param int $alpha - * @param string $colorType - * - * @return $this - */ - private function setGlowColor($color, $alpha, $colorType) - { - $this->glowProperties['color'] = $this->setColorProperties($color, $alpha, $colorType); - - return $this; - } - - /** - * Set Soft Edges Size. - * - * @param float $size - */ - public function setSoftEdges($size): void - { - if ($size !== null) { - $this->softEdges['size'] = $size; - } - } - - /** - * Get Soft Edges Size. - * - * @return string - */ - public function getSoftEdgesSize() - { - return $this->softEdges['size']; + return $this->crossBetween; } } diff --git a/src/PhpSpreadsheet/Chart/GridLines.php b/src/PhpSpreadsheet/Chart/GridLines.php index ad254c8c..8b86ccbd 100644 --- a/src/PhpSpreadsheet/Chart/GridLines.php +++ b/src/PhpSpreadsheet/Chart/GridLines.php @@ -10,450 +10,4 @@ namespace PhpOffice\PhpSpreadsheet\Chart; */ class GridLines extends Properties { - /** - * Properties of Class: - * Object State (State for Minor Tick Mark) @var bool - * Line Properties @var array of mixed - * Shadow Properties @var array of mixed - * Glow Properties @var array of mixed - * Soft Properties @var array of mixed. - */ - private $objectState = false; - - private $lineProperties = [ - 'color' => [ - 'type' => self::EXCEL_COLOR_TYPE_STANDARD, - 'value' => null, - 'alpha' => 0, - ], - 'style' => [ - 'width' => '9525', - 'compound' => self::LINE_STYLE_COMPOUND_SIMPLE, - 'dash' => self::LINE_STYLE_DASH_SOLID, - 'cap' => self::LINE_STYLE_CAP_FLAT, - 'join' => self::LINE_STYLE_JOIN_BEVEL, - 'arrow' => [ - 'head' => [ - 'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, - 'size' => self::LINE_STYLE_ARROW_SIZE_5, - ], - 'end' => [ - 'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, - 'size' => self::LINE_STYLE_ARROW_SIZE_8, - ], - ], - ], - ]; - - private $shadowProperties = Properties::PRESETS_OPTIONS[0]; - - private $glowProperties = [ - 'size' => null, - 'color' => [ - 'type' => self::EXCEL_COLOR_TYPE_STANDARD, - 'value' => 'black', - 'alpha' => 40, - ], - ]; - - private $softEdges = [ - 'size' => null, - ]; - - /** - * Get Object State. - * - * @return bool - */ - public function getObjectState() - { - return $this->objectState; - } - - /** - * Change Object State to True. - * - * @return $this - */ - private function activateObject() - { - $this->objectState = true; - - return $this; - } - - /** - * Set Line Color Properties. - * - * @param string $value - * @param int $alpha - * @param string $colorType - */ - public function setLineColorProperties($value, $alpha = 0, $colorType = self::EXCEL_COLOR_TYPE_STANDARD): void - { - $this->activateObject() - ->lineProperties['color'] = $this->setColorProperties( - $value, - $alpha, - $colorType - ); - } - - /** - * Set Line Color Properties. - * - * @param float $lineWidth - * @param string $compoundType - * @param string $dashType - * @param string $capType - * @param string $joinType - * @param string $headArrowType - * @param string $headArrowSize - * @param string $endArrowType - * @param string $endArrowSize - */ - public function setLineStyleProperties($lineWidth = null, $compoundType = null, $dashType = null, $capType = null, $joinType = null, $headArrowType = null, $headArrowSize = null, $endArrowType = null, $endArrowSize = null): void - { - $this->activateObject(); - ($lineWidth !== null) - ? $this->lineProperties['style']['width'] = $this->getExcelPointsWidth((float) $lineWidth) - : null; - ($compoundType !== null) - ? $this->lineProperties['style']['compound'] = (string) $compoundType - : null; - ($dashType !== null) - ? $this->lineProperties['style']['dash'] = (string) $dashType - : null; - ($capType !== null) - ? $this->lineProperties['style']['cap'] = (string) $capType - : null; - ($joinType !== null) - ? $this->lineProperties['style']['join'] = (string) $joinType - : null; - ($headArrowType !== null) - ? $this->lineProperties['style']['arrow']['head']['type'] = (string) $headArrowType - : null; - ($headArrowSize !== null) - ? $this->lineProperties['style']['arrow']['head']['size'] = (string) $headArrowSize - : null; - ($endArrowType !== null) - ? $this->lineProperties['style']['arrow']['end']['type'] = (string) $endArrowType - : null; - ($endArrowSize !== null) - ? $this->lineProperties['style']['arrow']['end']['size'] = (string) $endArrowSize - : null; - } - - /** - * Get Line Color Property. - * - * @param string $propertyName - * - * @return string - */ - public function getLineColorProperty($propertyName) - { - return $this->lineProperties['color'][$propertyName]; - } - - /** - * Get Line Style Property. - * - * @param array|string $elements - * - * @return string - */ - public function getLineStyleProperty($elements) - { - return $this->getArrayElementsValue($this->lineProperties['style'], $elements); - } - - /** - * Set Glow Properties. - * - * @param float $size - * @param string $colorValue - * @param int $colorAlpha - * @param string $colorType - */ - public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void - { - $this - ->activateObject() - ->setGlowSize($size) - ->setGlowColor($colorValue, $colorAlpha, $colorType); - } - - /** - * Get Glow Property. - * - * @param array|string $property - * - * @return null|string - */ - public function getGlowProperty($property) - { - return $this->getArrayElementsValue($this->glowProperties, $property); - } - - /** - * Get Glow Color Property. - * - * @param string $propertyName - * - * @return string - */ - public function getGlowColor($propertyName) - { - return $this->glowProperties['color'][$propertyName]; - } - - /** - * Get Glow Size. - * - * @return string - */ - public function getGlowSize() - { - return $this->glowProperties['size']; - } - - /** - * Set Glow Size. - * - * @param float $size - * - * @return $this - */ - private function setGlowSize($size) - { - $this->glowProperties['size'] = $size; - - return $this; - } - - /** - * Set Glow Color. - * - * @param string $color - * @param int $alpha - * @param string $colorType - * - * @return $this - */ - private function setGlowColor($color, $alpha, $colorType) - { - if ($color !== null) { - $this->glowProperties['color']['value'] = (string) $color; - } - if ($alpha !== null) { - $this->glowProperties['color']['alpha'] = (int) $alpha; - } - if ($colorType !== null) { - $this->glowProperties['color']['type'] = (string) $colorType; - } - - return $this; - } - - /** - * Get Line Style Arrow Parameters. - * - * @param string $arrowSelector - * @param string $propertySelector - * - * @return string - */ - public function getLineStyleArrowParameters($arrowSelector, $propertySelector) - { - return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrowSelector]['size'], $propertySelector); - } - - /** - * @param mixed $value - */ - public function setShadowProperty(string $propertyName, $value): self - { - $this->activateObject(); - $this->shadowProperties[$propertyName] = $value; - - return $this; - } - - /** - * Set Shadow Properties. - * - * @param int $presets - * @param string $colorValue - * @param string $colorType - * @param null|float|int|string $colorAlpha - * @param null|float $blur - * @param null|int $angle - * @param null|float $distance - */ - public function setShadowProperties($presets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void - { - $this->activateObject() - ->setShadowPresetsProperties((int) $presets) - ->setShadowColor( - $colorValue ?? $this->shadowProperties['color']['value'], - $colorAlpha === null ? (int) $this->shadowProperties['color']['alpha'] : (int) $colorAlpha, - $colorType ?? $this->shadowProperties['color']['type'] - ) - ->setShadowBlur($blur) - ->setShadowAngle($angle) - ->setShadowDistance($distance); - } - - /** - * Set Shadow Presets Properties. - * - * @param int $presets - * - * @return $this - */ - private function setShadowPresetsProperties($presets) - { - $this->shadowProperties['presets'] = $presets; - $this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets)); - - return $this; - } - - private const SHADOW_ARRAY_KEYS = ['size', 'color']; - - /** - * Set Shadow Properties Values. - * - * @param mixed $reference - * - * @return $this - */ - private function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null) - { - $base_reference = $reference; - foreach ($propertiesMap as $property_key => $property_val) { - if (is_array($property_val)) { - if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) { - $reference = &$this->shadowProperties[$property_key]; - $this->setShadowPropertiesMapValues($property_val, $reference); - } - } else { - if ($base_reference === null) { - $this->shadowProperties[$property_key] = $property_val; - } else { - $reference[$property_key] = $property_val; - } - } - } - - return $this; - } - - /** - * Set Shadow Color. - * - * @param string $color - * @param int $alpha - * @param string $colorType - * - * @return $this - */ - private 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. - * - * @param ?float $blur - * - * @return $this - */ - private function setShadowBlur($blur) - { - if ($blur !== null) { - $this->shadowProperties['blur'] = $blur; - } - - return $this; - } - - /** - * Set Shadow Angle. - * - * @param null|float|int|string $angle - * - * @return $this - */ - private function setShadowAngle($angle) - { - if (is_numeric($angle)) { - $this->shadowProperties['direction'] = $angle; - } - - return $this; - } - - /** - * Set Shadow Distance. - * - * @param ?float $distance - * - * @return $this - */ - private function setShadowDistance($distance) - { - if ($distance !== null) { - $this->shadowProperties['distance'] = $distance; - } - - return $this; - } - - /** - * Get Shadow Property. - * - * @param string|string[] $elements - * - * @return string - */ - public function getShadowProperty($elements) - { - return $this->getArrayElementsValue($this->shadowProperties, $elements); - } - - /** - * Set Soft Edges Size. - * - * @param float $size - */ - public function setSoftEdges($size): void - { - if ($size !== null) { - $this->activateObject(); - $this->softEdges['size'] = $size; - } - } - - /** - * Get Soft Edges Size. - * - * @return string - */ - public function getSoftEdgesSize() - { - return $this->softEdges['size']; - } } diff --git a/src/PhpSpreadsheet/Chart/Properties.php b/src/PhpSpreadsheet/Chart/Properties.php index 6db04809..c6b2d15b 100644 --- a/src/PhpSpreadsheet/Chart/Properties.php +++ b/src/PhpSpreadsheet/Chart/Properties.php @@ -120,14 +120,47 @@ abstract class Properties const ANGLE_MULTIPLIER = 60000; // direction and size-kx size-ky const PERCENTAGE_MULTIPLIER = 100000; // size sx and sy + /** @var bool */ + protected $objectState = false; // used only for minor gridlines + + /** @var array */ + protected $glowProperties = [ + 'size' => null, + 'color' => [ + 'type' => self::EXCEL_COLOR_TYPE_STANDARD, + 'value' => 'black', + 'alpha' => 40, + ], + ]; + + /** @var array */ + protected $softEdges = [ + 'size' => null, + ]; + + /** @var array */ + protected $shadowProperties = self::PRESETS_OPTIONS[0]; + /** - * @param float $width + * Get Object State. * - * @return float + * @return bool */ - protected function getExcelPointsWidth($width) + public function getObjectState() { - return $width * self::POINTS_WIDTH_MULTIPLIER; + return $this->objectState; + } + + /** + * Change Object State to True. + * + * @return $this + */ + protected function activateObject() + { + $this->objectState = true; + + return $this; } public static function pointsToXml(float $width): string @@ -181,27 +214,10 @@ abstract class Properties return [ 'type' => $colorType, 'value' => $color, - 'alpha' => (int) $alpha, + 'alpha' => ($alpha === null) ? null : (int) $alpha, ]; } - protected function getLineStyleArrowSize($arraySelector, $arrayKaySelector) - { - $sizes = [ - 1 => ['w' => 'sm', 'len' => 'sm'], - 2 => ['w' => 'sm', 'len' => 'med'], - 3 => ['w' => 'sm', 'len' => 'lg'], - 4 => ['w' => 'med', 'len' => 'sm'], - 5 => ['w' => 'med', 'len' => 'med'], - 6 => ['w' => 'med', 'len' => 'lg'], - 7 => ['w' => 'lg', 'len' => 'sm'], - 8 => ['w' => 'lg', 'len' => 'med'], - 9 => ['w' => 'lg', 'len' => 'lg'], - ]; - - return $sizes[$arraySelector][$arrayKaySelector]; - } - protected const PRESETS_OPTIONS = [ //NONE 0 => [ @@ -428,4 +444,476 @@ abstract class Properties return $reference; } + + /** + * Set Glow Properties. + * + * @param float $size + * @param ?string $colorValue + * @param ?int $colorAlpha + * @param ?string $colorType + */ + public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void + { + $this + ->activateObject() + ->setGlowSize($size) + ->setGlowColor($colorValue, $colorAlpha, $colorType); + } + + /** + * Get Glow Property. + * + * @param array|string $property + * + * @return null|string + */ + public function getGlowProperty($property) + { + return $this->getArrayElementsValue($this->glowProperties, $property); + } + + /** + * Get Glow Color Property. + * + * @param string $propertyName + * + * @return string + */ + public function getGlowColor($propertyName) + { + return $this->glowProperties['color'][$propertyName]; + } + + /** + * Get Glow Size. + * + * @return string + */ + public function getGlowSize() + { + return $this->glowProperties['size']; + } + + /** + * Set Glow Size. + * + * @param float $size + * + * @return $this + */ + protected function setGlowSize($size) + { + $this->glowProperties['size'] = $size; + + return $this; + } + + /** + * Set Glow Color. + * + * @param ?string $color + * @param ?int $alpha + * @param ?string $colorType + * + * @return $this + */ + protected function setGlowColor($color, $alpha, $colorType) + { + if ($color !== null) { + $this->glowProperties['color']['value'] = (string) $color; + } + if ($alpha !== null) { + $this->glowProperties['color']['alpha'] = (int) $alpha; + } + if ($colorType !== null) { + $this->glowProperties['color']['type'] = (string) $colorType; + } + + return $this; + } + + /** + * Set Soft Edges Size. + * + * @param float $size + */ + public function setSoftEdges($size): void + { + if ($size !== null) { + $this->activateObject(); + $this->softEdges['size'] = $size; + } + } + + /** + * Get Soft Edges Size. + * + * @return string + */ + public function getSoftEdgesSize() + { + return $this->softEdges['size']; + } + + /** + * @param mixed $value + */ + public function setShadowProperty(string $propertyName, $value): self + { + $this->activateObject(); + $this->shadowProperties[$propertyName] = $value; + + return $this; + } + + /** + * Set Shadow Properties. + * + * @param int $presets + * @param string $colorValue + * @param string $colorType + * @param null|float|int|string $colorAlpha + * @param null|float $blur + * @param null|int $angle + * @param null|float $distance + */ + public function setShadowProperties($presets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void + { + $this->activateObject() + ->setShadowPresetsProperties((int) $presets) + ->setShadowColor( + $colorValue ?? $this->shadowProperties['color']['value'], + $colorAlpha === null ? (int) $this->shadowProperties['color']['alpha'] : (int) $colorAlpha, + $colorType ?? $this->shadowProperties['color']['type'] + ) + ->setShadowBlur($blur) + ->setShadowAngle($angle) + ->setShadowDistance($distance); + } + + /** + * Set Shadow Presets Properties. + * + * @param int $presets + * + * @return $this + */ + protected function setShadowPresetsProperties($presets) + { + $this->shadowProperties['presets'] = $presets; + $this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets)); + + return $this; + } + + protected const SHADOW_ARRAY_KEYS = ['size', 'color']; + + /** + * Set Shadow Properties Values. + * + * @param mixed $reference + * + * @return $this + */ + protected function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null) + { + $base_reference = $reference; + foreach ($propertiesMap as $property_key => $property_val) { + if (is_array($property_val)) { + if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) { + $reference = &$this->shadowProperties[$property_key]; + $this->setShadowPropertiesMapValues($property_val, $reference); + } + } else { + if ($base_reference === null) { + $this->shadowProperties[$property_key] = $property_val; + } else { + $reference[$property_key] = $property_val; + } + } + } + + 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. + * + * @param ?float $blur + * + * @return $this + */ + protected function setShadowBlur($blur) + { + if ($blur !== null) { + $this->shadowProperties['blur'] = $blur; + } + + return $this; + } + + /** + * Set Shadow Angle. + * + * @param null|float|int|string $angle + * + * @return $this + */ + protected function setShadowAngle($angle) + { + if (is_numeric($angle)) { + $this->shadowProperties['direction'] = $angle; + } + + return $this; + } + + /** + * Set Shadow Distance. + * + * @param ?float $distance + * + * @return $this + */ + protected function setShadowDistance($distance) + { + if ($distance !== null) { + $this->shadowProperties['distance'] = $distance; + } + + return $this; + } + + /** + * Get Shadow Property. + * + * @param string|string[] $elements + * + * @return string + */ + public function getShadowProperty($elements) + { + return $this->getArrayElementsValue($this->shadowProperties, $elements); + } + + /** @var array */ + protected $lineProperties = [ + 'color' => [ + 'type' => '', //self::EXCEL_COLOR_TYPE_STANDARD, + 'value' => '', //null, + 'alpha' => null, + ], + 'style' => [ + 'width' => null, //'9525', + 'compound' => '', //self::LINE_STYLE_COMPOUND_SIMPLE, + 'dash' => '', //self::LINE_STYLE_DASH_SOLID, + 'cap' => '', //self::LINE_STYLE_CAP_FLAT, + 'join' => '', //self::LINE_STYLE_JOIN_BEVEL, + 'arrow' => [ + 'head' => [ + 'type' => '', //self::LINE_STYLE_ARROW_TYPE_NOARROW, + 'size' => '', //self::LINE_STYLE_ARROW_SIZE_5, + 'w' => '', + 'len' => '', + ], + 'end' => [ + 'type' => '', //self::LINE_STYLE_ARROW_TYPE_NOARROW, + 'size' => '', //self::LINE_STYLE_ARROW_SIZE_8, + 'w' => '', + 'len' => '', + ], + ], + ], + ]; + + /** + * Set Line Color Properties. + * + * @param string $value + * @param ?int $alpha + * @param string $colorType + */ + public function setLineColorProperties($value, $alpha = null, $colorType = self::EXCEL_COLOR_TYPE_STANDARD): void + { + $this->activateObject() + ->lineProperties['color'] = $this->setColorProperties( + $value, + $alpha, + $colorType + ); + } + + public function setColorPropertiesArray(array $color): void + { + $this->activateObject() + ->lineProperties['color'] = $color; + } + + /** + * Get Line Color Property. + * + * @param string $propertyName + * + * @return null|int|string + */ + public function getLineColorProperty($propertyName) + { + return $this->lineProperties['color'][$propertyName]; + } + + /** + * Set Line Style Properties. + * + * @param null|float|int|string $lineWidth + * @param string $compoundType + * @param string $dashType + * @param string $capType + * @param string $joinType + * @param string $headArrowType + * @param string $headArrowSize + * @param string $endArrowType + * @param string $endArrowSize + * @param string $headArrowWidth + * @param string $headArrowLength + * @param string $endArrowWidth + * @param string $endArrowLength + */ + public function setLineStyleProperties($lineWidth = null, $compoundType = '', $dashType = '', $capType = '', $joinType = '', $headArrowType = '', $headArrowSize = '', $endArrowType = '', $endArrowSize = '', $headArrowWidth = '', $headArrowLength = '', $endArrowWidth = '', $endArrowLength = ''): void + { + $this->activateObject(); + if (is_numeric($lineWidth)) { + $this->lineProperties['style']['width'] = $lineWidth; + } + if ($compoundType !== '') { + $this->lineProperties['style']['compound'] = $compoundType; + } + if ($dashType !== '') { + $this->lineProperties['style']['dash'] = $dashType; + } + if ($capType !== '') { + $this->lineProperties['style']['cap'] = $capType; + } + if ($joinType !== '') { + $this->lineProperties['style']['join'] = $joinType; + } + if ($headArrowType !== '') { + $this->lineProperties['style']['arrow']['head']['type'] = $headArrowType; + } + if (array_key_exists($headArrowSize, self::ARROW_SIZES)) { + $this->lineProperties['style']['arrow']['head']['size'] = $headArrowSize; + $this->lineProperties['style']['arrow']['head']['w'] = self::ARROW_SIZES[$headArrowSize]['w']; + $this->lineProperties['style']['arrow']['head']['len'] = self::ARROW_SIZES[$headArrowSize]['len']; + } + if ($endArrowType !== '') { + $this->lineProperties['style']['arrow']['end']['type'] = $endArrowType; + } + if (array_key_exists($endArrowSize, self::ARROW_SIZES)) { + $this->lineProperties['style']['arrow']['end']['size'] = $endArrowSize; + $this->lineProperties['style']['arrow']['end']['w'] = self::ARROW_SIZES[$endArrowSize]['w']; + $this->lineProperties['style']['arrow']['end']['len'] = self::ARROW_SIZES[$endArrowSize]['len']; + } + if ($headArrowWidth !== '') { + $this->lineProperties['style']['arrow']['head']['w'] = $headArrowWidth; + } + if ($headArrowLength !== '') { + $this->lineProperties['style']['arrow']['head']['len'] = $headArrowLength; + } + if ($endArrowWidth !== '') { + $this->lineProperties['style']['arrow']['end']['w'] = $endArrowWidth; + } + if ($endArrowLength !== '') { + $this->lineProperties['style']['arrow']['end']['len'] = $endArrowLength; + } + } + + /** + * Get Line Style Property. + * + * @param array|string $elements + * + * @return string + */ + public function getLineStyleProperty($elements) + { + return $this->getArrayElementsValue($this->lineProperties['style'], $elements); + } + + protected const ARROW_SIZES = [ + 1 => ['w' => 'sm', 'len' => 'sm'], + 2 => ['w' => 'sm', 'len' => 'med'], + 3 => ['w' => 'sm', 'len' => 'lg'], + 4 => ['w' => 'med', 'len' => 'sm'], + 5 => ['w' => 'med', 'len' => 'med'], + 6 => ['w' => 'med', 'len' => 'lg'], + 7 => ['w' => 'lg', 'len' => 'sm'], + 8 => ['w' => 'lg', 'len' => 'med'], + 9 => ['w' => 'lg', 'len' => 'lg'], + ]; + + protected function getLineStyleArrowSize($arraySelector, $arrayKaySelector) + { + return self::ARROW_SIZES[$arraySelector][$arrayKaySelector] ?? ''; + } + + /** + * Get Line Style Arrow Parameters. + * + * @param string $arrowSelector + * @param string $propertySelector + * + * @return string + */ + public function getLineStyleArrowParameters($arrowSelector, $propertySelector) + { + return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrowSelector]['size'], $propertySelector); + } + + /** + * Get Line Style Arrow Width. + * + * @param string $arrow + * + * @return string + */ + public function getLineStyleArrowWidth($arrow) + { + return $this->getLineStyleProperty(['arrow', $arrow, 'w']); + } + + /** + * Get Line Style Arrow Excel Length. + * + * @param string $arrow + * + * @return string + */ + public function getLineStyleArrowLength($arrow) + { + return $this->getLineStyleProperty(['arrow', $arrow, 'len']); + } } diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 8e3d6386..b046bc24 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -100,6 +100,14 @@ class Chart $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); } $this->readEffects($chartDetail, $xAxis); + if (isset($chartDetail->spPr)) { + $sppr = $chartDetail->spPr->children($this->aNamespace); + if (isset($sppr->solidFill)) { + $axisColorArray = $this->readColor($sppr->solidFill); + $xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); + } + } + $this->setAxisProperties($chartDetail, $xAxis); break; case 'dateAx': @@ -144,18 +152,28 @@ class Chart } } $this->readEffects($chartDetail, $whichAxis); + if ($whichAxis !== null && isset($chartDetail->spPr)) { + $sppr = $chartDetail->spPr->children($this->aNamespace); + if (isset($sppr->solidFill)) { + $axisColorArray = $this->readColor($sppr->solidFill); + $whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); + } + } if (isset($chartDetail->majorGridlines)) { $majorGridlines = new GridLines(); if (isset($chartDetail->majorGridlines->spPr)) { $this->readEffects($chartDetail->majorGridlines, $majorGridlines); + $this->readLineStyle($chartDetail->majorGridlines, $majorGridlines); } } if (isset($chartDetail->minorGridlines)) { $minorGridlines = new GridLines(); if (isset($chartDetail->minorGridlines->spPr)) { $this->readEffects($chartDetail->minorGridlines, $minorGridlines); + $this->readLineStyle($chartDetail->minorGridlines, $minorGridlines); } } + $this->setAxisProperties($chartDetail, $whichAxis); break; case 'barChart': @@ -1071,4 +1089,114 @@ class Chart return $result; } + + /** + * @param null|GridLines $chartObject may be extended to include other types + */ + private function readLineStyle(SimpleXMLElement $chartDetail, $chartObject): void + { + if (!isset($chartObject, $chartDetail->spPr)) { + return; + } + $sppr = $chartDetail->spPr->children($this->aNamespace); + + if (!isset($sppr->ln)) { + return; + } + $lineWidth = null; + /** @var string */ + $lineWidthTemp = self::getAttribute($sppr->ln, 'w', 'string'); + if (is_numeric($lineWidthTemp)) { + $lineWidth = Properties::xmlToPoints($lineWidthTemp); + } + /** @var string */ + $compoundType = self::getAttribute($sppr->ln, 'cmpd', 'string'); + /** @var string */ + $dashType = self::getAttribute($sppr->ln->prstDash, 'val', 'string'); + /** @var string */ + $capType = self::getAttribute($sppr->ln, 'cap', 'string'); + if (isset($sppr->ln->miter)) { + $joinType = Properties::LINE_STYLE_JOIN_MITER; + } elseif (isset($sppr->ln->bevel)) { + $joinType = Properties::LINE_STYLE_JOIN_BEVEL; + } else { + $joinType = ''; + } + $headArrowType = ''; + $headArrowSize = ''; + $endArrowType = ''; + $endArrowSize = ''; + /** @var string */ + $headArrowType = self::getAttribute($sppr->ln->headEnd, 'type', 'string'); + /** @var string */ + $headArrowWidth = self::getAttribute($sppr->ln->headEnd, 'w', 'string'); + /** @var string */ + $headArrowLength = self::getAttribute($sppr->ln->headEnd, 'len', 'string'); + /** @var string */ + $endArrowType = self::getAttribute($sppr->ln->tailEnd, 'type', 'string'); + /** @var string */ + $endArrowWidth = self::getAttribute($sppr->ln->tailEnd, 'w', 'string'); + /** @var string */ + $endArrowLength = self::getAttribute($sppr->ln->tailEnd, 'len', 'string'); + $chartObject->setLineStyleProperties( + $lineWidth, + $compoundType, + $dashType, + $capType, + $joinType, + $headArrowType, + $headArrowSize, + $endArrowType, + $endArrowSize, + $headArrowWidth, + $headArrowLength, + $endArrowWidth, + $endArrowLength + ); + $colorArray = $this->readColor($sppr->ln->solidFill); + $chartObject->setColorPropertiesArray($colorArray); + } + + private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAxis): void + { + if (!isset($whichAxis)) { + return; + } + if (isset($chartDetail->crossBetween)) { + $whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string')); + } + if (isset($chartDetail->majorTickMark)) { + $whichAxis->setAxisOption('major_tick_mark', (string) self::getAttribute($chartDetail->majorTickMark, 'val', 'string')); + } + if (isset($chartDetail->minorTickMark)) { + $whichAxis->setAxisOption('minor_tick_mark', (string) self::getAttribute($chartDetail->minorTickMark, 'val', 'string')); + } + if (isset($chartDetail->tickLblPos)) { + $whichAxis->setAxisOption('axis_labels', (string) self::getAttribute($chartDetail->tickLblPos, 'val', 'string')); + } + if (isset($chartDetail->crosses)) { + $whichAxis->setAxisOption('horizontal_crosses', (string) self::getAttribute($chartDetail->crosses, 'val', 'string')); + } + if (isset($chartDetail->crossesAt)) { + $whichAxis->setAxisOption('horizontal_crosses_value', (string) self::getAttribute($chartDetail->crossesAt, 'val', 'string')); + } + if (isset($chartDetail->scaling->orientation)) { + $whichAxis->setAxisOption('orientation', (string) self::getAttribute($chartDetail->scaling->orientation, 'val', 'string')); + } + if (isset($chartDetail->scaling->max)) { + $whichAxis->setAxisOption('maximum', (string) self::getAttribute($chartDetail->scaling->max, 'val', 'string')); + } + if (isset($chartDetail->scaling->min)) { + $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); + } + if (isset($chartDetail->scaling->min)) { + $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); + } + if (isset($chartDetail->majorUnit)) { + $whichAxis->setAxisOption('major_unit', (string) self::getAttribute($chartDetail->majorUnit, 'val', 'string')); + } + if (isset($chartDetail->minorUnit)) { + $whichAxis->setAxisOption('minor_unit', (string) self::getAttribute($chartDetail->minorUnit, 'val', 'string')); + } + } } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index dda395ac..1bdf4fe1 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -249,11 +249,11 @@ class Chart extends WriterPart $groupType = $plotGroup->getPlotType(); if ($groupType == $chartType) { $plotStyle = $plotGroup->getPlotStyle(); - if ($groupType === DataSeries::TYPE_RADARCHART) { + if (!empty($plotStyle) && $groupType === DataSeries::TYPE_RADARCHART) { $objWriter->startElement('c:radarStyle'); $objWriter->writeAttribute('val', $plotStyle); $objWriter->endElement(); - } elseif ($groupType === DataSeries::TYPE_SCATTERCHART) { + } elseif (!empty($plotStyle) && $groupType === DataSeries::TYPE_SCATTERCHART) { $objWriter->startElement('c:scatterStyle'); $objWriter->writeAttribute('val', $plotStyle); $objWriter->endElement(); @@ -431,10 +431,22 @@ class Chart extends WriterPart } $objWriter->startElement('c:scaling'); - $objWriter->startElement('c:orientation'); - $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('orientation')); - $objWriter->endElement(); - $objWriter->endElement(); + if ($yAxis->getAxisOptionsProperty('maximum') !== null) { + $objWriter->startElement('c:max'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('maximum')); + $objWriter->endElement(); + } + if ($yAxis->getAxisOptionsProperty('minimum') !== null) { + $objWriter->startElement('c:min'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minimum')); + $objWriter->endElement(); + } + if (!empty($yAxis->getAxisOptionsProperty('orientation'))) { + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('orientation')); + $objWriter->endElement(); + } + $objWriter->endElement(); // c:scaling $objWriter->startElement('c:delete'); $objWriter->writeAttribute('val', 0); @@ -486,19 +498,38 @@ class Chart extends WriterPart $objWriter->writeAttribute('sourceLinked', $yAxis->getAxisNumberSourceLinked()); $objWriter->endElement(); - $objWriter->startElement('c:majorTickMark'); - $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark')); - $objWriter->endElement(); + if (!empty($yAxis->getAxisOptionsProperty('major_tick_mark'))) { + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark')); + $objWriter->endElement(); + } - $objWriter->startElement('c:minorTickMark'); - $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark')); - $objWriter->endElement(); + if (!empty($yAxis->getAxisOptionsProperty('minor_tick_mark'))) { + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark')); + $objWriter->endElement(); + } - $objWriter->startElement('c:tickLblPos'); - $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels')); - $objWriter->endElement(); + if (!empty($yAxis->getAxisOptionsProperty('axis_labels'))) { + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels')); + $objWriter->endElement(); + } $objWriter->startElement('c:spPr'); + if (!empty($yAxis->getFillProperty('value'))) { + $objWriter->startElement('a:solidFill'); + $objWriter->startElement('a:' . $yAxis->getFillProperty('type')); + $objWriter->writeAttribute('val', $yAxis->getFillProperty('value')); + $alpha = $yAxis->getFillProperty('alpha'); + if (is_numeric($alpha)) { + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha)); + $objWriter->endElement(); + } + $objWriter->endElement(); + $objWriter->endElement(); + } $objWriter->startElement('a:effectLst'); $this->writeGlow($objWriter, $yAxis); $this->writeShadow($objWriter, $yAxis); @@ -506,14 +537,28 @@ class Chart extends WriterPart $objWriter->endElement(); // effectLst $objWriter->endElement(); // spPr + if ($yAxis->getAxisOptionsProperty('major_unit') !== null) { + $objWriter->startElement('c:majorUnit'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_unit')); + $objWriter->endElement(); + } + + if ($yAxis->getAxisOptionsProperty('minor_unit') !== null) { + $objWriter->startElement('c:minorUnit'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_unit')); + $objWriter->endElement(); + } + if ($id2 !== '0') { $objWriter->startElement('c:crossAx'); $objWriter->writeAttribute('val', $id2); $objWriter->endElement(); - $objWriter->startElement('c:crosses'); - $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses')); - $objWriter->endElement(); + if (!empty($yAxis->getAxisOptionsProperty('horizontal_crosses'))) { + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses')); + $objWriter->endElement(); + } } $objWriter->startElement('c:auto'); @@ -568,11 +613,13 @@ class Chart extends WriterPart $objWriter->endElement(); } - $objWriter->startElement('c:orientation'); - $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation')); + if (!empty($xAxis->getAxisOptionsProperty('orientation'))) { + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation')); + $objWriter->endElement(); + } - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); // c:scaling $objWriter->startElement('c:delete'); $objWriter->writeAttribute('val', 0); @@ -585,48 +632,8 @@ class Chart extends WriterPart $objWriter->startElement('c:majorGridlines'); $objWriter->startElement('c:spPr'); - if ($majorGridlines->getLineColorProperty('value') !== null) { - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', $majorGridlines->getLineStyleProperty('width')); - $objWriter->startElement('a:solidFill'); - $objWriter->startElement("a:{$majorGridlines->getLineColorProperty('type')}"); - $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('value')); - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('alpha')); - $objWriter->endElement(); //end alpha - $objWriter->endElement(); //end srgbClr - $objWriter->endElement(); //end solidFill + $this->writeGridlinesLn($objWriter, $majorGridlines); - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', $majorGridlines->getLineStyleProperty('dash')); - $objWriter->endElement(); - - if ($majorGridlines->getLineStyleProperty('join') == 'miter') { - $objWriter->startElement('a:miter'); - $objWriter->writeAttribute('lim', '800000'); - $objWriter->endElement(); - } else { - $objWriter->startElement('a:bevel'); - $objWriter->endElement(); - } - - if ($majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { - $objWriter->startElement('a:headEnd'); - $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type'])); - $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('head', 'w')); - $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('head', 'len')); - $objWriter->endElement(); - } - - if ($majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { - $objWriter->startElement('a:tailEnd'); - $objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type'])); - $objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('end', 'w')); - $objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('end', 'len')); - $objWriter->endElement(); - } - $objWriter->endElement(); //end ln - } $objWriter->startElement('a:effectLst'); $this->writeGlow($objWriter, $majorGridlines); $this->writeShadow($objWriter, $majorGridlines); @@ -640,48 +647,7 @@ class Chart extends WriterPart $objWriter->startElement('c:minorGridlines'); $objWriter->startElement('c:spPr'); - if ($minorGridlines->getLineColorProperty('value') !== null) { - $objWriter->startElement('a:ln'); - $objWriter->writeAttribute('w', $minorGridlines->getLineStyleProperty('width')); - $objWriter->startElement('a:solidFill'); - $objWriter->startElement("a:{$minorGridlines->getLineColorProperty('type')}"); - $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('value')); - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('alpha')); - $objWriter->endElement(); //end alpha - $objWriter->endElement(); //end srgbClr - $objWriter->endElement(); //end solidFill - - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', $minorGridlines->getLineStyleProperty('dash')); - $objWriter->endElement(); - - if ($minorGridlines->getLineStyleProperty('join') == 'miter') { - $objWriter->startElement('a:miter'); - $objWriter->writeAttribute('lim', '800000'); - $objWriter->endElement(); - } else { - $objWriter->startElement('a:bevel'); - $objWriter->endElement(); - } - - if ($minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { - $objWriter->startElement('a:headEnd'); - $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'head', 'type'])); - $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('head', 'w')); - $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('head', 'len')); - $objWriter->endElement(); - } - - if ($minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { - $objWriter->startElement('a:tailEnd'); - $objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'end', 'type'])); - $objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('end', 'w')); - $objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('end', 'len')); - $objWriter->endElement(); - } - $objWriter->endElement(); //end ln - } + $this->writeGridlinesLn($objWriter, $minorGridlines); $objWriter->startElement('a:effectLst'); $this->writeGlow($objWriter, $minorGridlines); @@ -737,78 +703,41 @@ class Chart extends WriterPart $objWriter->writeAttribute('sourceLinked', $xAxis->getAxisNumberSourceLinked()); $objWriter->endElement(); - $objWriter->startElement('c:majorTickMark'); - $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark')); - $objWriter->endElement(); + if (!empty($xAxis->getAxisOptionsProperty('major_tick_mark'))) { + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark')); + $objWriter->endElement(); + } - $objWriter->startElement('c:minorTickMark'); - $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark')); - $objWriter->endElement(); + if (!empty($xAxis->getAxisOptionsProperty('minor_tick_mark'))) { + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark')); + $objWriter->endElement(); + } - $objWriter->startElement('c:tickLblPos'); - $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels')); - $objWriter->endElement(); + if (!empty($xAxis->getAxisOptionsProperty('axis_labels'))) { + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels')); + $objWriter->endElement(); + } $objWriter->startElement('c:spPr'); - if ($xAxis->getFillProperty('value') !== null) { + if (!empty($xAxis->getFillProperty('value'))) { $objWriter->startElement('a:solidFill'); $objWriter->startElement('a:' . $xAxis->getFillProperty('type')); $objWriter->writeAttribute('val', $xAxis->getFillProperty('value')); - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $xAxis->getFillProperty('alpha')); - $objWriter->endElement(); + $alpha = $xAxis->getFillProperty('alpha'); + if (is_numeric($alpha)) { + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha)); + $objWriter->endElement(); + } $objWriter->endElement(); $objWriter->endElement(); } - $objWriter->startElement('a:ln'); - - $objWriter->writeAttribute('w', $xAxis->getLineStyleProperty('width')); - $objWriter->writeAttribute('cap', $xAxis->getLineStyleProperty('cap')); - $objWriter->writeAttribute('cmpd', $xAxis->getLineStyleProperty('compound')); - - if ($xAxis->getLineProperty('value') !== null) { - $objWriter->startElement('a:solidFill'); - $objWriter->startElement('a:' . $xAxis->getLineProperty('type')); - $objWriter->writeAttribute('val', $xAxis->getLineProperty('value')); - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $xAxis->getLineProperty('alpha')); - $objWriter->endElement(); - $objWriter->endElement(); - $objWriter->endElement(); - } - - $objWriter->startElement('a:prstDash'); - $objWriter->writeAttribute('val', $xAxis->getLineStyleProperty('dash')); - $objWriter->endElement(); - - if ($xAxis->getLineStyleProperty('join') == 'miter') { - $objWriter->startElement('a:miter'); - $objWriter->writeAttribute('lim', '800000'); - $objWriter->endElement(); - } else { - $objWriter->startElement('a:bevel'); - $objWriter->endElement(); - } - - if ($xAxis->getLineStyleProperty(['arrow', 'head', 'type']) !== null) { - $objWriter->startElement('a:headEnd'); - $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'head', 'type'])); - $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('head')); - $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('head')); - $objWriter->endElement(); - } - - if ($xAxis->getLineStyleProperty(['arrow', 'end', 'type']) !== null) { - $objWriter->startElement('a:tailEnd'); - $objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'end', 'type'])); - $objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('end')); - $objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('end')); - $objWriter->endElement(); - } - - $objWriter->endElement(); + $this->writeGridlinesLn($objWriter, $xAxis); $objWriter->startElement('a:effectLst'); $this->writeGlow($objWriter, $xAxis); @@ -828,14 +757,20 @@ class Chart extends WriterPart $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses_value')); $objWriter->endElement(); } else { - $objWriter->startElement('c:crosses'); - $objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses')); - $objWriter->endElement(); + $crosses = $xAxis->getAxisOptionsProperty('horizontal_crosses'); + if ($crosses) { + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', $crosses); + $objWriter->endElement(); + } } - $objWriter->startElement('c:crossBetween'); - $objWriter->writeAttribute('val', 'midCat'); - $objWriter->endElement(); + $crossBetween = $xAxis->getCrossBetween(); + if ($crossBetween !== '') { + $objWriter->startElement('c:crossBetween'); + $objWriter->writeAttribute('val', $crossBetween); + $objWriter->endElement(); + } if ($xAxis->getAxisOptionsProperty('major_unit') !== null) { $objWriter->startElement('c:majorUnit'); @@ -1521,7 +1456,7 @@ class Chart extends WriterPart */ private function writeShadow(XMLWriter $objWriter, $xAxis): void { - if ($xAxis->getShadowProperty('effect') === null) { + if (empty($xAxis->getShadowProperty('effect'))) { return; } /** @var string */ @@ -1609,4 +1544,73 @@ class Chart extends WriterPart $objWriter->writeAttribute('rad', Properties::pointsToXml((float) $softEdgeSize)); $objWriter->endElement(); //end softEdge } + + /** + * Write Line Style for Gridlines. + * + * @param Axis|GridLines $gridlines + */ + private function writeGridlinesLn(XMLWriter $objWriter, $gridlines): void + { + $objWriter->startElement('a:ln'); + $widthTemp = $gridlines->getLineStyleProperty('width'); + if (is_numeric($widthTemp)) { + $objWriter->writeAttribute('w', Properties::pointsToXml((float) $widthTemp)); + } + $this->writeNotEmpty($objWriter, 'cap', $gridlines->getLineStyleProperty('cap')); + $this->writeNotEmpty($objWriter, 'cmpd', $gridlines->getLineStyleProperty('compound')); + if (!empty($gridlines->getLineColorProperty('value'))) { + $objWriter->startElement('a:solidFill'); + $objWriter->startElement("a:{$gridlines->getLineColorProperty('type')}"); + $objWriter->writeAttribute('val', (string) $gridlines->getLineColorProperty('value')); + $alpha = $gridlines->getLineColorProperty('alpha'); + if (is_numeric($alpha)) { + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha)); + $objWriter->endElement(); // alpha + } + $objWriter->endElement(); //end srgbClr + $objWriter->endElement(); //end solidFill + } + + $dash = $gridlines->getLineStyleProperty('dash'); + if (!empty($dash)) { + $objWriter->startElement('a:prstDash'); + $this->writeNotEmpty($objWriter, 'val', $dash); + $objWriter->endElement(); + } + + if ($gridlines->getLineStyleProperty('join') === 'miter') { + $objWriter->startElement('a:miter'); + $objWriter->writeAttribute('lim', '800000'); + $objWriter->endElement(); + } elseif ($gridlines->getLineStyleProperty('join') === 'bevel') { + $objWriter->startElement('a:bevel'); + $objWriter->endElement(); + } + + if ($gridlines->getLineStyleProperty(['arrow', 'head', 'type'])) { + $objWriter->startElement('a:headEnd'); + $objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'head', 'type'])); + $this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('head', 'w')); + $this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('head', 'len')); + $objWriter->endElement(); + } + + if ($gridlines->getLineStyleProperty(['arrow', 'end', 'type'])) { + $objWriter->startElement('a:tailEnd'); + $objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'end', 'type'])); + $this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('end', 'w')); + $this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('end', 'len')); + $objWriter->endElement(); + } + $objWriter->endElement(); //end ln + } + + private function writeNotEmpty(XMLWriter $objWriter, string $name, ?string $value): void + { + if ($value !== null && $value !== '') { + $objWriter->writeAttribute($name, $value); + } + } } diff --git a/tests/PhpSpreadsheetTests/Chart/AxisPropertiesTest.php b/tests/PhpSpreadsheetTests/Chart/AxisPropertiesTest.php new file mode 100644 index 00000000..91df25cb --- /dev/null +++ b/tests/PhpSpreadsheetTests/Chart/AxisPropertiesTest.php @@ -0,0 +1,226 @@ +setIncludeCharts(true); + } + + public function writeCharts(XlsxWriter $writer): void + { + $writer->setIncludeCharts(true); + } + + public function testAxisProperties(): 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_LINECHART, // 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)'); + $xAxis = new Axis(); + $xAxis->setFillParameters('FF0000', null, 'srgbClr'); + self::assertSame('FF0000', $xAxis->getFillProperty('value')); + self::assertSame('', $xAxis->getFillProperty('alpha')); + self::assertSame('srgbClr', $xAxis->getFillProperty('type')); + + $xAxis->setAxisOptionsProperties( + Properties::AXIS_LABELS_HIGH, // axisLabels, + null, // $horizontalCrossesValue, + Properties::HORIZONTAL_CROSSES_MAXIMUM, //horizontalCrosses + Properties::ORIENTATION_REVERSED, //axisOrientation + Properties::TICK_MARK_INSIDE, //majorTmt + Properties::TICK_MARK_OUTSIDE, //minorTmt + '8', //minimum + '68', //maximum + '20', //majorUnit + '5' //minorUnit + ); + self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis->getAxisOptionsProperty('axis_labels')); + self::assertNull($xAxis->getAxisOptionsProperty('horizontal_crosses_value')); + self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis->getAxisOptionsProperty('horizontal_crosses')); + self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis->getAxisOptionsProperty('orientation')); + self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis->getAxisOptionsProperty('major_tick_mark')); + self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis->getAxisOptionsProperty('minor_tick_mark')); + self::assertSame('8', $xAxis->getAxisOptionsProperty('minimum')); + self::assertSame('68', $xAxis->getAxisOptionsProperty('maximum')); + self::assertSame('20', $xAxis->getAxisOptionsProperty('major_unit')); + self::assertSame('5', $xAxis->getAxisOptionsProperty('minor_unit')); + + $yAxis = new Axis(); + $yAxis->setFillParameters('accent1', 30, 'schemeClr'); + self::assertSame('accent1', $yAxis->getFillProperty('value')); + self::assertSame('30', $yAxis->getFillProperty('alpha')); + self::assertSame('schemeClr', $yAxis->getFillProperty('type')); + + // 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 + $xAxis, // xAxis + $yAxis, // yAxis + null, //majorGridlines, + null // minorGridlines + ); + $xAxis2 = $chart->getChartAxisX(); + self::assertSame('FF0000', $xAxis2->getFillProperty('value')); + self::assertSame('', $xAxis2->getFillProperty('alpha')); + self::assertSame('srgbClr', $xAxis2->getFillProperty('type')); + + self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis2->getAxisOptionsProperty('axis_labels')); + self::assertNull($xAxis2->getAxisOptionsProperty('horizontal_crosses_value')); + self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis2->getAxisOptionsProperty('horizontal_crosses')); + self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis2->getAxisOptionsProperty('orientation')); + self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis2->getAxisOptionsProperty('major_tick_mark')); + self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis2->getAxisOptionsProperty('minor_tick_mark')); + self::assertSame('8', $xAxis2->getAxisOptionsProperty('minimum')); + self::assertSame('68', $xAxis2->getAxisOptionsProperty('maximum')); + self::assertSame('20', $xAxis2->getAxisOptionsProperty('major_unit')); + self::assertSame('5', $xAxis2->getAxisOptionsProperty('minor_unit')); + + $yAxis2 = $chart->getChartAxisY(); + self::assertSame('accent1', $yAxis2->getFillProperty('value')); + self::assertSame('30', $yAxis2->getFillProperty('alpha')); + self::assertSame('schemeClr', $yAxis2->getFillProperty('type')); + + // 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); + $xAxis3 = $chart2->getChartAxisX(); + self::assertSame('FF0000', $xAxis3->getFillProperty('value')); + self::assertSame('', $xAxis3->getFillProperty('alpha')); + self::assertSame('srgbClr', $xAxis3->getFillProperty('type')); + + self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis3->getAxisOptionsProperty('axis_labels')); + self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis3->getAxisOptionsProperty('major_tick_mark')); + self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis3->getAxisOptionsProperty('minor_tick_mark')); + self::assertNull($xAxis3->getAxisOptionsProperty('horizontal_crosses_value')); + self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis3->getAxisOptionsProperty('horizontal_crosses')); + self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis3->getAxisOptionsProperty('orientation')); + self::assertSame('8', $xAxis3->getAxisOptionsProperty('minimum')); + self::assertSame('68', $xAxis3->getAxisOptionsProperty('maximum')); + self::assertSame('20', $xAxis3->getAxisOptionsProperty('major_unit')); + self::assertSame('5', $xAxis3->getAxisOptionsProperty('minor_unit')); + + $yAxis3 = $chart2->getChartAxisY(); + self::assertSame('accent1', $yAxis3->getFillProperty('value')); + self::assertSame('30', $yAxis3->getFillProperty('alpha')); + self::assertSame('schemeClr', $yAxis3->getFillProperty('type')); + + $xAxis3->setAxisOrientation(Properties::ORIENTATION_NORMAL); + self::assertSame(Properties::ORIENTATION_NORMAL, $xAxis3->getAxisOptionsProperty('orientation')); + $xAxis3->setAxisOptionsProperties( + Properties::AXIS_LABELS_HIGH, // axisLabels, + '5' // $horizontalCrossesValue, + ); + self::assertSame('5', $xAxis3->getAxisOptionsProperty('horizontal_crosses_value')); + + $yAxis3->setLineColorProperties('0000FF', null, 'srgbClr'); + self::assertSame('0000FF', $yAxis3->getLineProperty('value')); + self::assertNull($yAxis3->getLineProperty('alpha')); + self::assertSame('srgbClr', $yAxis3->getLineProperty('type')); + $yAxis3->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL); + self::assertFalse($yAxis3->getAxisIsNumericFormat()); + $yAxis3->setAxisNumberProperties(Properties::FORMAT_CODE_NUMBER); + self::assertTrue($yAxis3->getAxisIsNumericFormat()); + + $reloadedSpreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/PhpSpreadsheetTests/Chart/GridlinesLineStyleTest.php b/tests/PhpSpreadsheetTests/Chart/GridlinesLineStyleTest.php new file mode 100644 index 00000000..997413c5 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Chart/GridlinesLineStyleTest.php @@ -0,0 +1,215 @@ +setIncludeCharts(true); + } + + public function writeCharts(XlsxWriter $writer): void + { + $writer->setIncludeCharts(true); + } + + public function testLineStyles(): 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_LINECHART, // 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)'); + $majorGridlines = new GridLines(); + $width = 2; + $compound = Properties::LINE_STYLE_COMPOUND_THICKTHIN; + $dash = Properties::LINE_STYLE_DASH_ROUND_DOT; + $cap = Properties::LINE_STYLE_CAP_ROUND; + $join = Properties::LINE_STYLE_JOIN_MITER; + $headArrowType = Properties::LINE_STYLE_ARROW_TYPE_DIAMOND; + $headArrowSize = (string) Properties::LINE_STYLE_ARROW_SIZE_2; + $endArrowType = Properties::LINE_STYLE_ARROW_TYPE_OVAL; + $endArrowSize = (string) Properties::LINE_STYLE_ARROW_SIZE_3; + $majorGridlines->setLineStyleProperties( + $width, + $compound, + $dash, + $cap, + $join, + $headArrowType, + $headArrowSize, + $endArrowType, + $endArrowSize + ); + $minorGridlines = new GridLines(); + $minorGridlines->setLineColorProperties('00FF00', 30, 'srgbClr'); + + self::assertEquals($width, $majorGridlines->getLineStyleProperty('width')); + self::assertEquals($compound, $majorGridlines->getLineStyleProperty('compound')); + self::assertEquals($dash, $majorGridlines->getLineStyleProperty('dash')); + self::assertEquals($cap, $majorGridlines->getLineStyleProperty('cap')); + self::assertEquals($join, $majorGridlines->getLineStyleProperty('join')); + self::assertEquals($headArrowType, $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type'])); + self::assertEquals($headArrowSize, $majorGridlines->getLineStyleProperty(['arrow', 'head', 'size'])); + self::assertEquals($endArrowType, $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type'])); + self::assertEquals($endArrowSize, $majorGridlines->getLineStyleProperty(['arrow', 'end', 'size'])); + self::assertEquals('sm', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'w'])); + self::assertEquals('med', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'len'])); + self::assertEquals('sm', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'w'])); + self::assertEquals('lg', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'len'])); + self::assertEquals('sm', $majorGridlines->getLineStyleArrowWidth('end')); + self::assertEquals('lg', $majorGridlines->getLineStyleArrowLength('end')); + self::assertEquals('lg', $majorGridlines->getLineStyleArrowParameters('end', 'len')); + + self::assertSame('00FF00', $minorGridlines->getLineColorProperty('value')); + self::assertSame(30, $minorGridlines->getLineColorProperty('alpha')); + self::assertSame('srgbClr', $minorGridlines->getLineColorProperty('type')); + + // 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 + null, // xAxis + null, // yAxis + $majorGridlines, + $minorGridlines // minorGridlines + ); + $majorGridlines2 = $chart->getMajorGridlines(); + self::assertEquals($width, $majorGridlines2->getLineStyleProperty('width')); + self::assertEquals($compound, $majorGridlines2->getLineStyleProperty('compound')); + self::assertEquals($dash, $majorGridlines2->getLineStyleProperty('dash')); + self::assertEquals($cap, $majorGridlines2->getLineStyleProperty('cap')); + self::assertEquals($join, $majorGridlines2->getLineStyleProperty('join')); + self::assertEquals($headArrowType, $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'type'])); + self::assertEquals($headArrowSize, $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'size'])); + self::assertEquals($endArrowType, $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'type'])); + self::assertEquals($endArrowSize, $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'size'])); + self::assertEquals('sm', $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'w'])); + self::assertEquals('med', $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'len'])); + self::assertEquals('sm', $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'w'])); + self::assertEquals('lg', $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'len'])); + + $minorGridlines2 = $chart->getMinorGridlines(); + self::assertSame('00FF00', $minorGridlines2->getLineColorProperty('value')); + self::assertSame(30, $minorGridlines2->getLineColorProperty('alpha')); + self::assertSame('srgbClr', $minorGridlines2->getLineColorProperty('type')); + + // 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); + $majorGridlines3 = $chart2->getMajorGridlines(); + self::assertEquals($width, $majorGridlines3->getLineStyleProperty('width')); + self::assertEquals($compound, $majorGridlines3->getLineStyleProperty('compound')); + self::assertEquals($dash, $majorGridlines3->getLineStyleProperty('dash')); + self::assertEquals($cap, $majorGridlines3->getLineStyleProperty('cap')); + self::assertEquals($join, $majorGridlines3->getLineStyleProperty('join')); + self::assertEquals($headArrowType, $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'type'])); + self::assertEquals($endArrowType, $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'type'])); + self::assertEquals('sm', $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'w'])); + self::assertEquals('med', $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'len'])); + self::assertEquals('sm', $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'w'])); + self::assertEquals('lg', $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'len'])); + + $minorGridlines3 = $chart2->getMinorGridlines(); + self::assertSame('00FF00', $minorGridlines3->getLineColorProperty('value')); + self::assertSame(30, $minorGridlines3->getLineColorProperty('alpha')); + self::assertSame('srgbClr', $minorGridlines3->getLineColorProperty('type')); + + $reloadedSpreadsheet->disconnectWorksheets(); + } +}