From 72fce3aadaf3dd4044904c773117468fc48e8ce6 Mon Sep 17 00:00:00 2001 From: Adrien Loison Date: Sat, 20 Jul 2019 16:44:10 +0200 Subject: [PATCH] Support for missing styles XML file in XLSX Some files don't have a "styles.xml" file. Excel supports these files, Spout should do too. --- src/Spout/Reader/XLSX/Manager/StyleManager.php | 14 ++++++++++++-- .../Manager/WorkbookRelationshipsManager.php | 12 +++++++++++- .../Reader/XLSX/Manager/StyleManagerTest.php | 1 + tests/Spout/Reader/XLSX/ReaderTest.php | 13 +++++++++++++ .../file_with_no_styles_in_workbook_xml.xlsx | Bin 0 -> 3274 bytes 5 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 tests/resources/xlsx/file_with_no_styles_in_workbook_xml.xlsx diff --git a/src/Spout/Reader/XLSX/Manager/StyleManager.php b/src/Spout/Reader/XLSX/Manager/StyleManager.php index 9232ef1..193324d 100644 --- a/src/Spout/Reader/XLSX/Manager/StyleManager.php +++ b/src/Spout/Reader/XLSX/Manager/StyleManager.php @@ -48,7 +48,10 @@ class StyleManager /** @var string Path of the XLSX file being read */ protected $filePath; - /** @var string Path of the styles XML file */ + /** @var bool Whether the XLSX file contains a styles XML file */ + protected $hasStylesXMLFile; + + /** @var string|null Path of the styles XML file */ protected $stylesXMLFilePath; /** @var InternalEntityFactory Factory to create entities */ @@ -76,7 +79,10 @@ class StyleManager $this->filePath = $filePath; $this->entityFactory = $entityFactory; $this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping); - $this->stylesXMLFilePath = $workbookRelationshipsManager->getStylesXMLFilePath(); + $this->hasStylesXMLFile = $workbookRelationshipsManager->hasStylesXMLFile(); + if ($this->hasStylesXMLFile) { + $this->stylesXMLFilePath = $workbookRelationshipsManager->getStylesXMLFilePath(); + } } /** @@ -88,6 +94,10 @@ class StyleManager */ public function shouldFormatNumericValueAsDate($styleId) { + if (!$this->hasStylesXMLFile) { + return false; + } + $stylesAttributes = $this->getStylesAttributes(); // Default style (0) does not format numeric values as timestamps. Only custom styles do. diff --git a/src/Spout/Reader/XLSX/Manager/WorkbookRelationshipsManager.php b/src/Spout/Reader/XLSX/Manager/WorkbookRelationshipsManager.php index 2a9b4e0..68d8709 100644 --- a/src/Spout/Reader/XLSX/Manager/WorkbookRelationshipsManager.php +++ b/src/Spout/Reader/XLSX/Manager/WorkbookRelationshipsManager.php @@ -75,7 +75,17 @@ class WorkbookRelationshipsManager } /** - * @return string|null The path of the styles XML file + * @return bool Whether the XLSX file contains a styles XML file + */ + public function hasStylesXMLFile() + { + $workbookRelationships = $this->getWorkbookRelationships(); + + return isset($workbookRelationships[self::RELATIONSHIP_TYPE_STYLES]); + } + + /** + * @return string The path of the styles XML file */ public function getStylesXMLFilePath() { diff --git a/tests/Spout/Reader/XLSX/Manager/StyleManagerTest.php b/tests/Spout/Reader/XLSX/Manager/StyleManagerTest.php index a8aa190..794f4bc 100644 --- a/tests/Spout/Reader/XLSX/Manager/StyleManagerTest.php +++ b/tests/Spout/Reader/XLSX/Manager/StyleManagerTest.php @@ -19,6 +19,7 @@ class StyleManagerTest extends TestCase { $entityFactory = $this->createMock(InternalEntityFactory::class); $workbookRelationshipsManager = $this->createMock(WorkbookRelationshipsManager::class); + $workbookRelationshipsManager->method('hasStylesXMLFile')->willReturn(true); /** @var StyleManager $styleManager */ $styleManager = $this->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\StyleManager') diff --git a/tests/Spout/Reader/XLSX/ReaderTest.php b/tests/Spout/Reader/XLSX/ReaderTest.php index e5f5b6e..51a7b0e 100644 --- a/tests/Spout/Reader/XLSX/ReaderTest.php +++ b/tests/Spout/Reader/XLSX/ReaderTest.php @@ -473,6 +473,19 @@ class ReaderTest extends TestCase $this->assertEquals($expectedRows, $allRows); } + /** + * @return void + */ + public function testReadShouldSupportMissingStylesXMLFile() + { + $allRows = $this->getAllRowsForFile('file_with_no_styles_in_workbook_xml.xlsx'); + + $expectedRows = [ + ['s1--A1', 's1--B1'], + ]; + $this->assertEquals($expectedRows, $allRows); + } + /** * @return void */ diff --git a/tests/resources/xlsx/file_with_no_styles_in_workbook_xml.xlsx b/tests/resources/xlsx/file_with_no_styles_in_workbook_xml.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aea1af5ca725b9cff2b2860239ca61795969c294 GIT binary patch literal 3274 zcmZ`*3pkVQA0BheIf_r2kV9e?E0W4#&O#13)SQ<&ZVqXVeT0&PrBrl~sXjjXHWjtW zpNZ6nNQoT!hMccV$QjRGJF}8V9BXXP7T090kRN1cziJ?WjAXQYViriiyl> zw#*Z=pO9O|tRy9a1~n6X%{6jBWnI;|9i>qH3EO5WwVyH&_>kvj=$S@t>XI3rpk2f3&6NX#Sb4^d0+n`N2%;d6515E`AEHv_wGj`HQE=eJ|qnu zN>5H}%Ipb%_zb%TKmAVE?90zO@V5fC5!_G+dt5Fdcg2BbwJ`9^atCj!DEwOAo+hM?@j%@&;3NVLVeX~m7<+Z>8Vh+=Ux@BbGmhmtrpG0!y9(U zd+_WEuhSXuuPRC%?dYun)YAu46z5dY8;fO%cr&Z!0{0$q#H7%&$xEcpgb_kpDGBF+ z?TEFAfy0JHEqBk)KB;^#G=BV4O=0oa{0*~Hi4IEMB}3(AyAACWJ`>+nFNHp9FD6m@ z%#6|BM2bC5U)EZ1R5R%pa2DhaDzT$QqinvZT9h@{nT7GGHxgfl!{NfM)T@j8xkz)N zH&POJgZTv77P&`M!%p?D7=!1`pT~T`xZ&_Fjh(kXWW?LF?CqeuxJ_=1zSu+5XdPEj zbY;xpn+K84$ZJ$L))g3_iVI$=sEq-ls{yAm;Xx5-6e^Ol`W#ZGZQq__M2-M4m4I$C zpzX}XIAU3lJxu+aodiMP<7zrc<~)TH0&(%o0uWZYXJpmbQencWlNJ;cdTj1hu(2aP zpsh{_Bqm-oA=|3w94tdQ=*Exc7ymxkJ2kXY(Mc(?tn%r<)@WQ2Xrz$RZLaT%i=kj9 z42igrr5r&`iW0RR>3Q83`o=)@ z6MX$UF=W{e1MbdqWdIQe8SxQWnYgTP?AD;blJ+YLbrF8S{ybZF%3sQ8or$0rtX{Q%Mi7A$T`-7UO$*p0Rw-V+J94^_a4<2RUTcdA@D>u)3(T*1?vrc?4m>?!iC=#`oNu;-dBPbmHizuDD|^J0ZR>`z^|9!q6yR8DUDk=&0(45Erp; z5^wgs7GBsx#G5CIe9vzy?-(;^zM6gwW^q3g-lgFp8%YW!fkzrh-RSvOpaS*%LZm=_ zaC>BFMKUta5-!s|e6Zj1$&2UmaubDQn#`1#_1-h!0CDyL;)tzk$SF%krjaexP}p?VqT8E(@Fqbh z`7Ys;lLfM3yVpy-rU!oC4as%*@Ht~CWO!~RD!%dZfdaJ8$Q=)-zO0x_X`*tJ zanIWx{|gY5qShtL#oeuq`S!i#mfNLCnz=vdt!TZ&V14YkIn7AgK&cbu)mU&X=j?ko z7(!0M`qm<;_*T4VTAvx3epnci+Wv3qLgq!MQ1O~wQsobQZ)~CEl?PU@e94^e(%aPO zGgcN6(pnb3O>@6q0A7TYvG@Cd7b`yQXY45R+`n?>Lr)FB0lsNGAdn=$`M3!tG!hjW z>FE@WMMWT)d75}TihH&^XKYmvy_}M{|CfGD9-R@FRm*pGmcT2@HGL6 zrF(uAv=K4f*{Rj$2NRtb{TK-IsE*pcOKpc*TkcnK+>F?h{c)+1R?|VPyGHrk?7JTu z-jDiXeeUbF6fcOqiwjNo=U9ULMUdrYX zbXv1}qU_lHf869Da9y}}whiROE2~uFP;WKmn*leQ3?UI)Bzd0>E5>S&20T>ZN;8Da z(Rl>JpHINK@uN~nX-Hzl40H-7|F1ycZ2lKrQ{rfT!D}?cAZ6-EZ*Fo{cC5N4?Q%j) zNeR!U7|St5?Iq_|P>X1FH1WbM|lrxUtOrXSN#wOnYaK=v4rRfiph_0W$>>0By8;85R`C5kyEV+JNOW zf8JH|U)R*xR91ypZ;0&7`T=IYvq$y{8@Vw(i9PNB-G;-V*t9l!6eq0)P8erv{^3{v zvER5AJFQh>>)Sj#EjlkNEzXtKgV*;