From b1cf5f8aa3771d8d692380cb633b9baa4c261d3e Mon Sep 17 00:00:00 2001
From: oleibman <10341515+oleibman@users.noreply.github.com>
Date: Thu, 16 Feb 2023 19:58:15 -0800
Subject: [PATCH 1/4] WIP Conditional Formatting Improvements for Xlsx
Fix #3370. Conditional styles are always generated with 5 borders (right, left, top, bottom, diagonal) even though the border style is none in each case. For the spreadsheet in question, top and bottom were inappropriate and interfered with the desired formatting. A new border style, BORDER_OMIT is added which will cause the Xlsx Writer to not generate that style. All conditional borders will be initialized with that value. Any border included in the Xml will, of course, change it to the specified type.
Fix #3202. User wants a condition to use "No format set" as you can in Excel. A new boolean property `$noFormatSet`, along with setter and getter, is added to Style/Conditional. It is initialized to false. User can call setter to change it. More importantly for the issue in question, if the Xlsx Reader encounters a `cfRule` tag which does not have a `dxfId` attribute (i.e. no style is associated with the rule), it will set noFormatSet to true. Similarly, the Xlsx writer will not generate a `dfxId` tag when noFormatSet is true.
This change is applicable only to Xlsx. Html, Csv, and Ods do not have support for Conditional Formatting. Limited support was added to Xls with PR #2696 in April 2022 and PR #2702 about a month later. However, with the current release code, Xls equivalents of the two new test spreadsheets in this PR are too complicated to be handled correctly by PhpSpreadsheet - loading and then saving them as Xls results in Excel complaining of corruption, and the results don't meet expectations. Since I have no idea how BIFF works, and since the problems with those spreadsheets are not caused by this PR, I am not planning to address those problems at this time.
---
.../Reader/Xlsx/ConditionalStyles.php | 5 +-
src/PhpSpreadsheet/Reader/Xlsx/Styles.php | 22 +++++--
src/PhpSpreadsheet/Style/Border.php | 6 +-
src/PhpSpreadsheet/Style/Borders.php | 22 +++----
src/PhpSpreadsheet/Style/Conditional.php | 15 +++++
src/PhpSpreadsheet/Style/Style.php | 2 +-
src/PhpSpreadsheet/Writer/Xlsx/Style.php | 10 +--
src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php | 2 +-
.../Reader/Xlsx/ConditionalBorderTest.php | 38 ++++++++++++
.../Xlsx/ConditionalNoFormatSetTest.php | 58 ++++++++++++++++++
tests/data/Reader/XLSX/issue.3202.xlsx | Bin 0 -> 10728 bytes
tests/data/Reader/XLSX/issue.3370.xlsx | Bin 0 -> 10159 bytes
12 files changed, 155 insertions(+), 25 deletions(-)
create mode 100644 tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalBorderTest.php
create mode 100644 tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalNoFormatSetTest.php
create mode 100644 tests/data/Reader/XLSX/issue.3202.xlsx
create mode 100644 tests/data/Reader/XLSX/issue.3370.xlsx
diff --git a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php
index aa6b62b26f..59bf5b84eb 100644
--- a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php
+++ b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php
@@ -163,7 +163,7 @@ private function readConditionalStyles(SimpleXMLElement $xmlSheet): array
$conditionals = [];
foreach ($xmlSheet->conditionalFormatting as $conditional) {
foreach ($conditional->cfRule as $cfRule) {
- if (Conditional::isValidConditionType((string) $cfRule['type']) && isset($this->dxfs[(int) ($cfRule['dxfId'])])) {
+ if (Conditional::isValidConditionType((string) $cfRule['type']) && (!isset($cfRule['dxfId']) || isset($this->dxfs[(int) ($cfRule['dxfId'])]))) {
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
} elseif ((string) $cfRule['type'] == Conditional::CONDITION_DATABAR) {
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
@@ -197,6 +197,7 @@ private function readStyleRules(array $cfRules, SimpleXMLElement $extLst): array
$objConditional = new Conditional();
$objConditional->setConditionType((string) $cfRule['type']);
$objConditional->setOperatorType((string) $cfRule['operator']);
+ $objConditional->setNoFormatSet(!isset($cfRule['dxfId']));
if ((string) $cfRule['text'] != '') {
$objConditional->setText((string) $cfRule['text']);
@@ -227,7 +228,7 @@ private function readStyleRules(array $cfRules, SimpleXMLElement $extLst): array
$objConditional->setDataBar(
$this->readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions) // @phpstan-ignore-line
);
- } else {
+ } elseif (isset($cfRule['dxfId'])) {
$objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]);
}
diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php
index 5b089fa874..705b319e75 100644
--- a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php
+++ b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php
@@ -206,11 +206,21 @@ public function readBorderStyle(Borders $borderStyle, SimpleXMLElement $borderSt
$borderStyle->setDiagonalDirection(Borders::DIAGONAL_BOTH);
}
- $this->readBorder($borderStyle->getLeft(), $borderStyleXml->left);
- $this->readBorder($borderStyle->getRight(), $borderStyleXml->right);
- $this->readBorder($borderStyle->getTop(), $borderStyleXml->top);
- $this->readBorder($borderStyle->getBottom(), $borderStyleXml->bottom);
- $this->readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal);
+ if (isset($borderStyleXml->left)) {
+ $this->readBorder($borderStyle->getLeft(), $borderStyleXml->left);
+ }
+ if (isset($borderStyleXml->right)) {
+ $this->readBorder($borderStyle->getRight(), $borderStyleXml->right);
+ }
+ if (isset($borderStyleXml->top)) {
+ $this->readBorder($borderStyle->getTop(), $borderStyleXml->top);
+ }
+ if (isset($borderStyleXml->bottom)) {
+ $this->readBorder($borderStyle->getBottom(), $borderStyleXml->bottom);
+ }
+ if (isset($borderStyleXml->diagonal)) {
+ $this->readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal);
+ }
}
private function getAttribute(SimpleXMLElement $xml, string $attribute): string
@@ -233,6 +243,8 @@ private function readBorder(Border $border, SimpleXMLElement $borderXml): void
$style = $this->getAttribute($borderXml, 'style');
if ($style !== '') {
$border->setBorderStyle((string) $style);
+ } else {
+ $border->setBorderStyle(Border::BORDER_NONE);
}
if (isset($borderXml->color)) {
$border->getColor()->setARGB($this->readColor($borderXml->color));
diff --git a/src/PhpSpreadsheet/Style/Border.php b/src/PhpSpreadsheet/Style/Border.php
index c6fb51f159..568e1e006a 100644
--- a/src/PhpSpreadsheet/Style/Border.php
+++ b/src/PhpSpreadsheet/Style/Border.php
@@ -21,6 +21,7 @@ class Border extends Supervisor
const BORDER_SLANTDASHDOT = 'slantDashDot';
const BORDER_THICK = 'thick';
const BORDER_THIN = 'thin';
+ const BORDER_OMIT = 'omit'; // should be used only for Conditional
/**
* Border style.
@@ -48,7 +49,7 @@ class Border extends Supervisor
* Leave this value at default unless you understand exactly what
* its ramifications are
*/
- public function __construct($isSupervisor = false)
+ public function __construct($isSupervisor = false, bool $isConditional = false)
{
// Supervisor?
parent::__construct($isSupervisor);
@@ -60,6 +61,9 @@ public function __construct($isSupervisor = false)
if ($isSupervisor) {
$this->color->bindParent($this, 'color');
}
+ if ($isConditional) {
+ $this->borderStyle = self::BORDER_OMIT;
+ }
}
/**
diff --git a/src/PhpSpreadsheet/Style/Borders.php b/src/PhpSpreadsheet/Style/Borders.php
index 56a52709ed..a1247e859d 100644
--- a/src/PhpSpreadsheet/Style/Borders.php
+++ b/src/PhpSpreadsheet/Style/Borders.php
@@ -96,27 +96,27 @@ class Borders extends Supervisor
* Leave this value at default unless you understand exactly what
* its ramifications are
*/
- public function __construct($isSupervisor = false)
+ public function __construct($isSupervisor = false, bool $isConditional = false)
{
// Supervisor?
parent::__construct($isSupervisor);
// Initialise values
- $this->left = new Border($isSupervisor);
- $this->right = new Border($isSupervisor);
- $this->top = new Border($isSupervisor);
- $this->bottom = new Border($isSupervisor);
- $this->diagonal = new Border($isSupervisor);
+ $this->left = new Border($isSupervisor, $isConditional);
+ $this->right = new Border($isSupervisor, $isConditional);
+ $this->top = new Border($isSupervisor, $isConditional);
+ $this->bottom = new Border($isSupervisor, $isConditional);
+ $this->diagonal = new Border($isSupervisor, $isConditional);
$this->diagonalDirection = self::DIAGONAL_NONE;
// Specially for supervisor
if ($isSupervisor) {
// Initialize pseudo-borders
- $this->allBorders = new Border(true);
- $this->outline = new Border(true);
- $this->inside = new Border(true);
- $this->vertical = new Border(true);
- $this->horizontal = new Border(true);
+ $this->allBorders = new Border(true, $isConditional);
+ $this->outline = new Border(true, $isConditional);
+ $this->inside = new Border(true, $isConditional);
+ $this->vertical = new Border(true, $isConditional);
+ $this->horizontal = new Border(true, $isConditional);
// bind parent if we are a supervisor
$this->left->bindParent($this, 'left');
diff --git a/src/PhpSpreadsheet/Style/Conditional.php b/src/PhpSpreadsheet/Style/Conditional.php
index 019c0648d6..de565d3458 100644
--- a/src/PhpSpreadsheet/Style/Conditional.php
+++ b/src/PhpSpreadsheet/Style/Conditional.php
@@ -115,6 +115,9 @@ class Conditional implements IComparable
*/
private $style;
+ /** @var bool */
+ private $noFormatSet = false;
+
/**
* Create a new Conditional.
*/
@@ -124,6 +127,18 @@ public function __construct()
$this->style = new Style(false, true);
}
+ public function getNoFormatSet(): bool
+ {
+ return $this->noFormatSet;
+ }
+
+ public function setNoFormatSet(bool $noFormatSet): self
+ {
+ $this->noFormatSet = $noFormatSet;
+
+ return $this;
+ }
+
/**
* Get Condition type.
*
diff --git a/src/PhpSpreadsheet/Style/Style.php b/src/PhpSpreadsheet/Style/Style.php
index 62f20e92f3..be70639eb2 100644
--- a/src/PhpSpreadsheet/Style/Style.php
+++ b/src/PhpSpreadsheet/Style/Style.php
@@ -99,7 +99,7 @@ public function __construct($isSupervisor = false, $isConditional = false)
// Initialise values
$this->font = new Font($isSupervisor, $isConditional);
$this->fill = new Fill($isSupervisor, $isConditional);
- $this->borders = new Borders($isSupervisor);
+ $this->borders = new Borders($isSupervisor, $isConditional);
$this->alignment = new Alignment($isSupervisor, $isConditional);
$this->numberFormat = new NumberFormat($isSupervisor, $isConditional);
$this->protection = new Protection($isSupervisor, $isConditional);
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Style.php b/src/PhpSpreadsheet/Writer/Xlsx/Style.php
index b9146647b7..29f4eec957 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/Style.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/Style.php
@@ -527,8 +527,11 @@ private function writeCellStyleDxf(XMLWriter $objWriter, \PhpOffice\PhpSpreadshe
private function writeBorderPr(XMLWriter $objWriter, $name, Border $border): void
{
// Write BorderPr
- if ($border->getBorderStyle() != Border::BORDER_NONE) {
- $objWriter->startElement($name);
+ if ($border->getBorderStyle() === Border::BORDER_OMIT) {
+ return;
+ }
+ $objWriter->startElement($name);
+ if ($border->getBorderStyle() !== Border::BORDER_NONE) {
$objWriter->writeAttribute('style', $border->getBorderStyle());
// color
@@ -536,10 +539,9 @@ private function writeBorderPr(XMLWriter $objWriter, $name, Border $border): voi
$objWriter->startElement('color');
$objWriter->writeAttribute('rgb', $border->getColor()->getARGB());
$objWriter->endElement();
-
- $objWriter->endElement();
}
}
+ $objWriter->endElement();
}
/**
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
index f4904d2557..53c4512457 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
@@ -681,7 +681,7 @@ private function writeConditionalFormatting(XMLWriter $objWriter, Phpspreadsheet
$objWriter->writeAttribute('type', $conditional->getConditionType());
self::writeAttributeIf(
$objWriter,
- ($conditional->getConditionType() != Conditional::CONDITION_DATABAR),
+ ($conditional->getConditionType() !== Conditional::CONDITION_DATABAR && $conditional->getNoFormatSet() === false),
'dxfId',
(string) $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode())
);
diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalBorderTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalBorderTest.php
new file mode 100644
index 0000000000..6c0bc44080
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalBorderTest.php
@@ -0,0 +1,38 @@
+';
+ self::assertStringContainsString($expected, $data);
+
+ $reader = new XlsxReader();
+ $spreadsheet = $reader->load($testfile);
+ $outfile = File::temporaryFilename();
+ $writer = new XlsxWriter($spreadsheet);
+ $writer->save($outfile);
+ $spreadsheet->disconnectWorksheets();
+
+ $file = 'zip://';
+ $file .= $outfile;
+ $file .= '#xl/styles.xml';
+ $data = file_get_contents($file);
+ unlink($outfile);
+
+ $expected = '';
+ self::assertStringContainsString($expected, $data);
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalNoFormatSetTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalNoFormatSetTest.php
new file mode 100644
index 0000000000..570a613ea5
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalNoFormatSetTest.php
@@ -0,0 +1,58 @@
+'
+ . ''
+ . '$A1>5'
+ . ''
+ . ''
+ . '$A1>1'
+ . ''
+ . ''
+ . '$A1=3'
+ . ''
+ . '';
+ self::assertStringContainsString($expected, $data);
+
+ $reader = new XlsxReader();
+ $spreadsheet = $reader->load($testfile);
+ $outfile = File::temporaryFilename();
+ $writer = new XlsxWriter($spreadsheet);
+ $writer->save($outfile);
+ $spreadsheet->disconnectWorksheets();
+
+ $file = 'zip://';
+ $file .= $outfile;
+ $file .= '#xl/worksheets/sheet1.xml';
+ $data = file_get_contents($file);
+ unlink($outfile);
+
+ $expected = ''
+ . ''
+ . '$A1=3'
+ . ''
+ . ''
+ . '$A1>5'
+ . ''
+ . ''
+ . '$A1>1'
+ . ''
+ . '';
+ self::assertStringContainsString($expected, $data);
+ }
+}
diff --git a/tests/data/Reader/XLSX/issue.3202.xlsx b/tests/data/Reader/XLSX/issue.3202.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..93733238f03b946a04b2d436a1f98429b7949330
GIT binary patch
literal 10728
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
CB?UqN
literal 0
HcmV?d00001
From 09d074516aaca180d7443610736695bddcfcf8cc Mon Sep 17 00:00:00 2001
From: oleibman <10341515+oleibman@users.noreply.github.com>
Date: Fri, 17 Feb 2023 17:11:59 -0800
Subject: [PATCH 2/4] Update Documentation, Write Alignment and Font Less Often
It doesn't cause any particular harm except for small increases in file size and run time, but Alignment tags are written even when (a) all its attributes are null for Conditional Formatting, and (b) when the xml specifically indicates that Alignment should not be applied. Similarly, Font is written even when all its attributes are null for Conditional Formatting.
There are some errors in the Conditional Formatting documentation. Specifying a solid fill color in a Conditional Style requires the use of endColor, not StartColor. The discussion of Order of Evaluating is not entirely accurate. I have changed it to what I believe is an accurate explanation of how Excel works; and also added a mention that other spreadsheet programs might not work the same way, adding a couple of illustrations of the difference. The description of the multiple conditions did not quite match the diagram. 'Stop if true' was a blank paragraph; it is now described, and the new 'No format set' option is described in that paragraph since (I think) it would be used most often in conjunction with 'Stop if true'.
---
docs/topics/conditional-formatting.md | 35 ++++--
.../images/11-21-CF-Rule-Order-2.pic2.png | Bin 0 -> 43342 bytes
.../images/11-21-CF-Rule-Order-2.pic3.png | Bin 0 -> 5183 bytes
src/PhpSpreadsheet/Writer/Xlsx/Style.php | 106 +++++++++++-------
.../Reader/Xlsx/ConditionalBorderTest.php | 2 +-
5 files changed, 92 insertions(+), 51 deletions(-)
create mode 100644 docs/topics/images/11-21-CF-Rule-Order-2.pic2.png
create mode 100644 docs/topics/images/11-21-CF-Rule-Order-2.pic3.png
diff --git a/docs/topics/conditional-formatting.md b/docs/topics/conditional-formatting.md
index 086a794206..bc04c7cc04 100644
--- a/docs/topics/conditional-formatting.md
+++ b/docs/topics/conditional-formatting.md
@@ -43,7 +43,7 @@ $conditional->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERA
$conditional->addCondition(80);
$conditional->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
$conditional->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
-$conditional->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
+$conditional->getStyle()->getFill()->getEndColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles();
$conditionalStyles[] = $conditional;
@@ -63,7 +63,7 @@ $wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFor
$wizard->greaterThan(80);
$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
-$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
+$wizard->getStyle()->getFill()->getEndColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
$conditional = $wizard->getConditional();
```
@@ -84,7 +84,7 @@ $conditional2->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPER
$conditional2->addCondition(10);
$conditional2->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKRED);
$conditional2->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
-$conditional2->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
+$conditional2->getStyle()->getFill()->getEndColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles();
$conditionalStyles[] = $conditional2;
@@ -98,7 +98,7 @@ $wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFor
$wizard->lessThan(10);
$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
-$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
+$wizard->getStyle()->getFill()->getEndColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
$conditional = $wizard->getConditional();
```
@@ -106,9 +106,9 @@ $conditional = $wizard->getConditional();
### Order of Evaluating Multiple Rules/Conditions
-`$conditionalStyles` is an array, which not only represents multiple conditions that can be applied to a cell (or range of cells), but also the order in which they are checked. MS Excel will check each of those conditions in turn in the order they are defined; and will stop checking once it finds a first matching rule. This means that the order of checking conditions can be important.
+`$conditionalStyles` is an array, which not only represents multiple conditions that can be applied to a cell (or range of cells), but also the order in which they are checked. Some spreadsheet programs stop processing conditions once they find a match. On the other hand, MS Excel will check each of those conditions in turn in the order they are defined. It will stop checking only if it finds a matching rule that specifies 'stop if true'; however, if it finds conflicting matches with conflicting formatting (e.g. both set a background fill color but use different choices), the first match wins. In either case, this means that the order of checking conditions can be important.
-Consider the following. We have one condition that checks if a cell value is between -10 and 10, styling the cell in yellow if that condition matches; and a second condition that checks if the cell value is equal to 0, styling the cell in red if that matches.
+Consider the following. We have one condition that checks if a cell value is between -2 and 2, styling the fill color of the cell in yellow if that condition matches; and a second condition that checks if the cell value is equal to 0, styling the fill color of the cell in red if that matches.
- Yellow if value is between -2 and 2
- Red if value equals 0
@@ -120,12 +120,22 @@ If the rule order is reversed
- Red if value equals 0
- Yellow if value is between -2 and 2
-then the cell containing the value 0 will be rendered in red, because that is the first matching condition; and the between rule will not be assessed for that cell.
+then the cell containing the value 0 will be rendered in red, because that is the first matching condition; and the formatting in the other condition conflicts with this, so is discarded.

So when you have multiple conditions where the rules might "overlap", the order of these is important.
+If the cell matches multiple conditions, Excel (but not most other spreadsheet programs) will apply non-conflicting styles from each match. So, for the example above, if we wanted a match of 0 to have a different *font* color rather than a different *fill* color, Excel can honor both.
+
+
+
+Here is the same spreadsheet opened in LibreOffice - cell A4 has only the first conditional style applied to it. (You would see the same if you checked 'Stop if True' in Excel.) If you want the spreadsheet to appear the same in both Excel and LibreOffice, you would need to use more complicated conditions.
+
+
+
+PhpSpreadsheet supports the setting of [Stop If True](#stop-if-true-and-no-format-set).
+
### Reader/Writer Support
@@ -704,8 +714,17 @@ This example can also be found in the [code samples](https://github.com/PHPOffic
## General Notes
-### Stop If True
+### Stop If True, and No Format Set
+Normally, Excel continues to check even after it finds a match. To tell it to stop once a match is found, 'stop if true' should be specified:
+```php
+$conditional->setStopIfTrue(true);
+```
+
+Sometimes you want a matched cell to just show its unconditional format. This is most useful in conjunction with 'stop if true'.
+```php
+$conditional->setNoFormatSet(true);
+```
### Changing the Cell Range
diff --git a/docs/topics/images/11-21-CF-Rule-Order-2.pic2.png b/docs/topics/images/11-21-CF-Rule-Order-2.pic2.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3596a5c5cbc556a3726b34604715a29cc93bae4
GIT binary patch
literal 43342
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