From f1fb8dcf1fe0f3e00ae4ff6d22308394f2d2fdbb Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Sun, 28 Jun 2020 21:56:12 +0900 Subject: [PATCH] Don't ouput row and columns without any cells in HTML writer If row or column dimensions are accessed, then HTML writer would still generate lots of empty cells, to show nothing at all. This now ignore row and column dimensions to only output cell that actually exists (even if those cells are empty). Fixes #1235 Close #1537 --- CHANGELOG.md | 1 + src/PhpSpreadsheet/Writer/Html.php | 41 ++++---- .../Html/ExtendForChartsAndImagesTest.php | 94 +++++++++++++++++++ 3 files changed, 113 insertions(+), 23 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Writer/Html/ExtendForChartsAndImagesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 68aad0c1..1867f097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). - Fix for Issue [#1495](https://github.com/PHPOffice/PhpSpreadsheet/issues/1495) (Sheet index being changed when multiple sheets are used in formula) [#1500]((https://github.com/PHPOffice/PhpSpreadsheet/pull/1500)) - Fix for Issue [#1533](https://github.com/PHPOffice/PhpSpreadsheet/issues/1533) (A reference to a cell containing a string starting with "#" leads to errors in the generated xlsx.) [#1534](https://github.com/PHPOffice/PhpSpreadsheet/pull/1534) - Xls Writer - Correct Timestamp Bug [#1493](https://github.com/PHPOffice/PhpSpreadsheet/pull/1493) +- Don't ouput row and columns without any cells in HTML writer [#1235](https://github.com/PHPOffice/PhpSpreadsheet/issues/1235) ### Added - Add support for IFS() logical function [#1442](https://github.com/PHPOffice/PhpSpreadsheet/pull/1442) diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index eb50c456..ec8fec7d 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -449,22 +449,19 @@ class Html extends BaseWriter foreach ($sheets as $sheet) { // Write table header $html .= $this->generateTableHeader($sheet); + // Get worksheet dimension - $dimension = explode(':', $sheet->calculateWorksheetDimension()); - $dimension[0] = Coordinate::coordinateFromString($dimension[0]); - $dimension[0][0] = Coordinate::columnIndexFromString($dimension[0][0]); - $dimension[1] = Coordinate::coordinateFromString($dimension[1]); - $dimension[1][0] = Coordinate::columnIndexFromString($dimension[1][0]); + [$min, $max] = explode(':', $sheet->calculateWorksheetDataDimension()); + [$minCol, $minRow] = Coordinate::coordinateFromString($min); + $minCol = Coordinate::columnIndexFromString($minCol); + [$maxCol, $maxRow] = Coordinate::coordinateFromString($max); + $maxCol = Coordinate::columnIndexFromString($maxCol); - // row min,max - $rowMin = $dimension[0][1]; - $rowMax = $dimension[1][1]; - - [$theadStart, $theadEnd, $tbodyStart] = $this->generateSheetStarts($sheet, $rowMin); + [$theadStart, $theadEnd, $tbodyStart] = $this->generateSheetStarts($sheet, $minRow); // Loop through cells - $row = $rowMin - 1; - while ($row++ < $rowMax) { + $row = $minRow - 1; + while ($row++ < $maxRow) { [$cellType, $startTag, $endTag] = $this->generateSheetTags($row, $theadStart, $theadEnd, $tbodyStart); $html .= $startTag; @@ -473,8 +470,8 @@ class Html extends BaseWriter // Start a new rowData $rowData = []; // Loop through columns - $column = $dimension[0][0]; - while ($column <= $dimension[1][0]) { + $column = $minCol; + while ($column <= $maxCol) { // Cell exists? if ($sheet->cellExistsByColumnAndRow($column, $row)) { $rowData[$column] = Coordinate::stringFromColumnIndex($column) . $row; @@ -557,7 +554,7 @@ class Html extends BaseWriter * * @codeCoverageIgnore */ - private function extendRowsForCharts(Worksheet $pSheet, $row) + private function extendRowsForCharts(Worksheet $pSheet, int $row) { $rowMax = $row; $colMax = 'A'; @@ -582,7 +579,7 @@ class Html extends BaseWriter return [$rowMax, $colMax, $anyfound]; } - private function extendRowsForChartsAndImages(Worksheet $pSheet, $row) + private function extendRowsForChartsAndImages(Worksheet $pSheet, int $row): string { [$rowMax, $colMax, $anyfound] = $this->extendRowsForCharts($pSheet, $row); @@ -1169,7 +1166,7 @@ class Html extends BaseWriter * Generate table header. * * @param Worksheet $pSheet The worksheet for the table we are writing - * @param bool $showid whether or not to add id to table tag + * @param bool $showid whether or not to add id to table tag * * @return string */ @@ -1182,8 +1179,6 @@ class Html extends BaseWriter $id = $showid ? "id='sheet$sheetIndex'" : ''; if ($showid) { $html .= "
\n"; - //} elseif ($this->useInlineCss) { - // $html .= "
\n"; } else { $html .= "
\n"; } @@ -1621,11 +1616,11 @@ class Html extends BaseWriter /** * Get use embedded CSS? * - * @deprecated no longer used - * * @return bool * * @codeCoverageIgnore + * + * @deprecated no longer used */ public function getUseEmbeddedCSS() { @@ -1635,13 +1630,13 @@ class Html extends BaseWriter /** * Set use embedded CSS? * - * @deprecated no longer used - * * @param bool $pValue * * @return $this * * @codeCoverageIgnore + * + * @deprecated no longer used */ public function setUseEmbeddedCSS($pValue) { diff --git a/tests/PhpSpreadsheetTests/Writer/Html/ExtendForChartsAndImagesTest.php b/tests/PhpSpreadsheetTests/Writer/Html/ExtendForChartsAndImagesTest.php new file mode 100644 index 00000000..e3d23230 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Writer/Html/ExtendForChartsAndImagesTest.php @@ -0,0 +1,94 @@ +assertMaxColumnAndMaxRow($spreadsheet, 1, 1); + } + + public function testSimpleSheet(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('B3', 'foo'); + + $this->assertMaxColumnAndMaxRow($spreadsheet, 2, 3); + } + + public function testSheetWithExtraColumnDimensions(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('B3', 'foo'); + + // Artificially expend the sheet column count without any real cells + $sheet->getColumnDimension('E'); + + $this->assertMaxColumnAndMaxRow($spreadsheet, 2, 3); + } + + public function testSheetWithExtraRowDimensions(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('B3', 'foo'); + + // Artificially expend the sheet row count without any real cells + $sheet->getRowDimension(5); + + $this->assertMaxColumnAndMaxRow($spreadsheet, 2, 3); + } + + public function testSheetWithImageBelowData(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('B3', 'foo'); + + // Add a drawing to the worksheet + $drawing = new Drawing(); + $drawing->setPath('foo.png', false); + $drawing->setCoordinates('A5'); + $drawing->setWorksheet($sheet); + + $this->assertMaxColumnAndMaxRow($spreadsheet, 2, 5); + } + + public function testSheetWithImageRightOfData(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('B3', 'foo'); + + // Add a drawing to the worksheet + $drawing = new Drawing(); + $drawing->setPath('foo.png', false); + $drawing->setCoordinates('E1'); + $drawing->setWorksheet($sheet); + + $this->assertMaxColumnAndMaxRow($spreadsheet, 5, 3); + } + + private function assertMaxColumnAndMaxRow(Spreadsheet $spreadsheet, int $expectedColumnCount, int $expectedRowCount): void + { + $writer = new Html($spreadsheet); + $html = $writer->generateHtmlAll(); + + $rowCount = substr_count($html, '