From 653adf8e10e3ad36566506f288cef72e9ae3b5d6 Mon Sep 17 00:00:00 2001 From: Steffen Breiler Date: Fri, 15 Dec 2017 14:28:54 +0100 Subject: [PATCH] Adding option to stop at a conditional styling, if it matches This would be used like `$conditonal->setStopIfTrue()` and is only supported for XLSX format for now. Closes #292 --- CHANGELOG.md | 1 + src/PhpSpreadsheet/Reader/Xlsx.php | 4 ++ src/PhpSpreadsheet/Style/Conditional.php | 42 ++++++++--- src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php | 4 ++ .../Functional/ConditionalStopIfTrueTest.php | 72 +++++++++++++++++++ 5 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Functional/ConditionalStopIfTrueTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a9f810e..58890b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Support cell comments in HTML writer and reader- [#308](https://github.com/PHPOffice/PhpSpreadsheet/issues/308) +- Option to stop at a conditional styling, if it matches (only XLSX format) - [#292](https://github.com/PHPOffice/PhpSpreadsheet/pull/292) ### Fixed diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index f5750fd9..41b8f7b5 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -990,6 +990,10 @@ class Xlsx extends BaseReader $objConditional->setText((string) $cfRule['text']); } + if (isset($cfRule['stopIfTrue']) && (int) $cfRule['stopIfTrue'] === 1) { + $objConditional->setStopIfTrue(true); + } + if (count($cfRule->formula) > 1) { foreach ($cfRule->formula as $formula) { $objConditional->addCondition((string) $formula); diff --git a/src/PhpSpreadsheet/Style/Conditional.php b/src/PhpSpreadsheet/Style/Conditional.php index 20333a2e..91a000db 100644 --- a/src/PhpSpreadsheet/Style/Conditional.php +++ b/src/PhpSpreadsheet/Style/Conditional.php @@ -2,7 +2,6 @@ namespace PhpOffice\PhpSpreadsheet\Style; -use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; use PhpOffice\PhpSpreadsheet\IComparable; class Conditional implements IComparable @@ -33,14 +32,14 @@ class Conditional implements IComparable * * @var string */ - private $conditionType; + private $conditionType = self::CONDITION_NONE; /** * Operator type. * * @var string */ - private $operatorType; + private $operatorType = self::OPERATOR_NONE; /** * Text. @@ -49,6 +48,13 @@ class Conditional implements IComparable */ private $text; + /** + * Stop on this condition, if it matches. + * + * @var bool + */ + private $stopIfTrue = false; + /** * Condition. * @@ -69,10 +75,6 @@ class Conditional implements IComparable public function __construct() { // Initialise values - $this->conditionType = self::CONDITION_NONE; - $this->operatorType = self::OPERATOR_NONE; - $this->text = null; - $this->condition = []; $this->style = new Style(false, true); } @@ -148,6 +150,30 @@ class Conditional implements IComparable return $this; } + /** + * Get StopIfTrue. + * + * @return bool + */ + public function getStopIfTrue() + { + return $this->stopIfTrue; + } + + /** + * Set StopIfTrue. + * + * @param bool $value + * + * @return Conditional + */ + public function setStopIfTrue($value) + { + $this->stopIfTrue = $value; + + return $this; + } + /** * Get Conditions. * @@ -204,8 +230,6 @@ class Conditional implements IComparable * * @param Style $pValue * - * @throws PhpSpreadsheetException - * * @return Conditional */ public function setStyle(Style $pValue = null) diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 8dc6af38..3d706879 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -491,6 +491,10 @@ class Worksheet extends WriterPart $objWriter->writeAttribute('text', $conditional->getText()); } + if ($conditional->getStopIfTrue()) { + $objWriter->writeAttribute('stopIfTrue', '1'); + } + if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT && $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT && $conditional->getText() !== null) { diff --git a/tests/PhpSpreadsheetTests/Functional/ConditionalStopIfTrueTest.php b/tests/PhpSpreadsheetTests/Functional/ConditionalStopIfTrueTest.php new file mode 100644 index 00000000..3aa3f949 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Functional/ConditionalStopIfTrueTest.php @@ -0,0 +1,72 @@ + no styling + $condition0 = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); + $condition0->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION); + $condition0->addCondition('LEN(TRIM(A1))=0'); + $condition0->setStopIfTrue(true); // ! stop here + + // if value below 0.6 (matches also blank cells!) -> red background + $condition1 = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); + $condition1->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS); + $condition1->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN); + $condition1->addCondition(0.6); + $condition1->getStyle()->getFill() + ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID) + ->getEndColor()->setARGB(self::COLOR_RED); + + // if value above 0.6 -> green background + $condition2 = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); + $condition2->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS); + $condition2->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHAN); + $condition2->addCondition(0.6); + $condition2->getStyle()->getFill() + ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID) + ->getEndColor()->setARGB(self::COLOR_GREEN); + + $spreadsheet = new Spreadsheet(); + $spreadsheet->getActiveSheet()->getCell('A1')->setValue(0.7); + $spreadsheet->getActiveSheet()->getCell('A2')->setValue(''); + $spreadsheet->getActiveSheet()->getCell('A3')->setValue(0.4); + + // put all three conditions in sheet + $conditionalStyles = []; + array_push($conditionalStyles, $condition0); + array_push($conditionalStyles, $condition1); + array_push($conditionalStyles, $condition2); + $spreadsheet->getActiveSheet()->setConditionalStyles($pCoordinate, $conditionalStyles); + + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format); + + // see if we successfully written "StopIfTrue" + $newConditionalStyles = $reloadedSpreadsheet->getActiveSheet()->getConditionalStyles($pCoordinate); + self::assertTrue($newConditionalStyles[0]->getStopIfTrue(), 'StopIfTrue should be set (=true) on first condition'); + self::assertFalse($newConditionalStyles[1]->getStopIfTrue(), 'StopIfTrue should not be set (=false) on second condition'); + self::assertFalse($newConditionalStyles[2]->getStopIfTrue(), 'StopIfTrue should not be set (=false) on third condition'); + } +}