Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding option to stop at a conditional styling, if it matches (only Xlsx-Files) #292

Closed
wants to merge 11 commits into from
4 changes: 4 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,10 @@ public function load($pFilename)
$objConditional->setText((string) $cfRule['text']);
}

if ((true === isset($cfRule['stopIfTrue'])) && ((int) $cfRule['stopIfTrue'] === 1)) {
$objConditional->setStopIfTrue(true);
}

if (count($cfRule->formula) > 1) {
foreach ($cfRule->formula as $formula) {
$objConditional->addCondition((string) $formula);
Expand Down
32 changes: 32 additions & 0 deletions src/PhpSpreadsheet/Style/Conditional.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ class Conditional implements IComparable
*/
private $text;

/**
* Stop on this condition, if it matches.
*
* @var bool
*/
private $stopIfTrue;

/**
* Condition.
*
Expand All @@ -72,6 +79,7 @@ public function __construct()
$this->conditionType = self::CONDITION_NONE;
$this->operatorType = self::OPERATOR_NONE;
$this->text = null;
$this->stopIfTrue = false;
$this->condition = [];
$this->style = new Style(false, true);
}
Expand Down Expand Up @@ -148,6 +156,30 @@ public function setText($value)
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.
*
Expand Down
4 changes: 4 additions & 0 deletions src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ private function writeConditionalFormatting(XMLWriter $objWriter, Phpspreadsheet
$objWriter->writeAttribute('text', $conditional->getText());
}

if ($conditional->getStopIfTrue() == true) {
$objWriter->writeAttribute('stopIfTrue', '1');
}

if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
&& $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT
&& $conditional->getText() !== null) {
Expand Down
72 changes: 72 additions & 0 deletions tests/PhpSpreadsheetTests/Functional/ConditionalStopIfTrueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Functional;

use PhpOffice\PhpSpreadsheet\Spreadsheet;

class ConditionalStopIfTrueTest extends AbstractFunctional
{
const COLOR_GREEN = 'FF99FF66';
const COLOR_RED = 'FFFF5050';

public function providerFormats()
{
return [
['Xlsx'],
];
}

/**
* @dataProvider providerFormats
*
* @param string $format
*/
public function testConditionalStopIfTrue($format)
{
$pCoordinate = 'A1:A3';

// if blank cell -> 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');
}
}