What this test covered
The source file had two worksheets. Orders contained four synthetic records, four line-total formulas, currency and date formats, text IDs, numeric quantities, and boolean approval cells displayed as in-cell checkboxes. Summary contained four more formulas: gross sales, North-region sales, approved sales, and order count. No customer or company data appeared in the fixture.
| Cell | Original | Requested edit | Stored type after edit |
|---|---|---|---|
Orders!A7 | ORD-0004 | ORD-0004-R | Forced text |
Orders!B6 | North | West | Text |
Orders!D5 | 20 | 24 | Number |
Orders!E7 | 2026-09-04 | 2026-09-08 | Number with yyyy-mm-dd format |
Orders!G5 | FALSE | TRUE | Boolean |
The fixture is a small preservation test. The checkbox control was the only cell-control feature in the file, and it was lost during export even though the underlying boolean values remained. The test did not cover VBA, external links, array formulas, PivotTables, charts, protected sheets, named ranges, tables, data validation, hidden sheets, or conditional formatting. A production workbook containing any of those features needs a fixture that includes them.
Install the CLI locally
The run installed univer-cli@0.5.0 from npm and used Node.js 24.21.0. Univer CLI currently requires Node.js 24 or later. Running the package under Node.js 22 produced an EBADENGINE warning before the test moved to Node 24. The official project describes local XLSX import, isolated Worktrees, structured inspection, screenshots, and XLSX export in its README; release 0.5.0 is retained on the project release page.
node --version
npm install --save-dev univer-cli@0.5.0
npx univer doctor --json
If node --version reports a version below 24, switch to Node 24 with your version manager before running the install. The install and workbook run did not request a Claude account, Gemini account, model API key, or extra AI subscription. npm needed network access to download the package. The AI agent chose the edits and wrote the Facade script; Univer CLI executed that trusted JavaScript. This was a workflow test, not a comparison of agent models. The project warns that execute is not a sandbox for untrusted JavaScript.
Import without hiding stale caches
The source workbook already contained formula text and cached results. It was imported with calculation disabled so the test could distinguish preservation from recalculation:
npx univer import test.univer \
--file univer-cli-excel-test-source.xlsx \
--formula-calculation no \
--name "Synthetic order register" \
--json
npx univer worktree add test.univer \
--name "Edit units region date ID and approval" \
--json
Before any write, inspect range recorded each cell's stored value, type, formula, style ID, and display value. That baseline matters because a screenshot can show the expected number while the underlying formula cache or type is wrong.

Preserve the cell model during each edit
Univer cells separate the stored value v, the type t, formula text f, and style s. This test deep-copied the existing input cell, changed only the value and type, and left the style reference in place. The relevant type codes were text 1, number 2, boolean 3, and forced text 4.
const unitsCell = orders.getRange("D5").getCellData();
orders.getRange("D5").setValue({ ...unitsCell, v: 24, t: 2 });
const idCell = orders.getRange("A7").getCellData();
orders.getRange("A7").setValue({ ...idCell, v: "ORD-0004-R", t: 4 });
Writing a bare display string into a date, percentage, currency, identifier, or boolean cell can change how Excel stores it. Use structured inspection to capture the raw value and formula first. Keep display text for visual checks.
The first date edit failed
The first script read Orders!E7 through the Facade, received the formatted string 2026-09-04, and attempted Number(value) + 4. The result was NaN. The next structured inspect range call failed with Collaboration runtime result must be JSON-compatible, which made the corruption visible before export.
The successful retry used the raw serial from the pre-edit inspection. It changed 46269 to 46273, retained type 2, and kept the existing yyyy-mm-dd format. The displayed date then became 2026-09-08.
const dateCell = orders.getRange("E7").getCellData();
orders.getRange("E7").setValue({ ...dateCell, v: 46273, t: 2 });
This failure is easy to miss when code treats a formatted date as a JavaScript number. For a real workbook, read the raw serial through a structured inspection path before doing date arithmetic. Adding days to that raw value stays inside the workbook's existing date system. If code converts a calendar date to a serial from scratch, first check whether the workbook uses the 1900 or 1904 date system; the same serial does not represent the same date in both systems. Microsoft documents the difference in its Excel date systems guide.
The first boolean edit left a stale total
The first script wrote { v: 1, t: 3 } to Orders!G5. The cell reported boolean type 3, yet the dependent formula =SUMIF(Orders!G4:G7,TRUE,Orders!F4:F7) kept its old cached result of 2556. Rewriting the value as the JavaScript boolean true and forcing calculation produced 4698.
const approvalCell = orders.getRange("G5").getCellData();
orders.getRange("G5").setValue({ ...approvalCell, v: true, t: 3 });
const calculated = api.getFormula().onCalculationResultApplied();
api.getFormula().executeCalculation();
await calculated;
The completion promise was registered before calculation started. Univer's formula documentation exposes FORCED, WHEN_EMPTY, and NO_CALCULATION modes and recommends forced calculation when formula cells contain unexpected cached values. See the official formula guide.
What changed after recalculation
| Formula cell | Formula text | Before | After | Expected reason |
|---|---|---|---|---|
Orders!F5 | =C5*D5 | 1785.00 | 2142.00 | Units changed from 20 to 24 |
Summary!B3 | =SUM(Orders!F4:F7) | 5840.70 | 6197.70 | Gross sales includes the revised line total |
Summary!B4 | =SUMIF(Orders!B4:B7,"North",Orders!F4:F7) | 2556.00 | 1506.00 | Order ORD-0003 moved from North to West |
Summary!B5 | =SUMIF(Orders!G4:G7,TRUE,Orders!F4:F7) | 2556.00 | 4698.00 | Order ORD-0002 became approved |
Summary!B6 | =COUNTA(Orders!A4:A7) | 4 | 4 | The ID changed, but the row count did not |

