| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- <?php
- namespace PhpOffice\PhpSpreadsheetTests\Worksheet\Table;
- use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
- use PhpOffice\PhpSpreadsheet\Cell\CellRange;
- use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
- use PhpOffice\PhpSpreadsheet\Worksheet\Table;
- use PhpOffice\PhpSpreadsheet\Worksheet\Table\Column;
- use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
- class TableTest extends SetupTeardown
- {
- private const INITIAL_RANGE = 'H2:O256';
- public function testToString(): void
- {
- $expectedResult = self::INITIAL_RANGE;
- $table = new Table(self::INITIAL_RANGE);
- // magic __toString should return the active table range
- $result = (string) $table;
- self::assertEquals($expectedResult, $result);
- }
- /**
- * @dataProvider validTableNamesProvider
- */
- public function testValidTableNames(string $name, string $expected): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $result = $table->setName($name);
- self::assertInstanceOf(Table::class, $result);
- self::assertEquals($expected, $table->getName());
- }
- public function validTableNamesProvider(): array
- {
- return [
- ['', ''],
- ['Table_1', 'Table_1'],
- ['_table_2', '_table_2'],
- ['\table_3', '\table_3'],
- [" Table_4 \n", 'Table_4'],
- ['table.5', 'table.5'],
- ['தமிழ்', 'தமிழ்'], // UTF-8 letters with combined character
- ];
- }
- /**
- * @dataProvider invalidTableNamesProvider
- */
- public function testInvalidTableNames(string $name): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $this->expectException(PhpSpreadsheetException::class);
- $table->setName($name);
- }
- public function invalidTableNamesProvider(): array
- {
- return [
- ['C'],
- ['c'],
- ['R'],
- ['r'],
- ['Z100'],
- ['Z$100'],
- ['R1C1'],
- ['R1C'],
- ['R11C11'],
- ['123'],
- ['=Table'],
- ['ிக'], // starting with UTF-8 combined character
- [bin2hex(random_bytes(255))], // random string with length greater than 255
- ];
- }
- public function testUniqueTableName(): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- $sheet = $this->getSheet();
- $table1 = new Table();
- $table1->setName('Table_1');
- $sheet->addTable($table1);
- $table2 = new Table();
- $table2->setName('table_1'); // case insensitive
- $sheet->addTable($table2);
- }
- public function testVariousSets(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $result = $table->setShowHeaderRow(false);
- self::assertInstanceOf(Table::class, $result);
- self::assertFalse($table->getShowHeaderRow());
- $result = $table->setShowTotalsRow(true);
- self::assertInstanceOf(Table::class, $result);
- self::assertTrue($table->getShowTotalsRow());
- }
- public function testGetWorksheet(): void
- {
- $sheet = $this->getSheet();
- $table = new Table(self::INITIAL_RANGE);
- $sheet->addTable($table);
- $result = $table->getWorksheet();
- self::assertSame($sheet, $result);
- }
- public function testSetWorksheet(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $spreadsheet = $this->getSpreadsheet();
- $sheet2 = $spreadsheet->createSheet();
- // Setters return the instance to implement the fluent interface
- $result = $table->setWorksheet($sheet2);
- self::assertInstanceOf(Table::class, $result);
- }
- public function testGetRange(): void
- {
- $expectedResult = self::INITIAL_RANGE;
- $table = new Table(self::INITIAL_RANGE);
- // Result should be the active table range
- $result = $table->getRange();
- self::assertEquals($expectedResult, $result);
- }
- /**
- * @dataProvider validTableRangeProvider
- *
- * @param AddressRange|array<int>|string $fullRange
- * @param string $fullRange
- */
- public function testSetRangeValidRange($fullRange, string $actualRange): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $result = $table->setRange($fullRange);
- self::assertInstanceOf(Table::class, $result);
- self::assertEquals($actualRange, $table->getRange());
- }
- public function validTableRangeProvider(): array
- {
- $sheet = $this->getSheet();
- $title = $sheet->getTitle();
- return [
- ["$title!G1:J512", 'G1:J512'],
- ['K1:N20', 'K1:N20'],
- [[3, 5, 6, 8], 'C5:F8'],
- [new CellRange(new CellAddress('C5', $sheet), new CellAddress('F8', $sheet)), 'C5:F8'],
- ];
- }
- public function testClearRange(): void
- {
- $expectedResult = '';
- $table = new Table(self::INITIAL_RANGE);
- // Setters return the instance to implement the fluent interface
- $result = $table->setRange('');
- self::assertInstanceOf(Table::class, $result);
- // Result should be a clear range
- $result = $table->getRange();
- self::assertEquals($expectedResult, $result);
- }
- /**
- * @dataProvider invalidTableRangeProvider
- */
- public function testSetRangeInvalidRange(string $range): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- new Table($range);
- }
- public function invalidTableRangeProvider(): array
- {
- return [
- ['A1'],
- ['A1:A1'],
- ['B1:A4'],
- ['A1:D1'],
- ['D1:A1'],
- ];
- }
- public function testGetColumnsEmpty(): void
- {
- // There should be no columns yet defined
- $table = new Table(self::INITIAL_RANGE);
- $result = $table->getColumns();
- self::assertIsArray($result);
- self::assertCount(0, $result);
- }
- public function testGetColumnOffset(): void
- {
- $columnIndexes = [
- 'H' => 0,
- 'K' => 3,
- 'M' => 5,
- ];
- $table = new Table(self::INITIAL_RANGE);
- // If we request a specific column by its column ID, we should get an
- // integer returned representing the column offset within the range
- foreach ($columnIndexes as $columnIndex => $columnOffset) {
- $result = $table->getColumnOffset($columnIndex);
- self::assertEquals($columnOffset, $result);
- }
- }
- public function testRemoveColumns(): void
- {
- $sheet = $this->getSheet();
- $sheet->fromArray(range('H', 'O'), null, 'H2');
- $table = new Table(self::INITIAL_RANGE);
- $table->getColumn('L')->setShowFilterButton(false);
- $sheet->addTable($table);
- $sheet->removeColumn('K', 2);
- $result = $table->getRange();
- self::assertEquals('H2:M256', $result);
- // Check that the prop that was set for column L is no longer set
- self::assertTrue($table->getColumn('L')->getShowFilterButton());
- }
- public function testRemoveRows(): void
- {
- $sheet = $this->getSheet();
- $sheet->fromArray(range('H', 'O'), null, 'H2');
- $table = new Table(self::INITIAL_RANGE);
- $sheet->addTable($table);
- $sheet->removeRow(42, 128);
- $result = $table->getRange();
- self::assertEquals('H2:O128', $result);
- }
- public function testInsertColumns(): void
- {
- $sheet = $this->getSheet();
- $sheet->fromArray(range('H', 'O'), null, 'H2');
- $table = new Table(self::INITIAL_RANGE);
- $table->getColumn('N')->setShowFilterButton(false);
- $sheet->addTable($table);
- $sheet->insertNewColumnBefore('N', 3);
- $result = $table->getRange();
- self::assertEquals('H2:R256', $result);
- // Check that column N no longer has a prop
- self::assertTrue($table->getColumn('N')->getShowFilterButton());
- // Check that the prop originally set in column N has been moved to column Q
- self::assertFalse($table->getColumn('Q')->getShowFilterButton());
- }
- public function testInsertRows(): void
- {
- $sheet = $this->getSheet();
- $sheet->fromArray(range('H', 'O'), null, 'H2');
- $table = new Table(self::INITIAL_RANGE);
- $sheet->addTable($table);
- $sheet->insertNewRowBefore(3, 4);
- $result = $table->getRange();
- self::assertEquals('H2:O260', $result);
- }
- public function testGetInvalidColumnOffset(): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- $invalidColumn = 'G';
- $sheet = $this->getSheet();
- $table = new Table();
- $table->setWorksheet($sheet);
- $table->getColumnOffset($invalidColumn);
- }
- public function testSetColumnWithString(): void
- {
- $expectedResult = 'L';
- $table = new Table(self::INITIAL_RANGE);
- // Setters return the instance to implement the fluent interface
- $result = $table->setColumn($expectedResult);
- self::assertInstanceOf(Table::class, $result);
- $result = $table->getColumns();
- // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column
- // objects for each column we set indexed by the column ID
- self::assertIsArray($result);
- self::assertCount(1, $result);
- self::assertArrayHasKey($expectedResult, $result);
- self::assertInstanceOf(Column::class, $result[$expectedResult]);
- }
- public function testSetInvalidColumnWithString(): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- $table = new Table(self::INITIAL_RANGE);
- $invalidColumn = 'A';
- $table->setColumn($invalidColumn);
- }
- public function testSetColumnWithColumnObject(): void
- {
- $expectedResult = 'M';
- $columnObject = new Column($expectedResult);
- $table = new Table(self::INITIAL_RANGE);
- // Setters return the instance to implement the fluent interface
- $result = $table->setColumn($columnObject);
- self::assertInstanceOf(Table::class, $result);
- $result = $table->getColumns();
- // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column
- // objects for each column we set indexed by the column ID
- self::assertIsArray($result);
- self::assertCount(1, $result);
- self::assertArrayHasKey($expectedResult, $result);
- self::assertInstanceOf(Column::class, $result[$expectedResult]);
- }
- public function testSetInvalidColumnWithObject(): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- $invalidColumn = 'E';
- $table = new Table(self::INITIAL_RANGE);
- $table->setColumn($invalidColumn);
- }
- public function testSetColumnWithInvalidDataType(): void
- {
- $this->expectException(PhpSpreadsheetException::class);
- $table = new Table(self::INITIAL_RANGE);
- $invalidColumn = 123.456;
- // @phpstan-ignore-next-line
- $table->setColumn($invalidColumn);
- }
- public function testGetColumns(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $columnIndexes = ['L', 'M'];
- foreach ($columnIndexes as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- $result = $table->getColumns();
- // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column
- // objects for each column we set indexed by the column ID
- self::assertIsArray($result);
- self::assertCount(count($columnIndexes), $result);
- foreach ($columnIndexes as $columnIndex) {
- self::assertArrayHasKey($columnIndex, $result);
- self::assertInstanceOf(Column::class, $result[$columnIndex]);
- }
- $table->setRange('');
- self::assertCount(0, $table->getColumns());
- self::assertSame('', $table->getRange());
- }
- public function testGetColumn(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $columnIndexes = ['L', 'M'];
- foreach ($columnIndexes as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- // If we request a specific column by its column ID, we should
- // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column object returned
- foreach ($columnIndexes as $columnIndex) {
- $result = $table->getColumn($columnIndex);
- self::assertInstanceOf(Column::class, $result);
- }
- }
- public function testGetColumnByOffset(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $columnIndexes = [
- 0 => 'H',
- 3 => 'K',
- 5 => 'M',
- ];
- // If we request a specific column by its offset, we should
- // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column object returned
- foreach ($columnIndexes as $columnIndex => $columnID) {
- $result = $table->getColumnByOffset($columnIndex);
- self::assertInstanceOf(Column::class, $result);
- self::assertEquals($result->getColumnIndex(), $columnID);
- }
- }
- public function testGetColumnIfNotSet(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- // If we request a specific column by its column ID, we should
- // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table\Column object returned
- $result = $table->getColumn('K');
- self::assertInstanceOf(Column::class, $result);
- }
- public function testGetColumnWithoutRangeSet(): void
- {
- $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
- $table = new Table(self::INITIAL_RANGE);
- // Clear the range
- $table->setRange('');
- $table->getColumn('A');
- }
- public function testClearRangeWithExistingColumns(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $expectedResult = '';
- $columnIndexes = ['L', 'M', 'N'];
- foreach ($columnIndexes as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- // Setters return the instance to implement the fluent interface
- $result = $table->setRange('');
- self::assertInstanceOf(Table::class, $result);
- // Range should be cleared
- $result = $table->getRange();
- self::assertEquals($expectedResult, $result);
- // Column array should be cleared
- $result = $table->getColumns();
- self::assertIsArray($result);
- self::assertCount(0, $result);
- }
- public function testSetRangeWithExistingColumns(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $expectedResult = 'G1:J512';
- // These columns should be retained
- $columnIndexes1 = ['I', 'J'];
- foreach ($columnIndexes1 as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- // These columns should be discarded
- $columnIndexes2 = ['K', 'L', 'M'];
- foreach ($columnIndexes2 as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- // Setters return the instance to implement the fluent interface
- $result = $table->setRange($expectedResult);
- self::assertInstanceOf(Table::class, $result);
- // Range should be correctly set
- $result = $table->getRange();
- self::assertEquals($expectedResult, $result);
- // Only columns that existed in the original range and that
- // still fall within the new range should be retained
- $result = $table->getColumns();
- self::assertIsArray($result);
- self::assertCount(count($columnIndexes1), $result);
- }
- public function testClone(): void
- {
- $sheet = $this->getSheet();
- $table = new Table(self::INITIAL_RANGE);
- $sheet->addTable($table);
- $columnIndexes = ['L', 'M'];
- foreach ($columnIndexes as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- $result = clone $table;
- self::assertInstanceOf(Table::class, $result);
- self::assertSame($table->getRange(), $result->getRange());
- self::assertNull($result->getWorksheet());
- self::assertNotNull($table->getWorksheet());
- self::assertInstanceOf(Worksheet::class, $table->getWorksheet());
- $tableColumns = $table->getColumns();
- $resultColumns = $result->getColumns();
- self::assertIsArray($tableColumns);
- self::assertIsArray($resultColumns);
- self::assertCount(2, $tableColumns);
- self::assertCount(2, $resultColumns);
- self::assertArrayHasKey('L', $tableColumns);
- self::assertArrayHasKey('L', $resultColumns);
- self::assertArrayHasKey('M', $tableColumns);
- self::assertArrayHasKey('M', $resultColumns);
- self::assertInstanceOf(Column::class, $tableColumns['L']);
- self::assertInstanceOf(Column::class, $resultColumns['L']);
- self::assertInstanceOf(Column::class, $tableColumns['M']);
- self::assertInstanceOf(Column::class, $resultColumns['M']);
- }
- public function testNoWorksheet(): void
- {
- $table = new Table();
- self::assertNull($table->getWorksheet());
- }
- public function testClearColumn(): void
- {
- $table = new Table(self::INITIAL_RANGE);
- $columnIndexes = ['J', 'K', 'L', 'M'];
- foreach ($columnIndexes as $columnIndex) {
- $table->setColumn($columnIndex);
- }
- $columns = $table->getColumns();
- self::assertCount(4, $columns);
- self::assertArrayHasKey('J', $columns);
- self::assertArrayHasKey('K', $columns);
- self::assertArrayHasKey('L', $columns);
- self::assertArrayHasKey('M', $columns);
- $table->clearColumn('K');
- $columns = $table->getColumns();
- self::assertCount(3, $columns);
- self::assertArrayHasKey('J', $columns);
- self::assertArrayHasKey('L', $columns);
- self::assertArrayHasKey('M', $columns);
- }
- }
|