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
This commit is contained in:
Adrien Crivelli 2020-06-28 21:56:12 +09:00
parent a90bf863ab
commit f1fb8dcf1f
No known key found for this signature in database
GPG Key ID: B182FD79DC6DE92E
3 changed files with 113 additions and 23 deletions

View File

@ -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)

View File

@ -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 .= "<div style='page: page$sheetIndex'>\n";
//} elseif ($this->useInlineCss) {
// $html .= "<div style='page-break-before: always' ></div>\n";
} else {
$html .= "<div style='page: page$sheetIndex' class='scrpgbrk'>\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)
{

View File

@ -0,0 +1,94 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheet\Writer\Html;
use PhpOffice\PhpSpreadsheetTests\Functional;
class ExtendForChartsAndImagesTest extends Functional\AbstractFunctional
{
public function testEmptySheet(): void
{
$spreadsheet = new Spreadsheet();
$this->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, '<tr ');
self::assertSame($expectedRowCount, $rowCount);
$columnCount = substr_count($html, '<td ') / $rowCount;
self::assertSame($expectedColumnCount, $columnCount);
}
}