PluginProbe
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin / 6.5.1.7
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin v6.5.1.7
6.5.1.7 6.5.1.6 6.5.1.5 6.5.1.4 6.5.1.3 6.5.1.2 6.5.1.1 6.5.0.9 6.5.0.8 6.5.0.7 6.5.0.6 trunk 3.4.2.40 3.4.2.41 3.4.2.42 3.4.2.43 3.4.2.44 3.4.2.45 3.4.2.46 3.4.2.47 3.4.2.48 3.4.2.49 3.4.2.50 6.3.2 6.3.3.1 All 47 releases
wpdatatables / lib / phpoffice / phpspreadsheet / src / PhpSpreadsheet / Calculation / TextData / Format.php

Format.php in wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin 6.5.1.7, at lib/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php

328 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
4
5 use Composer\Pcre\Preg;
6 use DateTimeInterface;
7 use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
8 use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
9 use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
10 use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
11 use PhpOffice\PhpSpreadsheet\Calculation\Functions;
12 use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
13 use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
14 use PhpOffice\PhpSpreadsheet\RichText\RichText;
15 use PhpOffice\PhpSpreadsheet\Shared\Date;
16 use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
17 use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
18
19 class Format
20 {
21 use ArrayEnabled;
22
23 /**
24 * DOLLAR.
25 *
26 * This function converts a number to text using currency format, with the decimals rounded to the specified place.
27 * The format used is $#,##0.00_);($#,##0.00)..
28 *
29 * @param mixed $value The value to format
30 * Or can be an array of values
31 * @param mixed $decimals The number of digits to display to the right of the decimal point (as an integer).
32 * If decimals is negative, number is rounded to the left of the decimal point.
33 * If you omit decimals, it is assumed to be 2
34 * Or can be an array of values
35 *
36 * @return array|string
37 * If an array of values is passed for either of the arguments, then the returned result
38 * will also be an array with matching dimensions
39 */
40 public static function DOLLAR($value = 0, $decimals = 2)
41 {
42 if (is_array($value) || is_array($decimals)) {
43 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $decimals);
44 }
45
46 try {
47 $value = Helpers::extractFloat($value);
48 $decimals = Helpers::extractInt($decimals, -100, 0, true);
49 } catch (CalcExp $e) {
50 return $e->getMessage();
51 }
52
53 $mask = '$#,##0';
54 if ($decimals > 0) {
55 $mask .= '.' . str_repeat('0', $decimals);
56 } else {
57 $round = 10 ** abs($decimals);
58 if ($value < 0) {
59 $round = 0 - $round;
60 }
61 $value = MathTrig\Round::multiple($value, $round);
62 }
63 $mask = "{$mask};-{$mask}";
64
65 return NumberFormat::toFormattedString($value, $mask);
66 }
67
68 /**
69 * FIXED.
70 *
71 * @param mixed $value The value to format
72 * Or can be an array of values
73 * @param mixed $decimals Integer value for the number of decimal places that should be formatted
74 * Or can be an array of values
75 * @param mixed $noCommas Boolean value indicating whether the value should have thousands separators or not
76 * Or can be an array of values
77 *
78 * @return array|string
79 * If an array of values is passed for either of the arguments, then the returned result
80 * will also be an array with matching dimensions
81 */
82 public static function FIXEDFORMAT($value, $decimals = 2, $noCommas = false)
83 {
84 if (is_array($value) || is_array($decimals) || is_array($noCommas)) {
85 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $decimals, $noCommas);
86 }
87
88 try {
89 $value = Helpers::extractFloat($value);
90 $decimals = Helpers::extractInt($decimals, -100, 0, true);
91 } catch (CalcExp $e) {
92 return $e->getMessage();
93 }
94
95 $valueResult = round($value, $decimals);
96 if ($decimals < 0) {
97 $decimals = 0;
98 }
99 if ($noCommas === false) {
100 $valueResult = number_format(
101 $valueResult,
102 $decimals,
103 StringHelper::getDecimalSeparator(),
104 StringHelper::getThousandsSeparator()
105 );
106 }
107
108 return (string) $valueResult;
109 }
110
111 /**
112 * TEXT.
113 *
114 * @param mixed $value The value to format
115 * Or can be an array of values
116 * @param mixed $format A string with the Format mask that should be used
117 * Or can be an array of values
118 *
119 * @return array|string
120 * If an array of values is passed for either of the arguments, then the returned result
121 * will also be an array with matching dimensions
122 */
123 public static function TEXTFORMAT($value, $format)
124 {
125 if (is_array($value) || is_array($format)) {
126 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $format);
127 }
128
129 $value = Helpers::extractString($value);
130 $format = Helpers::extractString($format);
131
132 if (!is_numeric($value) && Date::isDateTimeFormatCode($format) && !Preg::isMatch('/^\s*\d+(\s+\d+)+\s*$/', $value)) {
133 $value1 = DateTimeExcel\DateValue::fromString($value);
134 $value2 = DateTimeExcel\TimeValue::fromString($value);
135 /** @var float|int|string */
136 $value = (is_numeric($value1) && is_numeric($value2)) ? ($value1 + $value2) : (is_numeric($value1) ? $value1 : (is_numeric($value2) ? $value2 : $value));
137 }
138
139 return (string) NumberFormat::toFormattedString($value, $format);
140 }
141
142 /**
143 * @param mixed $value Value to check
144 *
145 * @return mixed
146 */
147 private static function convertValue($value, bool $spacesMeanZero = false)
148 {
149 $value = $value ?? 0;
150 if (is_bool($value)) {
151 if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) {
152 $value = (int) $value;
153 } else {
154 throw new CalcExp(ExcelError::VALUE());
155 }
156 }
157 if (is_string($value)) {
158 $value = trim($value);
159 if ($spacesMeanZero && $value === '') {
160 $value = 0;
161 }
162 }
163
164 return $value;
165 }
166
167 /**
168 * VALUE.
169 *
170 * @param mixed $value Value to check
171 * Or can be an array of values
172 *
173 * @return array|DateTimeInterface|float|int|string A string if arguments are invalid
174 * If an array of values is passed for the argument, then the returned result
175 * will also be an array with matching dimensions
176 */
177 public static function VALUE($value = '')
178 {
179 if (is_array($value)) {
180 return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
181 }
182
183 try {
184 $value = self::convertValue($value);
185 } catch (CalcExp $e) {
186 return $e->getMessage();
187 }
188 if (!is_numeric($value)) {
189 $numberValue = str_replace(
190 StringHelper::getThousandsSeparator(),
191 '',
192 trim($value, " \t\n\r\0\x0B" . StringHelper::getCurrencyCode())
193 );
194 if ($numberValue === '') {
195 return ExcelError::VALUE();
196 }
197 if (is_numeric($numberValue)) {
198 return (float) $numberValue;
199 }
200
201 $dateSetting = Functions::getReturnDateType();
202 Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
203
204 if (strpos($value, ':') !== false) {
205 $timeValue = Functions::scalar(DateTimeExcel\TimeValue::fromString($value));
206 if ($timeValue !== ExcelError::VALUE()) {
207 Functions::setReturnDateType($dateSetting);
208
209 return $timeValue;
210 }
211 }
212 $dateValue = Functions::scalar(DateTimeExcel\DateValue::fromString($value));
213 if ($dateValue !== ExcelError::VALUE()) {
214 Functions::setReturnDateType($dateSetting);
215
216 return $dateValue;
217 }
218 Functions::setReturnDateType($dateSetting);
219
220 return ExcelError::VALUE();
221 }
222
223 return (float) $value;
224 }
225
226 /**
227 * TEXT.
228 *
229 * @param mixed $value The value to format
230 * Or can be an array of values
231 * @param mixed $format
232 *
233 * @return array|string
234 * If an array of values is passed for either of the arguments, then the returned result
235 * will also be an array with matching dimensions
236 */
237 public static function valueToText($value, $format = false)
238 {
239 if (is_array($value) || is_array($format)) {
240 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $format);
241 }
242
243 $format = (bool) $format;
244
245 if (is_object($value) && $value instanceof RichText) {
246 $value = $value->getPlainText();
247 }
248 if (is_string($value)) {
249 $value = ($format === true) ? Calculation::wrapResult($value) : $value;
250 $value = str_replace("\n", '', $value);
251 } elseif (is_bool($value)) {
252 $value = Calculation::getLocaleBoolean($value ? 'TRUE' : 'FALSE');
253 }
254
255 return (string) $value;
256 }
257
258 /**
259 * @param mixed $decimalSeparator
260 */
261 private static function getDecimalSeparator($decimalSeparator): string
262 {
263 return empty($decimalSeparator) ? StringHelper::getDecimalSeparator() : (string) $decimalSeparator;
264 }
265
266 /**
267 * @param mixed $groupSeparator
268 */
269 private static function getGroupSeparator($groupSeparator): string
270 {
271 return empty($groupSeparator) ? StringHelper::getThousandsSeparator() : (string) $groupSeparator;
272 }
273
274 /**
275 * NUMBERVALUE.
276 *
277 * @param mixed $value The value to format
278 * Or can be an array of values
279 * @param mixed $decimalSeparator A string with the decimal separator to use, defaults to locale defined value
280 * Or can be an array of values
281 * @param mixed $groupSeparator A string with the group/thousands separator to use, defaults to locale defined value
282 * Or can be an array of values
283 *
284 * @return array|float|string
285 */
286 public static function NUMBERVALUE($value = '', $decimalSeparator = null, $groupSeparator = null)
287 {
288 if (is_array($value) || is_array($decimalSeparator) || is_array($groupSeparator)) {
289 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $decimalSeparator, $groupSeparator);
290 }
291
292 try {
293 $value = self::convertValue($value, true);
294 $decimalSeparator = self::getDecimalSeparator($decimalSeparator);
295 $groupSeparator = self::getGroupSeparator($groupSeparator);
296 } catch (CalcExp $e) {
297 return $e->getMessage();
298 }
299
300 if (!is_numeric($value)) {
301 $decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator, '/') . '/', $value, $matches, PREG_OFFSET_CAPTURE);
302 if ($decimalPositions > 1) {
303 return ExcelError::VALUE();
304 }
305 $decimalOffset = array_pop($matches[0])[1] ?? null;
306 if ($decimalOffset === null || strpos($value, $groupSeparator, $decimalOffset) !== false) {
307 return ExcelError::VALUE();
308 }
309
310 $value = str_replace([$groupSeparator, $decimalSeparator], ['', '.'], $value);
311
312 // Handle the special case of trailing % signs
313 $percentageString = rtrim($value, '%');
314 if (!is_numeric($percentageString)) {
315 return ExcelError::VALUE();
316 }
317
318 $percentageAdjustment = strlen($value) - strlen($percentageString);
319 if ($percentageAdjustment) {
320 $value = (float) $percentageString;
321 $value /= 10 ** ($percentageAdjustment * 2);
322 }
323 }
324
325 return is_array($value) ? ExcelError::VALUE() : (float) $value;
326 }
327 }
328