Passed
Push — master ( 653645...08f2f1 )
by
unknown
16:09 queued 04:49
created

RowColumnInformation::convert0ToName()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 4
nc 2
nop 1
crap 4
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
use PhpOffice\PhpSpreadsheet\Cell\Cell;
9
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
10
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
11
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
12
13
class RowColumnInformation
14
{
15
    /**
16
     * Test if cellAddress is null or whitespace string.
17
     *
18
     * @param null|mixed[]|string $cellAddress A reference to a range of cells
19
     */
20 111
    private static function cellAddressNullOrWhitespace($cellAddress): bool
21
    {
22 111
        return $cellAddress === null || (!is_array($cellAddress) && trim($cellAddress) === '');
23
    }
24
25 2
    private static function cellColumn(?Cell $cell): int
26
    {
27 2
        return ($cell !== null) ? Coordinate::columnIndexFromString($cell->getColumn()) : 1;
28
    }
29
30
    /**
31
     * COLUMN.
32
     *
33
     * Returns the column number of the given cell reference
34
     *     If the cell reference is a range of cells, COLUMN returns the column numbers of each column
35
     *        in the reference as a horizontal array.
36
     *     If cell reference is omitted, and the function is being called through the calculation engine,
37
     *        then it is assumed to be the reference of the cell in which the COLUMN function appears;
38
     *        otherwise this function returns 1.
39
     *
40
     * Excel Function:
41
     *        =COLUMN([cellAddress])
42
     *
43
     * @param null|mixed[]|string $cellAddress A reference to a range of cells for which you want the column numbers
44
     *
45
     * @return int|int[]|string
46
     */
47 27
    public static function COLUMN($cellAddress = null, ?Cell $cell = null): int|string|array
48
    {
49 27
        if (self::cellAddressNullOrWhitespace($cellAddress)) {
50 1
            return self::cellColumn($cell);
51
        }
52
53 26
        if (is_array($cellAddress)) {
54 2
            foreach ($cellAddress as $columnKey => $value) {
55 1
                $columnKey = (string) preg_replace('/[^a-z]/i', '', $columnKey);
56
57 1
                return Coordinate::columnIndexFromString($columnKey);
58
            }
59
60 1
            return self::cellColumn($cell);
61
        }
62
63 24
        $cellAddress = $cellAddress ?? '';
64 24
        if ($cell != null) {
65 19
            [,, $sheetName] = Helpers::extractWorksheet($cellAddress, $cell);
66 19
            [,, $cellAddress] = Helpers::extractCellAddresses($cellAddress, true, $cell->getWorksheet(), $sheetName);
67
        }
68 24
        [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
69 24
        $cellAddress ??= '';
70
71 24
        if (str_contains($cellAddress, ':')) {
72 11
            [$startAddress, $endAddress] = explode(':', $cellAddress);
73 11
            $startAddress = (string) preg_replace('/[^a-z]/i', '', $startAddress);
74 11
            $endAddress = (string) preg_replace('/[^a-z]/i', '', $endAddress);
75
76 11
            return range(
77 11
                Coordinate::columnIndexFromString($startAddress),
78 11
                Coordinate::columnIndexFromString($endAddress)
79 11
            );
80
        }
81
82 16
        $cellAddress = (string) preg_replace('/[^a-z]/i', '', $cellAddress);
83
84
        try {
85 16
            return Coordinate::columnIndexFromString($cellAddress);
86 6
        } catch (SpreadsheetException) {
87 6
            return ExcelError::NAME();
88
        }
89
    }
90
91
    /**
92
     * COLUMNS.
93
     *
94
     * Returns the number of columns in an array or reference.
95
     *
96
     * Excel Function:
97
     *        =COLUMNS(cellAddress)
98
     *
99
     * @param null|mixed[]|string $cellAddress An array or array formula, or a reference to a range of cells
100
     *                                          for which you want the number of columns
101
     *
102
     * @return int|string The number of columns in cellAddress, or a string if arguments are invalid
103
     */
104 29
    public static function COLUMNS($cellAddress = null)
105
    {
106 29
        if (self::cellAddressNullOrWhitespace($cellAddress)) {
107 2
            return 1;
108
        }
109 27
        if (is_string($cellAddress) && ErrorValue::isError($cellAddress)) {
110 5
            return $cellAddress;
111
        }
112 23
        if (!is_array($cellAddress)) {
113 1
            return ExcelError::VALUE();
114
        }
115
116 22
        reset($cellAddress);
117 22
        $isMatrix = (is_numeric(key($cellAddress)));
118 22
        [$columns, $rows] = Calculation::getMatrixDimensions($cellAddress);
119
120 22
        if ($isMatrix) {
121 20
            return $rows;
122
        }
123
124 2
        return $columns;
125
    }
126
127 2
    private static function cellRow(?Cell $cell): int|string
128
    {
129 2
        return ($cell !== null) ? self::convert0ToName($cell->getRow()) : 1;
130
    }
131
132 18
    private static function convert0ToName(int|string $result): int|string
133
    {
134 18
        if (is_int($result) && ($result <= 0 || $result > 1048576)) {
135 5
            return ExcelError::NAME();
136
        }
137
138 13
        return $result;
139
    }
140
141
    /**
142
     * ROW.
143
     *
144
     * Returns the row number of the given cell reference
145
     *     If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference
146
     *        as a vertical array.
147
     *     If cell reference is omitted, and the function is being called through the calculation engine,
148
     *        then it is assumed to be the reference of the cell in which the ROW function appears;
149
     *        otherwise this function returns 1.
150
     *
151
     * Excel Function:
152
     *        =ROW([cellAddress])
153
     *
154
     * @param null|mixed[][]|string $cellAddress A reference to a range of cells for which you want the row numbers
155
     *
156
     * @return int|mixed[]|string
157
     */
158 30
    public static function ROW($cellAddress = null, ?Cell $cell = null): int|string|array
159
    {
160 30
        if (self::cellAddressNullOrWhitespace($cellAddress)) {
161 1
            return self::cellRow($cell);
162
        }
163
164 29
        if (is_array($cellAddress)) {
165 2
            foreach ($cellAddress as $rowKey => $rowValue) {
166 1
                foreach ($rowValue as $columnKey => $cellValue) {
167 1
                    return (int) preg_replace('/\D/', '', $rowKey);
168
                }
169
            }
170
171 1
            return self::cellRow($cell);
172
        }
173
174 27
        $cellAddress = $cellAddress ?? '';
175 27
        if ($cell !== null) {
176 22
            [,, $sheetName] = Helpers::extractWorksheet($cellAddress, $cell);
177 22
            [,, $cellAddress] = Helpers::extractCellAddresses($cellAddress, true, $cell->getWorksheet(), $sheetName);
178
        }
179 27
        [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
180 27
        $cellAddress ??= '';
181 27
        if (str_contains($cellAddress, ':')) {
182 11
            [$startAddress, $endAddress] = explode(':', $cellAddress);
183 11
            $startAddress = (int) (string) preg_replace('/\D/', '', $startAddress);
184 11
            $endAddress = (int) (string) preg_replace('/\D/', '', $endAddress);
185
186 11
            return array_map(
187 11
                fn ($value): array => [$value],
188 11
                range($startAddress, $endAddress)
189 11
            );
190
        }
191 18
        [$cellAddress] = explode(':', $cellAddress);
192
193 18
        return self::convert0ToName((int) preg_replace('/\D/', '', $cellAddress));
194
    }
195
196
    /**
197
     * ROWS.
198
     *
199
     * Returns the number of rows in an array or reference.
200
     *
201
     * Excel Function:
202
     *        =ROWS(cellAddress)
203
     *
204
     * @param null|mixed[]|string $cellAddress An array or array formula, or a reference to a range of cells
205
     *                                          for which you want the number of rows
206
     *
207
     * @return int|string The number of rows in cellAddress, or a string if arguments are invalid
208
     */
209 30
    public static function ROWS($cellAddress = null)
210
    {
211 30
        if (self::cellAddressNullOrWhitespace($cellAddress)) {
212 2
            return 1;
213
        }
214 28
        if (is_string($cellAddress) && ErrorValue::isError($cellAddress)) {
215 5
            return $cellAddress;
216
        }
217 24
        if (!is_array($cellAddress)) {
218 1
            return ExcelError::VALUE();
219
        }
220
221 23
        reset($cellAddress);
222 23
        $isMatrix = (is_numeric(key($cellAddress)));
223 23
        [$columns, $rows] = Calculation::getMatrixDimensions($cellAddress);
224
225 23
        if ($isMatrix) {
226 21
            return $columns;
227
        }
228
229 2
        return $rows;
230
    }
231
}
232