1 | <?php |
||
13 | class StyleHelper |
||
14 | { |
||
15 | /** Paths of XML files relative to the XLSX file root */ |
||
16 | const STYLES_XML_FILE_PATH = 'xl/styles.xml'; |
||
17 | |||
18 | /** Nodes used to find relevant information in the styles XML file */ |
||
19 | const XML_NODE_NUM_FMTS = 'numFmts'; |
||
20 | const XML_NODE_NUM_FMT = 'numFmt'; |
||
21 | const XML_NODE_CELL_XFS = 'cellXfs'; |
||
22 | const XML_NODE_XF = 'xf'; |
||
23 | |||
24 | /** Attributes used to find relevant information in the styles XML file */ |
||
25 | const XML_ATTRIBUTE_NUM_FMT_ID = 'numFmtId'; |
||
26 | const XML_ATTRIBUTE_FORMAT_CODE = 'formatCode'; |
||
27 | const XML_ATTRIBUTE_APPLY_NUMBER_FORMAT = 'applyNumberFormat'; |
||
28 | |||
29 | /** By convention, default style ID is 0 */ |
||
30 | const DEFAULT_STYLE_ID = 0; |
||
31 | |||
32 | /** |
||
33 | * @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx |
||
34 | * @var array Mapping between built-in numFmtId and the associated format - for dates only |
||
35 | */ |
||
36 | protected static $builtinNumFmtIdToNumFormatMapping = [ |
||
37 | 14 => 'm/d/yyyy', // @NOTE: ECMA spec is 'mm-dd-yy' |
||
38 | 15 => 'd-mmm-yy', |
||
39 | 16 => 'd-mmm', |
||
40 | 17 => 'mmm-yy', |
||
41 | 18 => 'h:mm AM/PM', |
||
42 | 19 => 'h:mm:ss AM/PM', |
||
43 | 20 => 'h:mm', |
||
44 | 21 => 'h:mm:ss', |
||
45 | 22 => 'm/d/yyyy h:mm', // @NOTE: ECMA spec is 'm/d/yy h:mm', |
||
46 | 45 => 'mm:ss', |
||
47 | 46 => '[h]:mm:ss', |
||
48 | 47 => 'mm:ss.0', // @NOTE: ECMA spec is 'mmss.0', |
||
49 | ]; |
||
50 | |||
51 | /** @var string Path of the XLSX file being read */ |
||
52 | protected $filePath; |
||
53 | |||
54 | /** @var array Array containing a mapping NUM_FMT_ID => FORMAT_CODE */ |
||
55 | protected $customNumberFormats; |
||
56 | |||
57 | /** @var array Array containing a mapping STYLE_ID => [STYLE_ATTRIBUTES] */ |
||
58 | protected $stylesAttributes; |
||
59 | |||
60 | /** |
||
61 | * @param string $filePath Path of the XLSX file being read |
||
62 | */ |
||
63 | 90 | public function __construct($filePath) |
|
67 | |||
68 | /** |
||
69 | * Reads the styles.xml file and extract the relevant information from the file. |
||
70 | * |
||
71 | * @return void |
||
72 | */ |
||
73 | 27 | protected function extractRelevantInfo() |
|
93 | |||
94 | /** |
||
95 | * Extracts number formats from the "numFmt" nodes. |
||
96 | * For simplicity, the styles attributes are kept in memory. This is possible thanks |
||
97 | * to the reuse of formats. So 1 million cells should not use 1 million formats. |
||
98 | * |
||
99 | * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XML Reader positioned on the "numFmts" node |
||
100 | * @return void |
||
101 | */ |
||
102 | 18 | protected function extractNumberFormats($xmlReader) |
|
115 | |||
116 | /** |
||
117 | * Extracts style attributes from the "xf" nodes, inside the "cellXfs" section. |
||
118 | * For simplicity, the styles attributes are kept in memory. This is possible thanks |
||
119 | * to the reuse of styles. So 1 million cells should not use 1 million styles. |
||
120 | * |
||
121 | * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XML Reader positioned on the "cellXfs" node |
||
122 | * @return void |
||
123 | */ |
||
124 | 27 | protected function extractStyleAttributes($xmlReader) |
|
138 | |||
139 | /** |
||
140 | * @return array The custom number formats |
||
141 | */ |
||
142 | 12 | protected function getCustomNumberFormats() |
|
150 | |||
151 | /** |
||
152 | * @return array The styles attributes |
||
153 | */ |
||
154 | 27 | protected function getStylesAttributes() |
|
162 | |||
163 | /** |
||
164 | * Returns whether the style with the given ID should consider |
||
165 | * numeric values as timestamps and format the cell as a date. |
||
166 | * |
||
167 | * @param int $styleId Zero-based style ID |
||
168 | * @return bool Whether the cell with the given cell should display a date instead of a numeric value |
||
169 | */ |
||
170 | 108 | public function shouldFormatNumericValueAsDate($styleId) |
|
191 | |||
192 | /** |
||
193 | * @param int $numFmtId |
||
194 | * @return bool Whether the number format ID indicates that the number is a timestamp |
||
195 | */ |
||
196 | 84 | protected function doesNumFmtIdIndicateDate($numFmtId) |
|
206 | |||
207 | /** |
||
208 | * @param int $numFmtId |
||
209 | * @return bool Whether the number format ID indicates the "General" format (0 by convention) |
||
210 | */ |
||
211 | 84 | protected function doesNumFmtIdIndicateGeneralFormat($numFmtId) |
|
215 | |||
216 | /** |
||
217 | * @param int $numFmtId |
||
218 | * @return bool Whether the number format ID indicates that the number is a timestamp |
||
219 | */ |
||
220 | 81 | protected function isNumFmtIdBuiltInDateFormat($numFmtId) |
|
225 | |||
226 | /** |
||
227 | * @param int $numFmtId |
||
228 | * @return bool Whether the number format ID indicates that the number is a timestamp |
||
229 | */ |
||
230 | 78 | protected function isNumFmtIdCustomDateFormat($numFmtId) |
|
263 | |||
264 | /** |
||
265 | * Returns the format as defined in "styles.xml" of the given style. |
||
266 | * NOTE: It is assumed that the style DOES have a number format associated to it. |
||
267 | * |
||
268 | * @param int $styleId Zero-based style ID |
||
269 | * @return string The number format associated with the given style |
||
270 | */ |
||
271 | 3 | public function getNumberFormat($styleId) |
|
286 | } |
||
287 |