Conditional Color Scale Improvements

Fix #4049. Some possible options were not included for read or write. In addition, although it isn't well documented, it appears that 2-color scale always has 2 cvfo entries in Xml in order minimum/maximum, and 3-color scale always has 3 entries in order minimum/midpoint/maximum.
This commit is contained in:
oleibman
2024-05-30 00:19:11 -07:00
parent 2ed696f0a2
commit 2760e5abb7
4 changed files with 106 additions and 18 deletions
@@ -285,29 +285,34 @@ class ConditionalStyles
private function readColorScale(SimpleXMLElement|stdClass $cfRule): ConditionalColorScale
{
$colorScale = new ConditionalColorScale();
$types = [];
$count = count($cfRule->colorScale->cfvo);
$idx = 0;
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));
if ($idx === 0) {
$method = 'setMinimumConditionalFormatValueObject';
} elseif ($idx === 1 && $count === 3) {
$method = 'setMidpointConditionalFormatValueObject';
} else {
$method = 'setMaximumConditionalFormatValueObject';
}
if ($type !== 'formula') {
$colorScale->$method(new ConditionalFormatValueObject($type, $val));
} else {
$colorScale->$method(new ConditionalFormatValueObject($type, null, $val));
}
++$idx;
}
$idx = 0;
foreach ($cfRule->colorScale->color as $color) {
$type = $types[$idx];
$rgb = $this->styleReader->readColor($color);
if ($type === 'min') {
if ($idx === 0) {
$colorScale->setMinimumColor(new Color($rgb));
} elseif ($type === 'percentile') {
} elseif ($idx === 1 && $count === 3) {
$colorScale->setMidpointColor(new Color($rgb));
} elseif ($type === 'max') {
} else {
$colorScale->setMaximumColor(new Color($rgb));
}
++$idx;
+51 -6
View File
@@ -763,8 +763,23 @@ class Worksheet extends WriterPart
$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());
$type = 'min';
$value = null;
if ($minCfvo !== null) {
$typex = $minCfvo->getType();
if ($typex === 'formula') {
$value = $minCfvo->getCellFormula();
if ($value !== null) {
$type = $typex;
}
} else {
$type = $typex;
$defaults = ['number' => '0', 'percent' => '0', 'percentile' => '10'];
$value = $minCfvo->getValue() ?? $defaults[$type] ?? null;
}
}
$objWriter->writeAttribute('type', $type);
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
$objWriter->endElement();
}
$midCfvo = $colorScale->getMidpointConditionalFormatValueObject();
@@ -772,8 +787,23 @@ class Worksheet extends WriterPart
$useMid = $midCfvo !== null || $midArgb !== null;
if ($useMid) {
$objWriter->startElement('cfvo');
$objWriter->writeAttribute('type', $midCfvo?->getType() ?? 'percentile');
$objWriter->writeAttribute('val', (string) (($midCfvo?->getValue()) ?? '50'));
$type = 'percentile';
$value = '50';
if ($midCfvo !== null) {
$type = $midCfvo->getType();
if ($type === 'formula') {
$value = $midCfvo->getCellFormula();
if ($value === null) {
$type = 'percentile';
$value = '50';
}
} else {
$defaults = ['number' => '0', 'percent' => '50', 'percentile' => '50'];
$value = $midCfvo->getValue() ?? $defaults[$type] ?? null;
}
}
$objWriter->writeAttribute('type', $type);
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
$objWriter->endElement();
}
$maxCfvo = $colorScale->getMaximumConditionalFormatValueObject();
@@ -781,8 +811,23 @@ class Worksheet extends WriterPart
$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());
$type = 'max';
$value = null;
if ($maxCfvo !== null) {
$typex = $maxCfvo->getType();
if ($typex === 'formula') {
$value = $maxCfvo->getCellFormula();
if ($value !== null) {
$type = $typex;
}
} else {
$type = $typex;
$defaults = ['number' => '0', 'percent' => '100', 'percentile' => '90'];
$value = $maxCfvo->getValue() ?? $defaults[$type] ?? null;
}
}
$objWriter->writeAttribute('type', $type);
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
$objWriter->endElement();
}
if ($useMin) {
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PHPUnit\Framework\TestCase;
class Issue4049Test extends TestCase
{
public static function testPr1869(): void
{
$xlsxFile = 'tests/data/Reader/XLSX/issue.4049.xlsx';
$reader = new Xlsx();
$spreadsheet = $reader->load($xlsxFile);
$sheet = $spreadsheet->getActiveSheet();
$conditionals = $sheet->getConditionalStylesCollection();
self::assertCount(1, $conditionals);
self::assertSame('E9:E14', array_keys($conditionals)[0]);
$cond1 = $conditionals['E9:E14'];
self::assertCount(1, $cond1);
self::assertSame('colorScale', $cond1[0]->getConditionType());
$colorScale = $cond1[0]->getColorScale();
self::assertNotNull($colorScale);
$min = $colorScale->getMinimumConditionalFormatValueObject();
self::assertSame('formula', $min->getType());
self::assertSame('25', $min->getCellFormula());
self::assertNull($colorScale->getMidpointConditionalFormatValueObject());
$max = $colorScale->getMaximumConditionalFormatValueObject();
self::assertSame('max', $max->getType());
self::assertNull($max->getValue());
$spreadsheet->disconnectWorksheets();
}
}
Binary file not shown.