Skip to content

Commit 1852923

Browse files
authored
Merge pull request #4050 from oleibman/issue4049
Conditional Color Scale Improvements
2 parents 626b08f + 15fb1b5 commit 1852923

File tree

5 files changed

+109
-18
lines changed

5 files changed

+109
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2828
- Incorrect Reader CSV with BOM. [Issue #4028](https://github.com/PHPOffice/PhpSpreadsheet/issues/4028) [PR #4029](https://github.com/PHPOffice/PhpSpreadsheet/pull/4029)
2929
- POWER Null/Bool Args. [PR #4031](https://github.com/PHPOffice/PhpSpreadsheet/pull/4031)
3030
- Do Not Output Alignment and Protection for Conditional Format. [Issue #4025](https://github.com/PHPOffice/PhpSpreadsheet/issues/4025) [PR #4027](https://github.com/PHPOffice/PhpSpreadsheet/pull/4027)
31+
- Conditional Color Scale Improvements. [Issue #4049](https://github.com/PHPOffice/PhpSpreadsheet/issues/4049) [PR #4050](https://github.com/PHPOffice/PhpSpreadsheet/pull/4050)
3132
- Mpdf and Tcpdf Borders on Merged Cells. [Issue #3557](https://github.com/PHPOffice/PhpSpreadsheet/issues/3557) [PR #4047](https://github.com/PHPOffice/PhpSpreadsheet/pull/4047)
3233
- Xls Conditional Format Improvements. [PR #4030](https://github.com/PHPOffice/PhpSpreadsheet/pull/4030) [PR #4033](https://github.com/PHPOffice/PhpSpreadsheet/pull/4033)
3334
- Csv Reader allow use of html mimetype. [Issue #4036](https://github.com/PHPOffice/PhpSpreadsheet/issues/4036) [PR #4049](https://github.com/PHPOffice/PhpSpreadsheet/pull/4040)

src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -285,29 +285,34 @@ private function readDataBarOfConditionalRule(SimpleXMLElement $cfRule, array $c
285285
private function readColorScale(SimpleXMLElement|stdClass $cfRule): ConditionalColorScale
286286
{
287287
$colorScale = new ConditionalColorScale();
288-
$types = [];
288+
$count = count($cfRule->colorScale->cfvo);
289+
$idx = 0;
289290
foreach ($cfRule->colorScale->cfvo as $cfvoXml) {
290291
$attr = $cfvoXml->attributes() ?? [];
291292
$type = (string) ($attr['type'] ?? '');
292-
$types[] = $type;
293293
$val = $attr['val'] ?? null;
294-
if ($type === 'min') {
295-
$colorScale->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val));
296-
} elseif ($type === 'percentile') {
297-
$colorScale->setMidpointConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val));
298-
} elseif ($type === 'max') {
299-
$colorScale->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject($type, $val));
294+
if ($idx === 0) {
295+
$method = 'setMinimumConditionalFormatValueObject';
296+
} elseif ($idx === 1 && $count === 3) {
297+
$method = 'setMidpointConditionalFormatValueObject';
298+
} else {
299+
$method = 'setMaximumConditionalFormatValueObject';
300+
}
301+
if ($type !== 'formula') {
302+
$colorScale->$method(new ConditionalFormatValueObject($type, $val));
303+
} else {
304+
$colorScale->$method(new ConditionalFormatValueObject($type, null, $val));
300305
}
306+
++$idx;
301307
}
302308
$idx = 0;
303309
foreach ($cfRule->colorScale->color as $color) {
304-
$type = $types[$idx];
305310
$rgb = $this->styleReader->readColor($color);
306-
if ($type === 'min') {
311+
if ($idx === 0) {
307312
$colorScale->setMinimumColor(new Color($rgb));
308-
} elseif ($type === 'percentile') {
313+
} elseif ($idx === 1 && $count === 3) {
309314
$colorScale->setMidpointColor(new Color($rgb));
310-
} elseif ($type === 'max') {
315+
} else {
311316
$colorScale->setMaximumColor(new Color($rgb));
312317
}
313318
++$idx;

src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -763,26 +763,71 @@ private static function writeColorScaleElements(XMLWriter $objWriter, ?Condition
763763
$useMin = $minCfvo !== null || $minArgb !== null;
764764
if ($useMin) {
765765
$objWriter->startElement('cfvo');
766-
$objWriter->writeAttribute('type', $minCfvo?->getType() ?? 'min');
767-
self::writeAttributeIf($objWriter, $minCfvo?->getValue() !== null, 'val', (string) $minCfvo?->getValue());
766+
$type = 'min';
767+
$value = null;
768+
if ($minCfvo !== null) {
769+
$typex = $minCfvo->getType();
770+
if ($typex === 'formula') {
771+
$value = $minCfvo->getCellFormula();
772+
if ($value !== null) {
773+
$type = $typex;
774+
}
775+
} else {
776+
$type = $typex;
777+
$defaults = ['number' => '0', 'percent' => '0', 'percentile' => '10'];
778+
$value = $minCfvo->getValue() ?? $defaults[$type] ?? null;
779+
}
780+
}
781+
$objWriter->writeAttribute('type', $type);
782+
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
768783
$objWriter->endElement();
769784
}
770785
$midCfvo = $colorScale->getMidpointConditionalFormatValueObject();
771786
$midArgb = $colorScale->getMidpointColor()?->getARGB();
772787
$useMid = $midCfvo !== null || $midArgb !== null;
773788
if ($useMid) {
774789
$objWriter->startElement('cfvo');
775-
$objWriter->writeAttribute('type', $midCfvo?->getType() ?? 'percentile');
776-
$objWriter->writeAttribute('val', (string) (($midCfvo?->getValue()) ?? '50'));
790+
$type = 'percentile';
791+
$value = '50';
792+
if ($midCfvo !== null) {
793+
$type = $midCfvo->getType();
794+
if ($type === 'formula') {
795+
$value = $midCfvo->getCellFormula();
796+
if ($value === null) {
797+
$type = 'percentile';
798+
$value = '50';
799+
}
800+
} else {
801+
$defaults = ['number' => '0', 'percent' => '50', 'percentile' => '50'];
802+
$value = $midCfvo->getValue() ?? $defaults[$type] ?? null;
803+
}
804+
}
805+
$objWriter->writeAttribute('type', $type);
806+
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
777807
$objWriter->endElement();
778808
}
779809
$maxCfvo = $colorScale->getMaximumConditionalFormatValueObject();
780810
$maxArgb = $colorScale->getMaximumColor()?->getARGB();
781811
$useMax = $maxCfvo !== null || $maxArgb !== null;
782812
if ($useMax) {
783813
$objWriter->startElement('cfvo');
784-
$objWriter->writeAttribute('type', $maxCfvo?->getType() ?? 'max');
785-
self::writeAttributeIf($objWriter, $maxCfvo?->getValue() !== null, 'val', (string) $maxCfvo?->getValue());
814+
$type = 'max';
815+
$value = null;
816+
if ($maxCfvo !== null) {
817+
$typex = $maxCfvo->getType();
818+
if ($typex === 'formula') {
819+
$value = $maxCfvo->getCellFormula();
820+
if ($value !== null) {
821+
$type = $typex;
822+
}
823+
} else {
824+
$type = $typex;
825+
$defaults = ['number' => '0', 'percent' => '100', 'percentile' => '90'];
826+
$value = $maxCfvo->getValue() ?? $defaults[$type] ?? null;
827+
}
828+
}
829+
$objWriter->writeAttribute('type', $type);
830+
self::writeAttributeIf($objWriter, $value !== null, 'val', (string) $value);
786831
$objWriter->endElement();
787832
}
788833
if ($useMin) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
8+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
9+
10+
class Issue4049Test extends AbstractFunctional
11+
{
12+
public function testColorScale(): void
13+
{
14+
$xlsxFile = 'tests/data/Reader/XLSX/issue.4049.xlsx';
15+
$reader = new Xlsx();
16+
$oldSpreadsheet = $reader->load($xlsxFile);
17+
$spreadsheet = $this->writeAndReload($oldSpreadsheet, 'Xlsx');
18+
$oldSpreadsheet->disconnectWorksheets();
19+
$sheet = $spreadsheet->getActiveSheet();
20+
$conditionals = $sheet->getConditionalStylesCollection();
21+
self::assertCount(1, $conditionals);
22+
self::assertSame('E9:E14', array_keys($conditionals)[0]);
23+
$cond1 = $conditionals['E9:E14'];
24+
self::assertCount(1, $cond1);
25+
self::assertSame('colorScale', $cond1[0]->getConditionType());
26+
$colorScale = $cond1[0]->getColorScale();
27+
self::assertNotNull($colorScale);
28+
$min = $colorScale->getMinimumConditionalFormatValueObject();
29+
self::assertSame('formula', $min->getType());
30+
self::assertSame('25', $min->getCellFormula());
31+
32+
self::assertNull($colorScale->getMidpointConditionalFormatValueObject());
33+
34+
$max = $colorScale->getMaximumConditionalFormatValueObject();
35+
self::assertSame('max', $max->getType());
36+
self::assertNull($max->getValue());
37+
38+
$spreadsheet->disconnectWorksheets();
39+
}
40+
}
4.66 KB
Binary file not shown.

0 commit comments

Comments
 (0)