pub struct TableCell {
pub blocks: Vec<Block>,
pub horizontal_span: Option<u32>,
pub vertical_merge: Option<VerticalMerge>,
pub border: bool,
pub shading_color: Option<String>,
pub vertical_alignment: Option<CellVerticalAlign>,
pub margin_top_twips: Option<u32>,
pub margin_left_twips: Option<u32>,
pub margin_bottom_twips: Option<u32>,
pub margin_right_twips: Option<u32>,
pub text_direction: Option<TextDirection>,
}Expand description
A table cell: a sequence of blocks (paragraphs, and optionally a nested table). CT_Tc reuses
the same block-level content model as the document body — w:tbl is a valid child of w:tc per
the schema — so a Block::Table here nests a table inside the cell, and a
Block::StructuredDocumentTag wraps more blocks the same way it does anywhere else a Block
is valid.
WordprocessingML requires every cell’s content to actually END with a paragraph — not just
contain one somewhere (CT_Tc’s block-level content group has minOccurs="1", but real Word
additionally expects the last child to be w:p, even after a nested table; violating this
causes Word’s repair prompt on open, the same class of “schema-valid but not what Word actually
wants” bug this project has been bitten by before). The writer enforces this automatically —
appending an empty trailing paragraph whenever blocks is empty, or its last entry isn’t
already a Block::Paragraph — so any TableCell is always valid to write regardless of
what the caller put in blocks.
Fields§
§blocks: Vec<Block>The blocks that make up this cell’s content, in order.
horizontal_span: Option<u32>How many grid columns this cell spans, for a horizontal merge (w:gridSpan,
CT_DecimalNumber) — None (or Some(1), treated identically) means an ordinary, unmerged
cell occupying exactly one column; Some(n) with n > 1 means this cell visually replaces
n consecutive cells in the row, which must NOT also be present in TableRow.cells (this
crate follows WordprocessingML’s own model: a horizontally merged row simply has fewer
w:tc elements than the table’s column count, not extra “merged-away” cells to skip — this
leaves column-counting entirely up to the caller).
vertical_merge: Option<VerticalMerge>This cell’s role in a vertical merge (w:vMerge, CT_VMerge), or None for a cell that
isn’t part of any vertical merge (and, per ECMA-376, closes any vertically merged group of
preceding cells in the same column). See VerticalMerge’s doc comment for how a
vertical merge spanning several rows is actually expressed: unlike a horizontal merge, EVERY
row still needs one TableCell per column — there’s no way to omit a cell vertically, only
mark it as continuing the merge above it.
border: boolWhether this cell has a border around it (w:tcPr/w:tcBorders), mirroring
Paragraph.border/Run.text_border’s fixed on/off appearance (val="single" sz="4" space="0" color="auto" on all four sides). CT_TcBorders’s insideH/insideV (only
meaningful when a cell’s borders are set individually across a merged region) and
tl2br/tr2bl (diagonal lines) aren’t modeled, same scope reduction as Run.text_border
not exposing CT_Border’s full richness.
shading_color: Option<String>This cell’s own background shading color (w:tcPr/w:shd), as a plain 6-digit RGB hex
string, mirroring Run.shading_color/ Paragraph.shading_color — same fixed
val="clear"/color="auto" pair, just written inside w:tcPr instead of w:rPr/w:pPr.
None leaves the cell’s background unset (inherits the table’s/row’s own shading, if any —
not modeled at those levels here).
vertical_alignment: Option<CellVerticalAlign>This cell’s vertical alignment of its content within the cell’s full height
(w:tcPr/w:vAlign), or None to leave it unspecified (Word’s default, effectively
top-aligned). See CellVerticalAlign’s doc comment.
margin_top_twips: Option<u32>This cell’s top margin override, in twips (w:tcPr/w:tcMar/w:top, always written with
w:type="dxa"), or None to use the table’s own default cell margins (Word’s built-in
default, since this crate doesn’t model table-wide w:tblCellMar either). See
margin_left_twips for why these are four separate fields rather than one struct.
margin_left_twips: Option<u32>This cell’s left margin override, in twips, mirroring margin_top_twips. Four separate
Option<u32> fields (rather than a single small struct) match this crate’s existing
convention for Paragraph.space_before/space_after — plain, independently optional fields
rather than introducing a new small aggregate type for four numbers.
margin_bottom_twips: Option<u32>This cell’s bottom margin override, in twips, mirroring margin_top_twips.
margin_right_twips: Option<u32>This cell’s right margin override, in twips, mirroring margin_top_twips.
text_direction: Option<TextDirection>This cell’s text flow direction (w:tcPr/w:textDirection), or None for the normal,
horizontal left-to-right flow (ST_TextDirection’s lrTb, Word’s default when the element
is omitted). See TextDirection’s doc comment for which rotated values are modeled.
Implementations§
Source§impl TableCell
impl TableCell
Sourcepub fn new() -> TableCell
pub fn new() -> TableCell
Creates an empty cell (still valid to write: the writer emits a single empty paragraph for it, as WordprocessingML requires).
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_text(text: impl Into<String>) -> TableCell
pub fn with_text(text: impl Into<String>) -> TableCell
Creates a cell containing a single paragraph with the given text.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_paragraph(self, paragraph: Paragraph) -> TableCell
pub fn with_paragraph(self, paragraph: Paragraph) -> TableCell
Appends a paragraph block and returns the cell for chaining.
Sourcepub fn with_table(self, table: Table) -> TableCell
pub fn with_table(self, table: Table) -> TableCell
Appends a nested table block and returns the cell for chaining.
WordprocessingML (CT_Tc) allows a w:tbl inside a cell’s content. The writer
automatically appends a trailing empty paragraph after the nested table if this cell doesn’t
already end with one, since Word requires cell content to end in a paragraph (see
TableCell’s doc comment).
Sourcepub fn paragraphs(&self) -> impl Iterator<Item = &Paragraph>
pub fn paragraphs(&self) -> impl Iterator<Item = &Paragraph>
Iterates over this cell’s paragraphs only, skipping any nested table.
Sourcepub fn tables(&self) -> impl Iterator<Item = &Table>
pub fn tables(&self) -> impl Iterator<Item = &Table>
Iterates over this cell’s nested tables only, skipping paragraphs.
Sourcepub fn with_horizontal_span(self, horizontal_span: u32) -> TableCell
pub fn with_horizontal_span(self, horizontal_span: u32) -> TableCell
Sets how many grid columns this cell spans (for a horizontal merge) and returns it for
chaining. See horizontal_span’s doc comment for how this interacts with TableRow.cells.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_vertical_merge(self, vertical_merge: VerticalMerge) -> TableCell
pub fn with_vertical_merge(self, vertical_merge: VerticalMerge) -> TableCell
Sets this cell’s role in a vertical merge and returns it for chaining.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_border(self, border: bool) -> TableCell
pub fn with_border(self, border: bool) -> TableCell
Sets whether this cell has a border around it and returns it for chaining. See border’s
doc comment.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_shading_color(self, shading_color: impl Into<String>) -> TableCell
pub fn with_shading_color(self, shading_color: impl Into<String>) -> TableCell
Sets this cell’s background shading color and returns it for chaining. See shading_color’s
doc comment.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("docx_tables.docx");
15
16 let plain_table = Table::new()
17 .with_row(
18 TableRow::new()
19 .with_cell(TableCell::with_text("Name"))
20 .with_cell(TableCell::with_text("Score")),
21 )
22 .with_row(
23 TableRow::new()
24 .with_cell(TableCell::with_text("Alice"))
25 .with_cell(TableCell::with_text("92")),
26 )
27 .with_row(
28 TableRow::new()
29 .with_cell(TableCell::with_text("Bob"))
30 .with_cell(TableCell::with_text("87")),
31 );
32
33 let merged_table = Table::new()
34 .with_row(
35 TableRow::new()
36 .with_repeat_as_header_row(true)
37 .with_cell(TableCell::with_text("Quarterly report").with_horizontal_span(3)),
38 )
39 .with_row(
40 TableRow::new()
41 .with_cell(
42 TableCell::with_text("Region").with_vertical_merge(VerticalMerge::Restart),
43 )
44 .with_cell(TableCell::with_text("Q1"))
45 .with_cell(TableCell::with_text("Q2")),
46 )
47 .with_row(
48 TableRow::new()
49 .with_cell(TableCell::new().with_vertical_merge(VerticalMerge::Continue))
50 .with_cell(TableCell::with_text("1,200"))
51 .with_cell(TableCell::with_text("1,350")),
52 );
53
54 let styled_table = Table::new()
55 .with_column_widths(vec![3_000, 3_000, 3_000])
56 .with_border_color("2E74B5")
57 .with_indent_twips(360)
58 .with_row(
59 TableRow::new()
60 .with_height_twips(500)
61 .with_cell(TableCell::with_text("Header A").with_shading_color("D9E2F3"))
62 .with_cell(TableCell::with_text("Header B").with_shading_color("D9E2F3"))
63 .with_cell(TableCell::with_text("Header C").with_shading_color("D9E2F3")),
64 )
65 .with_row(
66 TableRow::new()
67 .with_cant_split(true)
68 .with_cell(TableCell::with_text("1").with_border(true))
69 .with_cell(TableCell::with_text("2").with_border(true))
70 .with_cell(TableCell::with_text("3").with_border(true)),
71 );
72
73 let document = Document::new()
74 .with_paragraph(heading("A plain table", false))
75 .with_table(plain_table)
76 .with_paragraph(heading(
77 "Merged cells: a spanning header row and a vertically merged column",
78 true,
79 ))
80 .with_table(merged_table)
81 .with_paragraph(heading(
82 "Column widths, border color, shading and indentation",
83 true,
84 ))
85 .with_table(styled_table);
86
87 document.save_to_file(&path)?;
88 println!("Wrote {}", path.display());
89 Ok(())
90}Sourcepub fn with_vertical_alignment(
self,
vertical_alignment: CellVerticalAlign,
) -> TableCell
pub fn with_vertical_alignment( self, vertical_alignment: CellVerticalAlign, ) -> TableCell
Sets this cell’s vertical alignment and returns it for chaining. See vertical_alignment’s
doc comment.
Sourcepub fn with_margins_twips(
self,
top: u32,
left: u32,
bottom: u32,
right: u32,
) -> TableCell
pub fn with_margins_twips( self, top: u32, left: u32, bottom: u32, right: u32, ) -> TableCell
Sets this cell’s margin overrides (top/left/bottom/right, in twips) and returns it for
chaining. See margin_top_twips’s doc comment.
Sourcepub fn with_text_direction(self, text_direction: TextDirection) -> TableCell
pub fn with_text_direction(self, text_direction: TextDirection) -> TableCell
Sets this cell’s text flow direction and returns it for chaining. See text_direction’s doc
comment.
Sourcepub fn text(&self) -> String
pub fn text(&self) -> String
The cell’s text: its paragraphs’ text, joined with newlines. Any nested table’s text is not
included — use TableCell::tables to reach it.