diff --git a/samples/ConditionalFormatting/cond08_colorscale.php b/samples/ConditionalFormatting/cond08_colorscale.php new file mode 100644 index 000000000..d63145970 --- /dev/null +++ b/samples/ConditionalFormatting/cond08_colorscale.php @@ -0,0 +1,64 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); +$sheet = $spreadsheet->getActiveSheet(); + +// Set document properties +$helper->log('Set document properties'); +$spreadsheet->getProperties()->setCreator('Owen Leibman') + ->setLastModifiedBy('Owen Leibman') + ->setTitle('PhpSpreadsheet Test Document') + ->setSubject('PhpSpreadsheet Test Document') + ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') + ->setKeywords('office PhpSpreadsheet php') + ->setCategory('Test result file'); + +// Create the worksheet +$helper->log('Add data'); +$sheet + ->setCellValue('A1', 1) + ->setCellValue('A2', 2) + ->setCellValue('A3', 8) + ->setCellValue('A4', 4) + ->setCellValue('A5', 5) + ->setCellValue('A6', 6) + ->setCellValue('A7', 7) + ->setCellValue('A8', 3) + ->setCellValue('A9', 9) + ->setCellValue('A10', 10); + +// Set conditional formatting rules and styles +$helper->log('Define conditional formatting using Color Scales'); + +$cellRange = 'A1:A10'; +$condition1 = new Conditional(); +$condition1->setConditionType(Conditional::CONDITION_COLORSCALE); +$colorScale = new ConditionalColorScale(); +$condition1->setColorScale($colorScale); +$colorScale + ->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('min')) + ->setMidpointConditionalFormatValueObject(new ConditionalFormatValueObject('percentile', '40')) + ->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max')) + ->setMinimumColor(new Color('FFF8696B')) + ->setMidpointColor(new Color('FFFFEB84')) + ->setMaximumColor(new Color('FF63BE7B')); + +$conditionalStyles = [$condition1]; + +$sheet + ->getStyle($cellRange) + ->setConditionalStyles($conditionalStyles); +$sheet->setSelectedCells('B1'); + +// Save +$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 57d1c1c40..fad37d7f1 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -790,10 +790,10 @@ class Xlsx extends BaseReader // Setting Conditional Styles adjusts selected cells, so we need to execute this // before reading the sheet view data to get the actual selected cells if (!$this->readDataOnly && ($xmlSheet->conditionalFormatting)) { - (new ConditionalStyles($docSheet, $xmlSheet, $dxfs))->load(); + (new ConditionalStyles($docSheet, $xmlSheet, $dxfs, $this->styleReader))->load(); } if (!$this->readDataOnly && $xmlSheet->extLst) { - (new ConditionalStyles($docSheet, $xmlSheet, $dxfs))->loadFromExt($this->styleReader); + (new ConditionalStyles($docSheet, $xmlSheet, $dxfs, $this->styleReader))->loadFromExt(); } if (isset($xmlSheetMain->sheetViews, $xmlSheetMain->sheetViews->sheetView)) { $sheetViews = new SheetViews($xmlSheetMain->sheetViews->sheetView, $docSheet); diff --git a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index 27025c1b1..280c75eb0 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -3,7 +3,9 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles as StyleReader; +use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Style\Conditional; +use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalColorScale; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormatValueObject; @@ -25,11 +27,14 @@ class ConditionalStyles private array $dxfs; - public function __construct(Worksheet $workSheet, SimpleXMLElement $worksheetXml, array $dxfs = []) + private StyleReader $styleReader; + + public function __construct(Worksheet $workSheet, SimpleXMLElement $worksheetXml, array $dxfs, StyleReader $styleReader) { $this->worksheet = $workSheet; $this->worksheetXml = $worksheetXml; $this->dxfs = $dxfs; + $this->styleReader = $styleReader; } public function load(): void @@ -45,13 +50,13 @@ class ConditionalStyles $this->worksheet->setSelectedCells($selectedCells); } - public function loadFromExt(StyleReader $styleReader): void + public function loadFromExt(): void { $selectedCells = $this->worksheet->getSelectedCells(); $this->ns = $this->worksheetXml->getNamespaces(true); $this->setConditionalsFromExt( - $this->readConditionalsFromExt($this->worksheetXml->extLst, $styleReader) + $this->readConditionalsFromExt($this->worksheetXml->extLst) ); $this->worksheet->setSelectedCells($selectedCells); @@ -68,7 +73,7 @@ class ConditionalStyles } } - private function readConditionalsFromExt(SimpleXMLElement $extLst, StyleReader $styleReader): array + private function readConditionalsFromExt(SimpleXMLElement $extLst): array { $conditionals = []; if (!isset($extLst->ext)) { @@ -110,7 +115,7 @@ class ConditionalStyles $priority = (int) $attributes->priority; $conditional = $this->readConditionalRuleFromExt($extCfRuleXml, $attributes); - $cfStyle = $this->readStyleFromExt($extCfRuleXml, $styleReader); + $cfStyle = $this->readStyleFromExt($extCfRuleXml); $conditional->setStyle($cfStyle); $conditionals[$sqref][$priority] = $conditional; } @@ -146,17 +151,17 @@ class ConditionalStyles return $conditional; } - private function readStyleFromExt(SimpleXMLElement $extCfRuleXml, StyleReader $styleReader): Style + private function readStyleFromExt(SimpleXMLElement $extCfRuleXml): Style { $cfStyle = new Style(false, true); if ($extCfRuleXml->dxf) { $styleXML = $extCfRuleXml->dxf->children(); if ($styleXML->borders) { - $styleReader->readBorderStyle($cfStyle->getBorders(), $styleXML->borders); + $this->styleReader->readBorderStyle($cfStyle->getBorders(), $styleXML->borders); } if ($styleXML->fill) { - $styleReader->readFillStyle($cfStyle->getFill(), $styleXML->fill); + $this->styleReader->readFillStyle($cfStyle->getFill(), $styleXML->fill); } } @@ -198,6 +203,7 @@ class ConditionalStyles $conditionalFormattingRuleExtensions = ConditionalFormattingRuleExtension::parseExtLstXml($extLst); $conditionalStyles = []; + /** @var SimpleXMLElement $cfRule */ foreach ($cfRules as $cfRule) { $objConditional = new Conditional(); $objConditional->setConditionType((string) $cfRule['type']); @@ -231,7 +237,11 @@ class ConditionalStyles if (isset($cfRule->dataBar)) { $objConditional->setDataBar( - $this->readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions) // @phpstan-ignore-line + $this->readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions) + ); + } elseif (isset($cfRule->colorScale)) { + $objConditional->setColorScale( + $this->readColorScale($cfRule) ); } elseif (isset($cfRule['dxfId'])) { $objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]); @@ -270,7 +280,7 @@ class ConditionalStyles //color if (isset($cfRule->dataBar->color)) { - $dataBar->setColor((string) $cfRule->dataBar->color['rgb']); + $dataBar->setColor($this->styleReader->readColor($cfRule->dataBar->color)); } //extLst $this->readDataBarExtLstOfConditionalRule($dataBar, $cfRule, $conditionalFormattingRuleExtensions); @@ -278,6 +288,40 @@ class ConditionalStyles return $dataBar; } + private function readColorScale(simpleXMLElement|stdClass $cfRule): ConditionalColorScale + { + $colorScale = new ConditionalColorScale(); + $types = []; + foreach ($cfRule->colorScale->cfvo as $cfvoXml) { + $attr = $cfvoXml->attributes() ?? []; + $type = (string) ($attr['type'] ?? ''); + $types[] = $type; + $val = $attr['val'] ?? null; + if ($type === 'min') { + $colorScale->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val)); + } elseif ($type === 'percentile') { + $colorScale->setMidpointConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val)); + } elseif ($type === 'max') { + $colorScale->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val)); + } + } + $idx = 0; + foreach ($cfRule->colorScale->color as $color) { + $type = $types[$idx]; + $rgb = $this->styleReader->readColor($color); + if ($type === 'min') { + $colorScale->setMinimumColor(new Color($rgb)); + } elseif ($type === 'percentile') { + $colorScale->setMidpointColor(new Color($rgb)); + } elseif ($type === 'max') { + $colorScale->setMaximumColor(new Color($rgb)); + } + ++$idx; + } + + return $colorScale; + } + /** * @param SimpleXMLElement|stdClass $cfRule */ diff --git a/src/PhpSpreadsheet/Style/Conditional.php b/src/PhpSpreadsheet/Style/Conditional.php index 58d61ce87..9f6e8c7dc 100644 --- a/src/PhpSpreadsheet/Style/Conditional.php +++ b/src/PhpSpreadsheet/Style/Conditional.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Style; use PhpOffice\PhpSpreadsheet\IComparable; +use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalColorScale; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar; class Conditional implements IComparable @@ -11,6 +12,7 @@ class Conditional implements IComparable const CONDITION_NONE = 'none'; const CONDITION_BEGINSWITH = 'beginsWith'; const CONDITION_CELLIS = 'cellIs'; + const CONDITION_COLORSCALE = 'colorScale'; const CONDITION_CONTAINSBLANKS = 'containsBlanks'; const CONDITION_CONTAINSERRORS = 'containsErrors'; const CONDITION_CONTAINSTEXT = 'containsText'; @@ -27,6 +29,7 @@ class Conditional implements IComparable private const CONDITION_TYPES = [ self::CONDITION_BEGINSWITH, self::CONDITION_CELLIS, + self::CONDITION_COLORSCALE, self::CONDITION_CONTAINSBLANKS, self::CONDITION_CONTAINSERRORS, self::CONDITION_CONTAINSTEXT, @@ -91,10 +94,8 @@ class Conditional implements IComparable /** * Stop on this condition, if it matches. - * - * @var bool */ - private $stopIfTrue = false; + private bool $stopIfTrue = false; /** * Condition. @@ -103,18 +104,13 @@ class Conditional implements IComparable */ private $condition = []; - /** - * @var ConditionalDataBar - */ - private $dataBar; + private ?ConditionalDataBar $dataBar = null; + + private ?ConditionalColorScale $colorScale = null; - /** - * Style. - */ private Style $style; - /** @var bool */ - private $noFormatSet = false; + private bool $noFormatSet = false; /** * Create a new Conditional. @@ -296,21 +292,11 @@ class Conditional implements IComparable return $this; } - /** - * get DataBar. - * - * @return null|ConditionalDataBar - */ - public function getDataBar() + public function getDataBar(): ?ConditionalDataBar { return $this->dataBar; } - /** - * set DataBar. - * - * @return $this - */ public function setDataBar(ConditionalDataBar $dataBar): static { $this->dataBar = $dataBar; @@ -318,6 +304,18 @@ class Conditional implements IComparable return $this; } + public function getColorScale(): ?ConditionalColorScale + { + return $this->colorScale; + } + + public function setColorScale(ConditionalColorScale $colorScale): static + { + $this->colorScale = $colorScale; + + return $this; + } + /** * Get hash code. * diff --git a/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalColorScale.php b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalColorScale.php new file mode 100644 index 000000000..7fcc08038 --- /dev/null +++ b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalColorScale.php @@ -0,0 +1,92 @@ +minimumConditionalFormatValueObject; + } + + public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject): self + { + $this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject; + + return $this; + } + + public function getMidpointConditionalFormatValueObject(): ?ConditionalFormatValueObject + { + return $this->midpointConditionalFormatValueObject; + } + + public function setMidpointConditionalFormatValueObject(ConditionalFormatValueObject $midpointConditionalFormatValueObject): self + { + $this->midpointConditionalFormatValueObject = $midpointConditionalFormatValueObject; + + return $this; + } + + public function getMaximumConditionalFormatValueObject(): ?ConditionalFormatValueObject + { + return $this->maximumConditionalFormatValueObject; + } + + public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject): self + { + $this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject; + + return $this; + } + + public function getMinimumColor(): ?Color + { + return $this->minimumColor; + } + + public function setMinimumColor(Color $minimumColor): self + { + $this->minimumColor = $minimumColor; + + return $this; + } + + public function getMidpointColor(): ?Color + { + return $this->midpointColor; + } + + public function setMidpointColor(Color $midpointColor): self + { + $this->midpointColor = $midpointColor; + + return $this; + } + + public function getMaximumColor(): ?Color + { + return $this->maximumColor; + } + + public function setMaximumColor(Color $maximumColor): self + { + $this->maximumColor = $maximumColor; + + return $this; + } +} diff --git a/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php index c07c753b8..370f10254 100644 --- a/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php +++ b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php @@ -4,10 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting; class ConditionalDataBar { - /** attribute */ - - /** @var null|bool */ - private $showValue; + private ?bool $showValue = null; private ?ConditionalFormatValueObject $minimumConditionalFormatValueObject = null; @@ -17,18 +14,12 @@ class ConditionalDataBar private ?ConditionalFormattingRuleExtension $conditionalFormattingRuleExt = null; - /** - * @return null|bool - */ - public function getShowValue() + public function getShowValue(): ?bool { return $this->showValue; } - /** - * @param bool $showValue - */ - public function setShowValue($showValue): self + public function setShowValue(bool $showValue): self { $this->showValue = $showValue; diff --git a/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php index d2149d96d..43f480804 100644 --- a/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php +++ b/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php @@ -4,61 +4,44 @@ namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting; class ConditionalFormatValueObject { - /** @var mixed */ - private $type; + private string $type; - /** @var mixed */ - private $value; + private null|float|int|string $value; - /** @var mixed */ - private $cellFormula; + private mixed $cellFormula; - /** - * ConditionalFormatValueObject constructor. - * - * @param null|mixed $cellFormula - */ - public function __construct(mixed $type, mixed $value = null, $cellFormula = null) + public function __construct(string $type, null|float|int|string $value = null, mixed $cellFormula = null) { $this->type = $type; $this->value = $value; $this->cellFormula = $cellFormula; } - /** - * @return mixed - */ - public function getType() + public function getType(): string { return $this->type; } - public function setType(mixed $type): self + public function setType(string $type): self { $this->type = $type; return $this; } - /** - * @return mixed - */ - public function getValue() + public function getValue(): null|float|int|string { return $this->value; } - public function setValue(mixed $value): self + public function setValue(null|float|int|string $value): self { $this->value = $value; return $this; } - /** - * @return mixed - */ - public function getCellFormula() + public function getCellFormula(): mixed { return $this->cellFormula; } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 6c01911c4..7efaaf939 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -11,6 +11,7 @@ use PhpOffice\PhpSpreadsheet\Settings; use PhpOffice\PhpSpreadsheet\Shared\StringHelper; use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; use PhpOffice\PhpSpreadsheet\Style\Conditional; +use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalColorScale; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension; use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension; @@ -685,15 +686,15 @@ class Worksheet extends WriterPart $minCfvo = $dataBar->getMinimumConditionalFormatValueObject(); if ($minCfvo) { $objWriter->startElement('cfvo'); - self::writeAttributeIf($objWriter, $minCfvo->getType(), 'type', (string) $minCfvo->getType()); - self::writeAttributeIf($objWriter, $minCfvo->getValue(), 'val', (string) $minCfvo->getValue()); + $objWriter->writeAttribute('type', $minCfvo->getType()); + self::writeAttributeIf($objWriter, $minCfvo->getValue() !== null, 'val', (string) $minCfvo->getValue()); $objWriter->endElement(); } $maxCfvo = $dataBar->getMaximumConditionalFormatValueObject(); if ($maxCfvo) { $objWriter->startElement('cfvo'); - self::writeAttributeIf($objWriter, $maxCfvo->getType(), 'type', (string) $maxCfvo->getType()); - self::writeAttributeIf($objWriter, $maxCfvo->getValue(), 'val', (string) $maxCfvo->getValue()); + $objWriter->writeAttribute('type', $maxCfvo->getType()); + self::writeAttributeIf($objWriter, $maxCfvo->getValue() !== null, 'val', (string) $maxCfvo->getValue()); $objWriter->endElement(); } if ($dataBar->getColor()) { @@ -717,6 +718,57 @@ class Worksheet extends WriterPart } } + private static function writeColorScaleElements(XMLWriter $objWriter, ?ConditionalColorScale $colorScale): void + { + if ($colorScale) { + $objWriter->startElement('colorScale'); + + $minCfvo = $colorScale->getMinimumConditionalFormatValueObject(); + $minArgb = $colorScale->getMinimumColor()?->getARGB(); + $useMin = $minCfvo !== null || $minArgb !== null; + if ($useMin) { + $objWriter->startElement('cfvo'); + $objWriter->writeAttribute('type', $minCfvo?->getType() ?? 'min'); + self::writeAttributeIf($objWriter, $minCfvo?->getValue() !== null, 'val', (string) $minCfvo?->getValue()); + $objWriter->endElement(); + } + $midCfvo = $colorScale->getMidpointConditionalFormatValueObject(); + $midArgb = $colorScale->getMidpointColor()?->getARGB(); + $useMid = $midCfvo !== null || $midArgb !== null; + if ($useMid) { + $objWriter->startElement('cfvo'); + $objWriter->writeAttribute('type', $midCfvo?->getType() ?? 'percentile'); + $objWriter->writeAttribute('val', (string) (($midCfvo?->getValue()) ?? '50')); + $objWriter->endElement(); + } + $maxCfvo = $colorScale->getMaximumConditionalFormatValueObject(); + $maxArgb = $colorScale->getMaximumColor()?->getARGB(); + $useMax = $maxCfvo !== null || $maxArgb !== null; + if ($useMax) { + $objWriter->startElement('cfvo'); + $objWriter->writeAttribute('type', $maxCfvo?->getType() ?? 'max'); + self::writeAttributeIf($objWriter, $maxCfvo?->getValue() !== null, 'val', (string) $maxCfvo?->getValue()); + $objWriter->endElement(); + } + if ($useMin) { + $objWriter->startElement('color'); + self::writeAttributeIf($objWriter, $minArgb !== null, 'rgb', "$minArgb"); + $objWriter->endElement(); + } + if ($useMid) { + $objWriter->startElement('color'); + self::writeAttributeIf($objWriter, $midArgb !== null, 'rgb', "$midArgb"); + $objWriter->endElement(); + } + if ($useMax) { + $objWriter->startElement('color'); + self::writeAttributeIf($objWriter, $maxArgb !== null, 'rgb', "$maxArgb"); + $objWriter->endElement(); + } + $objWriter->endElement(); // end colorScale + } + } + /** * Write ConditionalFormatting. */ @@ -740,7 +792,9 @@ class Worksheet extends WriterPart $objWriter->writeAttribute('type', $conditional->getConditionType()); self::writeAttributeIf( $objWriter, - ($conditional->getConditionType() !== Conditional::CONDITION_DATABAR && $conditional->getNoFormatSet() === false), + ($conditional->getConditionType() !== Conditional::CONDITION_COLORSCALE + && $conditional->getConditionType() !== Conditional::CONDITION_DATABAR + && $conditional->getNoFormatSet() === false), 'dxfId', (string) $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) ); @@ -773,6 +827,8 @@ class Worksheet extends WriterPart self::writeTextCondElements($objWriter, $conditional, $topLeftCell); } elseif ($conditional->getConditionType() === Conditional::CONDITION_TIMEPERIOD) { self::writeTimePeriodCondElements($objWriter, $conditional, $topLeftCell); + } elseif ($conditional->getConditionType() === Conditional::CONDITION_COLORSCALE) { + self::writeColorScaleElements($objWriter, $conditional->getColorScale()); } else { self::writeOtherCondElements($objWriter, $conditional, $topLeftCell); } diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalColorScaleTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalColorScaleTest.php new file mode 100644 index 000000000..6296f8e97 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalColorScaleTest.php @@ -0,0 +1,33 @@ +load($filename); + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx'); + $spreadsheet->disconnectWorksheets(); + $worksheet = $reloadedSpreadsheet->getActiveSheet(); + $styles = $worksheet->getConditionalStyles('A1:A10'); + self::assertCount(1, $styles); + $colorScale = $styles[0]->getColorScale(); + self::assertNotNull($colorScale); + self::assertNotNull($colorScale->getMinimumConditionalFormatValueObject()); + self::assertNotNull($colorScale->getMidpointConditionalFormatValueObject()); + self::assertSame('50', $colorScale->getMidpointConditionalFormatValueObject()->getValue()); + self::assertNotNull($colorScale->getMaximumConditionalFormatValueObject()); + self::assertSame('FFF8696B', $colorScale->getMinimumColor()?->getARGB()); + self::assertSame('FFFFEB84', $colorScale->getMidpointColor()?->getARGB()); + self::assertSame('FF63BE7B', $colorScale->getMaximumColor()?->getARGB()); + $reloadedSpreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/data/Reader/XLSX/colorscale.xlsx b/tests/data/Reader/XLSX/colorscale.xlsx new file mode 100644 index 000000000..35652544c Binary files /dev/null and b/tests/data/Reader/XLSX/colorscale.xlsx differ