1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace PhpOffice\PhpSpreadsheetTests; |
6
|
|
|
|
7
|
|
|
use PhpOffice\PhpSpreadsheet\Cell\DataType; |
8
|
|
|
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink; |
9
|
|
|
use PhpOffice\PhpSpreadsheet\Comment; |
10
|
|
|
use PhpOffice\PhpSpreadsheet\NamedFormula; |
11
|
|
|
use PhpOffice\PhpSpreadsheet\NamedRange; |
12
|
|
|
use PhpOffice\PhpSpreadsheet\ReferenceHelper; |
|
|
|
|
13
|
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
14
|
|
|
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard; |
15
|
|
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
16
|
|
|
use PHPUnit\Framework\TestCase; |
17
|
|
|
|
18
|
|
|
class ReferenceHelperTest extends TestCase |
19
|
|
|
{ |
20
|
|
|
public function testColumnSort(): void |
21
|
|
|
{ |
22
|
|
|
$columnBase = $columnExpectedResult = [ |
23
|
|
|
'A', 'B', 'Z', |
24
|
|
|
'AA', 'AB', 'AZ', |
25
|
|
|
'BA', 'BB', 'BZ', |
26
|
|
|
'ZA', 'ZB', 'ZZ', |
27
|
|
|
'AAA', 'AAB', 'AAZ', |
28
|
|
|
'ABA', 'ABB', 'ABZ', |
29
|
|
|
'AZA', 'AZB', 'AZZ', |
30
|
|
|
'BAA', 'BAB', 'BAZ', |
31
|
|
|
'BBA', 'BBB', 'BBZ', |
32
|
|
|
'BZA', 'BZB', 'BZZ', |
33
|
|
|
]; |
34
|
|
|
shuffle($columnBase); |
35
|
|
|
usort($columnBase, [ReferenceHelper::class, 'columnSort']); |
36
|
|
|
foreach ($columnBase as $key => $value) { |
37
|
|
|
self::assertEquals($columnExpectedResult[$key], $value); |
38
|
|
|
} |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
public function testColumnReverseSort(): void |
42
|
|
|
{ |
43
|
|
|
$columnBase = $columnExpectedResult = [ |
44
|
|
|
'A', 'B', 'Z', |
45
|
|
|
'AA', 'AB', 'AZ', |
46
|
|
|
'BA', 'BB', 'BZ', |
47
|
|
|
'ZA', 'ZB', 'ZZ', |
48
|
|
|
'AAA', 'AAB', 'AAZ', |
49
|
|
|
'ABA', 'ABB', 'ABZ', |
50
|
|
|
'AZA', 'AZB', 'AZZ', |
51
|
|
|
'BAA', 'BAB', 'BAZ', |
52
|
|
|
'BBA', 'BBB', 'BBZ', |
53
|
|
|
'BZA', 'BZB', 'BZZ', |
54
|
|
|
]; |
55
|
|
|
shuffle($columnBase); |
56
|
|
|
$columnExpectedResult = array_reverse($columnExpectedResult); |
57
|
|
|
usort($columnBase, [ReferenceHelper::class, 'columnReverseSort']); |
58
|
|
|
foreach ($columnBase as $key => $value) { |
59
|
|
|
self::assertEquals($columnExpectedResult[$key], $value); |
60
|
|
|
} |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public function testCellSort(): void |
64
|
|
|
{ |
65
|
|
|
$cellBase = $columnExpectedResult = [ |
66
|
|
|
'A1', 'B1', 'AZB1', |
67
|
|
|
'BBB1', 'BB2', 'BAB2', |
68
|
|
|
'BZA2', 'Z3', 'AZA3', |
69
|
|
|
'BZB3', 'AB5', 'AZ6', |
70
|
|
|
'ABZ7', 'BA9', 'BZ9', |
71
|
|
|
'AAA9', 'AAZ9', 'BA10', |
72
|
|
|
'BZZ10', 'ZA11', 'AAB11', |
73
|
|
|
'BBZ29', 'BAA32', 'ZZ43', |
74
|
|
|
'AZZ43', 'BAZ67', 'ZB78', |
75
|
|
|
'ABA121', 'ABB289', 'BBA544', |
76
|
|
|
]; |
77
|
|
|
shuffle($cellBase); |
78
|
|
|
usort($cellBase, [ReferenceHelper::class, 'cellSort']); |
79
|
|
|
foreach ($cellBase as $key => $value) { |
80
|
|
|
self::assertEquals($columnExpectedResult[$key], $value); |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
public function testCellReverseSort(): void |
85
|
|
|
{ |
86
|
|
|
$cellBase = $columnExpectedResult = [ |
87
|
|
|
'BBA544', 'ABB289', 'ABA121', |
88
|
|
|
'ZB78', 'BAZ67', 'AZZ43', |
89
|
|
|
'ZZ43', 'BAA32', 'BBZ29', |
90
|
|
|
'AAB11', 'ZA11', 'BZZ10', |
91
|
|
|
'BA10', 'AAZ9', 'AAA9', |
92
|
|
|
'BZ9', 'BA9', 'ABZ7', |
93
|
|
|
'AZ6', 'AB5', 'BZB3', |
94
|
|
|
'AZA3', 'Z3', 'BZA2', |
95
|
|
|
'BAB2', 'BB2', 'BBB1', |
96
|
|
|
'AZB1', 'B1', 'A1', |
97
|
|
|
]; |
98
|
|
|
shuffle($cellBase); |
99
|
|
|
usort($cellBase, [ReferenceHelper::class, 'cellReverseSort']); |
100
|
|
|
foreach ($cellBase as $key => $value) { |
101
|
|
|
self::assertEquals($columnExpectedResult[$key], $value); |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* @dataProvider providerFormulaUpdates |
107
|
|
|
*/ |
108
|
|
|
public function testUpdateFormula(string $formula, int $insertRows, int $insertColumns, string $worksheet, string $expectedResult): void |
109
|
|
|
{ |
110
|
|
|
$referenceHelper = ReferenceHelper::getInstance(); |
111
|
|
|
|
112
|
|
|
$result = $referenceHelper->updateFormulaReferences($formula, 'A1', $insertRows, $insertColumns, $worksheet); |
113
|
|
|
|
114
|
|
|
self::assertSame($expectedResult, $result); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
public static function providerFormulaUpdates(): array |
118
|
|
|
{ |
119
|
|
|
return require 'tests/data/ReferenceHelperFormulaUpdates.php'; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @dataProvider providerMultipleWorksheetFormulaUpdates |
124
|
|
|
*/ |
125
|
|
|
public function testUpdateFormulaForMultipleWorksheets(string $formula, int $insertRows, int $insertColumns, string $expectedResult): void |
126
|
|
|
{ |
127
|
|
|
$referenceHelper = ReferenceHelper::getInstance(); |
128
|
|
|
|
129
|
|
|
$result = $referenceHelper->updateFormulaReferencesAnyWorksheet($formula, $insertRows, $insertColumns); |
130
|
|
|
|
131
|
|
|
self::assertSame($expectedResult, $result); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
public static function providerMultipleWorksheetFormulaUpdates(): array |
135
|
|
|
{ |
136
|
|
|
return require 'tests/data/ReferenceHelperFormulaUpdatesMultipleSheet.php'; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
public function testInsertNewBeforeRetainDataType(): void |
140
|
|
|
{ |
141
|
|
|
$spreadsheet = new Spreadsheet(); |
142
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
143
|
|
|
$cell = $sheet->getCell('A1'); |
144
|
|
|
$cell->setValueExplicit('+1', DataType::TYPE_STRING); |
145
|
|
|
$oldDataType = $cell->getDataType(); |
146
|
|
|
$oldValue = $cell->getValue(); |
147
|
|
|
|
148
|
|
|
$sheet->insertNewRowBefore(1); |
149
|
|
|
$newCell = $sheet->getCell('A2'); |
150
|
|
|
$newDataType = $newCell->getDataType(); |
151
|
|
|
$newValue = $newCell->getValue(); |
152
|
|
|
|
153
|
|
|
self::assertSame($oldValue, $newValue); |
154
|
|
|
self::assertSame($oldDataType, $newDataType); |
155
|
|
|
$spreadsheet->disconnectWorksheets(); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function testRemoveColumnShiftsCorrectColumnValueIntoRemovedColumnCoordinates(): void |
159
|
|
|
{ |
160
|
|
|
$spreadsheet = new Spreadsheet(); |
161
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
162
|
|
|
$sheet->fromArray([ |
163
|
|
|
['a1', 'b1', 'c1'], |
164
|
|
|
['a2', 'b2', null], |
165
|
|
|
]); |
166
|
|
|
|
167
|
|
|
$cells = $sheet->toArray(); |
168
|
|
|
self::assertSame('a1', $cells[0][0]); |
169
|
|
|
self::assertSame('b1', $cells[0][1]); |
170
|
|
|
self::assertSame('c1', $cells[0][2]); |
171
|
|
|
self::assertSame('a2', $cells[1][0]); |
172
|
|
|
self::assertSame('b2', $cells[1][1]); |
173
|
|
|
self::assertNull($cells[1][2]); |
174
|
|
|
|
175
|
|
|
$sheet->removeColumn('B'); |
176
|
|
|
|
177
|
|
|
$cells = $sheet->toArray(); |
178
|
|
|
self::assertSame('a1', $cells[0][0]); |
179
|
|
|
self::assertSame('c1', $cells[0][1]); |
180
|
|
|
self::assertArrayNotHasKey(2, $cells[0]); |
181
|
|
|
self::assertSame('a2', $cells[1][0]); |
182
|
|
|
self::assertNull($cells[1][1]); |
183
|
|
|
self::assertArrayNotHasKey(2, $cells[1]); |
184
|
|
|
$spreadsheet->disconnectWorksheets(); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
public function testInsertRowsWithPageBreaks(): void |
188
|
|
|
{ |
189
|
|
|
$spreadsheet = new Spreadsheet(); |
190
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
191
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
192
|
|
|
$sheet->setBreak('A2', Worksheet::BREAK_ROW); |
193
|
|
|
$sheet->setBreak('A5', Worksheet::BREAK_ROW); |
194
|
|
|
|
195
|
|
|
$sheet->insertNewRowBefore(2, 2); |
196
|
|
|
|
197
|
|
|
$breaks = $sheet->getBreaks(); |
198
|
|
|
ksort($breaks); |
199
|
|
|
self::assertSame(['A4' => Worksheet::BREAK_ROW, 'A7' => Worksheet::BREAK_ROW], $breaks); |
200
|
|
|
$spreadsheet->disconnectWorksheets(); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
public function testDeleteRowsWithPageBreaks(): void |
204
|
|
|
{ |
205
|
|
|
$spreadsheet = new Spreadsheet(); |
206
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
207
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
208
|
|
|
$sheet->setBreak('A2', Worksheet::BREAK_ROW); |
209
|
|
|
$sheet->setBreak('A5', Worksheet::BREAK_ROW); |
210
|
|
|
|
211
|
|
|
$sheet->removeRow(2, 2); |
212
|
|
|
|
213
|
|
|
$breaks = $sheet->getBreaks(); |
214
|
|
|
self::assertSame(['A3' => Worksheet::BREAK_ROW], $breaks); |
215
|
|
|
$spreadsheet->disconnectWorksheets(); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
public function testInsertRowsWithComments(): void |
219
|
|
|
{ |
220
|
|
|
$spreadsheet = new Spreadsheet(); |
221
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
222
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
223
|
|
|
$sheet->getComment('A2')->getText()->createText('First Comment'); |
224
|
|
|
$sheet->getComment('A5')->getText()->createText('Second Comment'); |
225
|
|
|
|
226
|
|
|
$sheet->insertNewRowBefore(2, 2); |
227
|
|
|
|
228
|
|
|
$comments = array_map( |
229
|
|
|
fn (Comment $value): string => $value->getText()->getPlainText(), |
230
|
|
|
$sheet->getComments() |
231
|
|
|
); |
232
|
|
|
|
233
|
|
|
self::assertSame(['A4' => 'First Comment', 'A7' => 'Second Comment'], $comments); |
234
|
|
|
$spreadsheet->disconnectWorksheets(); |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
public function testDeleteRowsWithComments(): void |
238
|
|
|
{ |
239
|
|
|
$spreadsheet = new Spreadsheet(); |
240
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
241
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
242
|
|
|
$sheet->getComment('A2')->getText()->createText('First Comment'); |
243
|
|
|
$sheet->getComment('A5')->getText()->createText('Second Comment'); |
244
|
|
|
|
245
|
|
|
$sheet->removeRow(2, 2); |
246
|
|
|
|
247
|
|
|
$comments = array_map( |
248
|
|
|
fn (Comment $value): string => $value->getText()->getPlainText(), |
249
|
|
|
$sheet->getComments() |
250
|
|
|
); |
251
|
|
|
|
252
|
|
|
self::assertSame(['A3' => 'Second Comment'], $comments); |
253
|
|
|
$spreadsheet->disconnectWorksheets(); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
public function testInsertRowsWithHyperlinks(): void |
257
|
|
|
{ |
258
|
|
|
$spreadsheet = new Spreadsheet(); |
259
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
260
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
261
|
|
|
$sheet->getCell('A2')->getHyperlink()->setUrl('https://github.com/PHPOffice/PhpSpreadsheet'); |
262
|
|
|
$sheet->getCell('A5')->getHyperlink()->setUrl('https://phpspreadsheet.readthedocs.io/en/latest/'); |
263
|
|
|
|
264
|
|
|
$sheet->insertNewRowBefore(2, 2); |
265
|
|
|
|
266
|
|
|
$hyperlinks = array_map( |
267
|
|
|
fn (Hyperlink $value) => $value->getUrl(), |
268
|
|
|
$sheet->getHyperlinkCollection() |
269
|
|
|
); |
270
|
|
|
ksort($hyperlinks); |
271
|
|
|
|
272
|
|
|
self::assertSame( |
273
|
|
|
[ |
274
|
|
|
'A4' => 'https://github.com/PHPOffice/PhpSpreadsheet', |
275
|
|
|
'A7' => 'https://phpspreadsheet.readthedocs.io/en/latest/', |
276
|
|
|
], |
277
|
|
|
$hyperlinks |
278
|
|
|
); |
279
|
|
|
$spreadsheet->disconnectWorksheets(); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
public function testDeleteRowsWithHyperlinks(): void |
283
|
|
|
{ |
284
|
|
|
$spreadsheet = new Spreadsheet(); |
285
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
286
|
|
|
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true); |
287
|
|
|
$sheet->getCell('A2')->getHyperlink()->setUrl('https://github.com/PHPOffice/PhpSpreadsheet'); |
288
|
|
|
$sheet->getCell('A5')->getHyperlink()->setUrl('https://phpspreadsheet.readthedocs.io/en/latest/'); |
289
|
|
|
|
290
|
|
|
$sheet->removeRow(2, 2); |
291
|
|
|
|
292
|
|
|
$hyperlinks = array_map( |
293
|
|
|
fn (Hyperlink $value) => $value->getUrl(), |
294
|
|
|
$sheet->getHyperlinkCollection() |
295
|
|
|
); |
296
|
|
|
|
297
|
|
|
self::assertSame(['A3' => 'https://phpspreadsheet.readthedocs.io/en/latest/'], $hyperlinks); |
298
|
|
|
$spreadsheet->disconnectWorksheets(); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
public function testInsertRowsWithDataValidation(): void |
302
|
|
|
{ |
303
|
|
|
$spreadsheet = new Spreadsheet(); |
304
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
305
|
|
|
|
306
|
|
|
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true); |
307
|
|
|
$cellAddress = 'E5'; |
308
|
|
|
$this->setDataValidation($sheet, $cellAddress); |
309
|
|
|
|
310
|
|
|
$sheet->insertNewRowBefore(2, 2); |
311
|
|
|
|
312
|
|
|
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation()); |
313
|
|
|
self::assertTrue($sheet->getCell('E7')->hasDataValidation()); |
314
|
|
|
self::assertSame('E7', $sheet->getDataValidation('E7')->getSqref()); |
315
|
|
|
$spreadsheet->disconnectWorksheets(); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
public function testDeleteRowsWithDataValidation(): void |
319
|
|
|
{ |
320
|
|
|
$spreadsheet = new Spreadsheet(); |
321
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
322
|
|
|
|
323
|
|
|
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true); |
324
|
|
|
$cellAddress = 'E5'; |
325
|
|
|
$this->setDataValidation($sheet, $cellAddress); |
326
|
|
|
|
327
|
|
|
$sheet->removeRow(2, 2); |
328
|
|
|
|
329
|
|
|
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation()); |
330
|
|
|
self::assertTrue($sheet->getCell('E3')->hasDataValidation()); |
331
|
|
|
self::assertSame('E3', $sheet->getDataValidation('E3')->getSqref()); |
332
|
|
|
$spreadsheet->disconnectWorksheets(); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
public function testDeleteColumnsWithDataValidation(): void |
336
|
|
|
{ |
337
|
|
|
$spreadsheet = new Spreadsheet(); |
338
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
339
|
|
|
|
340
|
|
|
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true); |
341
|
|
|
$cellAddress = 'E5'; |
342
|
|
|
$this->setDataValidation($sheet, $cellAddress); |
343
|
|
|
|
344
|
|
|
$sheet->removeColumn('B', 2); |
345
|
|
|
|
346
|
|
|
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation()); |
347
|
|
|
self::assertTrue($sheet->getCell('C5')->hasDataValidation()); |
348
|
|
|
self::assertSame('C5', $sheet->getDataValidation('C5')->getSqref()); |
349
|
|
|
$spreadsheet->disconnectWorksheets(); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
public function testInsertColumnsWithDataValidation(): void |
353
|
|
|
{ |
354
|
|
|
$spreadsheet = new Spreadsheet(); |
355
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
356
|
|
|
|
357
|
|
|
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true); |
358
|
|
|
$cellAddress = 'E5'; |
359
|
|
|
$this->setDataValidation($sheet, $cellAddress); |
360
|
|
|
|
361
|
|
|
$sheet->insertNewColumnBefore('C', 2); |
362
|
|
|
|
363
|
|
|
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation()); |
364
|
|
|
self::assertTrue($sheet->getCell('G5')->hasDataValidation()); |
365
|
|
|
self::assertSame('G5', $sheet->getDataValidation('G5')->getSqref()); |
366
|
|
|
$spreadsheet->disconnectWorksheets(); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
private function setDataValidation(Worksheet $sheet, string $cellAddress): void |
370
|
|
|
{ |
371
|
|
|
$validation = $sheet->getCell($cellAddress) |
372
|
|
|
->getDataValidation(); |
373
|
|
|
$validation->setType(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST); |
374
|
|
|
$validation->setErrorStyle(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION); |
375
|
|
|
$validation->setAllowBlank(false); |
376
|
|
|
$validation->setShowInputMessage(true); |
377
|
|
|
$validation->setShowErrorMessage(true); |
378
|
|
|
$validation->setShowDropDown(true); |
379
|
|
|
$validation->setErrorTitle('Input error'); |
380
|
|
|
$validation->setError('Value is not in list.'); |
381
|
|
|
$validation->setPromptTitle('Pick from list'); |
382
|
|
|
$validation->setPrompt('Please pick a value from the drop-down list.'); |
383
|
|
|
$validation->setFormula1('$A5:$A8'); |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
public function testInsertRowsWithConditionalFormatting(): void |
387
|
|
|
{ |
388
|
|
|
$spreadsheet = new Spreadsheet(); |
389
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
390
|
|
|
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true); |
391
|
|
|
$sheet->getCell('H5')->setValue(5); |
392
|
|
|
|
393
|
|
|
$cellRange = 'C3:F7'; |
394
|
|
|
$this->setConditionalFormatting($sheet, $cellRange); |
395
|
|
|
|
396
|
|
|
$sheet->insertNewRowBefore(4, 2); |
397
|
|
|
|
398
|
|
|
$styles = $sheet->getConditionalStylesCollection(); |
399
|
|
|
// verify that the conditional range has been updated |
400
|
|
|
self::assertSame('C3:F9', array_keys($styles)[0]); |
401
|
|
|
// verify that the conditions have been updated |
402
|
|
|
foreach ($styles as $style) { |
403
|
|
|
foreach ($style as $conditions) { |
404
|
|
|
self::assertSame('$H$7', $conditions->getConditions()[0]); |
405
|
|
|
} |
406
|
|
|
} |
407
|
|
|
$spreadsheet->disconnectWorksheets(); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
public function testInsertColumnssWithConditionalFormatting(): void |
411
|
|
|
{ |
412
|
|
|
$spreadsheet = new Spreadsheet(); |
413
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
414
|
|
|
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true); |
415
|
|
|
$sheet->getCell('H5')->setValue(5); |
416
|
|
|
|
417
|
|
|
$cellRange = 'C3:F7'; |
418
|
|
|
$this->setConditionalFormatting($sheet, $cellRange); |
419
|
|
|
|
420
|
|
|
$sheet->insertNewColumnBefore('C', 2); |
421
|
|
|
|
422
|
|
|
$styles = $sheet->getConditionalStylesCollection(); |
423
|
|
|
// verify that the conditional range has been updated |
424
|
|
|
self::assertSame('E3:H7', array_keys($styles)[0]); |
425
|
|
|
// verify that the conditions have been updated |
426
|
|
|
foreach ($styles as $style) { |
427
|
|
|
foreach ($style as $conditions) { |
428
|
|
|
self::assertSame('$J$5', $conditions->getConditions()[0]); |
429
|
|
|
} |
430
|
|
|
} |
431
|
|
|
$spreadsheet->disconnectWorksheets(); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
public function testDeleteRowsWithConditionalFormatting(): void |
435
|
|
|
{ |
436
|
|
|
$spreadsheet = new Spreadsheet(); |
437
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
438
|
|
|
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true); |
439
|
|
|
$sheet->getCell('H5')->setValue(5); |
440
|
|
|
|
441
|
|
|
$cellRange = 'C3:F7'; |
442
|
|
|
$this->setConditionalFormatting($sheet, $cellRange); |
443
|
|
|
|
444
|
|
|
$sheet->removeRow(4, 2); |
445
|
|
|
|
446
|
|
|
$styles = $sheet->getConditionalStylesCollection(); |
447
|
|
|
// verify that the conditional range has been updated |
448
|
|
|
self::assertSame('C3:F5', array_keys($styles)[0]); |
449
|
|
|
// verify that the conditions have been updated |
450
|
|
|
foreach ($styles as $style) { |
451
|
|
|
foreach ($style as $conditions) { |
452
|
|
|
self::assertSame('$H$5', $conditions->getConditions()[0]); |
453
|
|
|
} |
454
|
|
|
} |
455
|
|
|
$spreadsheet->disconnectWorksheets(); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
public function testDeleteColumnsWithConditionalFormatting(): void |
459
|
|
|
{ |
460
|
|
|
$spreadsheet = new Spreadsheet(); |
461
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
462
|
|
|
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true); |
463
|
|
|
$sheet->getCell('H5')->setValue(5); |
464
|
|
|
|
465
|
|
|
$cellRange = 'C3:F7'; |
466
|
|
|
$this->setConditionalFormatting($sheet, $cellRange); |
467
|
|
|
|
468
|
|
|
$sheet->removeColumn('D', 2); |
469
|
|
|
|
470
|
|
|
$styles = $sheet->getConditionalStylesCollection(); |
471
|
|
|
// verify that the conditional range has been updated |
472
|
|
|
self::assertSame('C3:D7', array_keys($styles)[0]); |
473
|
|
|
// verify that the conditions have been updated |
474
|
|
|
foreach ($styles as $style) { |
475
|
|
|
foreach ($style as $conditions) { |
476
|
|
|
self::assertSame('$F$5', $conditions->getConditions()[0]); |
477
|
|
|
} |
478
|
|
|
} |
479
|
|
|
$spreadsheet->disconnectWorksheets(); |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
private function setConditionalFormatting(Worksheet $sheet, string $cellRange): void |
483
|
|
|
{ |
484
|
|
|
$conditionalStyles = []; |
485
|
|
|
$wizardFactory = new Wizard($cellRange); |
486
|
|
|
/** @var Wizard\CellValue $cellWizard */ |
487
|
|
|
$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); |
488
|
|
|
|
489
|
|
|
$cellWizard->equals('$H$5', Wizard::VALUE_TYPE_CELL); |
490
|
|
|
$conditionalStyles[] = $cellWizard->getConditional(); |
491
|
|
|
|
492
|
|
|
$cellWizard->greaterThan('$H$5', Wizard::VALUE_TYPE_CELL); |
493
|
|
|
$conditionalStyles[] = $cellWizard->getConditional(); |
494
|
|
|
|
495
|
|
|
$cellWizard->lessThan('$H$5', Wizard::VALUE_TYPE_CELL); |
496
|
|
|
$conditionalStyles[] = $cellWizard->getConditional(); |
497
|
|
|
|
498
|
|
|
$sheet->getStyle($cellWizard->getCellRange()) |
499
|
|
|
->setConditionalStyles($conditionalStyles); |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
public function testInsertRowsWithPrintArea(): void |
503
|
|
|
{ |
504
|
|
|
$spreadsheet = new Spreadsheet(); |
505
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
506
|
|
|
$sheet->getPageSetup()->setPrintArea('A1:J10'); |
507
|
|
|
|
508
|
|
|
$sheet->insertNewRowBefore(2, 2); |
509
|
|
|
|
510
|
|
|
$printArea = $sheet->getPageSetup()->getPrintArea(); |
511
|
|
|
self::assertSame('A1:J12', $printArea); |
512
|
|
|
$spreadsheet->disconnectWorksheets(); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
public function testInsertColumnsWithPrintArea(): void |
516
|
|
|
{ |
517
|
|
|
$spreadsheet = new Spreadsheet(); |
518
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
519
|
|
|
$sheet->getPageSetup()->setPrintArea('A1:J10'); |
520
|
|
|
|
521
|
|
|
$sheet->insertNewColumnBefore('B', 2); |
522
|
|
|
|
523
|
|
|
$printArea = $sheet->getPageSetup()->getPrintArea(); |
524
|
|
|
self::assertSame('A1:L10', $printArea); |
525
|
|
|
$spreadsheet->disconnectWorksheets(); |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
public function testDeleteRowsWithPrintArea(): void |
529
|
|
|
{ |
530
|
|
|
$spreadsheet = new Spreadsheet(); |
531
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
532
|
|
|
$sheet->getPageSetup()->setPrintArea('A1:J10'); |
533
|
|
|
|
534
|
|
|
$sheet->removeRow(2, 2); |
535
|
|
|
|
536
|
|
|
$printArea = $sheet->getPageSetup()->getPrintArea(); |
537
|
|
|
self::assertSame('A1:J8', $printArea); |
538
|
|
|
$spreadsheet->disconnectWorksheets(); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
public function testDeleteColumnsWithPrintArea(): void |
542
|
|
|
{ |
543
|
|
|
$spreadsheet = new Spreadsheet(); |
544
|
|
|
$sheet = $spreadsheet->getActiveSheet(); |
545
|
|
|
$sheet->getPageSetup()->setPrintArea('A1:J10'); |
546
|
|
|
|
547
|
|
|
$sheet->removeColumn('B', 2); |
548
|
|
|
|
549
|
|
|
$printArea = $sheet->getPageSetup()->getPrintArea(); |
550
|
|
|
self::assertSame('A1:H10', $printArea); |
551
|
|
|
$spreadsheet->disconnectWorksheets(); |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
public function testInsertDeleteRowsWithDefinedNames(): void |
555
|
|
|
{ |
556
|
|
|
$spreadsheet = $this->buildDefinedNamesTestWorkbook(); |
557
|
|
|
/** @var Worksheet $dataSheet */ |
558
|
|
|
$dataSheet = $spreadsheet->getSheetByName('Data'); |
559
|
|
|
/** @var Worksheet $totalsSheet */ |
560
|
|
|
$totalsSheet = $spreadsheet->getSheetByName('Totals'); |
561
|
|
|
|
562
|
|
|
/** @var NamedRange $firstColumn */ |
563
|
|
|
$firstColumn = $spreadsheet->getNamedRange('FirstColumn'); |
564
|
|
|
/** @var NamedRange $secondColumn */ |
565
|
|
|
$secondColumn = $spreadsheet->getNamedRange('SecondColumn'); |
566
|
|
|
|
567
|
|
|
$dataSheet->setCellValue('D2', '=FirstTotal'); |
568
|
|
|
$dataSheet->setCellValue('D3', '=FirstTotal'); |
569
|
|
|
$dataSheet->setCellValue('B2', '=SecondTotal'); |
570
|
|
|
$dataSheet->setCellValue('B3', '=SecondTotal'); |
571
|
|
|
$dataSheet->setCellValue('B4', '=ProductTotal'); |
572
|
|
|
|
573
|
|
|
$dataSheet->insertNewRowBefore(2, 5); // 5 rows before row 2 |
574
|
|
|
self::assertSame('=Data!$A$7:$A6', $firstColumn->getRange()); |
575
|
|
|
self::assertSame('=Data!B$7:B6', $secondColumn->getRange()); |
576
|
|
|
$dataSheet->removeRow(2, 1); // remove one of inserted rows |
577
|
|
|
self::assertSame('=Data!$A$6:$A6', $firstColumn->getRange()); |
578
|
|
|
self::assertSame('=Data!B$6:B6', $secondColumn->getRange()); |
579
|
|
|
|
580
|
|
|
self::assertSame('=Data!$A$6:$A6', $firstColumn->getRange()); |
581
|
|
|
self::assertSame('=Data!B$6:B6', $secondColumn->getRange()); |
582
|
|
|
|
583
|
|
|
self::assertSame(42, $dataSheet->getCell('D6')->getCalculatedValue()); |
584
|
|
|
self::assertSame(56, $dataSheet->getCell('D7')->getCalculatedValue()); |
585
|
|
|
self::assertSame(36, $dataSheet->getCell('B6')->getCalculatedValue()); |
586
|
|
|
self::assertSame(49, $dataSheet->getCell('B7')->getCalculatedValue()); |
587
|
|
|
|
588
|
|
|
$totalsSheet->setCellValue('D6', '=FirstTotal'); |
589
|
|
|
$totalsSheet->setCellValue('D7', '=FirstTotal'); |
590
|
|
|
$totalsSheet->setCellValue('B6', '=SecondTotal'); |
591
|
|
|
$totalsSheet->setCellValue('B7', '=SecondTotal'); |
592
|
|
|
$totalsSheet->setCellValue('B8', '=ProductTotal'); |
593
|
|
|
self::assertSame($dataSheet->getCell('D6')->getCalculatedValue(), $totalsSheet->getCell('D6')->getCalculatedValue()); |
594
|
|
|
self::assertSame($dataSheet->getCell('D7')->getCalculatedValue(), $totalsSheet->getCell('D7')->getCalculatedValue()); |
595
|
|
|
self::assertSame($dataSheet->getCell('B6')->getCalculatedValue(), $totalsSheet->getCell('B6')->getCalculatedValue()); |
596
|
|
|
self::assertSame($dataSheet->getCell('B7')->getCalculatedValue(), $totalsSheet->getCell('B7')->getCalculatedValue()); |
597
|
|
|
self::assertSame(4608, $dataSheet->getCell('B8')->getCalculatedValue()); |
598
|
|
|
self::assertSame($dataSheet->getCell('B8')->getCalculatedValue(), $totalsSheet->getCell('B8')->getCalculatedValue()); |
599
|
|
|
|
600
|
|
|
$spreadsheet->disconnectWorksheets(); |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
public function testInsertDeleteColumnsWithDefinedNames(): void |
604
|
|
|
{ |
605
|
|
|
$spreadsheet = $this->buildDefinedNamesTestWorkbook(); |
606
|
|
|
/** @var Worksheet $dataSheet */ |
607
|
|
|
$dataSheet = $spreadsheet->getSheetByName('Data'); |
608
|
|
|
/** @var Worksheet $totalsSheet */ |
609
|
|
|
$totalsSheet = $spreadsheet->getSheetByName('Totals'); |
610
|
|
|
|
611
|
|
|
/** @var NamedRange $firstColumn */ |
612
|
|
|
$firstColumn = $spreadsheet->getNamedRange('FirstColumn'); |
613
|
|
|
/** @var NamedRange $secondColumn */ |
614
|
|
|
$secondColumn = $spreadsheet->getNamedRange('SecondColumn'); |
615
|
|
|
|
616
|
|
|
$dataSheet->setCellValue('D2', '=FirstTotal'); |
617
|
|
|
$dataSheet->setCellValue('D3', '=FirstTotal'); |
618
|
|
|
$dataSheet->setCellValue('B2', '=SecondTotal'); |
619
|
|
|
$dataSheet->setCellValue('B3', '=SecondTotal'); |
620
|
|
|
$dataSheet->setCellValue('B4', '=ProductTotal'); |
621
|
|
|
|
622
|
|
|
$dataSheet->insertNewColumnBefore('A', 3); |
623
|
|
|
self::assertSame('=Data!$D$2:$D6', $firstColumn->getRange()); |
624
|
|
|
self::assertSame('=Data!B$2:B6', $secondColumn->getRange()); |
625
|
|
|
$dataSheet->removeColumn('A'); |
626
|
|
|
self::assertSame('=Data!$C$2:$C6', $firstColumn->getRange()); |
627
|
|
|
self::assertSame('=Data!B$2:B6', $secondColumn->getRange()); |
628
|
|
|
|
629
|
|
|
self::assertSame(42, $dataSheet->getCell('F2')->getCalculatedValue()); |
630
|
|
|
self::assertSame(56, $dataSheet->getCell('F3')->getCalculatedValue()); |
631
|
|
|
self::assertSame(36, $dataSheet->getCell('D2')->getCalculatedValue()); |
632
|
|
|
self::assertSame(49, $dataSheet->getCell('D3')->getCalculatedValue()); |
633
|
|
|
|
634
|
|
|
$totalsSheet->setCellValue('B2', '=SecondTotal'); |
635
|
|
|
$totalsSheet->setCellValue('B3', '=SecondTotal'); |
636
|
|
|
self::assertSame(42, $totalsSheet->getCell('B2')->getCalculatedValue()); |
637
|
|
|
self::assertSame(56, $totalsSheet->getCell('B3')->getCalculatedValue()); |
638
|
|
|
|
639
|
|
|
self::assertSame(4608, $dataSheet->getCell('D4')->getCalculatedValue()); |
640
|
|
|
|
641
|
|
|
$spreadsheet->disconnectWorksheets(); |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
private function buildDefinedNamesTestWorkbook(): Spreadsheet |
645
|
|
|
{ |
646
|
|
|
$spreadsheet = new Spreadsheet(); |
647
|
|
|
$dataSheet = $spreadsheet->getActiveSheet(); |
648
|
|
|
$dataSheet->setTitle('Data'); |
649
|
|
|
|
650
|
|
|
$totalsSheet = $spreadsheet->addSheet(new Worksheet()); |
651
|
|
|
$totalsSheet->setTitle('Totals'); |
652
|
|
|
|
653
|
|
|
$spreadsheet->setActiveSheetIndexByName('Data'); |
654
|
|
|
|
655
|
|
|
$dataSheet->fromArray([['Column 1', 'Column 2'], [2, 1], [4, 3], [6, 5], [8, 7], [10, 9], [12, 11], [14, 13], [16, 15]], null, 'A1', true); |
656
|
|
|
$dataSheet->insertNewColumnBefore('B', 1); |
657
|
|
|
|
658
|
|
|
$spreadsheet->addNamedRange( |
659
|
|
|
new NamedRange('FirstColumn', $spreadsheet->getActiveSheet(), '=Data!$A$2:$A6') |
660
|
|
|
); |
661
|
|
|
$spreadsheet->addNamedFormula( |
662
|
|
|
new NamedFormula('FirstTotal', $spreadsheet->getActiveSheet(), '=SUM(FirstColumn)') |
663
|
|
|
); |
664
|
|
|
|
665
|
|
|
$spreadsheet->addNamedRange( |
666
|
|
|
new NamedRange('SecondColumn', $spreadsheet->getActiveSheet(), '=Data!B$2:B6') |
667
|
|
|
); |
668
|
|
|
$spreadsheet->addNamedFormula( |
669
|
|
|
new NamedFormula('SecondTotal', $spreadsheet->getActiveSheet(), '=SUM(SecondColumn)') |
670
|
|
|
); |
671
|
|
|
|
672
|
|
|
$spreadsheet->addNamedFormula( |
673
|
|
|
new NamedFormula('ProductTotal', $spreadsheet->getActiveSheet(), '=FirstTotal*SecondTotal') |
674
|
|
|
); |
675
|
|
|
|
676
|
|
|
return $spreadsheet; |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
private function buildDefinedNamesAbsoluteWorkbook(): Spreadsheet |
680
|
|
|
{ |
681
|
|
|
$spreadsheet = new Spreadsheet(); |
682
|
|
|
$dataSheet = $spreadsheet->getActiveSheet(); |
683
|
|
|
$dataSheet->setTitle('Data'); |
684
|
|
|
|
685
|
|
|
$totalsSheet = $spreadsheet->addSheet(new Worksheet()); |
686
|
|
|
$totalsSheet->setTitle('Totals'); |
687
|
|
|
|
688
|
|
|
$spreadsheet->setActiveSheetIndexByName('Data'); |
689
|
|
|
|
690
|
|
|
$dataSheet->fromArray([['Column 1', 'Column 2'], [2, 1], [4, 3], [6, 5], [8, 7], [10, 9], [12, 11], [14, 13], [16, 15]], null, 'A1', true); |
691
|
|
|
|
692
|
|
|
$spreadsheet->addNamedRange( |
693
|
|
|
new NamedRange('FirstColumn', $spreadsheet->getActiveSheet(), '=Data!$A$2:$A$6') |
694
|
|
|
); |
695
|
|
|
$spreadsheet->addNamedFormula( |
696
|
|
|
new NamedFormula('FirstTotal', $spreadsheet->getActiveSheet(), '=SUM(FirstColumn)') |
697
|
|
|
); |
698
|
|
|
$totalsSheet->setCellValue('A20', '=FirstTotal'); |
699
|
|
|
|
700
|
|
|
$spreadsheet->addNamedRange( |
701
|
|
|
new NamedRange('SecondColumn', $spreadsheet->getActiveSheet(), '=Data!$B$2:$B$6') |
702
|
|
|
); |
703
|
|
|
$spreadsheet->addNamedFormula( |
704
|
|
|
new NamedFormula('SecondTotal', $spreadsheet->getActiveSheet(), '=SUM(SecondColumn)') |
705
|
|
|
); |
706
|
|
|
$totalsSheet->setCellValue('B20', '=SecondTotal'); |
707
|
|
|
|
708
|
|
|
$spreadsheet->addNamedFormula( |
709
|
|
|
new NamedFormula('ProductTotal', $spreadsheet->getActiveSheet(), '=FirstTotal*SecondTotal') |
710
|
|
|
); |
711
|
|
|
$totalsSheet->setCellValue('D20', '=ProductTotal'); |
712
|
|
|
|
713
|
|
|
return $spreadsheet; |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
public function testInsertBothWithDefinedNamesAbsolute(): void |
717
|
|
|
{ |
718
|
|
|
$spreadsheet = $this->buildDefinedNamesAbsoluteWorkbook(); |
719
|
|
|
/** @var Worksheet $dataSheet */ |
720
|
|
|
$dataSheet = $spreadsheet->getSheetByName('Data'); |
721
|
|
|
/** @var Worksheet $totalsSheet */ |
722
|
|
|
$totalsSheet = $spreadsheet->getSheetByName('Totals'); |
723
|
|
|
|
724
|
|
|
$dataSheet->setCellValue('C2', '=FirstTotal'); |
725
|
|
|
$dataSheet->setCellValue('C3', '=FirstTotal'); |
726
|
|
|
$dataSheet->setCellValue('C4', '=SecondTotal'); |
727
|
|
|
|
728
|
|
|
$dataSheet->insertNewColumnBefore('A', 2); |
729
|
|
|
$dataSheet->insertNewRowBefore(2, 4); // 4 rows before row 2 |
730
|
|
|
|
731
|
|
|
/** @var NamedRange $firstColumn */ |
732
|
|
|
$firstColumn = $spreadsheet->getNamedRange('FirstColumn'); |
733
|
|
|
/** @var NamedRange $secondColumn */ |
734
|
|
|
$secondColumn = $spreadsheet->getNamedRange('SecondColumn'); |
735
|
|
|
|
736
|
|
|
self::assertSame('=Data!$C$6:$C$10', $firstColumn->getRange()); |
737
|
|
|
self::assertSame('=Data!$D$6:$D$10', $secondColumn->getRange()); |
738
|
|
|
|
739
|
|
|
self::assertSame(30, $totalsSheet->getCell('A20')->getCalculatedValue()); |
740
|
|
|
self::assertSame(25, $totalsSheet->getCell('B20')->getCalculatedValue()); |
741
|
|
|
self::assertSame(750, $totalsSheet->getCell('D20')->getCalculatedValue()); |
742
|
|
|
|
743
|
|
|
self::assertSame(30, $dataSheet->getCell('E6')->getCalculatedValue()); |
744
|
|
|
self::assertSame(30, $dataSheet->getCell('E7')->getCalculatedValue()); |
745
|
|
|
self::assertSame(25, $dataSheet->getCell('E8')->getCalculatedValue()); |
746
|
|
|
|
747
|
|
|
$spreadsheet->disconnectWorksheets(); |
748
|
|
|
} |
749
|
|
|
} |
750
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths