V4 V5

RichText lets formatting change per character inside a single cell. Each stretch between formatting changes is a run, and the text is the sequence of them.

The namespace is unvell.ReoGrid.Core.Text.

Formatting changing inside one cell

Building one

using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Text;

var rt = new RichText(
[
	new RichTextRun { Text = "Total " },
	new RichTextRun { Text = "12,800", Bold = true, Color = 0xFFCC0000 },
	new RichTextRun { Text = " USD" },
]);

ws.SetRichText(0, 0, rt);

RichTextRun

As with StyleRecord, everything is nullable. A null property inherits from the cell’s effective style.

PropertyType
Textstring
Bold / Italic / Underlinebool?
FontFamilystring?
FontSizefloat?
Coloruint? (ARGB)

Background color, alignment and wrapping cannot vary per run. Those are per-cell, on StyleRecord.

How lines are laid out

When several runs share a line, the baseline is a single one. Bold runs, runs at a different size, and Japanese runs all sit on the same bottom edge. A line’s height comes from its tallest run, so only lines containing a larger character grow.

Setting TextWrapMode on the cell wraps rich text too. The break points are decided from the whole string, not from run boundaries, so a word whose formatting changes partway through (a bold 12, followed by a plain 800) is never split at the formatting boundary. When a break does land inside a run, that run is split and both halves keep their formatting.

Reading

if (ws.HasRichText(0, 0))
{
	RichText? rt = ws.GetRichText(0, 0);
	Console.WriteLine(rt!.PlainText);      // the text with formatting stripped

	foreach (RichTextRun run in rt.Runs)
		Console.WriteLine($"{run.Text} bold={run.Bold}");
}

HasRichText answers without building an object. Use it on iteration hot paths.

Converting to and from plain text

var rt = RichText.FromPlain("a plain string");
var copy = rt.Clone();                  // duplicate it run by run

ws.SetRichText(0, 0, null);             // drop the rich text

Runs is a mutable list. Modifying a RichText you fetched affects the cell it came from, so Clone() it first if you intend to edit.

Relationship to the cell value

Rich text lives in a separate table from cell values.

  • Once rich text is set, it is what the cell displays
  • Calling ws.SetFormula(...) removes the cell’s rich text automatically
  • GetObjectValue / GetDisplayText return the PlainText equivalent

Where it is used

The grid renderer and the cell editor share the same layout code, which is why formatting can be changed per character while editing. The control-side API is:

  • control.ToggleEditingBold() / ToggleEditingItalic() / ToggleEditingUnderline()
  • control.SetEditingTextColor(color)

See Cell Editing.

Persistence

Round-trips through both reogrid-json and XLSX. In XLSX it is read and written as a rich string in the shared string table (a sequence of <r> elements).

Was this article helpful?