diff --git a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index b3de5d1c..722b7795 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -36,6 +36,8 @@ class ConditionalStyles if (((string) $cfRule['type'] == Conditional::CONDITION_NONE || (string) $cfRule['type'] == Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT + || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS + || (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS || (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION) && isset($this->dxfs[(int) ($cfRule['dxfId'])])) { $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; diff --git a/src/PhpSpreadsheet/Style/Conditional.php b/src/PhpSpreadsheet/Style/Conditional.php index 91a000db..48375937 100644 --- a/src/PhpSpreadsheet/Style/Conditional.php +++ b/src/PhpSpreadsheet/Style/Conditional.php @@ -12,6 +12,7 @@ class Conditional implements IComparable const CONDITION_CONTAINSTEXT = 'containsText'; const CONDITION_EXPRESSION = 'expression'; const CONDITION_CONTAINSBLANKS = 'containsBlanks'; + const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks'; // Operator types const OPERATOR_NONE = ''; diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index f148b7c3..bf811bdc 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -527,6 +527,9 @@ class Worksheet extends WriterPart } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) { // formula copied from ms xlsx xml source file $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(); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx2Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx2Test.php new file mode 100644 index 00000000..0544d74a --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx2Test.php @@ -0,0 +1,123 @@ +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]); + } +} diff --git a/tests/data/Reader/XLSX/conditionalFormatting2Test.xlsx b/tests/data/Reader/XLSX/conditionalFormatting2Test.xlsx new file mode 100644 index 00000000..cf2fa87e Binary files /dev/null and b/tests/data/Reader/XLSX/conditionalFormatting2Test.xlsx differ