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\Worksheet\Worksheet;
6
 
7
abstract class DefinedName
8
{
9
    protected const REGEXP_IDENTIFY_FORMULA = '[^_\p{N}\p{L}:, \$\'!]';
10
 
11
    /**
12
     * Name.
13
     */
14
    protected string $name;
15
 
16
    /**
17
     * Worksheet on which the defined name can be resolved.
18
     */
19
    protected ?Worksheet $worksheet;
20
 
21
    /**
22
     * Value of the named object.
23
     */
24
    protected string $value;
25
 
26
    /**
27
     * Is the defined named local? (i.e. can only be used on $this->worksheet).
28
     */
29
    protected bool $localOnly;
30
 
31
    /**
32
     * Scope.
33
     */
34
    protected ?Worksheet $scope;
35
 
36
    /**
37
     * Whether this is a named range or a named formula.
38
     */
39
    protected bool $isFormula;
40
 
41
    /**
42
     * Create a new Defined Name.
43
     */
44
    public function __construct(
45
        string $name,
46
        ?Worksheet $worksheet = null,
47
        ?string $value = null,
48
        bool $localOnly = false,
49
        ?Worksheet $scope = null
50
    ) {
51
        if ($worksheet === null) {
52
            $worksheet = $scope;
53
        }
54
 
55
        // Set local members
56
        $this->name = $name;
57
        $this->worksheet = $worksheet;
58
        $this->value = (string) $value;
59
        $this->localOnly = $localOnly;
60
        // If local only, then the scope will be set to worksheet unless a scope is explicitly set
61
        $this->scope = ($localOnly === true) ? (($scope === null) ? $worksheet : $scope) : null;
62
        // If the range string contains characters that aren't associated with the range definition (A-Z,1-9
63
        //      for cell references, and $, or the range operators (colon comma or space), quotes and ! for
64
        //      worksheet names
65
        //  then this is treated as a named formula, and not a named range
66
        $this->isFormula = self::testIfFormula($this->value);
67
    }
68
 
69
    public function __destruct()
70
    {
71
        $this->worksheet = null;
72
        $this->scope = null;
73
    }
74
 
75
    /**
76
     * Create a new defined name, either a range or a formula.
77
     */
78
    public static function createInstance(
79
        string $name,
80
        ?Worksheet $worksheet = null,
81
        ?string $value = null,
82
        bool $localOnly = false,
83
        ?Worksheet $scope = null
84
    ): self {
85
        $value = (string) $value;
86
        $isFormula = self::testIfFormula($value);
87
        if ($isFormula) {
88
            return new NamedFormula($name, $worksheet, $value, $localOnly, $scope);
89
        }
90
 
91
        return new NamedRange($name, $worksheet, $value, $localOnly, $scope);
92
    }
93
 
94
    public static function testIfFormula(string $value): bool
95
    {
96
        if (str_starts_with($value, '=')) {
97
            $value = substr($value, 1);
98
        }
99
 
100
        if (is_numeric($value)) {
101
            return true;
102
        }
103
 
104
        $segMatcher = false;
105
        foreach (explode("'", $value) as $subVal) {
106
            //    Only test in alternate array entries (the non-quoted blocks)
107
            $segMatcher = $segMatcher === false;
108
            if (
109
                $segMatcher
110
                && (preg_match('/' . self::REGEXP_IDENTIFY_FORMULA . '/miu', $subVal))
111
            ) {
112
                return true;
113
            }
114
        }
115
 
116
        return false;
117
    }
118
 
119
    /**
120
     * Get name.
121
     */
122
    public function getName(): string
123
    {
124
        return $this->name;
125
    }
126
 
127
    /**
128
     * Set name.
129
     */
130
    public function setName(string $name): self
131
    {
132
        if (!empty($name)) {
133
            // Old title
134
            $oldTitle = $this->name;
135
 
136
            // Re-attach
137
            if ($this->worksheet !== null) {
138
                $this->worksheet->getParentOrThrow()->removeNamedRange($this->name, $this->worksheet);
139
            }
140
            $this->name = $name;
141
 
142
            if ($this->worksheet !== null) {
143
                $this->worksheet->getParentOrThrow()->addDefinedName($this);
144
            }
145
 
146
            if ($this->worksheet !== null) {
147
                // New title
148
                $newTitle = $this->name;
149
                ReferenceHelper::getInstance()->updateNamedFormulae($this->worksheet->getParentOrThrow(), $oldTitle, $newTitle);
150
            }
151
        }
152
 
153
        return $this;
154
    }
155
 
156
    /**
157
     * Get worksheet.
158
     */
159
    public function getWorksheet(): ?Worksheet
160
    {
161
        return $this->worksheet;
162
    }
163
 
164
    /**
165
     * Set worksheet.
166
     */
167
    public function setWorksheet(?Worksheet $worksheet): self
168
    {
169
        $this->worksheet = $worksheet;
170
 
171
        return $this;
172
    }
173
 
174
    /**
175
     * Get range or formula value.
176
     */
177
    public function getValue(): string
178
    {
179
        return $this->value;
180
    }
181
 
182
    /**
183
     * Set range or formula  value.
184
     */
185
    public function setValue(string $value): self
186
    {
187
        $this->value = $value;
188
 
189
        return $this;
190
    }
191
 
192
    /**
193
     * Get localOnly.
194
     */
195
    public function getLocalOnly(): bool
196
    {
197
        return $this->localOnly;
198
    }
199
 
200
    /**
201
     * Set localOnly.
202
     */
203
    public function setLocalOnly(bool $localScope): self
204
    {
205
        $this->localOnly = $localScope;
206
        $this->scope = $localScope ? $this->worksheet : null;
207
 
208
        return $this;
209
    }
210
 
211
    /**
212
     * Get scope.
213
     */
214
    public function getScope(): ?Worksheet
215
    {
216
        return $this->scope;
217
    }
218
 
219
    /**
220
     * Set scope.
221
     */
222
    public function setScope(?Worksheet $worksheet): self
223
    {
224
        $this->scope = $worksheet;
225
        $this->localOnly = $worksheet !== null;
226
 
227
        return $this;
228
    }
229
 
230
    /**
231
     * Identify whether this is a named range or a named formula.
232
     */
233
    public function isFormula(): bool
234
    {
235
        return $this->isFormula;
236
    }
237
 
238
    /**
239
     * Resolve a named range to a regular cell range or formula.
240
     */
241
    public static function resolveName(string $definedName, Worksheet $worksheet, string $sheetName = ''): ?self
242
    {
243
        if ($sheetName === '') {
244
            $worksheet2 = $worksheet;
245
        } else {
246
            $worksheet2 = $worksheet->getParentOrThrow()->getSheetByName($sheetName);
247
            if ($worksheet2 === null) {
248
                return null;
249
            }
250
        }
251
 
252
        return $worksheet->getParentOrThrow()->getDefinedName($definedName, $worksheet2);
253
    }
254
 
255
    /**
256
     * Implement PHP __clone to create a deep clone, not just a shallow copy.
257
     */
258
    public function __clone()
259
    {
260
        $vars = get_object_vars($this);
261
        foreach ($vars as $key => $value) {
262
            if (is_object($value)) {
263
                $this->$key = clone $value;
264
            } else {
265
                $this->$key = $value;
266
            }
267
        }
268
    }
269
}