PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.0.3
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.0.3
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / phpoffice / phpexcel / Classes / PHPExcel / Shared / String.php

String.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.0.3, at vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/String.php

813 lines 23.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PHPExcel
4 *
5 * Copyright (c) 2006 - 2014 PHPExcel
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * @category PHPExcel
22 * @package PHPExcel_Shared
23 * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
24 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
25 * @version ##VERSION##, ##DATE##
26 */
27
28
29 /**
30 * PHPExcel_Shared_String
31 *
32 * @category PHPExcel
33 * @package PHPExcel_Shared
34 * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
35 */
36 class PHPExcel_Shared_String
37 {
38 /** Constants */
39 /** Regular Expressions */
40 // Fraction
41 const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)';
42
43
44 /**
45 * Control characters array
46 *
47 * @var string[]
48 */
49 private static $_controlCharacters = array();
50
51 /**
52 * SYLK Characters array
53 *
54 * $var array
55 */
56 private static $_SYLKCharacters = array();
57
58 /**
59 * Decimal separator
60 *
61 * @var string
62 */
63 private static $_decimalSeparator;
64
65 /**
66 * Thousands separator
67 *
68 * @var string
69 */
70 private static $_thousandsSeparator;
71
72 /**
73 * Currency code
74 *
75 * @var string
76 */
77 private static $_currencyCode;
78
79 /**
80 * Is mbstring extension avalable?
81 *
82 * @var boolean
83 */
84 private static $_isMbstringEnabled;
85
86 /**
87 * Is iconv extension avalable?
88 *
89 * @var boolean
90 */
91 private static $_isIconvEnabled;
92
93 /**
94 * Build control characters array
95 */
96 private static function _buildControlCharacters() {
97 for ($i = 0; $i <= 31; ++$i) {
98 if ($i != 9 && $i != 10 && $i != 13) {
99 $find = '_x' . sprintf('%04s' , strtoupper(dechex($i))) . '_';
100 $replace = chr($i);
101 self::$_controlCharacters[$find] = $replace;
102 }
103 }
104 }
105
106 /**
107 * Build SYLK characters array
108 */
109 private static function _buildSYLKCharacters()
110 {
111 self::$_SYLKCharacters = array(
112 "\x1B 0" => chr(0),
113 "\x1B 1" => chr(1),
114 "\x1B 2" => chr(2),
115 "\x1B 3" => chr(3),
116 "\x1B 4" => chr(4),
117 "\x1B 5" => chr(5),
118 "\x1B 6" => chr(6),
119 "\x1B 7" => chr(7),
120 "\x1B 8" => chr(8),
121 "\x1B 9" => chr(9),
122 "\x1B :" => chr(10),
123 "\x1B ;" => chr(11),
124 "\x1B <" => chr(12),
125 "\x1B :" => chr(13),
126 "\x1B >" => chr(14),
127 "\x1B ?" => chr(15),
128 "\x1B!0" => chr(16),
129 "\x1B!1" => chr(17),
130 "\x1B!2" => chr(18),
131 "\x1B!3" => chr(19),
132 "\x1B!4" => chr(20),
133 "\x1B!5" => chr(21),
134 "\x1B!6" => chr(22),
135 "\x1B!7" => chr(23),
136 "\x1B!8" => chr(24),
137 "\x1B!9" => chr(25),
138 "\x1B!:" => chr(26),
139 "\x1B!;" => chr(27),
140 "\x1B!<" => chr(28),
141 "\x1B!=" => chr(29),
142 "\x1B!>" => chr(30),
143 "\x1B!?" => chr(31),
144 "\x1B'?" => chr(127),
145 "\x1B(0" => '', // 128 in CP1252
146 "\x1B(2" => '', // 130 in CP1252
147 "\x1B(3" => 'ƒ', // 131 in CP1252
148 "\x1B(4" => '', // 132 in CP1252
149 "\x1B(5" => '', // 133 in CP1252
150 "\x1B(6" => '', // 134 in CP1252
151 "\x1B(7" => '', // 135 in CP1252
152 "\x1B(8" => 'ˆ', // 136 in CP1252
153 "\x1B(9" => '', // 137 in CP1252
154 "\x1B(:" => 'Š', // 138 in CP1252
155 "\x1B(;" => '', // 139 in CP1252
156 "\x1BNj" => 'Œ', // 140 in CP1252
157 "\x1B(>" => 'Ž', // 142 in CP1252
158 "\x1B)1" => '', // 145 in CP1252
159 "\x1B)2" => '', // 146 in CP1252
160 "\x1B)3" => '', // 147 in CP1252
161 "\x1B)4" => '', // 148 in CP1252
162 "\x1B)5" => '', // 149 in CP1252
163 "\x1B)6" => '', // 150 in CP1252
164 "\x1B)7" => '', // 151 in CP1252
165 "\x1B)8" => '˜', // 152 in CP1252
166 "\x1B)9" => '', // 153 in CP1252
167 "\x1B):" => 'š', // 154 in CP1252
168 "\x1B);" => '', // 155 in CP1252
169 "\x1BNz" => 'œ', // 156 in CP1252
170 "\x1B)>" => 'ž', // 158 in CP1252
171 "\x1B)?" => 'Ÿ', // 159 in CP1252
172 "\x1B*0" => ' ', // 160 in CP1252
173 "\x1BN!" => '¡', // 161 in CP1252
174 "\x1BN\"" => '¢', // 162 in CP1252
175 "\x1BN#" => '£', // 163 in CP1252
176 "\x1BN(" => '¤', // 164 in CP1252
177 "\x1BN%" => '¥', // 165 in CP1252
178 "\x1B*6" => '¦', // 166 in CP1252
179 "\x1BN'" => '§', // 167 in CP1252
180 "\x1BNH " => '¨', // 168 in CP1252
181 "\x1BNS" => '©', // 169 in CP1252
182 "\x1BNc" => 'ª', // 170 in CP1252
183 "\x1BN+" => '«', // 171 in CP1252
184 "\x1B*<" => '¬', // 172 in CP1252
185 "\x1B*=" => '­', // 173 in CP1252
186 "\x1BNR" => '®', // 174 in CP1252
187 "\x1B*?" => '¯', // 175 in CP1252
188 "\x1BN0" => '°', // 176 in CP1252
189 "\x1BN1" => '±', // 177 in CP1252
190 "\x1BN2" => '²', // 178 in CP1252
191 "\x1BN3" => '³', // 179 in CP1252
192 "\x1BNB " => '´', // 180 in CP1252
193 "\x1BN5" => 'µ', // 181 in CP1252
194 "\x1BN6" => '', // 182 in CP1252
195 "\x1BN7" => '·', // 183 in CP1252
196 "\x1B+8" => '¸', // 184 in CP1252
197 "\x1BNQ" => '¹', // 185 in CP1252
198 "\x1BNk" => 'º', // 186 in CP1252
199 "\x1BN;" => '»', // 187 in CP1252
200 "\x1BN<" => '¼', // 188 in CP1252
201 "\x1BN=" => '½', // 189 in CP1252
202 "\x1BN>" => '¾', // 190 in CP1252
203 "\x1BN?" => '¿', // 191 in CP1252
204 "\x1BNAA" => 'À', // 192 in CP1252
205 "\x1BNBA" => 'Á', // 193 in CP1252
206 "\x1BNCA" => 'Â', // 194 in CP1252
207 "\x1BNDA" => 'Ã', // 195 in CP1252
208 "\x1BNHA" => 'Ä', // 196 in CP1252
209 "\x1BNJA" => '�
210 ', // 197 in CP1252
211 "\x1BNa" => 'Æ', // 198 in CP1252
212 "\x1BNKC" => 'Ç', // 199 in CP1252
213 "\x1BNAE" => 'È', // 200 in CP1252
214 "\x1BNBE" => 'É', // 201 in CP1252
215 "\x1BNCE" => 'Ê', // 202 in CP1252
216 "\x1BNHE" => 'Ë', // 203 in CP1252
217 "\x1BNAI" => 'Ì', // 204 in CP1252
218 "\x1BNBI" => 'Í', // 205 in CP1252
219 "\x1BNCI" => 'Î', // 206 in CP1252
220 "\x1BNHI" => 'Ï', // 207 in CP1252
221 "\x1BNb" => 'Ð', // 208 in CP1252
222 "\x1BNDN" => 'Ñ', // 209 in CP1252
223 "\x1BNAO" => 'Ò', // 210 in CP1252
224 "\x1BNBO" => 'Ó', // 211 in CP1252
225 "\x1BNCO" => 'Ô', // 212 in CP1252
226 "\x1BNDO" => 'Õ', // 213 in CP1252
227 "\x1BNHO" => 'Ö', // 214 in CP1252
228 "\x1B-7" => '×', // 215 in CP1252
229 "\x1BNi" => 'Ø', // 216 in CP1252
230 "\x1BNAU" => 'Ù', // 217 in CP1252
231 "\x1BNBU" => 'Ú', // 218 in CP1252
232 "\x1BNCU" => 'Û', // 219 in CP1252
233 "\x1BNHU" => 'Ü', // 220 in CP1252
234 "\x1B-=" => 'Ý', // 221 in CP1252
235 "\x1BNl" => 'Þ', // 222 in CP1252
236 "\x1BN{" => 'ß', // 223 in CP1252
237 "\x1BNAa" => 'à', // 224 in CP1252
238 "\x1BNBa" => 'á', // 225 in CP1252
239 "\x1BNCa" => 'â', // 226 in CP1252
240 "\x1BNDa" => 'ã', // 227 in CP1252
241 "\x1BNHa" => 'ä', // 228 in CP1252
242 "\x1BNJa" => 'å', // 229 in CP1252
243 "\x1BNq" => 'æ', // 230 in CP1252
244 "\x1BNKc" => 'ç', // 231 in CP1252
245 "\x1BNAe" => 'è', // 232 in CP1252
246 "\x1BNBe" => 'é', // 233 in CP1252
247 "\x1BNCe" => 'ê', // 234 in CP1252
248 "\x1BNHe" => 'ë', // 235 in CP1252
249 "\x1BNAi" => 'ì', // 236 in CP1252
250 "\x1BNBi" => 'í', // 237 in CP1252
251 "\x1BNCi" => 'î', // 238 in CP1252
252 "\x1BNHi" => 'ï', // 239 in CP1252
253 "\x1BNs" => 'ð', // 240 in CP1252
254 "\x1BNDn" => 'ñ', // 241 in CP1252
255 "\x1BNAo" => 'ò', // 242 in CP1252
256 "\x1BNBo" => 'ó', // 243 in CP1252
257 "\x1BNCo" => 'ô', // 244 in CP1252
258 "\x1BNDo" => 'õ', // 245 in CP1252
259 "\x1BNHo" => 'ö', // 246 in CP1252
260 "\x1B/7" => '÷', // 247 in CP1252
261 "\x1BNy" => 'ø', // 248 in CP1252
262 "\x1BNAu" => 'ù', // 249 in CP1252
263 "\x1BNBu" => 'ú', // 250 in CP1252
264 "\x1BNCu" => 'û', // 251 in CP1252
265 "\x1BNHu" => 'ü', // 252 in CP1252
266 "\x1B/=" => 'ý', // 253 in CP1252
267 "\x1BN|" => 'þ', // 254 in CP1252
268 "\x1BNHy" => 'ÿ', // 255 in CP1252
269 );
270 }
271
272 /**
273 * Get whether mbstring extension is available
274 *
275 * @return boolean
276 */
277 public static function getIsMbstringEnabled()
278 {
279 if (isset(self::$_isMbstringEnabled)) {
280 return self::$_isMbstringEnabled;
281 }
282
283 self::$_isMbstringEnabled = function_exists('mb_convert_encoding') ?
284 true : false;
285
286 return self::$_isMbstringEnabled;
287 }
288
289 /**
290 * Get whether iconv extension is available
291 *
292 * @return boolean
293 */
294 public static function getIsIconvEnabled()
295 {
296 if (isset(self::$_isIconvEnabled)) {
297 return self::$_isIconvEnabled;
298 }
299
300 // Fail if iconv doesn't exist
301 if (!function_exists('iconv')) {
302 self::$_isIconvEnabled = false;
303 return false;
304 }
305
306 // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false,
307 if (!@iconv('UTF-8', 'UTF-16LE', 'x')) {
308 self::$_isIconvEnabled = false;
309 return false;
310 }
311
312 // Sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0
313 // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773)
314 if (!@iconv_substr('A', 0, 1, 'UTF-8')) {
315 self::$_isIconvEnabled = false;
316 return false;
317 }
318
319 // CUSTOM: IBM AIX iconv() does not work
320 if ( defined('PHP_OS') && @stristr(PHP_OS, 'AIX')
321 && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0)
322 && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0) )
323 {
324 self::$_isIconvEnabled = false;
325 return false;
326 }
327
328 // If we reach here no problems were detected with iconv
329 self::$_isIconvEnabled = true;
330 return true;
331 }
332
333 public static function buildCharacterSets() {
334 if(empty(self::$_controlCharacters)) {
335 self::_buildControlCharacters();
336 }
337 if(empty(self::$_SYLKCharacters)) {
338 self::_buildSYLKCharacters();
339 }
340 }
341
342 /**
343 * Convert from OpenXML escaped control character to PHP control character
344 *
345 * Excel 2007 team:
346 * ----------------
347 * That's correct, control characters are stored directly in the shared-strings table.
348 * We do encode characters that cannot be represented in XML using the following escape sequence:
349 * _xHHHH_ where H represents a hexadecimal character in the character's value...
350 * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
351 * element or in the shared string <t> element.
352 *
353 * @param string $value Value to unescape
354 * @return string
355 */
356 public static function ControlCharacterOOXML2PHP($value = '') {
357 return str_replace( array_keys(self::$_controlCharacters), array_values(self::$_controlCharacters), $value );
358 }
359
360 /**
361 * Convert from PHP control character to OpenXML escaped control character
362 *
363 * Excel 2007 team:
364 * ----------------
365 * That's correct, control characters are stored directly in the shared-strings table.
366 * We do encode characters that cannot be represented in XML using the following escape sequence:
367 * _xHHHH_ where H represents a hexadecimal character in the character's value...
368 * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
369 * element or in the shared string <t> element.
370 *
371 * @param string $value Value to escape
372 * @return string
373 */
374 public static function ControlCharacterPHP2OOXML($value = '') {
375 return str_replace( array_values(self::$_controlCharacters), array_keys(self::$_controlCharacters), $value );
376 }
377
378 /**
379 * Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
380 *
381 * @param string $value
382 * @return string
383 */
384 public static function SanitizeUTF8($value)
385 {
386 if (self::getIsIconvEnabled()) {
387 $value = @iconv('UTF-8', 'UTF-8', $value);
388 return $value;
389 }
390
391 if (self::getIsMbstringEnabled()) {
392 $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
393 return $value;
394 }
395
396 // else, no conversion
397 return $value;
398 }
399
400 /**
401 * Check if a string contains UTF8 data
402 *
403 * @param string $value
404 * @return boolean
405 */
406 public static function IsUTF8($value = '') {
407 return $value === '' || preg_match('/^./su', $value) === 1;
408 }
409
410 /**
411 * Formats a numeric value as a string for output in various output writers forcing
412 * point as decimal separator in case locale is other than English.
413 *
414 * @param mixed $value
415 * @return string
416 */
417 public static function FormatNumber($value) {
418 if (is_float($value)) {
419 return str_replace(',', '.', $value);
420 }
421 return (string) $value;
422 }
423
424 /**
425 * Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length)
426 * Writes the string using uncompressed notation, no rich text, no Asian phonetics
427 * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
428 * although this will give wrong results for non-ASCII strings
429 * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3
430 *
431 * @param string $value UTF-8 encoded string
432 * @param mixed[] $arrcRuns Details of rich text runs in $value
433 * @return string
434 */
435 public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = array())
436 {
437 // character count
438 $ln = self::CountCharacters($value, 'UTF-8');
439 // option flags
440 if(empty($arrcRuns)){
441 $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ?
442 0x0001 : 0x0000;
443 $data = pack('CC', $ln, $opt);
444 // characters
445 $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
446 }
447 else {
448 $data = pack('vC', $ln, 0x09);
449 $data .= pack('v', count($arrcRuns));
450 // characters
451 $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
452 foreach ($arrcRuns as $cRun){
453 $data .= pack('v', $cRun['strlen']);
454 $data .= pack('v', $cRun['fontidx']);
455 }
456 }
457 return $data;
458 }
459
460 /**
461 * Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length)
462 * Writes the string using uncompressed notation, no rich text, no Asian phonetics
463 * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
464 * although this will give wrong results for non-ASCII strings
465 * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3
466 *
467 * @param string $value UTF-8 encoded string
468 * @return string
469 */
470 public static function UTF8toBIFF8UnicodeLong($value)
471 {
472 // character count
473 $ln = self::CountCharacters($value, 'UTF-8');
474
475 // option flags
476 $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ?
477 0x0001 : 0x0000;
478
479 // characters
480 $chars = self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
481
482 $data = pack('vC', $ln, $opt) . $chars;
483 return $data;
484 }
485
486 /**
487 * Convert string from one encoding to another. First try mbstring, then iconv, finally strlen
488 *
489 * @param string $value
490 * @param string $to Encoding to convert to, e.g. 'UTF-8'
491 * @param string $from Encoding to convert from, e.g. 'UTF-16LE'
492 * @return string
493 */
494 public static function ConvertEncoding($value, $to, $from)
495 {
496 if (self::getIsIconvEnabled()) {
497 return iconv($from, $to, $value);
498 }
499
500 if (self::getIsMbstringEnabled()) {
501 return mb_convert_encoding($value, $to, $from);
502 }
503
504 if($from == 'UTF-16LE'){
505 return self::utf16_decode($value, false);
506 }else if($from == 'UTF-16BE'){
507 return self::utf16_decode($value);
508 }
509 // else, no conversion
510 return $value;
511 }
512
513 /**
514 * Decode UTF-16 encoded strings.
515 *
516 * Can handle both BOM'ed data and un-BOM'ed data.
517 * Assumes Big-Endian byte order if no BOM is available.
518 * This function was taken from http://php.net/manual/en/function.utf8-decode.php
519 * and $bom_be parameter added.
520 *
521 * @param string $str UTF-16 encoded data to decode.
522 * @return string UTF-8 / ISO encoded data.
523 * @access public
524 * @version 0.2 / 2010-05-13
525 * @author Rasmus Andersson {@link http://rasmusandersson.se/}
526 * @author vadik56
527 */
528 public static function utf16_decode($str, $bom_be = TRUE) {
529 if( strlen($str) < 2 ) return $str;
530 $c0 = ord($str{0});
531 $c1 = ord($str{1});
532 if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); }
533 elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; }
534 $len = strlen($str);
535 $newstr = '';
536 for($i=0;$i<$len;$i+=2) {
537 if( $bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); }
538 else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); }
539 $newstr .= ($val == 0x228) ? "\n" : chr($val);
540 }
541 return $newstr;
542 }
543
544 /**
545 * Get character count. First try mbstring, then iconv, finally strlen
546 *
547 * @param string $value
548 * @param string $enc Encoding
549 * @return int Character count
550 */
551 public static function CountCharacters($value, $enc = 'UTF-8')
552 {
553 if (self::getIsMbstringEnabled()) {
554 return mb_strlen($value, $enc);
555 }
556
557 if (self::getIsIconvEnabled()) {
558 return iconv_strlen($value, $enc);
559 }
560
561 // else strlen
562 return strlen($value);
563 }
564
565 /**
566 * Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen
567 *
568 * @param string $pValue UTF-8 encoded string
569 * @param int $pStart Start offset
570 * @param int $pLength Maximum number of characters in substring
571 * @return string
572 */
573 public static function Substring($pValue = '', $pStart = 0, $pLength = 0)
574 {
575 if (self::getIsMbstringEnabled()) {
576 return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
577 }
578
579 if (self::getIsIconvEnabled()) {
580 return iconv_substr($pValue, $pStart, $pLength, 'UTF-8');
581 }
582
583 // else substr
584 return substr($pValue, $pStart, $pLength);
585 }
586
587 /**
588 * Convert a UTF-8 encoded string to upper case
589 *
590 * @param string $pValue UTF-8 encoded string
591 * @return string
592 */
593 public static function StrToUpper($pValue = '')
594 {
595 if (function_exists('mb_convert_case')) {
596 return mb_convert_case($pValue, MB_CASE_UPPER, "UTF-8");
597 }
598 return strtoupper($pValue);
599 }
600
601 /**
602 * Convert a UTF-8 encoded string to lower case
603 *
604 * @param string $pValue UTF-8 encoded string
605 * @return string
606 */
607 public static function StrToLower($pValue = '')
608 {
609 if (function_exists('mb_convert_case')) {
610 return mb_convert_case($pValue, MB_CASE_LOWER, "UTF-8");
611 }
612 return strtolower($pValue);
613 }
614
615 /**
616 * Convert a UTF-8 encoded string to title/proper case
617 * (uppercase every first character in each word, lower case all other characters)
618 *
619 * @param string $pValue UTF-8 encoded string
620 * @return string
621 */
622 public static function StrToTitle($pValue = '')
623 {
624 if (function_exists('mb_convert_case')) {
625 return mb_convert_case($pValue, MB_CASE_TITLE, "UTF-8");
626 }
627 return ucwords($pValue);
628 }
629
630 public static function mb_is_upper($char)
631 {
632 return mb_strtolower($char, "UTF-8") != $char;
633 }
634
635 public static function mb_str_split($string)
636 {
637 # Split at all position not after the start: ^
638 # and not before the end: $
639 return preg_split('/(?<!^)(?!$)/u', $string );
640 }
641
642 /**
643 * Reverse the case of a string, so that all uppercase characters become lowercase
644 * and all lowercase characters become uppercase
645 *
646 * @param string $pValue UTF-8 encoded string
647 * @return string
648 */
649 public static function StrCaseReverse($pValue = '')
650 {
651 if (self::getIsMbstringEnabled()) {
652 $characters = self::mb_str_split($pValue);
653 foreach($characters as &$character) {
654 if(self::mb_is_upper($character)) {
655 $character = mb_strtolower($character, 'UTF-8');
656 } else {
657 $character = mb_strtoupper($character, 'UTF-8');
658 }
659 }
660 return implode('', $characters);
661 }
662 return strtolower($pValue) ^ strtoupper($pValue) ^ $pValue;
663 }
664
665 /**
666 * Identify whether a string contains a fractional numeric value,
667 * and convert it to a numeric if it is
668 *
669 * @param string &$operand string value to test
670 * @return boolean
671 */
672 public static function convertToNumberIfFraction(&$operand) {
673 if (preg_match('/^'.self::STRING_REGEXP_FRACTION.'$/i', $operand, $match)) {
674 $sign = ($match[1] == '-') ? '-' : '+';
675 $fractionFormula = '='.$sign.$match[2].$sign.$match[3];
676 $operand = PHPExcel_Calculation::getInstance()->_calculateFormulaValue($fractionFormula);
677 return true;
678 }
679 return false;
680 } // function convertToNumberIfFraction()
681
682 /**
683 * Get the decimal separator. If it has not yet been set explicitly, try to obtain number
684 * formatting information from locale.
685 *
686 * @return string
687 */
688 public static function getDecimalSeparator()
689 {
690 if (!isset(self::$_decimalSeparator)) {
691 $localeconv = localeconv();
692 self::$_decimalSeparator = ($localeconv['decimal_point'] != '')
693 ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point'];
694
695 if (self::$_decimalSeparator == '') {
696 // Default to .
697 self::$_decimalSeparator = '.';
698 }
699 }
700 return self::$_decimalSeparator;
701 }
702
703 /**
704 * Set the decimal separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString()
705 * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF
706 *
707 * @param string $pValue Character for decimal separator
708 */
709 public static function setDecimalSeparator($pValue = '.')
710 {
711 self::$_decimalSeparator = $pValue;
712 }
713
714 /**
715 * Get the thousands separator. If it has not yet been set explicitly, try to obtain number
716 * formatting information from locale.
717 *
718 * @return string
719 */
720 public static function getThousandsSeparator()
721 {
722 if (!isset(self::$_thousandsSeparator)) {
723 $localeconv = localeconv();
724 self::$_thousandsSeparator = ($localeconv['thousands_sep'] != '')
725 ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep'];
726
727 if (self::$_thousandsSeparator == '') {
728 // Default to .
729 self::$_thousandsSeparator = ',';
730 }
731 }
732 return self::$_thousandsSeparator;
733 }
734
735 /**
736 * Set the thousands separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString()
737 * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF
738 *
739 * @param string $pValue Character for thousands separator
740 */
741 public static function setThousandsSeparator($pValue = ',')
742 {
743 self::$_thousandsSeparator = $pValue;
744 }
745
746 /**
747 * Get the currency code. If it has not yet been set explicitly, try to obtain the
748 * symbol information from locale.
749 *
750 * @return string
751 */
752 public static function getCurrencyCode()
753 {
754 if (!isset(self::$_currencyCode)) {
755 $localeconv = localeconv();
756 self::$_currencyCode = ($localeconv['currency_symbol'] != '')
757 ? $localeconv['currency_symbol'] : $localeconv['int_curr_symbol'];
758
759 if (self::$_currencyCode == '') {
760 // Default to $
761 self::$_currencyCode = '$';
762 }
763 }
764 return self::$_currencyCode;
765 }
766
767 /**
768 * Set the currency code. Only used by PHPExcel_Style_NumberFormat::toFormattedString()
769 * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF
770 *
771 * @param string $pValue Character for currency code
772 */
773 public static function setCurrencyCode($pValue = '$')
774 {
775 self::$_currencyCode = $pValue;
776 }
777
778 /**
779 * Convert SYLK encoded string to UTF-8
780 *
781 * @param string $pValue
782 * @return string UTF-8 encoded string
783 */
784 public static function SYLKtoUTF8($pValue = '')
785 {
786 // If there is no escape character in the string there is nothing to do
787 if (strpos($pValue, '') === false) {
788 return $pValue;
789 }
790
791 foreach (self::$_SYLKCharacters as $k => $v) {
792 $pValue = str_replace($k, $v, $pValue);
793 }
794
795 return $pValue;
796 }
797
798 /**
799 * Retrieve any leading numeric part of a string, or return the full string if no leading numeric
800 * (handles basic integer or float, but not exponent or non decimal)
801 *
802 * @param string $value
803 * @return mixed string or only the leading numeric part of the string
804 */
805 public static function testStringAsNumeric($value)
806 {
807 if (is_numeric($value))
808 return $value;
809 $v = floatval($value);
810 return (is_numeric(substr($value, 0, strlen($v)))) ? $v : $value;
811 }
812 }
813