From 9611a6dd69f0b8bd273823d7dca55be940ede778 Mon Sep 17 00:00:00 2001 From: Hergen Dillema Date: Mon, 25 Nov 2024 15:22:16 +0100 Subject: [PATCH] Added functions to get dimensions, freezepanes and tab colors --- README.md | 73 ++++++++++ demo/files/demo-07-size-freeze-tabs.xlsx | Bin 0 -> 47974 bytes src/FastExcelReader/Sheet.php | 172 ++++++++++++++++++++++- tests/FastExcelReaderTest.php | 46 ++++++ 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 demo/files/demo-07-size-freeze-tabs.xlsx diff --git a/README.md b/README.md index 390d401..90fc4bc 100644 --- a/README.md +++ b/README.md @@ -624,6 +624,76 @@ $validations = $sheet->getDataValidations(); */ ``` +## Column Widths +Retrieve the width of a specific column in a sheet: + +```php +$excel = Excel::open($file); +$sheet = $excel->selectSheet('SheetName'); + +// Get the width of column 1 (column 'A') +$columnWidth = $sheet->getColumnWidth(1); + +echo $columnWidth; // Example: 11.85 +``` + +## Row Heights +Retrieve the height of a specific row in a sheet: + +```php +$excel = Excel::open($file); +$sheet = $excel->selectSheet('SheetName'); + +// Get the height of row 1 +$rowHeight = $sheet->getRowHeight(1); + +echo $rowHeight; // Example: 15 +``` + +## Freeze Pane Configuration +Retrieve the freeze pane configuration for a sheet: + +```php +$excel = Excel::open($file); +$sheet = $excel->selectSheet('SheetName'); + +// Get the freeze pane configuration +$freezePaneConfig = $sheet->getFreezePaneConfig(); + +print_r($freezePaneConfig); +/* +Example Output: +Array +( + [xSplit] => 0 + [ySplit] => 1 + [topLeftCell] => 'A2' +) +*/ +``` + +## Tab Color Configuration +Retrieve the tab color settings for a sheet: + +```php +Copy code +$excel = Excel::open($file); +$sheet = $excel->selectSheet('SheetName'); + +// Get the tab color configuration +$tabColorConfig = $sheet->getTabColorConfiguration(); + +print_r($tabColorConfig); +/* +Example Output: +Array +( + [theme] => '2' + [tint] => '-0.499984740745262' +) +*/ +``` + ## Support merged cells You can use the following methods: @@ -664,6 +734,9 @@ if ($sheet->isMerged('B3')) { * ```firstCol()``` -- The first column letter * ```readFirstRow()``` -- Returns values of cells of 1st row as array * ```readFirstRowWithStyles()``` -- Returns values and styles of cells of 1st row as array +* ```getColumnWidth(int)``` -- Returns the width of a given column number +* ```getFreezePaneConfig()``` -- Returns an array containing freeze pane configuration +* ```getTabColorConfiguration()``` -- Returns an array containing tab color configuration ## Do you want to support FastExcelReader? diff --git a/demo/files/demo-07-size-freeze-tabs.xlsx b/demo/files/demo-07-size-freeze-tabs.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5dfcc6a83fad63e5eda942f3a9f696c0ecea7326 GIT binary patch literal 47974 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 = $excel; @@ -1761,4 +1769,166 @@ protected function parseExtendedDataValidation(InterfaceXmlReader $xmlReader): a 'formula2' => $formula2 ]; } -} + + public function setDefaultRowHeight(float $rowHeight): void + { + $this->defaultRowHeight = $rowHeight; + } + + /** + * Parses and retrieves column widths and row heights from the sheet XML. + * + * @return void + */ + protected function extractColumnWidthsAndRowHeights(): void + { + $this->colWidths = []; + $this->rowHeights = []; + + $xmlReader = $this->getReader(); + $xmlReader->openZip($this->pathInZip); + + while ($xmlReader->read()) { + if ($xmlReader->nodeType === \XMLReader::ELEMENT) { + // Extract column width + if ($xmlReader->name === 'col') { + $min = (int)$xmlReader->getAttribute('min'); + $max = (int)$xmlReader->getAttribute('max'); + $width = (float)$xmlReader->getAttribute('width'); + + for ($i = $min; $i <= $max; $i++) { + $this->colWidths[$i] = $width; + } + } + // Extract row height + elseif ($xmlReader->name === 'row') { + $rowIndex = (int)$xmlReader->getAttribute('r'); + $height = $xmlReader->getAttribute('ht') ? (float)$xmlReader->getAttribute('ht') : $this->defaultRowHeight; + $this->rowHeights[$rowIndex] = $height; + } + } + } + + $xmlReader->close(); + } + + /** + * Returns column width for a specific column number. + * + * @param int $colNumber + * @return float|null + */ + public function getColumnWidth(int $colNumber): ?float + { + if ($this->colWidths === null) { + $this->extractColumnWidthsAndRowHeights(); + } + return $this->colWidths[$colNumber] ?? null; + } + + /** + * Returns row height for a specific row number. + * + * @param int $rowNumber + * @return float|null + */ + public function getRowHeight(int $rowNumber): ?float + { + if ($this->rowHeights === null) { + $this->extractColumnWidthsAndRowHeights(); + } + return $this->rowHeights[$rowNumber] ?? null; + } + + /** + * Parses and retrieves frozen pane configuration from the sheet XML. + * + * @return array|null + */ + public function getFreezePaneConfig(): ?array + { + $xmlReader = $this->getReader(); + $xmlReader->openZip($this->pathInZip); + + $freezePane = null; + + while ($xmlReader->read()) { + if ($xmlReader->nodeType === \XMLReader::ELEMENT && $xmlReader->name === 'pane') { + $xSplit = (int)$xmlReader->getAttribute('xSplit'); + $ySplit = (int)$xmlReader->getAttribute('ySplit'); + $topLeftCell = $xmlReader->getAttribute('topLeftCell'); + + $freezePane = [ + 'xSplit' => $xSplit, + 'ySplit' => $ySplit, + 'topLeftCell' => $topLeftCell, + ]; + break; + } + } + + $xmlReader->close(); + return $freezePane; + } + + /** + * Extracts the tab properties from the sheet XML + * + * @return void + */ + protected function _readTabProperties(): void + { + if ($this->tabProperties !== null) { + return; + } + + $this->tabProperties = [ + 'color' => null, + ]; + + $xmlReader = $this->getReader(); + $xmlReader->openZip($this->pathInZip); + + while ($xmlReader->read()) { + if ($xmlReader->nodeType === \XMLReader::ELEMENT && $xmlReader->name === 'sheetPr') { + while ($xmlReader->read()) { + if ($xmlReader->nodeType === \XMLReader::ELEMENT && $xmlReader->name === 'tabColor') { + $this->tabProperties['color'] = [ + 'rgb' => $xmlReader->getAttribute('rgb'), + 'theme' => $xmlReader->getAttribute('theme'), + 'tint' => $xmlReader->getAttribute('tint'), + 'indexed' => $xmlReader->getAttribute('indexed'), + ]; + + $this->tabProperties['color'] = array_filter( + $this->tabProperties['color'], + static fn($value) => $value !== null + ); + break; + } + if ($xmlReader->nodeType === \XMLReader::END_ELEMENT && $xmlReader->name === 'sheetPr') { + break; + } + } + break; + } + } + + $xmlReader->close(); + } + + /** + * Returns the tab color configuration of the sheet + * Contains any of: rgb, theme, tint, indexed + * + * @return array|null + */ + public function getTabColorConfiguration(): ?array + { + if ($this->tabProperties === null) { + $this->_readTabProperties(); + } + + return $this->tabProperties['color']; + } +} \ No newline at end of file diff --git a/tests/FastExcelReaderTest.php b/tests/FastExcelReaderTest.php index 79f6605..b6bcb47 100644 --- a/tests/FastExcelReaderTest.php +++ b/tests/FastExcelReaderTest.php @@ -406,6 +406,52 @@ public function testFillRow() $this->assertEquals(['#' => 1, 'name' => 'James Bond', 'birthday' => -2205187200, 'random_int' => 4573], $rows[2]); } + public function testGetColumnWidth(): void + { + $file = self::DEMO_DIR . 'demo-07-size-freeze-tabs.xlsx'; + $excel = Excel::open($file); + $width_1 = $excel->selectSheet('report')->getColumnWidth(1); + $width_3 = $excel->selectSheet('report')->getColumnWidth(3); + + $this->assertEquals(11.85546875, $width_1); + $this->assertEquals(27.85546875, $width_3); + } + + public function testGetRowHeight(): void + { + $file = self::DEMO_DIR . 'demo-07-size-freeze-tabs.xlsx'; + $excel = Excel::open($file); + $height_1 = $excel->selectSheet('report')->getRowHeight(1); + $height_3 = $excel->selectSheet('report')->getRowHeight(3); + + $this->assertEquals(15, $height_1); + $this->assertEquals(35.25, $height_3); + } + + public function testGetFreezePane(): void + { + $file = self::DEMO_DIR . 'demo-07-size-freeze-tabs.xlsx'; + $excel = Excel::open($file); + $freezePane = $excel->selectSheet('report')->getFreezePaneConfig(); + + $this->assertEquals([ + 'xSplit' => 0, + 'ySplit' => 1, + 'topLeftCell' => 'A2' + ], $freezePane); + } + + public function testGetTabColorConfig(): void + { + $file = self::DEMO_DIR . 'demo-07-size-freeze-tabs.xlsx'; + $excel = Excel::open($file); + $config = $excel->selectSheet('report')->getTabColorConfiguration(); + + $this->assertEquals([ + 'theme' => '2', + 'tint' => '-0.499984740745262' + ], $config); + } public function testRefPath() {