PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Style / NumberFormat.php

NumberFormat.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Style/NumberFormat.php

541 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Style;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\RichText\RichText;
6
7 class NumberFormat extends Supervisor
8 {
9 // Pre-defined formats
10 const FORMAT_GENERAL = 'General';
11
12 const FORMAT_TEXT = '@';
13
14 const FORMAT_NUMBER = '0';
15 const FORMAT_NUMBER_0 = '0.0';
16 const FORMAT_NUMBER_00 = '0.00';
17 const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00';
18 const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-';
19
20 const FORMAT_PERCENTAGE = '0%';
21 const FORMAT_PERCENTAGE_0 = '0.0%';
22 const FORMAT_PERCENTAGE_00 = '0.00%';
23
24 const FORMAT_DATE_YYYYMMDD = 'yyyy-mm-dd';
25 const FORMAT_DATE_DDMMYYYY = 'dd/mm/yyyy';
26 const FORMAT_DATE_DMYSLASH = 'd"/"m"/"yy';
27 const FORMAT_DATE_DMYMINUS = 'd-m-yy';
28 const FORMAT_DATE_DMMINUS = 'd-m';
29 const FORMAT_DATE_MYMINUS = 'm-yy';
30 const FORMAT_DATE_XLSX14 = 'mm-dd-yy';
31 const FORMAT_DATE_XLSX14_ACTUAL = 'm/d/yyyy';
32 const FORMAT_DATE_XLSX15 = 'd-mmm-yy';
33 const FORMAT_DATE_XLSX15_YYYY = 'd-mmm-yyyy';
34 const FORMAT_DATE_XLSX16 = 'd-mmm';
35 const FORMAT_DATE_XLSX17 = 'mmm-yy';
36 const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm';
37 const FORMAT_DATE_XLSX22_ACTUAL = 'm/d/yyyy h:mm';
38 const FORMAT_DATE_DATETIME = 'd/m/yy h:mm';
39 const FORMAT_DATE_DATETIME_BETTER = 'yyyy-mm-dd hh:mm';
40 const FORMAT_DATE_TIME1 = 'h:mm AM/PM';
41 const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM';
42 const FORMAT_DATE_TIME3 = 'h:mm';
43 const FORMAT_DATE_TIME4 = 'h:mm:ss';
44 const FORMAT_DATE_TIME5 = 'mm:ss';
45 const FORMAT_DATE_TIME6 = 'h:mm:ss';
46 const FORMAT_DATE_TIME7 = 'i:s.S';
47 const FORMAT_DATE_TIME8 = 'h:mm:ss;@';
48 const FORMAT_DATE_TIME_INTERVAL_HMS = '[hh]:mm:ss';
49 const FORMAT_DATE_YYYYMMDDSLASH = 'yyyy"/"mm"/"dd;@';
50 const FORMAT_DATE_LONG_DATE = 'dddd, mmmm d, yyyy';
51
52 const DATE_TIME_OR_DATETIME_ARRAY = [
53 self::FORMAT_DATE_YYYYMMDD,
54 self::FORMAT_DATE_DDMMYYYY,
55 self::FORMAT_DATE_DMYSLASH,
56 self::FORMAT_DATE_DMYMINUS,
57 self::FORMAT_DATE_DMMINUS,
58 self::FORMAT_DATE_MYMINUS,
59 self::FORMAT_DATE_XLSX14,
60 self::FORMAT_DATE_XLSX14_ACTUAL,
61 self::FORMAT_DATE_XLSX15,
62 self::FORMAT_DATE_XLSX16,
63 self::FORMAT_DATE_XLSX17,
64 self::FORMAT_DATE_XLSX22,
65 self::FORMAT_DATE_XLSX22_ACTUAL,
66 self::FORMAT_DATE_DATETIME,
67 self::FORMAT_DATE_DATETIME_BETTER,
68 self::FORMAT_DATE_TIME1,
69 self::FORMAT_DATE_TIME2,
70 self::FORMAT_DATE_TIME3,
71 self::FORMAT_DATE_TIME4,
72 self::FORMAT_DATE_TIME5,
73 self::FORMAT_DATE_TIME6,
74 self::FORMAT_DATE_TIME7,
75 self::FORMAT_DATE_TIME8,
76 self::FORMAT_DATE_TIME_INTERVAL_HMS,
77 self::FORMAT_DATE_YYYYMMDDSLASH,
78 self::FORMAT_DATE_LONG_DATE,
79 ];
80 const TIME_OR_DATETIME_ARRAY = [
81 self::FORMAT_DATE_XLSX22,
82 self::FORMAT_DATE_DATETIME,
83 self::FORMAT_DATE_DATETIME_BETTER,
84 self::FORMAT_DATE_TIME1,
85 self::FORMAT_DATE_TIME2,
86 self::FORMAT_DATE_TIME3,
87 self::FORMAT_DATE_TIME4,
88 self::FORMAT_DATE_TIME5,
89 self::FORMAT_DATE_TIME6,
90 self::FORMAT_DATE_TIME7,
91 self::FORMAT_DATE_TIME8,
92 self::FORMAT_DATE_TIME_INTERVAL_HMS,
93 ];
94
95 private const FORMAT_CURRENCY_AMOUNT_INTEGER = '#,##0_-';
96 private const FORMAT_CURRENCY_AMOUNT_FLOAT = '#,##0.00_-';
97 const FORMAT_CURRENCY_USD_INTEGER = '$' . self::FORMAT_CURRENCY_AMOUNT_INTEGER;
98 const FORMAT_CURRENCY_USD = '$' . self::FORMAT_CURRENCY_AMOUNT_FLOAT;
99 const FORMAT_CURRENCY_GBP_INTEGER = '£' . self::FORMAT_CURRENCY_AMOUNT_INTEGER;
100 const FORMAT_CURRENCY_GBP = '£' . self::FORMAT_CURRENCY_AMOUNT_FLOAT;
101 const FORMAT_CURRENCY_YEN_YUAN_INTEGER = '¥' . self::FORMAT_CURRENCY_AMOUNT_INTEGER;
102 const FORMAT_CURRENCY_YEN_YUAN = '¥' . self::FORMAT_CURRENCY_AMOUNT_FLOAT;
103 const FORMAT_CURRENCY_EUR_INTEGER = '#,##0_-[$€]';
104 const FORMAT_CURRENCY_EUR = '#,##0.00_-[$€]';
105 const FORMAT_ACCOUNTING_USD = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)';
106 const FORMAT_ACCOUNTING_EUR = '_("€"* #,##0.00_);_("€"* \(#,##0.00\);_("€"* "-"??_);_(@_)';
107
108 const SHORT_DATE_INDEX = 14;
109 const DATE_TIME_INDEX = 22;
110 const FORMAT_SYSDATE_X = '[$-x-sysdate]';
111 const FORMAT_SYSDATE_F800 = '[$-F800]';
112 const FORMAT_SYSTIME_X = '[$-x-systime]';
113 const FORMAT_SYSTIME_F400 = '[$-F400]';
114
115 protected static string $shortDateFormat = self::FORMAT_DATE_XLSX14_ACTUAL;
116
117 protected static string $longDateFormat = self::FORMAT_DATE_LONG_DATE;
118
119 protected static string $dateTimeFormat = self::FORMAT_DATE_XLSX22_ACTUAL;
120
121 protected static string $timeFormat = self::FORMAT_DATE_TIME2;
122
123 /**
124 * Excel built-in number formats.
125 *
126 * @var string[]
127 */
128 protected static array $builtInFormats;
129
130 /**
131 * Excel built-in number formats (flipped, for faster lookups).
132 *
133 * @var int[]
134 */
135 protected static array $flippedBuiltInFormats;
136
137 /**
138 * Format Code.
139 */
140 protected ?string $formatCode = self::FORMAT_GENERAL;
141
142 /**
143 * Built-in format Code.
144 *
145 * @var false|int
146 */
147 protected $builtInFormatCode = 0;
148
149 /**
150 * Create a new NumberFormat.
151 *
152 * @param bool $isSupervisor Flag indicating if this is a supervisor or not
153 * Leave this value at default unless you understand exactly what
154 * its ramifications are
155 * @param bool $isConditional Flag indicating if this is a conditional style or not
156 * Leave this value at default unless you understand exactly what
157 * its ramifications are
158 */
159 public function __construct(bool $isSupervisor = false, bool $isConditional = false)
160 {
161 // Supervisor?
162 parent::__construct($isSupervisor);
163
164 if ($isConditional) {
165 $this->formatCode = null;
166 $this->builtInFormatCode = false;
167 }
168 }
169
170 /**
171 * Get the shared style component for the currently active cell in currently active sheet.
172 * Only used for style supervisor.
173 */
174 public function getSharedComponent(): self
175 {
176 /** @var Style $parent */
177 $parent = $this->parent;
178
179 return $parent->getSharedComponent()->getNumberFormat();
180 }
181
182 /**
183 * Build style array from subcomponents.
184 *
185 * @param mixed[] $array
186 *
187 * @return array{numberFormat: mixed[]}
188 */
189 public function getStyleArray(array $array): array
190 {
191 return ['numberFormat' => $array];
192 }
193
194 /**
195 * Apply styles from array.
196 *
197 * <code>
198 * $spreadsheet->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray(
199 * [
200 * 'formatCode' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE
201 * ]
202 * );
203 * </code>
204 *
205 * @param string[] $styleArray Array containing style information
206 *
207 * @return $this
208 */
209 public function applyFromArray(array $styleArray)
210 {
211 if ($this->isSupervisor) {
212 $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($styleArray));
213 } else {
214 if (isset($styleArray['formatCode'])) {
215 $this->setFormatCode($styleArray['formatCode']);
216 }
217 }
218
219 return $this;
220 }
221
222 /**
223 * Get Format Code.
224 */
225 public function getFormatCode(bool $extended = false): ?string
226 {
227 if ($this->isSupervisor) {
228 return $this->getSharedComponent()->getFormatCode($extended);
229 }
230 $builtin = $this->getBuiltInFormatCode();
231 if (is_int($builtin)) {
232 if ($extended) {
233 if ($builtin === self::SHORT_DATE_INDEX) {
234 return self::$shortDateFormat;
235 }
236 if ($builtin === self::DATE_TIME_INDEX) {
237 return self::$dateTimeFormat;
238 }
239 }
240
241 return self::builtInFormatCode($builtin);
242 }
243
244 return $extended ? self::convertSystemFormats($this->formatCode) : $this->formatCode;
245 }
246
247 public static function convertSystemFormats(?string $formatCode): ?string
248 {
249 if (is_string($formatCode)) {
250 if (stripos($formatCode, self::FORMAT_SYSDATE_F800) !== false || stripos($formatCode, self::FORMAT_SYSDATE_X) !== false) {
251 return self::$longDateFormat;
252 }
253 if (stripos($formatCode, self::FORMAT_SYSTIME_F400) !== false || stripos($formatCode, self::FORMAT_SYSTIME_X) !== false) {
254 return self::$timeFormat;
255 }
256 }
257
258 return $formatCode;
259 }
260
261 /**
262 * Set Format Code.
263 *
264 * @param string $formatCode see self::FORMAT_*
265 *
266 * @return $this
267 */
268 public function setFormatCode(string $formatCode)
269 {
270 if ($formatCode == '') {
271 $formatCode = self::FORMAT_GENERAL;
272 }
273 if ($this->isSupervisor) {
274 $styleArray = $this->getStyleArray(['formatCode' => $formatCode]);
275 $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
276 } else {
277 $this->formatCode = $formatCode;
278 $this->builtInFormatCode = self::builtInFormatCodeIndex($formatCode);
279 }
280
281 return $this;
282 }
283
284 /**
285 * Get Built-In Format Code.
286 *
287 * @return false|int
288 */
289 public function getBuiltInFormatCode()
290 {
291 if ($this->isSupervisor) {
292 return $this->getSharedComponent()->getBuiltInFormatCode();
293 }
294
295 return $this->builtInFormatCode;
296 }
297
298 /**
299 * Set Built-In Format Code.
300 *
301 * @param int $formatCodeIndex Id of the built-in format code to use
302 *
303 * @return $this
304 */
305 public function setBuiltInFormatCode(int $formatCodeIndex)
306 {
307 if ($this->isSupervisor) {
308 $styleArray = $this->getStyleArray(['formatCode' => self::builtInFormatCode($formatCodeIndex)]);
309 $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
310 } else {
311 $this->builtInFormatCode = $formatCodeIndex;
312 $this->formatCode = self::builtInFormatCode($formatCodeIndex);
313 }
314
315 return $this;
316 }
317
318 /**
319 * Fill built-in format codes.
320 */
321 private static function fillBuiltInFormatCodes(): void
322 {
323 // [MS-OI29500: Microsoft Office Implementation Information for ISO/IEC-29500 Standard Compliance]
324 // 18.8.30. numFmt (Number Format)
325 //
326 // The ECMA standard defines built-in format IDs
327 // 14: "mm-dd-yy"
328 // 22: "m/d/yy h:mm"
329 // 37: "#,##0 ;(#,##0)"
330 // 38: "#,##0 ;[Red](#,##0)"
331 // 39: "#,##0.00;(#,##0.00)"
332 // 40: "#,##0.00;[Red](#,##0.00)"
333 // 47: "mmss.0"
334 // KOR fmt 55: "yyyy-mm-dd"
335 // Excel defines built-in format IDs
336 // 14: "m/d/yyyy"
337 // 22: "m/d/yyyy h:mm"
338 // 37: "#,##0_);(#,##0)"
339 // 38: "#,##0_);[Red](#,##0)"
340 // 39: "#,##0.00_);(#,##0.00)"
341 // 40: "#,##0.00_);[Red](#,##0.00)"
342 // 47: "mm:ss.0"
343 // KOR fmt 55: "yyyy/mm/dd"
344
345 // Built-in format codes
346 if (empty(self::$builtInFormats)) {
347 self::$builtInFormats = [];
348
349 // General
350 self::$builtInFormats[0] = self::FORMAT_GENERAL;
351 self::$builtInFormats[1] = '0';
352 self::$builtInFormats[2] = '0.00';
353 self::$builtInFormats[3] = '#,##0';
354 self::$builtInFormats[4] = '#,##0.00';
355
356 self::$builtInFormats[9] = '0%';
357 self::$builtInFormats[10] = '0.00%';
358 self::$builtInFormats[11] = '0.00E+00';
359 self::$builtInFormats[12] = '# ?/?';
360 self::$builtInFormats[13] = '# ??/??';
361 self::$builtInFormats[14] = self::FORMAT_DATE_XLSX14_ACTUAL; // Despite ECMA 'mm-dd-yy';
362 self::$builtInFormats[15] = self::FORMAT_DATE_XLSX15;
363 self::$builtInFormats[16] = 'd-mmm';
364 self::$builtInFormats[17] = 'mmm-yy';
365 self::$builtInFormats[18] = 'h:mm AM/PM';
366 self::$builtInFormats[19] = 'h:mm:ss AM/PM';
367 self::$builtInFormats[20] = 'h:mm';
368 self::$builtInFormats[21] = 'h:mm:ss';
369 self::$builtInFormats[22] = self::FORMAT_DATE_XLSX22_ACTUAL; // Despite ECMA 'm/d/yy h:mm';
370
371 self::$builtInFormats[37] = '#,##0_);(#,##0)'; // Despite ECMA '#,##0 ;(#,##0)';
372 self::$builtInFormats[38] = '#,##0_);[Red](#,##0)'; // Despite ECMA '#,##0 ;[Red](#,##0)';
373 self::$builtInFormats[39] = '#,##0.00_);(#,##0.00)'; // Despite ECMA '#,##0.00;(#,##0.00)';
374 self::$builtInFormats[40] = '#,##0.00_);[Red](#,##0.00)'; // Despite ECMA '#,##0.00;[Red](#,##0.00)';
375
376 self::$builtInFormats[44] = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)';
377 self::$builtInFormats[45] = 'mm:ss';
378 self::$builtInFormats[46] = '[h]:mm:ss';
379 self::$builtInFormats[47] = 'mm:ss.0'; // Despite ECMA 'mmss.0';
380 self::$builtInFormats[48] = '##0.0E+0';
381 self::$builtInFormats[49] = '@';
382
383 // CHT
384 self::$builtInFormats[27] = '[$-404]e/m/d';
385 self::$builtInFormats[30] = 'm/d/yy';
386 self::$builtInFormats[36] = '[$-404]e/m/d';
387 self::$builtInFormats[50] = '[$-404]e/m/d';
388 self::$builtInFormats[57] = '[$-404]e/m/d';
389
390 // THA
391 self::$builtInFormats[59] = 't0';
392 self::$builtInFormats[60] = 't0.00';
393 self::$builtInFormats[61] = 't#,##0';
394 self::$builtInFormats[62] = 't#,##0.00';
395 self::$builtInFormats[67] = 't0%';
396 self::$builtInFormats[68] = 't0.00%';
397 self::$builtInFormats[69] = 't# ?/?';
398 self::$builtInFormats[70] = 't# ??/??';
399
400 // JPN
401 self::$builtInFormats[28] = '[$-411]ggge"年"m"月"d"日"';
402 self::$builtInFormats[29] = '[$-411]ggge"年"m"月"d"日"';
403 self::$builtInFormats[31] = 'yyyy"年"m"月"d"日"';
404 self::$builtInFormats[32] = 'h"時"mm"分"';
405 self::$builtInFormats[33] = 'h"時"mm"分"ss"秒"';
406 self::$builtInFormats[34] = 'yyyy"年"m"月"';
407 self::$builtInFormats[35] = 'm"月"d"日"';
408 self::$builtInFormats[51] = '[$-411]ggge"年"m"月"d"日"';
409 self::$builtInFormats[52] = 'yyyy"年"m"月"';
410 self::$builtInFormats[53] = 'm"月"d"日"';
411 self::$builtInFormats[54] = '[$-411]ggge"年"m"月"d"日"';
412 self::$builtInFormats[55] = 'yyyy"年"m"月"';
413 self::$builtInFormats[56] = 'm"月"d"日"';
414 self::$builtInFormats[58] = '[$-411]ggge"年"m"月"d"日"';
415
416 // Flip array (for faster lookups)
417 self::$flippedBuiltInFormats = array_flip(self::$builtInFormats);
418 }
419 }
420
421 /**
422 * Get built-in format code.
423 */
424 public static function builtInFormatCode(int $index): string
425 {
426 // Clean parameter
427 $index = (int) $index;
428
429 // Ensure built-in format codes are available
430 self::fillBuiltInFormatCodes();
431
432 // Lookup format code
433 if (isset(self::$builtInFormats[$index])) {
434 return self::$builtInFormats[$index];
435 }
436
437 return '';
438 }
439
440 /**
441 * Get built-in format code index.
442 *
443 * @return false|int
444 */
445 public static function builtInFormatCodeIndex(string $formatCodeIndex)
446 {
447 // Ensure built-in format codes are available
448 self::fillBuiltInFormatCodes();
449
450 // Lookup format code
451 if (array_key_exists($formatCodeIndex, self::$flippedBuiltInFormats)) {
452 return self::$flippedBuiltInFormats[$formatCodeIndex];
453 }
454
455 return false;
456 }
457
458 /**
459 * Get hash code.
460 *
461 * @return string Hash code
462 */
463 public function getHashCode(): string
464 {
465 if ($this->isSupervisor) {
466 return $this->getSharedComponent()->getHashCode();
467 }
468
469 return md5(
470 $this->formatCode
471 . $this->builtInFormatCode
472 . __CLASS__
473 );
474 }
475
476 /**
477 * Convert a value in a pre-defined format to a PHP string.
478 *
479 * @param mixed $value Value to format
480 * @param string $format Format code: see = self::FORMAT_* for predefined values;
481 * or can be any valid MS Excel custom format string
482 * @param null|callable(string, string): string $callBack Callback function for additional formatting of string
483 * @param bool $lessFloatPrecision If true, unstyled floats will be converted to a more human-friendly but less computationally accurate value
484 *
485 * @return string Formatted string
486 */
487 public static function toFormattedString($value, string $format, ?callable $callBack = null, bool $lessFloatPrecision = false): string
488 {
489 return NumberFormat\Formatter::toFormattedString($value, $format, $callBack, $lessFloatPrecision);
490 }
491
492 /** @return mixed[] */
493 protected function exportArray1(): array
494 {
495 $exportedArray = [];
496 $this->exportArray2($exportedArray, 'formatCode', $this->getFormatCode());
497
498 return $exportedArray;
499 }
500
501 public static function getShortDateFormat(): string
502 {
503 return self::$shortDateFormat;
504 }
505
506 public static function setShortDateFormat(string $shortDateFormat): void
507 {
508 self::$shortDateFormat = $shortDateFormat;
509 }
510
511 public static function getLongDateFormat(): string
512 {
513 return self::$longDateFormat;
514 }
515
516 public static function setLongDateFormat(string $longDateFormat): void
517 {
518 self::$longDateFormat = $longDateFormat;
519 }
520
521 public static function getDateTimeFormat(): string
522 {
523 return self::$dateTimeFormat;
524 }
525
526 public static function setDateTimeFormat(string $dateTimeFormat): void
527 {
528 self::$dateTimeFormat = $dateTimeFormat;
529 }
530
531 public static function getTimeFormat(): string
532 {
533 return self::$timeFormat;
534 }
535
536 public static function setTimeFormat(string $timeFormat): void
537 {
538 self::$timeFormat = $timeFormat;
539 }
540 }
541