diff --git a/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/src/PhpSpreadsheet/Worksheet/AutoFilter.php index cbc4ff65fe..62347a2abf 100644 --- a/src/PhpSpreadsheet/Worksheet/AutoFilter.php +++ b/src/PhpSpreadsheet/Worksheet/AutoFilter.php @@ -1049,7 +1049,11 @@ public function showHideRows() } } // Set show/hide for the row based on the result of the autoFilter result - $this->workSheet->getRowDimension((int) $row)->setVisible($result); + // If the RowDimension object has not been allocated yet and the row should be visible, + // then we can avoid any operation since the rows are visible by default (saves a lot of memory) + if ($result === false || $this->workSheet->rowDimensionExists((int) $row)) { + $this->workSheet->getRowDimension((int) $row)->setVisible($result); + } } $this->evaluated = true; diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 78d460cdb1..3e2d53a1d0 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -3875,4 +3875,9 @@ public static function nameRequiresQuotes(string $sheetName): bool { return preg_match(self::SHEET_NAME_REQUIRES_NO_QUOTES, $sheetName) !== 1; } + + public function isRowVisible(int $row): bool + { + return !$this->rowDimensionExists($row) || $this->getRowDimension($row)->getVisible(); + } } diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index 5c907149ef..9e1df0dc16 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -504,7 +504,7 @@ public function generateSheetData() $html .= $startTag; // Write row if there are HTML table cells in it - $mpdfInvisible = $this->isMPdf && $sheet->getRowDimension($row)->getVisible() === false; + $mpdfInvisible = $this->isMPdf && !$sheet->isRowVisible($row); if (!$mpdfInvisible && !isset($this->isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row])) { // Start a new rowData $rowData = []; diff --git a/src/PhpSpreadsheet/Writer/Ods/Content.php b/src/PhpSpreadsheet/Writer/Ods/Content.php index f52dcfad48..3a5cdbd7a7 100644 --- a/src/PhpSpreadsheet/Writer/Ods/Content.php +++ b/src/PhpSpreadsheet/Writer/Ods/Content.php @@ -171,7 +171,7 @@ private function writeRows(XMLWriter $objWriter, Worksheet $sheet, int $sheetInd $objWriter->endElement(); $span_row = 0; } else { - if ($sheet->getRowDimension($row->getRowIndex())->getRowHeight() > 0) { + if ($sheet->rowDimensionExists($row->getRowIndex()) && $sheet->getRowDimension($row->getRowIndex())->getRowHeight() > 0) { $objWriter->writeAttribute( 'table:style-name', sprintf('%s_%d_%d', Style::ROW_STYLE_PREFIX, $sheetIndex, $row->getRowIndex()) diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index ddc96fa96f..0e72c5d123 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -13,6 +13,7 @@ use PhpOffice\PhpSpreadsheet\Style\Conditional; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension; +use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension; use PhpOffice\PhpSpreadsheet\Worksheet\SheetView; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as PhpspreadsheetWorksheet; @@ -1143,11 +1144,12 @@ private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $w } $currentRow = 0; + $emptyDimension = new RowDimension(); while ($currentRow++ < $highestRow) { $isRowSet = isset($cellsByRow[$currentRow]); if ($isRowSet || $worksheet->rowDimensionExists($currentRow)) { // Get row dimension - $rowDimension = $worksheet->getRowDimension($currentRow); + $rowDimension = $worksheet->rowDimensionExists($currentRow) ? $worksheet->getRowDimension($currentRow) : $emptyDimension; // Write current row? $writeCurrentRow = $isRowSet || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() === false || $rowDimension->getCollapsed() === true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null; diff --git a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php index 83a0b2f429..72a3d1a6b1 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php +++ b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php @@ -95,6 +95,7 @@ public function testEqualsListSimple(): void public function testEqualsList(): void { $sheet = $this->initSheet(); + $sheet->getRowDimension(4)->setRowHeight(25); $maxRow = $this->maxRow; $autoFilter = $sheet->getAutoFilter(); $autoFilter->setRange("A1:A$maxRow"); @@ -115,6 +116,17 @@ public function testEqualsList(): void ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); self::assertEquals([3, 4, 9, 10], $this->getVisible()); + self::assertTrue($sheet->rowDimensionExists(2)); + self::assertFalse($sheet->rowDimensionExists(3), 'row visible by default'); + self::assertTrue($sheet->rowDimensionExists(4), 'row is visible but height has been set'); + self::assertTrue($sheet->rowDimensionExists(5)); + self::assertTrue($sheet->rowDimensionExists(6)); + self::assertTrue($sheet->rowDimensionExists(7)); + self::assertTrue($sheet->rowDimensionExists(8)); + self::assertFalse($sheet->rowDimensionExists(9), 'row visible by default'); + self::assertFalse($sheet->rowDimensionExists(10), 'row visible by default'); + self::assertTrue($sheet->rowDimensionExists(11)); + self::assertTrue($sheet->rowDimensionExists(12)); } public function testNotEqualsList(): void diff --git a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php index 3546bc3231..c77cf7f881 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php @@ -62,7 +62,7 @@ public function getVisibleSheet(Worksheet $sheet): array $sheet->getAutoFilter()->showHideRows(); $actualVisible = []; for ($row = 2; $row <= $this->maxRow; ++$row) { - if ($sheet->getRowDimension($row)->getVisible()) { + if ($sheet->isRowVisible($row)) { $actualVisible[] = $row; } } diff --git a/tests/PhpSpreadsheetTests/Worksheet/RowDimensionSaveTest.php b/tests/PhpSpreadsheetTests/Worksheet/RowDimensionSaveTest.php new file mode 100644 index 0000000000..ab09de26e1 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/RowDimensionSaveTest.php @@ -0,0 +1,55 @@ +getActiveSheet(); + $sheet->getCell('A1')->setValue(1); + $sheet->getCell('A2')->setValue(2); + $sheet->getCell('A3')->setValue(3); + $sheet->getRowDimension(2)->setVisible(false); + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $type); + self::assertFalse($sheet->rowDimensionExists(1)); + self::assertTrue($sheet->rowDimensionExists(2)); + self::assertFalse($sheet->rowDimensionExists(3)); + $spreadsheet->disconnectWorksheets(); + $reloadedSpreadsheet->disconnectWorksheets(); + } + + public static function typeProvider(): array + { + return [ + ['Xlsx'], + ['Xls'], + ['Ods'], + ['Html'], + ]; + } + + public function testSaveNoAllocateRowDimensionMpdf(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue(1); + $sheet->getCell('A2')->setValue(2); + $sheet->getCell('A3')->setValue(3); + $sheet->getRowDimension(2)->setVisible(false); + $writer = new Mpdf($spreadsheet); + $writer->generateHtmlAll(); + self::assertFalse($sheet->rowDimensionExists(1)); + self::assertTrue($sheet->rowDimensionExists(2)); + self::assertFalse($sheet->rowDimensionExists(3)); + $spreadsheet->disconnectWorksheets(); + } +}