V5 is a complete redesign with no backward compatibility. This page shows developers coming
from V4 (unvell.ReoGrid4) what changed and how. It focuses on differences in API shape,
not on whether individual features exist.
For the actual migration process (decision points, order of work, and fixes for common errors), see Migrating from V4. This page is the quick-reference table to keep at hand during that work.
Changes in design philosophy
Most of the differences derive from these.
| Aspect | V4 | V5 |
|---|---|---|
| Model and UI | ReoGridControl is the entry point; the model is tightly coupled to the UI | Workbook / Worksheet are UI-independent; fully usable without a control |
| Cell values | Boxed object (roughly 160 B per cell) | 16-byte CellValue struct plus a shared string pool |
| Styles | Mutable WorksheetRangeStyle plus PlainStyleFlag | Immutable record StyleRecord (apply diffs with with), interned |
| Colors | System.Drawing.Color | uint ARGB (core and I/O do not depend on System.Drawing) |
| Platform separation | #if WINFORM / WPF | Separated by class structure (swappable IGridGraphics implementations) |
| Events | Many, on Worksheet | The model has no events; events exist only in the control layer |
| Persistence | RGF (XML) / BinaryFormatter | reogrid-json (interoperable with the web edition) |
Namespaces and packages
| V4 | V5 | |
|---|---|---|
| Root namespace | unvell.ReoGrid | unvell.ReoGrid.Core (plus .Style, .CellTypes, .ConditionalFormatting, .IO, and more) |
| WinForms control | unvell.ReoGrid.ReoGridControl | unvell.ReoGrid.WinForms.ReoGridControl |
| WPF control | Same name (switched via #if, unvell.ReoGridWPF.dll) | unvell.ReoGrid.Wpf.ReoGridControl (separate assembly) |
| Packages | unvell.ReoGrid4 / unvell.ReoGrid4.Wpf | unvell.ReoGrid.One / .One.Wpf / .One.Avalonia / .One.Core |
| XLSX / PDF | Built into the main DLL | unvell.ReoGrid.IO.Excel / .IO.Pdf (bundled with the One packages) |
The V4 package IDs are frozen at 4.x, and V5 ships under different IDs. If V5 were published as 5.x under the same IDs, builds would break the moment you bumped the version.
Creating a Workbook / Worksheet
In V4 you normally went through the control, and headless use required a dedicated API,
ReoGridControl.CreateMemoryWorkbook(). In V5 you construct the model directly.
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.CellTypes;
using unvell.ReoGrid.Core.ConditionalFormatting;
using unvell.ReoGrid.Core.Style;
var wb = new Workbook();
var ws = wb.AddWorksheet("Sheet1"); // 既定で 1,048,576 × 16,384(スパースなのでコストなし)
control.LoadWorkbook(wb); // UI に載せるときだけコントロールへ
control.CurrentWorksheet→control.ActiveWorksheet(on the model side,wb.ActiveWorksheet/wb.ActiveSheetIndex)- The V4 notion of “sheet = actual size” is gone. V5 always uses the full Excel dimensions with sparse storage
Reading and writing cell values — the biggest rewrite
The V4-style object assignment, sheet["A1"] = 10, has been removed.
ws.SetNumber(0, 0, 10);
ws.SetText(4, 0, "text");
ws.Cell("A1").SetNumber(10); // CellCursor(struct・チェーン可)
ws.Cell("B1").SetText("hello").SetStyle(style);
object? v = ws.GetObjectValue(0, 0); // object が欲しい場合
string display = ws.GetDisplayText(0, 0); // 書式適用後の表示文字列
- The actual value is the
CellValuestruct (Number/Boolean/DateTime/Text/Error). You can work with it directly viaGetValue/SetValue - There is no sugar equivalent to V4’s bulk 1D / 2D
object[]fill (write a loop) - Converting a user-input string to a value (
=for formulas, number parsing, TRUE/FALSE) goes through the control’sSetActiveCellInput(text)
Formulas
V4 assigned "=..." as a value; V5 uses a dedicated API, and the leading = is omitted.
ws.SetFormula(2, 0, "SUM(A1:A2)"); // 先頭の '=' は付けない
string? f = ws.GetFormula(2, 0); // "SUM(A1:A2)"
ws.Recalculate(); // 明示的な全再計算(通常は依存再計算が自動)
V5 automatically handles recalculation via the dependency graph, as well as reference shifting
when rows or columns are inserted or deleted. Cross-sheet references (Sheet2!A1) and defined
names are also supported.
Position types
Both are zero-based. V5 unifies string parsing under static Parse / TryParse.
var pos = CellPosition.Parse("B3"); // "$B$3"・小文字可。TryParse あり
var range = RangePosition.Parse("B4:E6"); // "A1"・"$A$1:$C$3"・コーナー逆順も可
var cols = RangePosition.Parse("A:C"); // フル列
var rows = RangePosition.Parse("3:5"); // フル行
var num = RangePosition.FromBounds(3, 1, 5, 4);
// シート文脈で解決(フル列・行をシート寸法へクランプし、定義名も解決する)
var r1 = ws.ResolveRange("A:C");
var r2 = ws.ResolveRange("MyRange"); // TryResolveRange あり
Sheet-qualified references (Sheet1!A1:B2) cannot be handled by RangePosition.Parse
(a RangePosition carries no sheet information). Use Worksheet.ResolveRange or the defined-name APIs.
Styles
PlainStyleFlag is gone. The nullable properties on StyleRecord (null = unspecified)
take over the flag’s role.
ws.SetCellStyle(r, c, (ws.GetCellStyle(r, c) ?? StyleRecord.Default)
with { BackgroundColor = 0xFFFFFF00u, Bold = true });
ws.SetRowStyle(3, new StyleRecord { Bold = true }); // 行・列の既定(O(1))
ws.SetColumnStyle(0, new StyleRecord { TextAlign = HAlign.Right });
- There is no range-wide
SetRangeStylesonWorksheet. For whole rows and columns use the default styles; for arbitrary ranges loop over the cells, or through the UI use thecontrol.SetSelectionBackColor(...)family - The effective style after inheritance is resolved comes from
ws.GetEffectiveStyle(r, c) - Colors are
uintARGB (opaque yellow is0xFFFFFF00u).System.Drawing.Colorexists only in the WinForms layer
Borders
The BorderPositions bit flags and the presets (such as RangeBorderStyle.BlackSolid) are gone,
replaced by the ws.Borders side table.
var edge = new BorderEdge(BorderLineStyle.Solid, 0xFF000000u, 1);
ws.Borders.SetOutline(range, edge);
ws.Borders.SetEdge(r, c, BorderSide.Bottom, edge);
Bulk application inside a range (the equivalent of V4’s InsideAll / InsideHorizontal) is
currently limited to the outline; inner borders take a loop over the cells. For the UI selection
there is control.SetSelectionAllBorders(...).
Number formats
CellDataFormatFlag and the *FormatArgs types are gone entirely, unified into the same
format code strings Excel uses. Interop with XLSX becomes lossless.
ws.SetNumberFormat(range, "#,##0.00");
ws.SetNumberFormat(r, c, "yyyy/mm/dd");
ws.SetNumberFormat(r, c, "[Red]-#,##0;[Blue]#,##0"); // セクション・条件・色に対応
V4 options such as NumberNegativeStyle.RedBrackets are expressed as format codes (#,##0;[Red](#,##0)).
Structural operations
| Operation | V4 | V5 |
|---|---|---|
| Merging | MergeRange(range) / UnmergeRange | ws.MergeRange(range) / ws.UnmergeAt(r, c) (check with ws.Merges.IsMerged(r, c)) |
| Column width / row height | SetColumnsWidth(col, count, w) | ws.Columns.SetSize(i, w) / ws.Rows.SetSize(i, h) (hide with SetHidden) |
| Insert / delete | InsertRows / DeleteRows and others | Same names (merges, borders, formula references, and cell types shift automatically) |
| Freeze | worksheet.FreezeToCell(r, c) plus FreezeArea | control.SetFreeze(rows, cols) — view-side state; the model does not hold it |
| Outlines | GroupRows / CollapseOutline and others | ws.GroupRows(row, count) / ws.UngroupRows / ws.RowOutlines |
| AutoFit | AutoFitColumnWidth | control.AutoFitSelectedColumns() / AutoFitSelectedRows() (measures only the used range) |
Cell types
V4 assigned a body instance to every cell, creating one object per cell. V5 assigns flyweight descriptors to ranges (a checkbox column spanning a million rows costs a single entry).
ws.SetCellType(3, 1, CheckboxCellType.Instance);
ws.SetCellType(range, new DropdownCellType(["Apple", "Orange"], editable: false));
ws.Cell("C3").SetCellType(new ProgressCellType(max: 100));
- State (checked or not, the selected value) is stored in the cell value. Descriptors are shared and stateless
- V4’s per-body events (such as
btn.Click) are gone. Handle them through the control’sCellButtonClicked - Built-in types: CheckBox / DropdownList / Progress / Button / Hyperlink, plus Sparkline (new in V5)
Conditional formatting
V4’s ConditionalStyle was a simple mechanism; V5 provides the full OOXML-compliant set
(cellIs / expression / containsText / colorScale / dataBar / top10 / aboveAverage /
duplicate / unique / iconSet, with priority plus stopIfTrue, and XLSX round-tripping).
ws.AddConditionalFormat(range, new CellIsRule
{
Operator = CfOperator.GreaterThan,
Value1 = CfValue.Num(100),
Style = new CfStyle { BackgroundColor = 0xFFFFC7CE, Color = 0xFF9C0006 },
});
The control
| V4 | V5 | |
|---|---|---|
| Selection | worksheet.SelectionRange / SelectRange(...) | control.Selection (get) plus control.MoveTo(r, c). The model holds no selection state |
| Events | CellDataChanged, CellMouseDown/Up/Move, Before/AfterCellEdit, and many more (on Worksheet) | Only a few, on the control (SelectionChanged, WorkbookChanged, ActiveSheetChanged, HistoryChanged, ZoomChanged, ContextMenuRequested, CellButtonClicked) |
| Editing | StartEdit / EndEdit | BeginEdit(initial) / CancelEdit(), GetActiveCellInput() / SetActiveCellInput(text) |
| Clipboard | Copy / Cut / Paste | CopySelection() / CutSelection() / PasteClipboard() |
| Context menu | Built-in menu included | The host builds it in ContextMenuRequested |
| View toggles | SetSettings(WorksheetSettings.View_ShowGridLine, ...) | control.ShowGridLines / ShowHeaders / ShowOutlines properties |
The small number of events is a deliberate design choice. Because the model carries no events, headless usage does not drag along notification paths it never needs.
I/O
Automatic format detection via the FileFormat enum is gone, replaced by a static class per format.
| V4 | V5 | |
|---|---|---|
| XLSX read | wb.Load(path) | XlsxReader.Read(path) (streaming; use OpenVirtual for huge files) |
| XLSX write | wb.Save(path, FileFormat.Excel2007) | XlsxWriter.Write(wb, path) |
| Native format | RGF (SaveRGF) | RGF is gone → reogrid-json (ReoGridJsonIO.Write / Read) |
| CSV | worksheet.ExportAsCSV(path) | CsvIO.Write(ws) / CsvIO.Read(ws, text) |
| Via printing only | PdfExporter.Export(wb, path, settings) (new in V5) |
- The migration path for V4 assets is: save as XLSX in V4, then load it in V5
- When loading XLSX, formulas keep Excel’s cached values and are not re-evaluated (call
Recalculate()explicitly)
Deliberately removed (not coming back)
RunScript / ReoScript, RGF, PlainStyleFlag, CellDataFormatFlag and the *FormatArgs types,
the FileFormat enum, #if WINFORM / WPF, System.Drawing dependencies in the public API
(core and I/O), and Android / iOS support.
Migration cheat sheet
| Task | V4 | V5 |
|---|---|---|
| Write a value | sheet["A1"] = 10 | ws.Cell("A1").SetNumber(10) |
| Read a value | sheet.GetCellData<double>("A1") | ws.GetObjectValue(0, 0) / ws.GetValue(0, 0) |
| Formula | sheet["A3"] = "=SUM(A1:A2)" | ws.SetFormula(2, 0, "SUM(A1:A2)") |
| Background color | SetRangeStyles(r, style { Flag = BackColor }) | SetCellStyle(… with { BackgroundColor = argb }) |
| Number format | SetRangeDataFormat(r, Number, args) | ws.SetNumberFormat(r, "#,##0.00") |
| Borders | SetRangeBorders(r, Outside, BlackSolid) | ws.Borders.SetOutline(r, edge) |
| Merge | MergeRange(r) | ws.MergeRange(r) |
| Column width | SetColumnsWidth(c, n, w) | ws.Columns.SetSize(c, w) |
| Freeze | ws.FreezeToCell(r, c) | control.SetFreeze(rows, cols) |
| Checkbox | sheet[r, c] = new CheckBoxCell() | ws.SetCellType(r, c, CheckboxCellType.Instance) |
| Save | wb.Save(path, FileFormat.Excel2007) | XlsxWriter.Write(wb, path) |
| Load | wb.Load(path) | XlsxReader.Read(path) |
| Get selection | worksheet.SelectionRange | control.Selection |
| Active sheet | control.CurrentWorksheet | control.ActiveWorksheet |
Your license key still works
Keys issued for V4 are accepted as-is in V5. No reissue is needed. See Applying a License Key for details.