Skip to content

Commit 7156317

Browse files
author
MarkBaker
committed
LEFT(), RIGHT, MID(), CLEAN(), TRIM(), TEXTJOIN() and REPT() functions
1 parent c988612 commit 7156317

File tree

14 files changed

+269
-31
lines changed

14 files changed

+269
-31
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,11 +1940,6 @@ parameters:
19401940
count: 1
19411941
path: src/PhpSpreadsheet/Calculation/TextData.php
19421942

1943-
-
1944-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\:\\:TRIMNONPRINTABLE\\(\\) should return string but returns string\\|null\\.$#"
1945-
count: 1
1946-
path: src/PhpSpreadsheet/Calculation/TextData.php
1947-
19481943
-
19491944
message: "#^Parameter \\#1 \\$glue of function implode expects string, mixed given\\.$#"
19501945
count: 1

src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class NetworkDays
3030
* @param mixed $dateArgs An array of dates (such as holidays) to exclude from the calculation
3131
*
3232
* @return array|int|string Interval between the dates
33+
* If an array of values is passed for the $startDate or $endDate arguments, then the returned result
34+
* will also be an array with matching dimensions
3335
*/
3436
public static function count($startDate, $endDate, ...$dateArgs)
3537
{

src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class YearFrac
2626
*
2727
* @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
2828
* PHP DateTime object, or a standard date string
29-
* Or can be an array of methods
29+
* Or can be an array of values
3030
* @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
3131
* PHP DateTime object, or a standard date string
3232
* Or can be an array of methods

src/PhpSpreadsheet/Calculation/TextData.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static function CHARACTER($character)
3434
*
3535
* @param mixed $stringValue Value to check
3636
*
37-
* @return string
37+
* @return null|array|string
3838
*/
3939
public static function TRIMNONPRINTABLE($stringValue = '')
4040
{
@@ -50,7 +50,7 @@ public static function TRIMNONPRINTABLE($stringValue = '')
5050
*
5151
* @param mixed $stringValue Value to check
5252
*
53-
* @return string
53+
* @return array|string
5454
*/
5555
public static function TRIMSPACES($stringValue = '')
5656
{
@@ -170,10 +170,10 @@ public static function FIXEDFORMAT($value, $decimals = 2, $no_commas = false)
170170
*
171171
* @see Use the left() method in the TextData\Extract class instead
172172
*
173-
* @param string $value Value
174-
* @param int $chars Number of characters
173+
* @param array|string $value Value
174+
* @param array|int $chars Number of characters
175175
*
176-
* @return string
176+
* @return array|string
177177
*/
178178
public static function LEFT($value = '', $chars = 1)
179179
{
@@ -187,11 +187,11 @@ public static function LEFT($value = '', $chars = 1)
187187
*
188188
* @see Use the mid() method in the TextData\Extract class instead
189189
*
190-
* @param string $value Value
191-
* @param int $start Start character
192-
* @param int $chars Number of characters
190+
* @param array|string $value Value
191+
* @param array|int $start Start character
192+
* @param array|int $chars Number of characters
193193
*
194-
* @return string
194+
* @return array|string
195195
*/
196196
public static function MID($value = '', $start = 1, $chars = null)
197197
{
@@ -205,10 +205,10 @@ public static function MID($value = '', $start = 1, $chars = null)
205205
*
206206
* @see Use the right() method in the TextData\Extract class instead
207207
*
208-
* @param string $value Value
209-
* @param int $chars Number of characters
208+
* @param array|string $value Value
209+
* @param array|int $chars Number of characters
210210
*
211-
* @return string
211+
* @return array|string
212212
*/
213213
public static function RIGHT($value = '', $chars = 1)
214214
{
@@ -420,7 +420,7 @@ public static function EXACT($value1, $value2)
420420
* @param mixed $ignoreEmpty
421421
* @param mixed $args
422422
*
423-
* @return string
423+
* @return array|string
424424
*/
425425
public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args)
426426
{
@@ -436,10 +436,10 @@ public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args)
436436
*
437437
* @see Use the builtinREPT() method in the TextData\Concatenate class instead
438438
*
439-
* @param string $str Should be numeric
439+
* @param array|string $str Should be numeric
440440
* @param mixed $number Should be int
441441
*
442-
* @return string
442+
* @return array|string
443443
*/
444444
public static function builtinREPT($str, $number)
445445
{

src/PhpSpreadsheet/Calculation/TextData/Concatenate.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
67

78
class Concatenate
89
{
10+
use ArrayEnabled;
11+
912
/**
1013
* CONCATENATE.
1114
*
@@ -28,12 +31,28 @@ public static function CONCATENATE(...$args): string
2831
/**
2932
* TEXTJOIN.
3033
*
31-
* @param mixed $delimiter
32-
* @param mixed $ignoreEmpty
33-
* @param mixed $args
34+
* @param mixed $delimiter The delimter to use between the joined arguments
35+
* Or can be an array of values
36+
* @param mixed $ignoreEmpty true/false Flag indicating whether empty arguments should be skipped
37+
* Or can be an array of values
38+
* @param mixed $args The values to join
39+
*
40+
* @return array|string The joined string
41+
* If an array of values is passed for the $delimiter or $ignoreEmpty arguments, then the returned result
42+
* will also be an array with matching dimensions
3443
*/
35-
public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args): string
44+
public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args)
3645
{
46+
if (is_array($delimiter) || is_array($ignoreEmpty)) {
47+
return self::evaluateArrayArgumentsSubset(
48+
[self::class, __FUNCTION__],
49+
2,
50+
$delimiter,
51+
$ignoreEmpty,
52+
...$args
53+
);
54+
}
55+
3756
$delimiter = Functions::flattenSingleValue($delimiter);
3857
$ignoreEmpty = Functions::flattenSingleValue($ignoreEmpty);
3958
// Loop through arguments
@@ -55,10 +74,20 @@ public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args): string
5574
* Returns the result of builtin function round after validating args.
5675
*
5776
* @param mixed $stringValue The value to repeat
77+
* Or can be an array of values
5878
* @param mixed $repeatCount The number of times the string value should be repeated
79+
* Or can be an array of values
80+
*
81+
* @return array|string The repeated string
82+
* If an array of values is passed for the $stringValue or $repeatCount arguments, then the returned result
83+
* will also be an array with matching dimensions
5984
*/
60-
public static function builtinREPT($stringValue, $repeatCount): string
85+
public static function builtinREPT($stringValue, $repeatCount)
6186
{
87+
if (is_array($stringValue) || is_array($repeatCount)) {
88+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $stringValue, $repeatCount);
89+
}
90+
6291
$repeatCount = Functions::flattenSingleValue($repeatCount);
6392
$stringValue = Helpers::extractString($stringValue);
6493

src/PhpSpreadsheet/Calculation/TextData/Extract.php

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,31 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
67

78
class Extract
89
{
10+
use ArrayEnabled;
11+
912
/**
1013
* LEFT.
1114
*
1215
* @param mixed $value String value from which to extract characters
16+
* Or can be an array of values
1317
* @param mixed $chars The number of characters to extract (as an integer)
18+
* Or can be an array of values
19+
*
20+
* @return array|string The joined string
21+
* If an array of values is passed for the $value or $chars arguments, then the returned result
22+
* will also be an array with matching dimensions
1423
*/
15-
public static function left($value, $chars = 1): string
24+
public static function left($value, $chars = 1)
1625
{
26+
if (is_array($value) || is_array($chars)) {
27+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $chars);
28+
}
29+
1730
try {
1831
$value = Helpers::extractString($value);
1932
$chars = Helpers::extractInt($chars, 0, 1);
@@ -28,11 +41,22 @@ public static function left($value, $chars = 1): string
2841
* MID.
2942
*
3043
* @param mixed $value String value from which to extract characters
44+
* Or can be an array of values
3145
* @param mixed $start Integer offset of the first character that we want to extract
46+
* Or can be an array of values
3247
* @param mixed $chars The number of characters to extract (as an integer)
48+
* Or can be an array of values
49+
*
50+
* @return array|string The joined string
51+
* If an array of values is passed for the $value, $start or $chars arguments, then the returned result
52+
* will also be an array with matching dimensions
3353
*/
34-
public static function mid($value, $start, $chars): string
54+
public static function mid($value, $start, $chars)
3555
{
56+
if (is_array($value) || is_array($start) || is_array($chars)) {
57+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $start, $chars);
58+
}
59+
3660
try {
3761
$value = Helpers::extractString($value);
3862
$start = Helpers::extractInt($start, 1);
@@ -48,10 +72,20 @@ public static function mid($value, $start, $chars): string
4872
* RIGHT.
4973
*
5074
* @param mixed $value String value from which to extract characters
75+
* Or can be an array of values
5176
* @param mixed $chars The number of characters to extract (as an integer)
77+
* Or can be an array of values
78+
*
79+
* @return array|string The joined string
80+
* If an array of values is passed for the $value or $chars arguments, then the returned result
81+
* will also be an array with matching dimensions
5282
*/
53-
public static function right($value, $chars = 1): string
83+
public static function right($value, $chars = 1)
5484
{
85+
if (is_array($value) || is_array($chars)) {
86+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $chars);
87+
}
88+
5589
try {
5690
$value = Helpers::extractString($value);
5791
$chars = Helpers::extractInt($chars, 0, 1);

src/PhpSpreadsheet/Calculation/TextData/Trim.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,28 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6+
57
class Trim
68
{
9+
use ArrayEnabled;
10+
711
/**
812
* CLEAN.
913
*
1014
* @param mixed $stringValue String Value to check
15+
* Or can be an array of values
1116
*
12-
* @return null|string
17+
* @return null|array|string
18+
* If an array of values is passed as the argument, then the returned result will also be an array
19+
* with the same dimensions
1320
*/
1421
public static function nonPrintable($stringValue = '')
1522
{
23+
if (is_array($stringValue)) {
24+
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $stringValue);
25+
}
26+
1627
$stringValue = Helpers::extractString($stringValue);
1728

1829
return preg_replace('/[\\x00-\\x1f]/', '', "$stringValue");
@@ -22,11 +33,18 @@ public static function nonPrintable($stringValue = '')
2233
* TRIM.
2334
*
2435
* @param mixed $stringValue String Value to check
36+
* Or can be an array of values
2537
*
26-
* @return string
38+
* @return array|string
39+
* If an array of values is passed as the argument, then the returned result will also be an array
40+
* with the same dimensions
2741
*/
2842
public static function spaces($stringValue = '')
2943
{
44+
if (is_array($stringValue)) {
45+
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $stringValue);
46+
}
47+
3048
$stringValue = Helpers::extractString($stringValue);
3149

3250
return trim(preg_replace('/ +/', ' ', trim("$stringValue", ' ')) ?? '', ' ');

tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CleanTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6+
57
class CleanTest extends AllSetupTeardown
68
{
79
/**
@@ -28,4 +30,25 @@ public function providerCLEAN(): array
2830
{
2931
return require 'tests/data/Calculation/TextData/CLEAN.php';
3032
}
33+
34+
/**
35+
* @dataProvider providerCleanArray
36+
*/
37+
public function testCleanArray(array $expectedResult, string $array): void
38+
{
39+
$calculation = Calculation::getInstance();
40+
41+
$formula = "=CLEAN({$array})";
42+
$result = $calculation->_calculateFormulaValue($formula);
43+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
44+
}
45+
46+
public function providerCleanArray(): array
47+
{
48+
return [
49+
'row vector' => [[['PHP', 'MS Excel', 'Open/Libre Office']], '{"PHP", "MS Excel", "Open/Libre Office"}'],
50+
'column vector' => [[['PHP'], ['MS Excel'], ['Open/Libre Office']], '{"PHP"; "MS Excel"; "Open/Libre Office"}'],
51+
'matrix' => [[['PHP', 'MS Excel'], ['PhpSpreadsheet', 'Open/Libre Office']], '{"PHP", "MS Excel"; "PhpSpreadsheet", "Open/Libre Office"}'],
52+
];
53+
}
3154
}

tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LeftTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
56
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
67
use PhpOffice\PhpSpreadsheet\Settings;
78

@@ -180,4 +181,26 @@ public function providerCalculationTypeLEFTNull(): array
180181
],
181182
];
182183
}
184+
185+
/**
186+
* @dataProvider providerLeftArray
187+
*/
188+
public function testLeftArray(array $expectedResult, string $argument1, string $argument2): void
189+
{
190+
$calculation = Calculation::getInstance();
191+
192+
$formula = "=LEFT({$argument1}, {$argument2})";
193+
$result = $calculation->_calculateFormulaValue($formula);
194+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
195+
}
196+
197+
public function providerLeftArray(): array
198+
{
199+
return [
200+
'row vector #1' => [[['Hel', 'Wor', 'Php']], '{"Hello", "World", "PhpSpreadsheet"}', '3'],
201+
'column vector #1' => [[['Hel'], ['Wor'], ['Php']], '{"Hello"; "World"; "PhpSpreadsheet"}', '3'],
202+
'matrix #1' => [[['Hel', 'Wor'], ['Php', 'Exc']], '{"Hello", "World"; "PhpSpreadsheet", "Excel"}', '3'],
203+
'column vector #2' => [[['Php'], ['PhpSp']], '"PhpSpreadsheet"', '{3; 5}'],
204+
];
205+
}
183206
}

0 commit comments

Comments
 (0)