Skip to content

Xls Writer uses 1-based column indices in BIFF DIMENSIONS record instead of required 0-based indices #4682

@zlatanovic-nebojsa

Description

@zlatanovic-nebojsa

Description:

The PhpSpreadsheet Xls writer incorrectly uses 1-based
column indices when writing the BIFF8 DIMENSIONS record
(0x0200), causing an extra empty column to appear in the
generated XLS files. According to the [Microsoft BIFF8
specification](https://learn.microsoft.com/en-us/openspecs/
office_file_formats/ms-xls/5fd3837c-9f3d-4952-8a85-ad93ddb3
7ced), the DIMENSIONS record requires 0-based column
indices
.

Root Cause:

In src/PhpSpreadsheet/Writer/Xls/Worksheet.php, the
constructor calculates column indices using:

$maxC = $this->phpSheet->getHighestColumn();
$this->firstColumnIndex =
Coordinate::columnIndexFromString($minC);
$this->lastColumnIndex =
Coordinate::columnIndexFromString($maxC);

The problem is that Coordinate::columnIndexFromString()
returns 1-based indices (e.g., 'A' = 1, 'G' = 7), but the
BIFF8 DIMENSIONS record expects 0-based indices (e.g., 'A'
= 0, 'G' = 6).

Impact:

When converting XLS files to CSV or text format, an extra
empty column appears with a trailing comma/delimiter on
each row.

Steps to Reproduce:

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xls;

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

// Create 7 columns (A-G)
$sheet->setCellValue('A1', 'Column A');
$sheet->setCellValue('B1', 'Column B');
$sheet->setCellValue('C1', 'Column C');
$sheet->setCellValue('D1', 'Column D');
$sheet->setCellValue('E1', 'Column E');
$sheet->setCellValue('F1', 'Column F');
$sheet->setCellValue('G1', 'Column G');

$writer = new Xls($spreadsheet);
$writer->save('test.xls');

// Inspect DIMENSIONS record - shows colMic=1, colMac=8 
(should be colMic=0, colMac=7)

Expected Behavior:
- For 7 columns (A-G), DIMENSIONS record should have:
colMic = 0, colMac = 7
- XLS file should contain exactly 7 columns when converted
to CSV/text

Actual Behavior:
- DIMENSIONS record has: colMic = 1, colMac = 8
- XLS file appears to have 8 columns, resulting in trailing
 commas in CSV conversion

Specification Reference:

According to
https://learn.microsoft.com/en-us/openspecs/office_file_for
mats/ms-xls/5fd3837c-9f3d-4952-8a85-ad93ddb37ced:

colMic: A ColU structure that specifies the first column in
 the sheet that contains a used cell.

colMac: An unsigned integer that specifies the zero-based 
index of the column after the last column in the sheet that
 contains a used cell.

Proposed Fix:

In src/PhpSpreadsheet/Writer/Xls/Worksheet.php, convert the
 column indices to 0-based:

$maxC = $this->phpSheet->getHighestColumn();
$this->firstColumnIndex =
Coordinate::columnIndexFromString($minC) - 1;
$this->lastColumnIndex =
Coordinate::columnIndexFromString($maxC) - 1;

Environment:
- PhpSpreadsheet version: latest
- PHP version: 8.3
- Operating System: Windows

Workaround:

Binary post-processing of the XLS file to correct the
DIMENSIONS record after generation.

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