Skip to content

Allow differing column counts per row in CSV export #1414

@AndrewMonty

Description

@AndrewMonty

This is:

What is the expected behavior?

There should be an option for each row in a CSV file to have a different number of columns.

Consider a spreadsheet where the first few rows are not actually column headers, but rather some custom heading (in my case a requirement of some third party system consuming the CSV file).

Represented as an array, this might look like:

$data = [
    ['Pretext', 'More pretext'],
    ['this', 'is not', 'a header'],
    ['value 1'],
    ['value 2'],
    ['value 3']
];

And as a spreadsheet:

A B C
Pretext More pretext
this is not a header
value 1
value 2
value 3

Writing to a CSV should have the option to exclude the blank cells on each row:

"Pretext","More pretext"
"this","is not","a header"
"value 1"
"value 2"
"value 3"

What is the current behavior?

Currently, the spreadsheet described above would save as a csv like:

"Pretext","More pretext",
"this","is not","a header"
"value 1",,
"value 2",,
"value 3",,

Where the row with the most columns dictates the column count for all rows, and any that fall short are filled with blanks.

What are the steps to reproduce?

Please provide a Minimal, Complete, and Verifiable example of code that exhibits the issue without relying on an external Excel file or a web server:

<?php

namespace PhpOffice\PhpSpreadsheetTests\Writer\Csv;

use PHPUnit\Framework\TestCase;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Shared\File;

class VariableColumnsTest extends TestCase
{
    public function testVariableColumns()
    {
        $spreadsheet = new Spreadsheet();
        $spreadsheet->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->save($filename);

        $contents = file_get_contents($filename);

        $rows = explode(PHP_EOL, $contents);

        // current
        $this->assertEquals('"A1","B1",""', $rows[0]);
        $this->assertEquals('"A2","B2","C2"', $rows[1]);
        $this->assertEquals('"A3","",""', $rows[2]);

        // desired
        $this->assertEquals('"A1","B1"', $rows[0]);
        $this->assertEquals('"A2","B2","C2"', $rows[1]);
        $this->assertEquals('"A3"', $rows[2]);
    }
}

Which versions of PhpSpreadsheet and PHP are affected?

PhpSpreadsheet 1.10.1

PHP 7.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions