The spreadsheet engine parsed typed input with the invariant culture while
displaying values with the current culture, breaking the edit round-trip on
non-en-US hosts and making comma-decimal entry (10,50) impossible.
Workbook gains a Culture property (defaults to CurrentCulture) which the
component stamps from its inherited Culture parameter. It drives:
- Cell input parsing (CellData type inference), including day-month date
handling for cultures where the group and date separators collide (de-DE)
- Edit text and display rendering (GetValue, GetValueAsString, GetDisplayText)
- Number format rendering - format codes stay canonical invariant tokens while
separators, month names, and AM/PM designators follow the culture
- Formula entry and display via the new FormulaLocalizer (Excel FormulaLocal
semantics: ';' argument separators and ',' decimals in comma-decimal
cultures, lenient comma acceptance where unambiguous, canonical invariant
storage)
- Dialog input (data validation, conditional format, filter) via shared
conversion helpers on SpreadsheetDialogBase
XLSX and CSV files read and write canonical invariant values regardless of
the workbook culture, including autofit column widths. Malformed formulas now
surface as error trees instead of an unhandled lexer exception. Number format
parsing is cached (hard-bounded) since CellView reparsed per render.
Includes localization demos for the Spreadsheet and Document Processing
sections and culture test suites.
Note: headless code on non-en-US hosts now parses string values with the
host culture; set Workbook.Culture explicitly (or to InvariantCulture) for
host-independent processing.
Formats, quote prefixes and hyperlinks are now copied, empty source
cells blank their destinations and cut clears the source, matching
Excel. Entering a value over a formula cell replaces the formula, quote
prefixed entries store literal text and undo restores cells exactly as
captured, including after redo.
Breaking change: RangeSnapshotCommandBase snapshots cells as detached
clones (Dictionary<CellRef, Cell?>) instead of a value/formula/format
tuple.
For IDictionary data the aggregate Property is a dynamic LINQ expression, so
reflection cannot resolve its type and isNumeric was always false, causing
Sum/Average/Min/Max to degrade to Count. Fall back to the configured Type when
reflection fails, mirroring RadzenPivotField.FilterPropertyType.
CJK, kana, hangul, fullwidth forms and emoji render at roughly twice
the digit width (15.25px regular / 15.75px bold, measured against
Excel), so the ASCII fallback under-sized such columns by half. Runs
over runes so surrogate pairs count as one glyph.
A width that snugly fits content rendered with the browser theme font
can clip in Excel, which renders the Normal style font with different
character widths - most visibly currency values whose digits are wider
in Aptos Narrow than in typical UI fonts.
On export, auto fitted columns recompute their width from the column
content using per-character advance widths of Aptos Narrow 11 measured
against Excel (regular and bold), keeping the larger of the model width
and the required width. The in-component width is unchanged.
Canvas metrics of the theme font differ from what other renderers use
for the same content (Excel renders exported columns with the Normal
style font), so an exact fit can clip after export. 3% covers the
observed drift while keeping the in-component fit tight.
Exported files write Aptos Narrow 11 as the Normal style font but column
widths were converted with Calibri 11's 7px maximum digit width, and
columns at the default width were not exported at all - Excel applied
its own 68px default and numeric cells overflowed as ####.
XLSX column widths are measured in characters of the Normal font's
maximum digit width (ISO/IEC 29500 18.3.1.13). Excel renders Aptos
Narrow 11 columns at 7.5px per character (measured empirically), so the
conversion now uses a per-font digit width - 7.5 for Aptos Narrow,
scaled by font size, 7 for Calibri and other fonts - selected from the
file's Normal font on read. The default column width is persisted as
sheetFormatPr defaultColWidth and restored on load, so default-width
columns render at the same pixel width in Excel as in the component.
Replaces the character-count width estimate with Excel-faithful auto fit:
the displayed text (number format applied to the evaluated value) of the
column's populated cells is measured with canvas.measureText using the
active theme's cell font, so formulas, number formats, bold and
conditional formatting fit correctly in any theme. Empty columns keep
their width, merged cells are ignored, hidden rows are included and the
width is clamped to Excel's 255 character limit. The behavior was
verified against Excel via COM automation.
Auto fitted columns are tracked per column and persisted as bestFit in
XLSX; manual resize and undo clear the flag.
Add explicit TagName to RadzenText usages that rendered real heading
elements (H1-H6, DisplayH1-H6, Subtitle1/2) purely for visual styling,
and convert raw HTML headings in examples to RadzenText with proper
TextStyle and TagName. Visual labels now render as <p>, genuine
headings use correct levels without skips (WCAG 1.3.1).
Fixes#2596
RadzenFormField rendered for="@Component" on the wrapping <div> (invalid - <div>
does not take for) and on the label even when Component was unset, producing for=""
which accessibility checkers flag as a label with no association. Removed the div
for and only emit the label for when Component is set. Updated the FormFieldTextBox
demo to give each input an id matching the FormField Component so the label resolves.