Failed Conditions
Pull Request — master (#3962)
by Owen
11:35
created

ExcelArrayPseudoFunctions::single()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 26
rs 8.8333
cc 7
nc 9
nop 2
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\Internal;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
use PhpOffice\PhpSpreadsheet\Cell\Cell;
9
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
10
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
11
12
class ExcelArrayPseudoFunctions
13
{
14
    public static function single(string $cellReference, Cell $cell): mixed
15
    {
16
        $worksheet = $cell->getWorksheet();
17
18
        [$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true);
19
        if (preg_match('/^([$]?[a-z]{1,3})([$]?([0-9]{1,7})):([$]?[a-z]{1,3})([$]?([0-9]{1,7}))$/i', "$referenceCellCoordinate", $matches) === 1) {
20
            $ourRow = $cell->getRow();
21
            $firstRow = (int) $matches[3];
22
            $lastRow = (int) $matches[6];
23
            if ($ourRow < $firstRow || $ourRow > $lastRow || $matches[1] !== $matches[4]) {
24
                return ExcelError::VALUE();
25
            }
26
            $referenceCellCoordinate = $matches[1] . $ourRow;
27
        }
28
        $referenceCell = ($referenceWorksheetName === '')
29
            ? $worksheet->getCell((string) $referenceCellCoordinate)
30
            : $worksheet->getParentOrThrow()
31
                ->getSheetByNameOrThrow((string) $referenceWorksheetName)
32
                ->getCell((string) $referenceCellCoordinate);
33
34
        $result = $referenceCell->getCalculatedValue();
35
        while (is_array($result)) {
36
            $result = array_shift($result);
37
        }
38
39
        return $result;
40
    }
41
42
    public static function anchorArray(string $cellReference, Cell $cell): array|string
43
    {
44
        //$coordinate = $cell->getCoordinate();
45
        $worksheet = $cell->getWorksheet();
46
47
        [$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true);
48
        $referenceCell = ($referenceWorksheetName === '')
49
            ? $worksheet->getCell((string) $referenceCellCoordinate)
50
            : $worksheet->getParentOrThrow()
51
                ->getSheetByNameOrThrow((string) $referenceWorksheetName)
52
                ->getCell((string) $referenceCellCoordinate);
53
54
        // We should always use the sizing for the array formula range from the referenced cell formula
55
        //$referenceRange = null;
56
        /*if ($referenceCell->isFormula() && $referenceCell->isArrayFormula()) {
57
            $referenceRange = $referenceCell->arrayFormulaRange();
58
        }*/
59
60
        $calcEngine = Calculation::getInstance($worksheet->getParent());
61
        $result = $calcEngine->calculateCellValue($referenceCell, false);
62
        if (!is_array($result)) {
63
            $result = ExcelError::REF();
64
        }
65
66
        // Ensure that our array result dimensions match the specified array formula range dimensions,
67
        //    from the referenced cell, expanding or shrinking it as necessary.
68
        /*$result = Functions::resizeMatrix(
69
            $result,
70
            ...Coordinate::rangeDimension($referenceRange ?? $coordinate)
71
        );*/
72
73
        // Set the result for our target cell (with spillage)
74
        // But if we do write it, we get problems with #SPILL! Errors if the spreadsheet is saved
75
        // TODO How are we going to identify and handle a #SPILL! or a #CALC! error?
76
//        IOFactory::setLoading(true);
77
//        $worksheet->fromArray(
78
//            $result,
79
//            null,
80
//            $coordinate,
81
//            true
82
//        );
83
//        IOFactory::setLoading(true);
84
85
        // Calculate the array formula range that we should set for our target, based on our target cell coordinate
86
//        [$col, $row] = Coordinate::indexesFromString($coordinate);
87
//        $row += count($result) - 1;
88
//        $col = Coordinate::stringFromColumnIndex($col + count($result[0]) - 1);
89
//        $arrayFormulaRange = "{$coordinate}:{$col}{$row}";
90
//        $formulaAttributes = ['t' => 'array', 'ref' => $arrayFormulaRange];
91
92
        // Using fromArray() would reset the value for this cell with the calculation result
93
        //      as well as updating the spillage cells,
94
        //  so we need to restore this cell to its formula value, attributes, and datatype
95
//        $cell = $worksheet->getCell($coordinate);
96
//        $cell->setValueExplicit($value, DataType::TYPE_FORMULA, true, $arrayFormulaRange);
97
//        $cell->setFormulaAttributes($formulaAttributes);
98
99
//        $cell->updateInCollection();
100
101
        return $result;
102
    }
103
}
104