Skip to content

Fix worksheet dimension after cell writes#2295

Open
rootsec1 wants to merge 1 commit into
qax-os:masterfrom
rootsec1:fix/worksheet-dimension-on-cell-write
Open

Fix worksheet dimension after cell writes#2295
rootsec1 wants to merge 1 commit into
qax-os:masterfrom
rootsec1:fix/worksheet-dimension-on-cell-write

Conversation

@rootsec1

Copy link
Copy Markdown
Contributor

Summary

This change keeps worksheet <dimension> metadata in sync when cell writes expand the used range.

Today the cell-writing paths grow SheetData, but they do not update ws.Dimension. As a result, the serialized worksheet can keep an old <dimension ref="..."> even after writing cells outside that range.

A simple repro before this change:

f := excelize.NewFile()
_ = f.SetCellValue("Sheet1", "C5", "value")
_ = f.SaveAs("out.xlsx")

The saved worksheet still reports A1 as its dimension instead of C5.

The same problem shows up for existing workbooks too. If a worksheet starts with B2:E61 and a write lands at G64, the saved worksheet still reports B2:E61.

Some readers and validators trust worksheet dimensions as the authoritative used range. When that metadata stays stale, the sheet can be interpreted as truncated, and stricter consumers may treat the workbook as inconsistent.

Root Cause

All of the common cell write paths eventually call prepareSheetXML(col, row) so that the target row and cell nodes exist before writing.

prepareSheetXML currently:

  • appends missing rows
  • fills contiguous cells in the target row

But it does not expand ws.Dimension.

That means the actual worksheet data grows while the dimension element remains frozen at its previous value.

Fix

This patch adds expandSheetDimension(col, row) and calls it from prepareSheetXML.

Behavior:

  • no-op for row-only / column-only preparation (col < 1 or row < 1)
  • initializes the dimension when it is missing
  • expands an existing range to include the written cell
  • preserves non-A1 starting bounds when the worksheet already has a non-default used range
  • falls back safely if the current stored dimension cannot be parsed

This keeps dimension updates centralized in the same helper that already owns worksheet growth, so all cell-writing APIs benefit without duplicating logic.

Tests

The change adds coverage for the two cases above:

  • writing C5 in a new workbook updates the worksheet dimension to C5
  • writing G64 to a sheet whose dimension is B2:E61 updates it to B2:G64

It also updates TestWorksheetWriter to reflect that a worksheet modified through SetCellValue now serializes with a maintained <dimension> element.

Validation

I validated this in three ways:

  • focused unit coverage for worksheet dimension behavior
  • full go test ./...
  • manual reproduction on existing .xlsx files where writes outside the prior used range previously left stale dimensions in the saved XML

Compatibility Notes

This does not change how cell values are written. It only keeps the worksheet metadata aligned with the cells that were actually prepared and written.

For new workbooks, the resulting dimension is the exact used range (C5, not A1:C5) which matches the worksheet's real populated bounds.

@xuri xuri added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants