Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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