Open cell-bold.xlsx (A1='Hello bold cell' with bold style s=1), assign ws['A1']='hello', save. Assert (a) A1's displayed value is 'hello' (via sharedStrings), (b) A1's @s='1' is preserved — the cell's bold formatting must not be clobbered by the value change, (c) the dimension ref and other structural attributes are unchanged.
Library verdicts: python-xlsx: — xlsxjs: —
| Feature id | xlsx/modify-set-cell-value |
|---|---|
| Format | xlsx |
| Category | modify-in-place |
| Spec | ecma-376-5-part-1 § 18.3.1.4 c |
| ID / part | Predicate | XPath | python-xlsx | xlsxjs |
|---|---|---|---|---|
a1-style-preservedxl/worksheets/sheet1.xml | equal = 1A1's @s index (pointing at the bold cellXf entry) must be preserved — the value change must not drop the style reference. | //s:sheetData/s:row/s:c[@r='A1']/@s | — | — |
a1-is-string-typedxl/worksheets/sheet1.xml | equal = sA1 must remain a shared-string-typed cell. | //s:sheetData/s:row/s:c[@r='A1']/@t | — | — |
a1-references-shared-stringxl/worksheets/sheet1.xml | existA1 must still carry a <v> child — some bugs drop the value element entirely. | //s:sheetData/s:row/s:c[@r='A1']/s:v | — | — |
new-value-in-sharedstringsxl/sharedStrings.xml | existThe shared-strings table must now carry the new 'hello' entry referenced by A1. | //s:si/s:t[normalize-space()='hello'] | — | — |
a1-resolves-to-helloxl/sharedStrings.xml | equal = helloBecause A1's <v>0</v> references sst[0], the first <si> must resolve to 'hello'. | /s:sst/s:si[1]/s:t | — | — |
row-count-unchangedxl/worksheets/sheet1.xml | match = ^1(\.0+)?$Setting A1's value must not add phantom rows — exactly 1 row (the source had 1). | count(//s:sheetData/s:row) | — | — |
dimension-unchangedxl/worksheets/sheet1.xml | equal = A1:A1dimension/@ref (adjacent attribute) must be preserved byte-for-byte. | //s:dimension/@ref | — | — |
No render assertions declared.
scripts/gen_modify_set_cell_value.py
#!/usr/bin/env python3
"""Generate ``fixtures/xlsx/cell-bold--set-cell-value.xlsx``.
Thin wrapper around ``scripts.mutations.xlsx_set_cell_value``. Opens
``fixtures/xlsx/cell-bold.xlsx``, sets ws['A1']='hello', saves.
Satisfies ``features/xlsx/modify-set-cell-value.json``.
"""
from __future__ import annotations
from pathlib import Path
from mutations import xlsx_set_cell_value
_REPO_ROOT = Path(__file__).resolve().parent.parent
_IN = _REPO_ROOT / "fixtures" / "xlsx" / "cell-bold.xlsx"
_OUT = _REPO_ROOT / "fixtures" / "xlsx" / "cell-bold--set-cell-value.xlsx"
def main() -> int:
xlsx_set_cell_value(_IN, _OUT)
print(_OUT)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "xlsx/modify-set-cell-value",
"title": "Modify: overwrite cell value on existing .xlsx",
"format": "xlsx",
"category": "modify-in-place",
"summary": "Open cell-bold.xlsx (A1='Hello bold cell' with bold style s=1), assign ws['A1']='hello', save. Assert (a) A1's displayed value is 'hello' (via sharedStrings), (b) A1's @s='1' is preserved — the cell's bold formatting must not be clobbered by the value change, (c) the dimension ref and other structural attributes are unchanged.",
"roles": [
"authoring"
],
"spec": {
"source": "ecma-376-5-part-1",
"clause": "18.3.1.4",
"element": "c",
"rnc_reference": "spec/ecma-376-5/part-1/rnc/SpreadsheetML.rnc",
"xsd_reference": "spec/ecma-376-5/part-1/xsd/sml.xsd",
"notes": "SpreadsheetML cells carry value and style independently: <c r=\"A1\" s=\"1\" t=\"s\"><v>0</v></c> — @s indexes styles.xml and must survive a value change. openpyxl/python-xlsx reuses the Cell object's style on reassignment."
},
"fixtures": {
"machine": "xlsx/cell-bold--set-cell-value"
},
"modify": {
"input_fixture": "fixtures/xlsx/cell-bold.xlsx",
"mutation": "xlsx_set_cell_value",
"output_fixture": "fixtures/xlsx/cell-bold--set-cell-value.xlsx"
},
"generator": {
"python": "scripts/gen_modify_set_cell_value.py"
},
"assertions": [
{
"id": "a1-style-preserved",
"part": "xl/worksheets/sheet1.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//s:sheetData/s:row/s:c[@r='A1']/@s",
"must": "equal",
"value": "1",
"description": "A1's @s index (pointing at the bold cellXf entry) must be preserved — the value change must not drop the style reference."
},
{
"id": "a1-is-string-typed",
"part": "xl/worksheets/sheet1.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//s:sheetData/s:row/s:c[@r='A1']/@t",
"must": "equal",
"value": "s",
"description": "A1 must remain a shared-string-typed cell."
},
{
"id": "a1-references-shared-string",
"part": "xl/worksheets/sheet1.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//s:sheetData/s:row/s:c[@r='A1']/s:v",
"must": "exist",
"description": "A1 must still carry a <v> child — some bugs drop the value element entirely."
},
{
"id": "new-value-in-sharedstrings",
"part": "xl/sharedStrings.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//s:si/s:t[normalize-space()='hello']",
"must": "exist",
"description": "The shared-strings table must now carry the new 'hello' entry referenced by A1."
},
{
"id": "a1-resolves-to-hello",
"part": "xl/sharedStrings.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "/s:sst/s:si[1]/s:t",
"must": "equal",
"value": "hello",
"description": "Because A1's <v>0</v> references sst[0], the first <si> must resolve to 'hello'."
},
{
"id": "row-count-unchanged",
"part": "xl/worksheets/sheet1.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "count(//s:sheetData/s:row)",
"must": "match",
"value": "^1(\\.0+)?$",
"description": "Setting A1's value must not add phantom rows — exactly 1 row (the source had 1)."
},
{
"id": "dimension-unchanged",
"part": "xl/worksheets/sheet1.xml",
"namespaces": {
"s": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
},
"xpath": "//s:dimension/@ref",
"must": "equal",
"value": "A1:A1",
"description": "dimension/@ref (adjacent attribute) must be preserved byte-for-byte."
}
]
}
No rendered reference is available for this case.