Table of Contents

Class DocxBlock

Namespace
DocToolkit
Assembly
DocToolkit.dll

One block of content in a document built by Create(IEnumerable<DocxBlock>).

The hierarchy is CLOSED: the constructor is private protected, the concrete types are internal sealed, and a block can only be obtained from one of the factory methods below. A consumer therefore cannot define a block the writer has never heard of — an unrenderable block is unrepresentable rather than a runtime failure.

Each factory validates its arguments immediately, so a bad value throws at the line that produced it rather than later inside a Create(IEnumerable<DocxBlock>) call assembling many blocks at once.

public abstract class DocxBlock
Inheritance
DocxBlock
Inherited Members

Methods

Heading(string, int)

A heading at level, rendered with a real Word heading style so it appears in the navigation pane and can drive a table of contents.

public static DocxBlock Heading(string text, int level)

Parameters

text string

The heading's text.

level int

1 to 6, matching HTML h1h6. Word itself defines nine; six is the deliberate stopping point. Out of range throws rather than clamping, because a silently demoted heading is only ever noticed in the finished document.

Returns

DocxBlock

Exceptions

ArgumentNullException

text is null.

ArgumentOutOfRangeException

level is not 1–6.

Image(byte[], double?, double?, string?)

An inline image. PNG and JPEG only, decided by magic bytes rather than by anything the caller says — a part declaring image/png while holding JPEG bytes renders as a blank frame, silently.

Size is in points, matching ReplaceImage(byte[], string, byte[], double?, double?). Omit both and the image's intrinsic size at 96 DPI is used; give one and the other scales to preserve the aspect ratio; give both and the image is stretched, distortion accepted as the caller's choice.

altText becomes the drawing's descr, which is what a screen reader announces. Omit it and the attribute is omitted too, rather than filled with a placeholder: a generated value like "Image 1" is worse than nothing, because it is read out as though it described the picture. Supply it for any image carrying meaning; leave it off for one that is purely decorative.

public static DocxBlock Image(byte[] image, double? widthPoints = null, double? heightPoints = null, string? altText = null)

Parameters

image byte[]

PNG or JPEG bytes.

widthPoints double?

Rendered width in points, or null to derive it.

heightPoints double?

Rendered height in points, or null to derive it.

altText string

What a screen reader announces in place of the image. Null omits it.

Returns

DocxBlock

Exceptions

ArgumentNullException

image is null.

ArgumentException

image is empty, or is neither PNG nor JPEG.

ArgumentOutOfRangeException

A supplied size is zero or negative, or the resulting size is larger than a drawing extent can hold — see ReplaceImage(byte[], string, byte[], double?, double?) for the same bound on the editing path.

Paragraph(string)

A body paragraph. Empty text is allowed and produces a blank line.

public static DocxBlock Paragraph(string text)

Parameters

text string

Returns

DocxBlock

Exceptions

ArgumentNullException

text is null.

Table(IEnumerable<string>, IEnumerable<IEnumerable<object?>>)

A table with a bold header row.

Cell values are typed the same WAY as Create(string, IEnumerable<IEnumerable<object?>>)bool, DateTime, DateOnly, TimeOnly and TimeSpan are handled by name, and everything else, numbers included, is formatted through InvariantCulture — but they do not always render to the same TEXT, and that is deliberate. A spreadsheet cell stores a typed value that Excel formats on display; a Word table cell stores only text, so the value is rendered here and the rendering is this library's choice. For example:

  • Dates use ISO-8601 (2026-08-06). The workbook path renders the same date in a slashed form whose field order follows the reader's culture — 08/06/2026 or 06/08/2026 for this date, depending on the machine. That ambiguity between day-first and month-first readings is precisely what ISO-8601 removes.
  • A TimeSpan keeps its days (1.02:03:04). Excel flattens them into hours (26:03:04), which is a different unit convention, not just a different pattern.
  • A very large decimal, long or ulong keeps every digit here. The workbook path converts through double first, so it can show a rounded value — decimal.MaxValue becomes 7.92281625142643E+28 there and stays 79228162514264337593543950335 here. That is a different number, not a different pattern.

Those examples are illustrative, not an exhaustive list of the differences. What both guarantee identically is that the same input produces the same output on every machine, because neither consults the current culture.

Rows are materialised immediately; mutating the caller's sequence afterwards does not change the block.

A row SHORTER than the header is padded with empty cells: ragged data is normal, and padding discards nothing. A row LONGER than the header throws, and the asymmetry is the point — the surplus values could only be dropped, which is data loss with no signal anywhere. Word would render the table as though it were complete. Same reasoning as Heading(string, int) refusing to clamp an out-of-range level: a loss that only shows up in the finished document is worth more than the convenience of accepting the call.

public static DocxBlock Table(IEnumerable<string> headers, IEnumerable<IEnumerable<object?>> rows)

Parameters

headers IEnumerable<string>
rows IEnumerable<IEnumerable<object>>

Returns

DocxBlock

Exceptions

ArgumentNullException

headers or rows is null.

ArgumentException

headers is empty, a row is null, or a row has more cells than there are headers.