From aeccdb35e248f037e936c596378d145a53ecaa66 Mon Sep 17 00:00:00 2001 From: oleibman Date: Tue, 20 Apr 2021 08:20:59 -0700 Subject: [PATCH] XLSX Reader and Empty Fill Tag (#2011) Openpyxl can generate the xml tag ``, possibly even as a default style. Excel has no problem with this, treating it as "fill none", but PhpSpreadsheet has a glitch because it treats it as "fill solid white". So, when PhpSpreadsheet loads and saves such a file, the result at first appears as if gridlines are disabled; in fact, the gridlines are merely invisible behind the cells with their solid white fill. This PR makes PhpSpreadsheet behave the same as Excel in this circumstance. Co-authored-by: Mark Baker --- src/PhpSpreadsheet/Reader/Xlsx.php | 3 +- src/PhpSpreadsheet/Reader/Xlsx/Styles.php | 2 +- .../Reader/Xlsx/DefaultFillTest.php | 32 ++++++++++++++++++ tests/data/Reader/XLSX/pr1769g.py.xlsx | Bin 0 -> 4754 bytes 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Reader/Xlsx/DefaultFillTest.php create mode 100644 tests/data/Reader/XLSX/pr1769g.py.xlsx diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index a3dcf6c2..a7c71c73 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -30,6 +30,7 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\Borders; use PhpOffice\PhpSpreadsheet\Style\Color; +use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Style\Protection; use PhpOffice\PhpSpreadsheet\Style\Style; @@ -1646,7 +1647,7 @@ class Xlsx extends BaseReader $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color)); $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)); } elseif ($style->fill->patternFill) { - $patternType = (string) $style->fill->patternFill['patternType'] != '' ? (string) $style->fill->patternFill['patternType'] : 'solid'; + $patternType = (string) $style->fill->patternFill['patternType'] != '' ? (string) $style->fill->patternFill['patternType'] : Fill::FILL_NONE; $docStyle->getFill()->setFillType($patternType); if ($style->fill->patternFill->fgColor) { $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true)); diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index 290e8cb7..c43ccc97 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -97,7 +97,7 @@ class Styles extends BaseParserClass $fillStyle->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color)); $fillStyle->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)); } elseif ($fillStyleXml->patternFill) { - $patternType = (string) $fillStyleXml->patternFill['patternType'] != '' ? (string) $fillStyleXml->patternFill['patternType'] : 'solid'; + $patternType = (string) $fillStyleXml->patternFill['patternType'] != '' ? (string) $fillStyleXml->patternFill['patternType'] : Fill::FILL_NONE; $fillStyle->setFillType($patternType); if ($fillStyleXml->patternFill->fgColor) { $fillStyle->getStartColor()->setARGB(self::readColor($fillStyleXml->patternFill->fgColor, true)); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/DefaultFillTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/DefaultFillTest.php new file mode 100644 index 00000000..88d666b2 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/DefaultFillTest.php @@ -0,0 +1,32 @@ +', $data); + } + $reader = IOFactory::createReader('Xlsx'); + $spreadsheet = $reader->load($filename); + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame('none', $sheet->getCell('A1')->getStyle()->getFill()->getFillType()); + self::assertSame('none', $sheet->getCell('D4')->getStyle()->getFill()->getFillType()); + self::assertSame('none', $sheet->getCell('J16')->getStyle()->getFill()->getFillType()); + self::assertSame('solid', $sheet->getCell('C2')->getStyle()->getFill()->getFillType()); + } +} diff --git a/tests/data/Reader/XLSX/pr1769g.py.xlsx b/tests/data/Reader/XLSX/pr1769g.py.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1e580da6d34aeb72d694bc90a4f07c9a1391b83e GIT binary patch literal 4754 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 WP>{AD0D#k^Q<+r1m49wI0saFq9~syH literal 0 HcmV?d00001