Class DocxForm
- Namespace
- DocToolkit
- Assembly
- DocToolkit.Docx.dll
Reads, checks and fills the content controls a Word document carries — the format's own answer to a fill-in form.
public static class DocxForm
- Inheritance
-
DocxForm
- Inherited Members
Remarks
This library now has three template models, and a caller has whichever one their document was authored with. They are not interchangeable and none replaces the others:
| model | marker · who writes it |
|---|---|
| DocxEditor |
{{placeholder}} — plain text, typed by anyone. A convention this library invented, and
breakable by editing inside the token. |
| DocxMailMerge |
MERGEFIELD — a real Word field, from Insert → Merge Field. |
| this class | a content control — a named region Word itself protects, which is what makes it sturdier than a placeholder. |
Validate(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey) checks keys and, for a typed control, values. A drop-down value outside its list, a non-date for a date picker and a non-boolean for a check box are each reported under their own kind. A plain text control validates anything, because there is no constraint to check it against.
Fill(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey) is
lenient about a MISSING value, where Merge(byte[], IReadOnlyDictionary<string, string>) refuses. Two measured
differences justify that: a control given no value keeps its own existing text rather than
showing an injected marker, and unlike mail merge this class ships a Validate a caller can
run first.
It is NOT lenient about a value that does not fit a typed control, and the three typed kinds
do not agree with each other. Measured: a drop-down value outside its list throws,
while a non-date for a date picker and a non-boolean for a check box are silently skipped and the
control keeps its old content. That asymmetry is the library beneath, not a choice made here —
which is the strongest reason to run Validate first, since it reports all three the same
way, before anything is written.
Only the document BODY is read or written. A content control in a header or a footer is
invisible to every method here: it is not in Inspect(byte[], DocxFormKey)'s report,
a value aimed at it is reported as UnusedValue — which reads as
though the caller invented the name — and Fill leaves it untouched. Measured.
DocxMailMerge does reach headers, so the two template APIs genuinely differ
here; if your form lives in a header, that is the one to use.
Images are supplied as bytes and never as a path — see DocxFormValue.
Methods
Fill(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey)
A copy of docx with each named control set to its value.
public static byte[] Fill(byte[] docx, IReadOnlyDictionary<string, DocxFormValue> values, DocxFormKey key = DocxFormKey.TagThenAlias)
Parameters
docxbyte[]The document to fill.
valuesIReadOnlyDictionary<string, DocxFormValue>The value for each control.
keyDocxFormKeyWhich name identifies a control.
Returns
- byte[]
Remarks
Lenient. A control with no entry in values is left exactly as it
was — measured: it keeps its own text rather than showing a marker, so a partial fill is a
supported workflow. Call
Validate(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey) first
if you need to know what will be skipped.
This returns bytes rather than a count of what it wrote. The count answers "did my data
match this template?", which is Validate's question and is better asked before a
document exists than inferred from one.
Exceptions
- ArgumentNullException
docxorvaluesis null.- ArgumentException
docxis empty, or a value is null.- DocumentConversionException
The document could not be read or written, or a value did not fit a typed control in a way the library beneath refuses — measured: a drop-down value outside its list throws here, while a bad date or boolean is skipped silently. Run Validate(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey) first to see all three before writing.
FillAsync(Stream, Stream, IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey, CancellationToken)
Writes a copy of the document in source to destination
with each named control set to its value. source is read to its end
and destination is written; neither is disposed, closed nor sought.
public static Task FillAsync(Stream source, Stream destination, IReadOnlyDictionary<string, DocxFormValue> values, DocxFormKey key = DocxFormKey.TagThenAlias, CancellationToken ct = default)
Parameters
sourceStreamThe document to fill.
destinationStreamReceives the filled document.
valuesIReadOnlyDictionary<string, DocxFormValue>The value for each control.
keyDocxFormKeyWhich name identifies a control.
ctCancellationTokenCancels before the document is read, and while it is written.
Returns
Remarks
Lenient. A control with no entry in values is left exactly as it
was — measured: it keeps its own text rather than showing a marker, so a partial fill is a
supported workflow. Call
Validate(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey) first
if you need to know what will be skipped.
This returns bytes rather than a count of what it wrote. The count answers "did my data
match this template?", which is Validate's question and is better asked before a
document exists than inferred from one.
Exceptions
- ArgumentNullException
A stream or
valuesis null.- ArgumentException
A stream is unusable,
sourceheld no bytes, or a value is null.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The document could not be read or written.
- InvalidOperationException
The fill would change a content control the document locks against editing (A119). Nothing is written, and the document passed in is untouched. Before 0.54.0 this succeeded and left the lock in place, producing a file that declared the control protected while its content had been replaced.
Inspect(byte[], DocxFormKey)
Reads the content controls in docx's body, and what they hold.
public static DocxFormReport Inspect(byte[] docx, DocxFormKey key = DocxFormKey.TagThenAlias)
Parameters
docxbyte[]The document to read.
keyDocxFormKeyWhich name identifies a control.
Returns
Remarks
Not every control in the document — see Fields for the three reasons one can be absent. A document with no content controls reports none rather than failing, which is how a caller catches having passed the wrong document, since filling one succeeds and changes nothing.
Exceptions
- ArgumentNullException
docxis null.- ArgumentException
docxis empty.- DocumentConversionException
The document could not be opened or read.
InspectAsync(Stream, DocxFormKey, CancellationToken)
Reads every content control in the document in source.
source is read to its end and is neither disposed, closed nor
sought.
public static Task<DocxFormReport> InspectAsync(Stream source, DocxFormKey key = DocxFormKey.TagThenAlias, CancellationToken ct = default)
Parameters
sourceStreamThe document to read.
keyDocxFormKeyWhich name identifies a control.
ctCancellationTokenCancels before the document is read.
Returns
Remarks
Not every control in the document — see Fields for the three reasons one can be absent. A document with no content controls reports none rather than failing, which is how a caller catches having passed the wrong document, since filling one succeeds and changes nothing.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The document could not be opened or read.
Validate(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey)
Checks values against the controls in docx, without
writing anything.
public static DocxFormValidation Validate(byte[] docx, IReadOnlyDictionary<string, DocxFormValue> values, DocxFormKey key = DocxFormKey.TagThenAlias)
Parameters
docxbyte[]The document to check against.
valuesIReadOnlyDictionary<string, DocxFormValue>The values to check.
keyDocxFormKeyWhich name identifies a control.
Returns
Remarks
Run this before Fill(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey), which will not tell you what it skipped.
It is not a complete guarantee that Fill will succeed. Measured: image bytes
that are not a readable image validate clean and then throw from Fill, because nothing
here decodes them. A clean result means no key or typed-value problem was found.
Every issue is reported and IsValid means "none of any kind". Filter Issues by Kind if you do not care about one of them.
Exceptions
- ArgumentNullException
docxorvaluesis null.- ArgumentException
docxis empty, or a value is null.- DocumentConversionException
The document could not be opened or read.
ValidateAsync(Stream, IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey, CancellationToken)
Checks values against the document in source.
source is read to its end and is neither disposed, closed nor
sought.
public static Task<DocxFormValidation> ValidateAsync(Stream source, IReadOnlyDictionary<string, DocxFormValue> values, DocxFormKey key = DocxFormKey.TagThenAlias, CancellationToken ct = default)
Parameters
sourceStreamThe document to check against.
valuesIReadOnlyDictionary<string, DocxFormValue>The values to check.
keyDocxFormKeyWhich name identifies a control.
ctCancellationTokenCancels before the document is read.
Returns
Remarks
Run this before Fill(byte[], IReadOnlyDictionary<string, DocxFormValue>, DocxFormKey), which will not tell you what it skipped.
It is not a complete guarantee that Fill will succeed. Measured: image bytes
that are not a readable image validate clean and then throw from Fill, because nothing
here decodes them. A clean result means no key or typed-value problem was found.
Every issue is reported and IsValid means "none of any kind". Filter Issues by Kind if you do not care about one of them.
Exceptions
- ArgumentNullException
sourceorvaluesis null.- ArgumentException
A stream is unusable,
sourceheld no bytes, or a value is null.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The document could not be opened or read.