The formula ledger compared all eight formula cells, while the table above shows the five affected results. The changed-formula count was zero. That proves formula text was preserved for this fixture. It does not establish that Univer supports every Excel function or feature.
Export with the calculated caches already in place
The final export used --formula-calculation no so another calculation could not hide a stale worktree cache. The official Univer import and export documentation lists XLSX as a supported Sheet import and export format and describes both collaborative and snapshot export paths in its import and export guide.
npx univer export test.univer univer-cli-excel-test-modified.xlsx \
--worktree wt-mudmoy7s-yopqxp \
--unit u-mudmohnd-ahtn31 \
--formula-calculation no \
--json
The exported XLSX passed ZIP integrity checking. A separate workbook reader reopened it before recalculation and found the expected cached results: 6197.7, 1506, 4698, and 4. Recalculation in that reader produced the same values and found no spreadsheet error tokens.
Which formats and cell features survived the XLSX round trip
Direct OOXML inspection confirmed that the edited ID remained text with the @ format, units remained numeric with the 0 format, the date remained numeric with yyyy-mm-dd, and approval remained an XLSX boolean. The currency format on unit price and line total also survived. Style indexes changed during export, while the checked number-format codes, visible font face, size, color and emphasis, solid-fill pattern and foreground, and four border sides matched the source. The comparison ignored default-only XML serialization differences such as 10 versus 10.00 for font size.

The checkbox presentation did not survive. The source XLSX contained xl/featurePropertyBag/featurePropertyBag.xml with a Checkbox feature and matching style references. The Univer export omitted that part and its workbook relationship. The reopened render therefore showed 1 and 0 in the approval column. The boolean values and formulas still worked, but a workbook that depends on in-cell checkboxes needs a separate preservation test.
LibreOfficeDev 26.8.0.0.alpha0 then opened and resaved the exported file. The four summary results remained identical. Its serializer normalized the boolean criterion from TRUE to TRUE(), so this second-office check supports semantic preservation, not byte-for-byte formula identity after another application resaves the file. Microsoft Excel desktop was not used in this test.
When this result is enough, and when it is not
This result supports formula, cache, basic cell-type, and checked-style preservation for a similarly small workbook. It is not evidence that in-cell checkbox controls will survive. For a workbook without that dependency, enumerate the intended input edits, record every formula before and after, force calculation, compare stored types and formats, inspect the exported OOXML, and reopen the file through a second reader or office application.
Expand the fixture before touching a production file that uses in-cell controls, macros, external references, dynamic arrays, PivotTables, charts, validation, conditional formatting, named ranges, hidden sheets, protection, or uncommon functions. Include one representative instance of every feature that must survive. If the exported file cannot pass formula diff, cached-result checks, type and format inspection, visual review, and an independent reopen, keep the original workbook unchanged.
