Table of Contents

Fields

Word fields are small instructions inside a document, such as { DATE }, { DOCPROPERTY Company }, { = SUM(ABOVE) } or { IF … }, each with a cached result. DocWright.Dom.Fields finds them, evaluates them with values you supply, and rewrites them.

Find the fields in a document

using DocWright.Dom.Fields;

foreach (FieldRegion field in document.FindFields())
{
    Console.WriteLine($"{field.Instruction.Name,-12} support: {FieldKindInfo.GetSupport(field.Instruction.Kind),-10} cached: {field.CachedResult}");
}

FindFields() on a document covers the body, headers, footers, footnotes and endnotes. It returns top-level fields; a field nested inside another is available through NestedFields. FindFields(FieldKind.MergeField) limits the search to one kind.

Update them

using System.Globalization;
using DocWright.Dom.Fields;

var handlers = new FieldHandlerRegistry();
handlers.Add(new TicketFieldHandler());

var options = new FieldUpdateOptions
{
    Culture = CultureInfo.GetCultureInfo("en-NZ"),
    Clock = new DateTimeOffset(2026, 10, 1, 9, 0, 0, TimeSpan.Zero),   // never read from the machine
    Handlers = handlers,
};
options.DocumentProperties["Company"] = "Riverbend Health Trust";
options.DocumentVariables["Region"] = "Waikato";

FieldUpdateResult result = document.UpdateFields(options);
Console.WriteLine($"{result.FieldsUpdated} updated, {result.FieldsSkipped} skipped, "
                + $"{result.FieldsInError} in error, of {result.FieldsFound}");

Console.WriteLine(document.GetText().TrimEnd());

Output (both steps)

DOCPROPERTY  support: Evaluated  cached: [company]
DATE         support: Evaluated  cached: [date]
DOCVARIABLE  support: Evaluated  cached: [region]
=            support: Evaluated  cached: [total]
TICKET       support: Unrecognized cached: [ticket]
5 updated, 0 skipped, 0 in error, of 5
Prepared for: Riverbend Health Trust
Date: 1 October 2026
Region: Waikato
Total with tax: 1,437.50
Action: #4711: Replace fire extinguishers
1437.5
!Zero Divide

Two rules govern updates:

  • Nothing comes from the machine. The date, user name, file name, document properties and variables all come from FieldUpdateOptions. With no Clock, a DATE field keeps its cached value rather than showing today, so output is reproducible.
  • A field that can't be evaluated keeps its cached result and reports a diagnostic. It is never blanked.

Which fields are evaluated

Evaluated Computed during layout Kept as-is
IF, COMPARE, = formulas, MERGEFIELD and the merge family, SET, REF, DOCPROPERTY, DOCVARIABLE, STYLEREF, QUOTE, SYMBOL, date and document-property fields PAGE, NUMPAGES, SECTIONPAGES, PAGEREF, SEQ TOC, INDEX, HYPERLINK, INCLUDETEXT and interactive fields, which are parsed and preserved

FieldKindInfo.GetSupport(kind) tells you which applies to a field. Nothing is fetched: INCLUDETEXT, INCLUDEPICTURE, LINK and DDE name external files or URLs, and DocWright never follows them (diagnostic DXP5003). A field that makes the server fetch a URL is a security hole.

Add your own field

Implement IFieldHandler and register it. Later registrations win, so you can also override a built-in field:

using DocWright.Dom.Fields;

/// <summary>Evaluates a custom { TICKET id } field from your own data.</summary>
internal sealed class TicketFieldHandler : IFieldHandler
{
    private static readonly Dictionary<string, string> Titles = new()
    {
        ["4711"] = "Replace fire extinguishers",
    };

    public IReadOnlyList<string> FieldNames => ["TICKET"];

    public bool TryEvaluate(FieldEvaluationContext context, out string? result)
    {
        FieldArgument? id = context.Instruction.Arguments.FirstOrDefault();
        if (id is null)
        {
            result = FieldErrors.Syntax("TICKET");   // shows Word's own error text
            return true;
        }

        result = Titles.TryGetValue(id.Text, out string? title) ? $"#{id.Text}: {title}" : $"#{id.Text}";
        return true;                                   // false keeps the cached result
    }
}

Return false from TryEvaluate to decline and keep the cached result. FieldErrors produces Word's own error texts, such as !Syntax Error and !Zero Divide.

Rewrite a field by hand

A FieldRegion offers four operations:

Method Result
SetResult(text) New result text; the field stays.
ReplaceWithText(text) The field is removed and plain text stays.
Unwrap() The field is removed and its current result stays.
Delete() The whole field, including its result, is removed.

Formulas

The = field's expression engine is available directly:

using System.Globalization;
using DocWright.Dom.Fields;

var context = new FieldFormulaContext { Culture = CultureInfo.InvariantCulture };
Console.WriteLine(FieldFormula.Evaluate("1250 * 1.15", context));
Console.WriteLine(FieldFormula.Evaluate("10 / 0", context));

Errors come back as Word's result strings, such as !Syntax Error, rather than as exceptions, because that is what the document would show. Table references such as SUM(ABOVE) follow Word's actual cell-selection rules.