Repository navigation
sheet range set-style unmerges fully covered merged ranges despite style-only contract (v1.0.63) #1497
Description
Environment
DWS v1.0.63, commit 4cd5d05 (2026-10-03). Reproduced on 2026-10-13 with a newly created disposable Sheet containing only synthetic text.
Minimal trigger
Create a disposable Sheet and use nodeId and sheetId returned by create-with-data. No existing business Sheet is needed.
dws sheet create-with-data --name DWS-MERGE-REPRO --values '[["","SYNTHETIC_TITLE","","CONTROL"],["","SYNTHETIC_GUIDE","",""],["CONTROL","","",""]]' --format json
dws sheet merge-cells --node NODE_FROM_CREATE --sheet-id SHEET_FROM_CREATE --range B1:C1 --format json
dws sheet info --node NODE_FROM_CREATE --sheet-id SHEET_FROM_CREATE --format json
dws sheet range set-style --node NODE_FROM_CREATE --sheet-id SHEET_FROM_CREATE --range B1:C1 --font-weight bold --format json
dws sheet info --node NODE_FROM_CREATE --sheet-id SHEET_FROM_CREATE --format json
dws sheet range read --node NODE_FROM_CREATE --sheet-id SHEET_FROM_CREATE --range A1:D3 --format jsonBefore set-style, mergedRanges is ["B1:C1"]. The style call succeeds. Afterward, mergedRanges is [], while the values are unchanged and both cells have fontWeight=bold. One pre-existing merged block and one style-only write suffice.
The dry-run translates the write to set_cell_range with only nodeId, sheetId, rangeAddress, and cells=[[{cellStyles:{fontWeight:"bold"}},{cellStyles:{fontWeight:"bold"}}]]. It contains no value or explicit unmerge operation.
Expected behavior
Pure style writes should preserve existing merged ranges, or explicitly reject unsupported shapes without changing structure. The pinned source documents style-only writes as safe for merged cells:
dingtalk-workspace-cli/internal/helpers/sheet_style.go
Lines 15 to 19 in 4cd5d05
| // set-style / batch-set-style | |
| // | |
| // 方案 A(对齐飞书 +cells-set-style):样式统一走 set_cell_range 的 cellStyles 路径, | |
| // 每个单元格产出 {"cellStyles":{...}}(不写值,保留原值);纯样式写入对合并单元格安全 | |
| // (底层 setComplexValues 仅对写值 cell 拦截合并冲突)。 |
Isolation matrix
Before each case we restored B1:C1 and B2:C2 and read both structure and A1:D3 content. Each case contained one operation. Standalone and batch-update produced the same merge-preservation and value outcomes. Their error envelopes differ for the full merged-range value case: standalone returns MERGED_CELLS_CONFLICT, while batch-update returns stateServer.invalid_operation with MERGED_CELLS_CONFLICT as the cause. The standalone B1:C1 value case was separately reconfirmed on the same version with raw stdout/stderr, exit code, and complete before/after reads:
| Operation | Result | Merges afterward |
|---|---|---|
| set-style B1:C1 | success | only B2:C2 remains |
| set-style B1 | success | both remain |
| set-style C1 | success | both remain |
| set-style D3 | success | both remain |
| range update B1:C1 with text cells | MERGED_CELLS_CONFLICT | both remain |
| range update B1 | MERGED_CELLS_CONFLICT | both remain |
| range update C1 | MERGED_CELLS_CONFLICT | both remain |
| range update D3 | success | both remain |
A separate style-only B1:C2 write removes both merged blocks. Values remain intact throughout the style probes. All range reads reported hasMore=false. The batch variant used exactly one range set-style operation, ruling out interactions with other subcommands.
Temporary compatibility handling
After reading the original merge ranges and proving subordinate cells contain no unique values, a strict batch containing the style write followed by explicit merge-cells (B1:C2, mergeRows) restored both original merges. A subsequent info/range read verified both merges, all values, and the requested bold style. This is a caller workaround verified only on the disposable synthetic sample; the underlying merged-range preservation issue still needs correction.
Limits
The reproduction identifies the public operation and range shape that changes structure. Server-side implementation is not visible, so this report does not claim whether the final defect lies in CLI translation or the remote Sheet tool. No credentials, personnel records, internal document links, or original business payloads are included.
Activity
dzshzx commentedon Oct 13, 2026
Clarification of the value-write rows in the isolation matrix: the error-envelope difference applies to all three merged targets, not only the full merged range.
sheet range update:error.server_error_codesheet batch-update:error.server_error_codeB1:C1MERGED_CELLS_CONFLICTstateServer.invalid_operationB1MERGED_CELLS_CONFLICTstateServer.invalid_operationC1MERGED_CELLS_CONFLICTstateServer.invalid_operationFor each batch case, the error message identifies
MERGED_CELLS_CONFLICTas the cause. The issue body's Result column records the standalone error code for these three rows. Both invocation modes preserved the existing merges and cell values in the recorded before/after reads; their outer error codes are different.My previous body edit replaced “Standalone and batch-update gave identical outcomes” with a statement about matching merge-preservation and value outcomes, added the distinct error envelopes, and documented a separate same-version recheck of the standalone
B1:C1value write with captured stdout, stderr, exit code, and complete before/after reads. The phrase “for the full merged-range value case” was too narrow: the retained raw errors show the same envelope distinction forB1andC1as well. This comment clarifies all three rows; it does not report a new table write or a fix to the style-only unmerge issue.