diff --git a/CHANGELOG.md b/CHANGELOG.md index ca24d6f0e5..552e0869b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added - Improved the ARABIC function to also hande short-hand roman numerals +- Option for CSV files to have varying numbers of columns for each individual row ### Fixed diff --git a/docs/topics/reading-and-writing-to-file.md b/docs/topics/reading-and-writing-to-file.md index 3b6a037cdc..6d7f561056 100644 --- a/docs/topics/reading-and-writing-to-file.md +++ b/docs/topics/reading-and-writing-to-file.md @@ -544,6 +544,18 @@ $writer->setUseBOM(true); $writer->save("05featuredemo.csv"); ``` +#### Writing CSV files with varying numbers of columns + +A CSV file can have a different number of columns in each row. This +differs from the default behavior when saving as a .csv in Excel, but +can be enabled in PhpSpreadsheet by using the following code: + +``` php +$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); +$writer->setVariableColumns(true); +$writer->save("05featuredemo.csv"); +``` + #### Decimal and thousands separators If the worksheet you are exporting contains numbers with decimal or diff --git a/src/PhpSpreadsheet/Writer/Csv.php b/src/PhpSpreadsheet/Writer/Csv.php index 1166bd25b1..18c2590382 100644 --- a/src/PhpSpreadsheet/Writer/Csv.php +++ b/src/PhpSpreadsheet/Writer/Csv.php @@ -64,6 +64,15 @@ class Csv extends BaseWriter */ private $excelCompatibility = false; + /** + * Whether number of columns should be allowed to vary + * between rows, or use a fixed range based on the max + * column overall. + * + * @var bool + */ + private $variableColumns = false; + /** * Create a new CSV. * @@ -119,6 +128,9 @@ public function save($pFilename) // Write rows to file for ($row = 1; $row <= $maxRow; ++$row) { + if ($this->variableColumns) { + $maxCol = $sheet->getHighestDataColumn($row); + } // Convert the row to an array... $cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas); // ... and write to the file @@ -280,6 +292,34 @@ public function setExcelCompatibility($pValue) return $this; } + /** + * Get whether number of columns should be allowed to vary + * between rows, or use a fixed range based on the max + * column overall. + * + * @return bool + */ + public function getVariableColumns() + { + return $this->variableColumns; + } + + /** + * Set whether number of columns should be allowed to vary + * between rows, or use a fixed range based on the max + * column overall. + * + * @param bool $pValue Set the writer to allow variable column counts + * + * @return $this + */ + public function setVariableColumns($pValue) + { + $this->variableColumns = $pValue; + + return $this; + } + /** * Get sheet index. * diff --git a/tests/PhpSpreadsheetTests/Writer/Csv/VariableColumnsTest.php b/tests/PhpSpreadsheetTests/Writer/Csv/VariableColumnsTest.php new file mode 100644 index 0000000000..d852c91104 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Writer/Csv/VariableColumnsTest.php @@ -0,0 +1,36 @@ +setActiveSheetIndex(0); + $spreadsheet->getActiveSheet()->setCellValue('A1', 'A1'); + $spreadsheet->getActiveSheet()->setCellValue('B1', 'B1'); + $spreadsheet->getActiveSheet()->setCellValue('A2', 'A2'); + $spreadsheet->getActiveSheet()->setCellValue('B2', 'B2'); + $spreadsheet->getActiveSheet()->setCellValue('C2', 'C2'); + $spreadsheet->getActiveSheet()->setCellValue('A3', 'A3'); + + $filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test'); + $writer = IOFactory::createWriter($spreadsheet, 'Csv'); + $writer->setVariableColumns(true); + $writer->save($filename); + + $contents = file_get_contents($filename); + + $rows = explode(PHP_EOL, $contents); + + $this->assertEquals('"A1","B1"', $rows[0]); + $this->assertEquals('"A2","B2","C2"', $rows[1]); + $this->assertEquals('"A3"', $rows[2]); + } +}