pub struct Table {
pub rows: Vec<TableRow>,
pub column_widths: Vec<u32>,
pub border_color: Option<String>,
pub alignment: Option<Alignment>,
pub indent_twips: Option<u32>,
pub style_id: Option<String>,
}Expand description
A table: a sequence of rows.
Column count is always derived from the widest row (accounting for TableCell.horizontal_span),
never stored explicitly. Column WIDTHS default to equal, fixed widths (see writer.rs’s
DEFAULT_COLUMN_WIDTH_TWIPS) unless column_widths overrides them.
Fields§
§rows: Vec<TableRow>The rows that make up this table, in order.
column_widths: Vec<u32>Per-column preferred widths, in twips (twentieths of a point, w:gridCol/@w’s own unit —
see Run.character_spacing’s doc comment for the same “expose the raw unit, no conversion”
convention used throughout this crate), one entry per grid column in order. Left empty (the
default) to keep the writer’s previous behavior: every column gets the same fixed default
width. When non-empty, entries beyond the table’s real column count are simply unused, and a
real column count exceeding column_widths.len() falls back to the default width for the
remaining columns — not validated or required to match exactly, same “best-effort, not
strictly enforced” policy as Paragraph.numbering_id/style_id referencing a declaration
that may or may not actually exist.
Setting this also makes the writer emit <w:tblLayout w:type="fixed"/>
(CT_TblLayoutType’s two values are fixed/ autofit, autofit being Word’s default when
the element is omitted entirely). This matters a lot in practice: under the default
autofit layout, Word treats tblGrid’s widths as mere starting suggestions and actively
reflows columns based on cell content (“the presence of long non-breaking content can widen
a column, proportionally shrinking the others” — ECMA-376’s own worked example for
ST_TblLayoutType) — so explicit widths would often be silently overridden without fixed
layout forcing Word to honor them regardless of content.
border_color: Option<String>The color of the table’s own border lines (w:tblBorders‘s sides’ color attribute, a
plain 6-digit RGB hex string), or None to use the fixed "auto" (black) this crate has
always used. Overrides all six sides (top/left/bottom/right/insideH/insideV)
uniformly — WordprocessingML allows each side its own independent color, but a single
uniform color covers the common case and matches the fixed-appearance convention already
used for Paragraph.border/Run.text_border/TableCell.border.
alignment: Option<Alignment>The table’s own horizontal alignment/positioning on the page (w:tblPr/w:jc, CT_JcTable)
— where the whole table sits relative to the page margins, distinct from
Paragraph.alignment (which aligns text within a paragraph). None leaves it unspecified
(Word’s default, effectively left-aligned). Reuses Alignment even though CT_JcTable’s
own enumeration (ST_JcTable) is actually a different, smaller type than ST_Jc (no
distribute, but it does still cover left/center/right/both) — the values this
crate models for Alignment (Left/Center/Right/Justify) all happen to also be valid
ST_JcTable values, so sharing the type avoids a near-duplicate enum.
indent_twips: Option<u32>The table’s indentation from the leading margin, in twips (w:tblPr/w:tblInd,
CT_TblWidth, always written with w:type="dxa"), or None to leave it unspecified (no
extra indentation).
style_id: Option<String>The id of a table-type named style to apply (w:tblPr/w:tblStyle), or None. Unlike
Paragraph.style_id/Run.style_id, this crate does not model declaring a table style in
Document.styles (CT_Style’s table-kind styles carry their own rich conditional
formatting — CT_TblStylePr per table region: first row, banding, corner cells. — a large
surface with no real need seen yet, matching the scope reduction already applied to
StyleKind, which only models paragraph/character). Referencing one of Word’s built-in
table style ids (e.g. "TableGrid", "LightList-Accent1") still works perfectly well
without a local declaration, the same way referencing a built-in paragraph style like
"Heading1" does — Word resolves those from its own built-in style set when the document
doesn’t declare them itself.
Implementations§
Source§impl Table
impl Table
Sourcepub fn new() -> Table
pub fn new() -> Table
Creates an empty table.
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_row(self, row: TableRow) -> Table
pub fn with_row(self, row: TableRow) -> Table
Appends a row and returns the table 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_column_widths(self, column_widths: Vec<u32>) -> Table
pub fn with_column_widths(self, column_widths: Vec<u32>) -> Table
Sets this table’s per-column preferred widths (in twips, one entry per grid column) and
returns it for chaining. See column_widths’s doc comment for how this also switches the
table to a fixed (rather than autofit) layout.
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_color(self, border_color: impl Into<String>) -> Table
pub fn with_border_color(self, border_color: impl Into<String>) -> Table
Sets this table’s border color and returns it for chaining. See border_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_alignment(self, alignment: Alignment) -> Table
pub fn with_alignment(self, alignment: Alignment) -> Table
Sets this table’s own horizontal alignment/positioning and returns it for chaining. See
alignment’s doc comment.
Sourcepub fn with_indent_twips(self, indent_twips: u32) -> Table
pub fn with_indent_twips(self, indent_twips: u32) -> Table
Sets this table’s indentation, in twips, and returns it for chaining. See indent_twips’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_style_id(self, style_id: impl Into<String>) -> Table
pub fn with_style_id(self, style_id: impl Into<String>) -> Table
Sets the id of a named table style to apply and returns it for chaining. See style_id’s
doc comment.