Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
4
 
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
7
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
8
use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;
9
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
10
use PhpOffice\PhpSpreadsheet\Cell\DataType;
11
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
12
 
13
class Concatenate
14
{
15
    use ArrayEnabled;
16
 
17
    /**
18
     * This implements the CONCAT function, *not* CONCATENATE.
19
     *
20
     * @param array $args
21
     */
22
    public static function CONCATENATE(...$args): string
23
    {
24
        $returnValue = '';
25
 
26
        // Loop through arguments
27
        $aArgs = Functions::flattenArray($args);
28
 
29
        foreach ($aArgs as $arg) {
30
            $value = Helpers::extractString($arg);
31
            if (ErrorValue::isError($value, true)) {
32
                $returnValue = $value;
33
 
34
                break;
35
            }
36
            $returnValue .= Helpers::extractString($arg);
37
            if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
38
                $returnValue = ExcelError::CALC();
39
 
40
                break;
41
            }
42
        }
43
 
44
        return $returnValue;
45
    }
46
 
47
    /**
48
     * This implements the CONCATENATE function.
49
     *
50
     * @param array $args data to be concatenated
51
     */
52
    public static function actualCONCATENATE(...$args): array|string
53
    {
54
        if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_GNUMERIC) {
55
            return self::CONCATENATE(...$args);
56
        }
57
        $result = '';
58
        foreach ($args as $operand2) {
59
            $result = self::concatenate2Args($result, $operand2);
60
            if (ErrorValue::isError($result, true) === true) {
61
                break;
62
            }
63
        }
64
 
65
        return $result;
66
    }
67
 
68
    private static function concatenate2Args(array|string $operand1, null|array|bool|float|int|string $operand2): array|string
69
    {
70
        if (is_array($operand1) || is_array($operand2)) {
71
            $operand1 = Calculation::boolToString($operand1);
72
            $operand2 = Calculation::boolToString($operand2);
73
            [$rows, $columns] = Calculation::checkMatrixOperands($operand1, $operand2, 2);
74
            $errorFound = false;
75
            for ($row = 0; $row < $rows && !$errorFound; ++$row) {
76
                for ($column = 0; $column < $columns; ++$column) {
77
                    if (ErrorValue::isError($operand2[$row][$column])) {
78
                        return $operand2[$row][$column];
79
                    }
80
                    $operand1[$row][$column]
81
                        = Calculation::boolToString($operand1[$row][$column])
82
                        . Calculation::boolToString($operand2[$row][$column]);
83
                    if (mb_strlen($operand1[$row][$column]) > DataType::MAX_STRING_LENGTH) {
84
                        $operand1 = ExcelError::CALC();
85
                        $errorFound = true;
86
 
87
                        break;
88
                    }
89
                }
90
            }
91
        } elseif (ErrorValue::isError($operand2, true) === true) {
92
            $operand1 = (string) $operand2;
93
        } else {
94
            $operand1 .= (string) Calculation::boolToString($operand2);
95
            if (mb_strlen($operand1) > DataType::MAX_STRING_LENGTH) {
96
                $operand1 = ExcelError::CALC();
97
            }
98
        }
99
 
100
        return $operand1;
101
    }
102
 
103
    /**
104
     * TEXTJOIN.
105
     *
106
     * @param mixed $delimiter The delimter to use between the joined arguments
107
     *                         Or can be an array of values
108
     * @param mixed $ignoreEmpty true/false Flag indicating whether empty arguments should be skipped
109
     *                         Or can be an array of values
110
     * @param mixed $args The values to join
111
     *
112
     * @return array|string The joined string
113
     *         If an array of values is passed for the $delimiter or $ignoreEmpty arguments, then the returned result
114
     *            will also be an array with matching dimensions
115
     */
116
    public static function TEXTJOIN(mixed $delimiter = '', mixed $ignoreEmpty = true, mixed ...$args): array|string
117
    {
118
        if (is_array($delimiter) || is_array($ignoreEmpty)) {
119
            return self::evaluateArrayArgumentsSubset(
120
                [self::class, __FUNCTION__],
121
                2,
122
                $delimiter,
123
                $ignoreEmpty,
124
                ...$args
125
            );
126
        }
127
 
128
        $delimiter ??= '';
129
        $ignoreEmpty ??= true;
130
        $aArgs = Functions::flattenArray($args);
131
        $returnValue = self::evaluateTextJoinArray($ignoreEmpty, $aArgs);
132
 
133
        $returnValue ??= implode($delimiter, $aArgs);
134
        if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
135
            $returnValue = ExcelError::CALC();
136
        }
137
 
138
        return $returnValue;
139
    }
140
 
141
    private static function evaluateTextJoinArray(bool $ignoreEmpty, array &$aArgs): ?string
142
    {
143
        foreach ($aArgs as $key => &$arg) {
144
            $value = Helpers::extractString($arg);
145
            if (ErrorValue::isError($value, true)) {
146
                return $value;
147
            }
148
 
149
            if ($ignoreEmpty === true && ((is_string($arg) && trim($arg) === '') || $arg === null)) {
150
                unset($aArgs[$key]);
151
            } elseif (is_bool($arg)) {
152
                $arg = Helpers::convertBooleanValue($arg);
153
            }
154
        }
155
 
156
        return null;
157
    }
158
 
159
    /**
160
     * REPT.
161
     *
162
     * Returns the result of builtin function round after validating args.
163
     *
164
     * @param mixed $stringValue The value to repeat
165
     *                         Or can be an array of values
166
     * @param mixed $repeatCount The number of times the string value should be repeated
167
     *                         Or can be an array of values
168
     *
169
     * @return array|string The repeated string
170
     *         If an array of values is passed for the $stringValue or $repeatCount arguments, then the returned result
171
     *            will also be an array with matching dimensions
172
     */
173
    public static function builtinREPT(mixed $stringValue, mixed $repeatCount): array|string
174
    {
175
        if (is_array($stringValue) || is_array($repeatCount)) {
176
            return self::evaluateArrayArguments([self::class, __FUNCTION__], $stringValue, $repeatCount);
177
        }
178
 
179
        $stringValue = Helpers::extractString($stringValue);
180
 
181
        if (!is_numeric($repeatCount) || $repeatCount < 0) {
182
            $returnValue = ExcelError::VALUE();
183
        } elseif (ErrorValue::isError($stringValue, true)) {
184
            $returnValue = $stringValue;
185
        } else {
186
            $returnValue = str_repeat($stringValue, (int) $repeatCount);
187
            if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
188
                $returnValue = ExcelError::VALUE(); // note VALUE not CALC
189
            }
190
        }
191
 
192
        return $returnValue;
193
    }
194
}