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;
4
 
5
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
6
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7
 
8
class CellReferenceHelper
9
{
10
    protected string $beforeCellAddress;
11
 
12
    protected int $beforeColumn;
13
 
14
    protected bool $beforeColumnAbsolute = false;
15
 
16
    protected string $beforeColumnString;
17
 
18
    protected int $beforeRow;
19
 
20
    protected bool $beforeRowAbsolute = false;
21
 
22
    protected int $numberOfColumns;
23
 
24
    protected int $numberOfRows;
25
 
26
    public function __construct(string $beforeCellAddress = 'A1', int $numberOfColumns = 0, int $numberOfRows = 0)
27
    {
28
        $this->beforeColumnAbsolute = $beforeCellAddress[0] === '$';
29
        $this->beforeRowAbsolute = strpos($beforeCellAddress, '$', 1) !== false;
30
        $this->beforeCellAddress = str_replace('$', '', $beforeCellAddress);
31
        $this->numberOfColumns = $numberOfColumns;
32
        $this->numberOfRows = $numberOfRows;
33
 
34
        // Get coordinate of $beforeCellAddress
35
        [$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($beforeCellAddress);
36
        $this->beforeColumnString = $beforeColumn;
37
        $this->beforeColumn = (int) Coordinate::columnIndexFromString($beforeColumn);
38
        $this->beforeRow = (int) $beforeRow;
39
    }
40
 
41
    public function beforeCellAddress(): string
42
    {
43
        return $this->beforeCellAddress;
44
    }
45
 
46
    public function refreshRequired(string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): bool
47
    {
48
        return $this->beforeCellAddress !== $beforeCellAddress
49
            || $this->numberOfColumns !== $numberOfColumns
50
            || $this->numberOfRows !== $numberOfRows;
51
    }
52
 
53
    public function updateCellReference(string $cellReference = 'A1', bool $includeAbsoluteReferences = false, bool $onlyAbsoluteReferences = false, ?bool $topLeft = null): string
54
    {
55
        if (Coordinate::coordinateIsRange($cellReference)) {
56
            throw new Exception('Only single cell references may be passed to this method.');
57
        }
58
 
59
        // Get coordinate of $cellReference
60
        [$newColumn, $newRow] = Coordinate::coordinateFromString($cellReference);
61
        $newColumnIndex = Coordinate::columnIndexFromString(str_replace('$', '', $newColumn));
62
        $newRowIndex = (int) str_replace('$', '', $newRow);
63
 
64
        $absoluteColumn = $newColumn[0] === '$' ? '$' : '';
65
        $absoluteRow = $newRow[0] === '$' ? '$' : '';
66
        // Verify which parts should be updated
67
        if ($onlyAbsoluteReferences === true) {
68
            $updateColumn = (($absoluteColumn === '$') && $newColumnIndex >= $this->beforeColumn);
69
            $updateRow = (($absoluteRow === '$') && $newRowIndex >= $this->beforeRow);
70
        } elseif ($includeAbsoluteReferences === false) {
71
            $updateColumn = (($absoluteColumn !== '$') && $newColumnIndex >= $this->beforeColumn);
72
            $updateRow = (($absoluteRow !== '$') && $newRowIndex >= $this->beforeRow);
73
        } else {
74
            $newColumnIndex = $this->computeNewColumnIndex($newColumnIndex, $topLeft);
75
            $newColumn = $absoluteColumn . Coordinate::stringFromColumnIndex($newColumnIndex);
76
            $updateColumn = false;
77
 
78
            $newRowIndex = $this->computeNewRowIndex($newRowIndex, $topLeft);
79
            $newRow = $absoluteRow . $newRowIndex;
80
            $updateRow = false;
81
        }
82
 
83
        // Create new column reference
84
        if ($updateColumn) {
85
            $newColumn = $this->updateColumnReference($newColumnIndex, $absoluteColumn);
86
        }
87
 
88
        // Create new row reference
89
        if ($updateRow) {
90
            $newRow = $this->updateRowReference($newRowIndex, $absoluteRow);
91
        }
92
 
93
        // Return new reference
94
        return "{$newColumn}{$newRow}";
95
    }
96
 
97
    public function computeNewColumnIndex(int $newColumnIndex, ?bool $topLeft): int
98
    {
99
        // A special case is removing the left/top or bottom/right edge of a range
100
        // $topLeft is null if we aren't adjusting a range at all.
101
        if (
102
            $topLeft !== null
103
            && $this->numberOfColumns < 0
104
            && $newColumnIndex >= $this->beforeColumn + $this->numberOfColumns
105
            && $newColumnIndex <= $this->beforeColumn - 1
106
        ) {
107
            if ($topLeft) {
108
                $newColumnIndex = $this->beforeColumn + $this->numberOfColumns;
109
            } else {
110
                $newColumnIndex = $this->beforeColumn + $this->numberOfColumns - 1;
111
            }
112
        } elseif ($newColumnIndex >= $this->beforeColumn) {
113
            // Create new column reference
114
            $newColumnIndex += $this->numberOfColumns;
115
        }
116
 
117
        return $newColumnIndex;
118
    }
119
 
120
    public function computeNewRowIndex(int $newRowIndex, ?bool $topLeft): int
121
    {
122
        // A special case is removing the left/top or bottom/right edge of a range
123
        // $topLeft is null if we aren't adjusting a range at all.
124
        if (
125
            $topLeft !== null
126
            && $this->numberOfRows < 0
127
            && $newRowIndex >= $this->beforeRow + $this->numberOfRows
128
            && $newRowIndex <= $this->beforeRow - 1
129
        ) {
130
            if ($topLeft) {
131
                $newRowIndex = $this->beforeRow + $this->numberOfRows;
132
            } else {
133
                $newRowIndex = $this->beforeRow + $this->numberOfRows - 1;
134
            }
135
        } elseif ($newRowIndex >= $this->beforeRow) {
136
            $newRowIndex = $newRowIndex + $this->numberOfRows;
137
        }
138
 
139
        return $newRowIndex;
140
    }
141
 
142
    public function cellAddressInDeleteRange(string $cellAddress): bool
143
    {
144
        [$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
145
        $cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
146
        //    Is cell within the range of rows/columns if we're deleting
147
        if (
148
            $this->numberOfRows < 0
149
            && ($cellRow >= ($this->beforeRow + $this->numberOfRows))
150
            && ($cellRow < $this->beforeRow)
151
        ) {
152
            return true;
153
        } elseif (
154
            $this->numberOfColumns < 0
155
            && ($cellColumnIndex >= ($this->beforeColumn + $this->numberOfColumns))
156
            && ($cellColumnIndex < $this->beforeColumn)
157
        ) {
158
            return true;
159
        }
160
 
161
        return false;
162
    }
163
 
164
    protected function updateColumnReference(int $newColumnIndex, string $absoluteColumn): string
165
    {
166
        $newColumn = Coordinate::stringFromColumnIndex(min($newColumnIndex + $this->numberOfColumns, AddressRange::MAX_COLUMN_INT));
167
 
168
        return "{$absoluteColumn}{$newColumn}";
169
    }
170
 
171
    protected function updateRowReference(int $newRowIndex, string $absoluteRow): string
172
    {
173
        $newRow = $newRowIndex + $this->numberOfRows;
174
        $newRow = ($newRow > AddressRange::MAX_ROW) ? AddressRange::MAX_ROW : $newRow;
175
 
176
        return "{$absoluteRow}{$newRow}";
177
    }
178
}