Passed
Pull Request — master (#3257)
by Mark
11:38
created

WorksheetTest::testGetTableByName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
4
5
use Exception;
6
use PhpOffice\PhpSpreadsheet\Cell\DataType;
7
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
8
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
10
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
11
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
12
use PHPUnit\Framework\TestCase;
13
14
class WorksheetTest extends TestCase
15
{
16
    public function testSetTitle(): void
17
    {
18
        $testTitle = str_repeat('a', 31);
19
20
        $worksheet = new Worksheet();
21
        $worksheet->setTitle($testTitle);
22
        self::assertSame($testTitle, $worksheet->getTitle());
23
    }
24
25
    public function setTitleInvalidProvider(): array
26
    {
27
        return [
28
            [str_repeat('a', 32), 'Maximum 31 characters allowed in sheet title.'],
29
            ['invalid*title', 'Invalid character found in sheet title'],
30
        ];
31
    }
32
33
    /**
34
     * @param string $title
35
     * @param string $expectMessage
36
     *
37
     * @dataProvider setTitleInvalidProvider
38
     */
39
    public function testSetTitleInvalid($title, $expectMessage): void
40
    {
41
        // First, test setting title with validation disabled -- should be successful
42
        $worksheet = new Worksheet();
43
        $worksheet->setTitle($title, true, false);
44
45
        // Next, test again with validation enabled -- this time we should fail
46
        $worksheet = new Worksheet();
47
        $this->expectException(Exception::class);
48
        $this->expectExceptionMessage($expectMessage);
49
        $worksheet->setTitle($title);
50
    }
51
52
    public function testSetTitleDuplicate(): void
53
    {
54
        // Create a Spreadsheet with three Worksheets (the first is created automatically)
55
        $spreadsheet = new Spreadsheet();
56
        $spreadsheet->createSheet();
57
        $spreadsheet->createSheet();
58
59
        // Set unique title -- should be unchanged
60
        $sheet = $spreadsheet->getSheet(0);
61
        $sheet->setTitle('Test Title');
62
        self::assertSame('Test Title', $sheet->getTitle());
63
64
        // Set duplicate title -- should have numeric suffix appended
65
        $sheet = $spreadsheet->getSheet(1);
66
        $sheet->setTitle('Test Title');
67
        self::assertSame('Test Title 1', $sheet->getTitle());
68
69
        // Set duplicate title with validation disabled -- should be unchanged
70
        $sheet = $spreadsheet->getSheet(2);
71
        $sheet->setTitle('Test Title', true, false);
72
        self::assertSame('Test Title', $sheet->getTitle());
73
    }
74
75
    public function testSetCodeName(): void
76
    {
77
        $testCodeName = str_repeat('a', 31);
78
79
        $worksheet = new Worksheet();
80
        $worksheet->setCodeName($testCodeName);
81
        self::assertSame($testCodeName, $worksheet->getCodeName());
82
    }
83
84
    public function setCodeNameInvalidProvider(): array
85
    {
86
        return [
87
            [str_repeat('a', 32), 'Maximum 31 characters allowed in sheet code name.'],
88
            ['invalid*code*name', 'Invalid character found in sheet code name'],
89
        ];
90
    }
91
92
    /**
93
     * @param string $codeName
94
     * @param string $expectMessage
95
     *
96
     * @dataProvider setCodeNameInvalidProvider
97
     */
98
    public function testSetCodeNameInvalid($codeName, $expectMessage): void
99
    {
100
        // First, test setting code name with validation disabled -- should be successful
101
        $worksheet = new Worksheet();
102
        $worksheet->setCodeName($codeName, false);
103
104
        // Next, test again with validation enabled -- this time we should fail
105
        $worksheet = new Worksheet();
106
        $this->expectException(Exception::class);
107
        $this->expectExceptionMessage($expectMessage);
108
        $worksheet->setCodeName($codeName);
109
    }
110
111
    public function testSetCodeNameDuplicate(): void
112
    {
113
        // Create a Spreadsheet with three Worksheets (the first is created automatically)
114
        $spreadsheet = new Spreadsheet();
115
        $spreadsheet->createSheet();
116
        $spreadsheet->createSheet();
117
118
        // Set unique code name -- should be massaged to Snake_Case
119
        $sheet = $spreadsheet->getSheet(0);
120
        $sheet->setCodeName('Test Code Name');
121
        self::assertSame('Test_Code_Name', $sheet->getCodeName());
122
123
        // Set duplicate code name -- should be massaged and have numeric suffix appended
124
        $sheet = $spreadsheet->getSheet(1);
125
        $sheet->setCodeName('Test Code Name');
126
        self::assertSame('Test_Code_Name_1', $sheet->getCodeName());
127
128
        // Set duplicate code name with validation disabled -- should be unchanged, and unmassaged
129
        $sheet = $spreadsheet->getSheet(2);
130
        $sheet->setCodeName('Test Code Name', false);
131
        self::assertSame('Test Code Name', $sheet->getCodeName());
132
    }
133
134
    public function testFreezePaneSelectedCell(): void
135
    {
136
        $worksheet = new Worksheet();
137
        $worksheet->freezePane('B2');
138
        self::assertSame('B2', $worksheet->getTopLeftCell());
139
    }
140
141
    public function extractSheetTitleProvider(): array
142
    {
143
        return [
144
            ['B2', '', '', 'B2'],
145
            ['testTitle!B2', 'testTitle', 'B2', 'B2'],
146
            ['test!Title!B2', 'test!Title', 'B2', 'B2'],
147
            ['test Title!B2', 'test Title', 'B2', 'B2'],
148
            ['test!Title!B2', 'test!Title', 'B2', 'B2'],
149
            ["'testSheet 1'!A3", "'testSheet 1'", 'A3', 'A3'],
150
            ["'testSheet1'!A2", "'testSheet1'", 'A2', 'A2'],
151
            ["'testSheet 2'!A1", "'testSheet 2'", 'A1', 'A1'],
152
        ];
153
    }
154
155
    /**
156
     * @param string $range
157
     * @param string $expectTitle
158
     * @param string $expectCell
159
     * @param string $expectCell2
160
     *
161
     * @dataProvider extractSheetTitleProvider
162
     */
163
    public function testExtractSheetTitle($range, $expectTitle, $expectCell, $expectCell2): void
164
    {
165
        // only cell reference
166
        self::assertSame($expectCell, Worksheet::extractSheetTitle($range));
167
        // with title in array
168
        $arRange = Worksheet::extractSheetTitle($range, true);
169
        self::assertSame($expectTitle, $arRange[0]);
170
        self::assertSame($expectCell2, $arRange[1]);
171
    }
172
173
    /**
174
     * Fix https://github.com/PHPOffice/PhpSpreadsheet/issues/868 when cells are not removed correctly
175
     * on row deletion.
176
     */
177
    public function testRemoveCellsCorrectlyWhenRemovingRow(): void
178
    {
179
        $workbook = new Spreadsheet();
180
        $worksheet = $workbook->getActiveSheet();
181
        $worksheet->getCell('A2')->setValue('A2');
182
        $worksheet->getCell('C1')->setValue('C1');
183
        $worksheet->removeRow(1);
184
        self::assertEquals(
185
            'A2',
186
            $worksheet->getCell('A1')->getValue()
187
        );
188
        self::assertNull(
189
            $worksheet->getCell('C1')->getValue()
190
        );
191
    }
192
193
    public function removeColumnProvider(): array
194
    {
195
        return [
196
            'Remove first column' => [
197
                [
198
                    ['A1', 'B1', 'C1'],
199
                    ['A2', 'B2', 'C2'],
200
                ],
201
                'A',
202
                1,
203
                [
204
                    ['B1', 'C1'],
205
                    ['B2', 'C2'],
206
                ],
207
                'B',
208
            ],
209
            'Remove middle column' => [
210
                [
211
                    ['A1', 'B1', 'C1'],
212
                    ['A2', 'B2', 'C2'],
213
                ],
214
                'B',
215
                1,
216
                [
217
                    ['A1', 'C1'],
218
                    ['A2', 'C2'],
219
                ],
220
                'B',
221
            ],
222
            'Remove last column' => [
223
                [
224
                    ['A1', 'B1', 'C1'],
225
                    ['A2', 'B2', 'C2'],
226
                ],
227
                'C',
228
                1,
229
                [
230
                    ['A1', 'B1'],
231
                    ['A2', 'B2'],
232
                ],
233
                'B',
234
            ],
235
            'Remove a column out of range' => [
236
                [
237
                    ['A1', 'B1', 'C1'],
238
                    ['A2', 'B2', 'C2'],
239
                ],
240
                'D',
241
                1,
242
                [
243
                    ['A1', 'B1', 'C1'],
244
                    ['A2', 'B2', 'C2'],
245
                ],
246
                'C',
247
            ],
248
            'Remove multiple columns' => [
249
                [
250
                    ['A1', 'B1', 'C1'],
251
                    ['A2', 'B2', 'C2'],
252
                ],
253
                'B',
254
                5,
255
                [
256
                    ['A1'],
257
                    ['A2'],
258
                ],
259
                'A',
260
            ],
261
        ];
262
    }
263
264
    /**
265
     * @dataProvider removeColumnProvider
266
     */
267
    public function testRemoveColumn(
268
        array $initialData,
269
        string $columnToBeRemoved,
270
        int $columnsToBeRemoved,
271
        array $expectedData,
272
        string $expectedHighestColumn
273
    ): void {
274
        $spreadsheet = new Spreadsheet();
275
        $worksheet = $spreadsheet->getActiveSheet();
276
        $worksheet->fromArray($initialData);
277
278
        $worksheet->removeColumn($columnToBeRemoved, $columnsToBeRemoved);
279
280
        self::assertSame($expectedHighestColumn, $worksheet->getHighestColumn());
281
        self::assertSame($expectedData, $worksheet->toArray());
282
    }
283
284
    public function removeRowsProvider(): array
285
    {
286
        return [
287
            'Remove all rows except first one' => [
288
                [
289
                    ['A1', 'B1', 'C1'],
290
                    ['A2', 'B2', 'C2'],
291
                    ['A3', 'B3', 'C3'],
292
                    ['A4', 'B4', 'C4'],
293
                ],
294
                2,
295
                3,
296
                [
297
                    ['A1', 'B1', 'C1'],
298
                ],
299
                1,
300
            ],
301
            'Remove all rows except last one' => [
302
                [
303
                    ['A1', 'B1', 'C1'],
304
                    ['A2', 'B2', 'C2'],
305
                    ['A3', 'B3', 'C3'],
306
                    ['A4', 'B4', 'C4'],
307
                ],
308
                1,
309
                3,
310
                [
311
                    ['A4', 'B4', 'C4'],
312
                ],
313
                1,
314
            ],
315
            'Remove last row' => [
316
                [
317
                    ['A1', 'B1', 'C1'],
318
                    ['A2', 'B2', 'C2'],
319
                    ['A3', 'B3', 'C3'],
320
                    ['A4', 'B4', 'C4'],
321
                ],
322
                4,
323
                1,
324
                [
325
                    ['A1', 'B1', 'C1'],
326
                    ['A2', 'B2', 'C2'],
327
                    ['A3', 'B3', 'C3'],
328
                ],
329
                3,
330
            ],
331
            'Remove first row' => [
332
                [
333
                    ['A1', 'B1', 'C1'],
334
                    ['A2', 'B2', 'C2'],
335
                    ['A3', 'B3', 'C3'],
336
                    ['A4', 'B4', 'C4'],
337
                ],
338
                1,
339
                1,
340
                [
341
                    ['A2', 'B2', 'C2'],
342
                    ['A3', 'B3', 'C3'],
343
                    ['A4', 'B4', 'C4'],
344
                ],
345
                3,
346
            ],
347
            'Remove all rows except first and last' => [
348
                [
349
                    ['A1', 'B1', 'C1'],
350
                    ['A2', 'B2', 'C2'],
351
                    ['A3', 'B3', 'C3'],
352
                    ['A4', 'B4', 'C4'],
353
                ],
354
                2,
355
                2,
356
                [
357
                    ['A1', 'B1', 'C1'],
358
                    ['A4', 'B4', 'C4'],
359
                ],
360
                2,
361
            ],
362
            'Remove non existing rows' => [
363
                [
364
                    ['A1', 'B1', 'C1'],
365
                    ['A2', 'B2', 'C2'],
366
                    ['A3', 'B3', 'C3'],
367
                    ['A4', 'B4', 'C4'],
368
                ],
369
                2,
370
                10,
371
                [
372
                    ['A1', 'B1', 'C1'],
373
                ],
374
                1,
375
            ],
376
            'Remove only non existing rows' => [
377
                [
378
                    ['A1', 'B1', 'C1'],
379
                    ['A2', 'B2', 'C2'],
380
                    ['A3', 'B3', 'C3'],
381
                    ['A4', 'B4', 'C4'],
382
                ],
383
                5,
384
                10,
385
                [
386
                    ['A1', 'B1', 'C1'],
387
                    ['A2', 'B2', 'C2'],
388
                    ['A3', 'B3', 'C3'],
389
                    ['A4', 'B4', 'C4'],
390
                ],
391
                4,
392
            ],
393
        ];
394
    }
395
396
    /**
397
     * @dataProvider removeRowsProvider
398
     */
399
    public function testRemoveRows(
400
        array $initialData,
401
        int $rowToRemove,
402
        int $rowsQtyToRemove,
403
        array $expectedData,
404
        int $expectedHighestRow
405
    ): void {
406
        $workbook = new Spreadsheet();
407
        $worksheet = $workbook->getActiveSheet();
408
        $worksheet->fromArray($initialData);
409
410
        $worksheet->removeRow($rowToRemove, $rowsQtyToRemove);
411
412
        self::assertSame($expectedData, $worksheet->toArray());
413
        self::assertSame($expectedHighestRow, $worksheet->getHighestRow());
414
    }
415
416
    private static function getPopulatedSheetForEmptyRowTest(Spreadsheet $spreadsheet): Worksheet
417
    {
418
        $sheet = $spreadsheet->getActiveSheet();
419
        $sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
420
        $sheet->setCellValueExplicit('B3', null, DataType::TYPE_NULL);
421
        $sheet->setCellValueExplicit('B4', '', DataType::TYPE_STRING);
422
        $sheet->setCellValueExplicit('B5', null, DataType::TYPE_NULL);
423
        $sheet->setCellValueExplicit('C5', '', DataType::TYPE_STRING);
424
        $sheet->setCellValueExplicit('B6', null, DataType::TYPE_NULL);
425
        $sheet->setCellValueExplicit('C6', 'PHP', DataType::TYPE_STRING);
426
        $sheet->setCellValueExplicit('B7', '', DataType::TYPE_STRING);
427
        $sheet->setCellValueExplicit('C7', 'PHP', DataType::TYPE_STRING);
428
        $sheet->setCellValueExplicit('B8', null, DataType::TYPE_NULL);
429
        $sheet->setCellValueExplicit('C8', '', DataType::TYPE_STRING);
430
        $sheet->setCellValueExplicit('D8', 'PHP', DataType::TYPE_STRING);
431
432
        return $sheet;
433
    }
434
435
    private static function getPopulatedSheetForEmptyColumnTest(Spreadsheet $spreadsheet): Worksheet
436
    {
437
        $sheet = $spreadsheet->getActiveSheet();
438
        $sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
439
        $sheet->setCellValueExplicit('C2', null, DataType::TYPE_NULL);
440
        $sheet->setCellValueExplicit('D2', '', DataType::TYPE_STRING);
441
        $sheet->setCellValueExplicit('E2', null, DataType::TYPE_NULL);
442
        $sheet->setCellValueExplicit('E3', '', DataType::TYPE_STRING);
443
        $sheet->setCellValueExplicit('F2', null, DataType::TYPE_NULL);
444
        $sheet->setCellValueExplicit('F3', 'PHP', DataType::TYPE_STRING);
445
        $sheet->setCellValueExplicit('G2', '', DataType::TYPE_STRING);
446
        $sheet->setCellValueExplicit('G3', 'PHP', DataType::TYPE_STRING);
447
        $sheet->setCellValueExplicit('H2', null, DataType::TYPE_NULL);
448
        $sheet->setCellValueExplicit('H3', '', DataType::TYPE_STRING);
449
        $sheet->setCellValueExplicit('H4', 'PHP', DataType::TYPE_STRING);
450
451
        return $sheet;
452
    }
453
454
    /**
455
     * @dataProvider emptyRowProvider
456
     */
457
    public function testIsEmptyRow(int $rowId, bool $expectedEmpty): void
458
    {
459
        $spreadsheet = new Spreadsheet();
460
        $sheet = self::getPopulatedSheetForEmptyRowTest($spreadsheet);
461
462
        $isEmpty = $sheet->isEmptyRow($rowId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
463
464
        self::assertSame($expectedEmpty, $isEmpty);
465
        $spreadsheet->disconnectWorksheets();
466
    }
467
468
    public function emptyRowProvider(): array
469
    {
470
        return [
471
            [1, false],
472
            [2, true],
473
            [3, true],
474
            [4, true],
475
            [5, true],
476
            [6, false],
477
            [7, false],
478
            [8, false],
479
            [9, true],
480
        ];
481
    }
482
483
    /**
484
     * @dataProvider emptyColumnProvider
485
     */
486
    public function testIsEmptyColumn(string $columnId, bool $expectedEmpty): void
487
    {
488
        $spreadsheet = new Spreadsheet();
489
        $sheet = self::getPopulatedSheetForEmptyColumnTest($spreadsheet);
490
491
        $isEmpty = $sheet->isEmptyColumn($columnId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
492
493
        self::assertSame($expectedEmpty, $isEmpty);
494
        $spreadsheet->disconnectWorksheets();
495
    }
496
497
    public function emptyColumnProvider(): array
498
    {
499
        return [
500
            ['A', false],
501
            ['B', true],
502
            ['C', true],
503
            ['D', true],
504
            ['E', true],
505
            ['F', false],
506
            ['G', false],
507
            ['H', false],
508
            ['I', true],
509
        ];
510
    }
511
512
    public function testGetTableNames(): void
513
    {
514
        $reader = new Xlsx();
515
        $spreadsheet = $reader->load('tests/data/Worksheet/Table/TableFormulae.xlsx');
516
        $worksheet = $spreadsheet->getActiveSheet();
517
518
        $tables = $worksheet->getTableNames();
519
        self::assertSame(['DeptSales'], $tables);
520
    }
521
522
    public function testGetTableByName(): void
523
    {
524
        $reader = new Xlsx();
525
        $spreadsheet = $reader->load('tests/data/Worksheet/Table/TableFormulae.xlsx');
526
        $worksheet = $spreadsheet->getActiveSheet();
527
528
        $table = $worksheet->getTableByName('Non-existent Table');
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $table is correct as $worksheet->getTableByName('Non-existent Table') targeting PhpOffice\PhpSpreadsheet...sheet::getTableByName() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
529
        self::assertNull($table);
530
531
        $table = $worksheet->getTableByName('DeptSales');
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $table is correct as $worksheet->getTableByName('DeptSales') targeting PhpOffice\PhpSpreadsheet...sheet::getTableByName() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
532
        self::assertInstanceOf(Table::class, $table);
533
    }
534
}
535