Repository navigation
ROneCOne 1.9.0
ROneCOne 1.9.0
Excel Tables become a first-class input, and the JSON writer stops polluting the caller's error
state.
The two are connected. Building a demo for Tables turned up the second defect, and reviewing that
demo turned up the honest answer to the first: the runtime had never heard of a ListObject.
Searching the source for the type returned zero hits, the documentation never mentioned it, and
the only advice on offer was to pass listObject.Range yourself and work around a 438.
Upgrading is a drop-in replacement of ROneCOne.cls. One behavior changes, in favour of the
documented contract: Json.Serialize handed a bare Range used to serialize that cell's value
and now raises, which is what the JSON reference has always said it would do.
Added
Every worksheet entry point takes a Table. DataTableFromRange, ListFromRange,
LoadFromRange, and ToRange accept a ListObject or a single ListColumn directly, resolved
through one guarded helper. With headers wanted the slice stops after the last body row, so a
totals row is never read as data, and an empty Table yields its columns with no rows rather than
failing.
ROneCOne.Table(listObject) goes further: the table it returns remembers where it came from.
Refresh re-reads it in place, and WriteBack writes rows into the Table and resizes it to fit.
ToRange given a Table performs the same write, so a DataView can drive it.
Refresh is a Sub rather than a Function returning a copy, because a bare Refresh statement
on a Function would compile and silently do nothing.
Excel behavior this works around
Four things about resizing a Table are awkward, and every one was measured in a live instance
before a line of the implementation existed:
- Resizing to a header row alone raises 1004: a Table must keep at least one data row. Writing
zero rows goes throughDataBodyRange.Deleteinstead, which leaves the Table and its headers
in place. - Shrinking leaves the vacated cells populated below the Table.
WriteBackclears them. - A totals row lands inside the requested range when a Table grows and outside it when one
shrinks. Rather than encode that asymmetry, totals are switched off around the resize and
restored after. - Name, style, and header text survive a resize, so none of them need saving.
Fixed
Every JSON serialization left a stray error behind
(issue #5). This is the IsArray
hazard closed in 1.8.1, in a second intrinsic. VarType also evaluates its argument in a value
context, so a Variant holding a runtime value was dereferenced through its default member, Run,
which rejects the zero arguments that dereference supplies. VarType then reported vbObject
precisely because that call failed, so the text came out correct and only the error state was
poisoned, for any caller running under On Error Resume Next. The JSON writer opens with a
VarType test on the value it was handed, so lists, dictionaries, tables, rows, and views were
all affected. ToCsv was not, because the CSV writer never asks a Variant for its type.
All 52 type tests now route through a guarded VarTypeOf, and a source contract pins VarType to
that one site.
ToJson(True) also ignored indentation for tables, rows, and views, returning text identical to
ToJson() while the documentation promised otherwise. The indented writer now covers them.
A note on the guard that caught its own author
The source contract that pins Friend member access found a regression inside this very change.
Collection.Item returns a Variant, so reading the Friend InternalDataRows off it in the
new write-back path reintroduced the 438 closed in
issue #3 with no Object local
anywhere in the code. The contract as written only looked at declared late-bound locals, so the
analyzer caught it and the contract did not. The contract now rejects any .Item(...).Member
chain reaching a Friend member.
Release evidence
Each of three fresh Microsoft 365 Excel processes passed 997 live assertions, up from 959 by
thirty-eight: twelve covering error cleanliness and indented output across every serializable
shape, and twenty-six over a real ListObject built in the suite workbook, covering each bridge
taking the Table directly, the attached surface, WriteBack shrinking with the vacated cells
cleared, Refresh, WriteBack growing, a view driving ToRange into the Table, a totals row
surviving the resize, and four guardrails asserted on the raised error rather than the answer.
All ten suite benchmark scenarios met their release gates in every sample. Sixteen demo workbooks
were rebuilt against this runtime and every example in each one passed; the Excel Table demo's
forty-four examples ran with its 5,000-row read, filter, and write-back benchmark inside its
five-second gate.
Static analysis on pyVBAanalysis 1.3.0 reported zero diagnostics across the runtime source, the
live test modules, and all sixteen demo modules. Python contract tests pin the source and demo shapes. Every packaged VBA
module round-tripped byte-for-byte.
Method note
Both defects were reproduced live before any code changed, and neither is visible to static
analysis. The VarType defect was isolated by testing each construct against a Variant holding a
runtime value and recording Err after each one: argument passing is innocent in every form, and
VarType alone fires the default member. That the intrinsic dereferences a foreign object through
its default member was then confirmed directly, with a Range holding text reporting vbString
rather than vbObject.