Conditionals - Extend Support for (NOT)CONTAINSBLANKS (#1278)

Support for the CONTAINSBLANKS conditional style was added a while ago.
However, that support was on write only; any cells which used
CONTAINSBLANKS on a file being read would drop that style.

I am also adding support for NOTCONTAINSBLANKS, on read and write.
This commit is contained in:
oleibman 2020-01-04 09:50:04 -08:00 committed by Mark Baker
parent 1c6dd8923e
commit 082266aacd
5 changed files with 129 additions and 0 deletions

View File

@ -36,6 +36,8 @@ class ConditionalStyles
if (((string) $cfRule['type'] == Conditional::CONDITION_NONE if (((string) $cfRule['type'] == Conditional::CONDITION_NONE
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS
|| (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION) || (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
&& isset($this->dxfs[(int) ($cfRule['dxfId'])])) { && isset($this->dxfs[(int) ($cfRule['dxfId'])])) {
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;

View File

@ -12,6 +12,7 @@ class Conditional implements IComparable
const CONDITION_CONTAINSTEXT = 'containsText'; const CONDITION_CONTAINSTEXT = 'containsText';
const CONDITION_EXPRESSION = 'expression'; const CONDITION_EXPRESSION = 'expression';
const CONDITION_CONTAINSBLANKS = 'containsBlanks'; const CONDITION_CONTAINSBLANKS = 'containsBlanks';
const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks';
// Operator types // Operator types
const OPERATOR_NONE = ''; const OPERATOR_NONE = '';

View File

@ -527,6 +527,9 @@ class Worksheet extends WriterPart
} elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) { } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) {
// formula copied from ms xlsx xml source file // formula copied from ms xlsx xml source file
$objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))=0'); $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))=0');
} elseif ($conditional->getConditionType() == Conditional::CONDITION_NOTCONTAINSBLANKS) {
// formula copied from ms xlsx xml source file
$objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))>0');
} }
$objWriter->endElement(); $objWriter->endElement();

View File

@ -0,0 +1,123 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PHPUnit\Framework\TestCase;
class Xlsx2Test extends TestCase
{
public function tearDown()
{
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
if (file_exists($outfile)) {
unlink($outfile);
}
}
public function testLoadXlsxConditionalFormatting2()
{
// Make sure Conditionals are read correctly from existing file
$filename = './data/Reader/XLSX/conditionalFormatting2Test.xlsx';
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($filename);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A2:A8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_NOTCONTAINSBLANKS, $conditionalRule->getConditionType());
self::assertEquals('LEN(TRIM(A2))>0', $conditions[0]);
$conditionalStyle = $worksheet->getConditionalStyles('B2:B8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_CONTAINSBLANKS, $conditionalRule->getConditionType());
self::assertEquals('LEN(TRIM(B2))=0', $conditions[0]);
$conditionalStyle = $worksheet->getConditionalStyles('C2:C8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_CELLIS, $conditionalRule->getConditionType());
self::assertEquals(Conditional::OPERATOR_GREATERTHAN, $conditionalRule->getOperatorType());
self::assertEquals('5', $conditions[0]);
}
public function testReloadXlsxConditionalFormatting2()
{
// Make sure conditionals from existing file are maintained across save
$filename = './data/Reader/XLSX/conditionalFormatting2Test.xlsx';
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$reader = IOFactory::createReader('Xlsx');
$spreadshee1 = $reader->load($filename);
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
$writer->save($outfile);
$spreadsheet = $reader->load($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A2:A8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_NOTCONTAINSBLANKS, $conditionalRule->getConditionType());
self::assertEquals('LEN(TRIM(A2:A8))>0', $conditions[0]);
$conditionalStyle = $worksheet->getConditionalStyles('B2:B8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_CONTAINSBLANKS, $conditionalRule->getConditionType());
self::assertEquals('LEN(TRIM(B2:B8))=0', $conditions[0]);
$conditionalStyle = $worksheet->getConditionalStyles('C2:C8');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_CELLIS, $conditionalRule->getConditionType());
self::assertEquals(Conditional::OPERATOR_GREATERTHAN, $conditionalRule->getOperatorType());
self::assertEquals('5', $conditions[0]);
}
public function testNewXlsxConditionalFormatting2()
{
// Make sure blanks/non-blanks added by PhpSpreadsheet are handled correctly
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$spreadshee1 = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadshee1->getActiveSheet();
$sheet->setCellValue('A2', 'a2');
$sheet->setCellValue('A4', 'a4');
$sheet->setCellValue('A6', 'a6');
$cond1 = new Conditional();
$cond1->setConditionType(Conditional::CONDITION_CONTAINSBLANKS);
$cond1->getStyle()->getFill()->setFillType(Fill::FILL_SOLID);
$cond1->getStyle()->getFill()->getEndColor()->setARGB(Color::COLOR_RED);
$cond = [$cond1];
$sheet->getStyle('A1:A6')->setConditionalStyles($cond);
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
$writer->save($outfile);
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A1:A6');
self::assertNotEmpty($conditionalStyle);
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_CONTAINSBLANKS, $conditionalRule->getConditionType());
self::assertEquals('LEN(TRIM(A1:A6))=0', $conditions[0]);
}
}

Binary file not shown.