1use std::path::Path;
6
7use rdocx::{BorderStyle, Document, Length, VerticalAlignment};
8
9fn main() {
10 let samples_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
11 .parent()
12 .unwrap()
13 .parent()
14 .unwrap()
15 .join("samples");
16 std::fs::create_dir_all(&samples_dir).unwrap();
17
18 let out = samples_dir.join("styled_tables.docx");
19 generate_styled_tables(&out);
20 println!(" Created: styled_tables.docx");
21 println!("\nDone!");
22}
23
24fn generate_styled_tables(path: &Path) {
25 let mut doc = Document::new();
26 doc.set_page_size(Length::inches(8.5), Length::inches(11.0));
27 doc.set_margins(
28 Length::inches(0.75),
29 Length::inches(0.75),
30 Length::inches(0.75),
31 Length::inches(0.75),
32 );
33
34 doc.add_paragraph("Styled Tables Showcase")
35 .style("Heading1");
36
37 doc.add_paragraph("");
38
39 doc.add_paragraph("1. Report Table with Alternating Row Colors")
43 .style("Heading2");
44
45 {
46 let mut tbl = doc.add_table(8, 4);
47 tbl = tbl.borders(BorderStyle::Single, 2, "BFBFBF");
48 tbl = tbl.width_pct(100.0);
49
50 let headers = ["Product", "Q1 Sales", "Q2 Sales", "Growth"];
52 for (col, h) in headers.iter().enumerate() {
53 tbl.cell(0, col).unwrap().shading("2E75B6");
54 tbl.cell(0, col).unwrap().set_text(h);
55 }
56 tbl.row(0).unwrap().header();
57
58 let data = [
60 ["Enterprise Suite", "$245,000", "$312,000", "+27.3%"],
61 ["Professional", "$189,000", "$201,000", "+6.3%"],
62 ["Starter Pack", "$67,000", "$84,500", "+26.1%"],
63 ["Add-ons", "$34,000", "$41,200", "+21.2%"],
64 ["Training", "$22,000", "$28,900", "+31.4%"],
65 ["Support Plans", "$56,000", "$62,300", "+11.3%"],
66 ];
67
68 for (i, row) in data.iter().enumerate() {
69 let row_idx = i + 1;
70 for (col, val) in row.iter().enumerate() {
71 tbl.cell(row_idx, col).unwrap().set_text(val);
72 if i % 2 == 0 {
74 tbl.cell(row_idx, col).unwrap().shading("F2F7FB");
75 }
76 }
77 }
78
79 tbl.cell(7, 0).unwrap().set_text("TOTAL");
81 tbl.cell(7, 0).unwrap().shading("D6E4F0");
82 tbl.cell(7, 1).unwrap().set_text("$613,000");
83 tbl.cell(7, 1).unwrap().shading("D6E4F0");
84 tbl.cell(7, 2).unwrap().set_text("$729,900");
85 tbl.cell(7, 2).unwrap().shading("D6E4F0");
86 tbl.cell(7, 3).unwrap().set_text("+19.1%");
87 tbl.cell(7, 3).unwrap().shading("D6E4F0");
88 }
89
90 doc.add_paragraph("");
91
92 doc.add_paragraph("2. Invoice Table with Merged Header & Row Spans")
96 .style("Heading2");
97
98 {
99 let mut tbl = doc.add_table(7, 4);
100 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
101 tbl = tbl.width_pct(100.0);
102
103 tbl.cell(0, 0).unwrap().set_text("INVOICE #2026-0042");
105 tbl.cell(0, 0).unwrap().grid_span(4);
106 tbl.cell(0, 0).unwrap().shading("1F4E79");
107
108 let headers = ["Item", "Description", "Qty", "Amount"];
110 for (col, h) in headers.iter().enumerate() {
111 tbl.cell(1, col).unwrap().set_text(h);
112 tbl.cell(1, col).unwrap().shading("D6E4F0");
113 }
114
115 tbl.cell(2, 0).unwrap().set_text("LIC-ENT-500");
117 tbl.cell(2, 1)
118 .unwrap()
119 .set_text("Enterprise License (500 seats)");
120 tbl.cell(2, 2).unwrap().set_text("1");
121 tbl.cell(2, 3).unwrap().set_text("$60,000");
122
123 tbl.cell(3, 0).unwrap().set_text("SVC-IMPL");
124 tbl.cell(3, 1).unwrap().set_text("Implementation Services");
125 tbl.cell(3, 2).unwrap().set_text("1");
126 tbl.cell(3, 3).unwrap().set_text("$25,000");
127
128 tbl.cell(4, 0).unwrap().set_text("SVC-TRAIN");
129 tbl.cell(4, 1)
130 .unwrap()
131 .set_text("On-site Training (3 days)");
132 tbl.cell(4, 2).unwrap().set_text("1");
133 tbl.cell(4, 3).unwrap().set_text("$4,500");
134
135 tbl.cell(5, 0).unwrap().set_text("Subtotal");
137 tbl.cell(5, 0).unwrap().grid_span(3);
138 tbl.cell(5, 0).unwrap().shading("F2F2F2");
139 tbl.cell(5, 3).unwrap().set_text("$89,500");
140 tbl.cell(5, 3).unwrap().shading("F2F2F2");
141
142 tbl.cell(6, 0).unwrap().set_text("TOTAL DUE");
144 tbl.cell(6, 0).unwrap().grid_span(3);
145 tbl.cell(6, 0).unwrap().shading("1F4E79");
146 tbl.cell(6, 3).unwrap().set_text("$89,500");
147 tbl.cell(6, 3).unwrap().shading("1F4E79");
148 }
149
150 doc.add_paragraph("");
151
152 doc.add_paragraph("3. Specification Table with Vertical Merges")
156 .style("Heading2");
157
158 {
159 let mut tbl = doc.add_table(8, 3);
160 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
161 tbl = tbl.width_pct(100.0);
162
163 tbl.cell(0, 0).unwrap().set_text("Category");
165 tbl.cell(0, 0).unwrap().shading("2E75B6");
166 tbl.cell(0, 1).unwrap().set_text("Specification");
167 tbl.cell(0, 1).unwrap().shading("2E75B6");
168 tbl.cell(0, 2).unwrap().set_text("Value");
169 tbl.cell(0, 2).unwrap().shading("2E75B6");
170
171 tbl.cell(1, 0).unwrap().set_text("Hardware");
173 tbl.cell(1, 0).unwrap().v_merge_restart();
174 tbl.cell(1, 0).unwrap().shading("E2EFDA");
175 tbl.cell(1, 0)
176 .unwrap()
177 .vertical_alignment(VerticalAlignment::Center);
178 tbl.cell(1, 1).unwrap().set_text("Processor");
179 tbl.cell(1, 2).unwrap().set_text("Intel Xeon E-2388G");
180
181 tbl.cell(2, 0).unwrap().v_merge_continue();
182 tbl.cell(2, 1).unwrap().set_text("Memory");
183 tbl.cell(2, 2).unwrap().set_text("64 GB DDR4 ECC");
184
185 tbl.cell(3, 0).unwrap().v_merge_continue();
186 tbl.cell(3, 1).unwrap().set_text("Storage");
187 tbl.cell(3, 2).unwrap().set_text("2x 1TB NVMe SSD (RAID 1)");
188
189 tbl.cell(4, 0).unwrap().set_text("Network");
191 tbl.cell(4, 0).unwrap().v_merge_restart();
192 tbl.cell(4, 0).unwrap().shading("FCE4D6");
193 tbl.cell(4, 0)
194 .unwrap()
195 .vertical_alignment(VerticalAlignment::Center);
196 tbl.cell(4, 1).unwrap().set_text("Ethernet");
197 tbl.cell(4, 2).unwrap().set_text("4x 10GbE SFP+");
198
199 tbl.cell(5, 0).unwrap().v_merge_continue();
200 tbl.cell(5, 1).unwrap().set_text("Management");
201 tbl.cell(5, 2).unwrap().set_text("1x 1GbE IPMI");
202
203 tbl.cell(6, 0).unwrap().set_text("Software");
205 tbl.cell(6, 0).unwrap().v_merge_restart();
206 tbl.cell(6, 0).unwrap().shading("D6E4F0");
207 tbl.cell(6, 0)
208 .unwrap()
209 .vertical_alignment(VerticalAlignment::Center);
210 tbl.cell(6, 1).unwrap().set_text("Operating System");
211 tbl.cell(6, 2).unwrap().set_text("Ubuntu 24.04 LTS");
212
213 tbl.cell(7, 0).unwrap().v_merge_continue();
214 tbl.cell(7, 1).unwrap().set_text("Monitoring");
215 tbl.cell(7, 2).unwrap().set_text("Prometheus + Grafana");
216 }
217
218 doc.add_paragraph("");
219
220 doc.add_paragraph("4. Nested Table").style("Heading2");
224
225 {
226 let mut tbl = doc.add_table(2, 2);
227 tbl = tbl.borders(BorderStyle::Single, 6, "2E75B6");
228 tbl = tbl.width_pct(100.0);
229 tbl = tbl.cell_margins(
230 Length::twips(72),
231 Length::twips(108),
232 Length::twips(72),
233 Length::twips(108),
234 );
235
236 tbl.cell(0, 0).unwrap().set_text("Project Alpha");
237 tbl.cell(0, 0).unwrap().shading("2E75B6");
238 tbl.cell(0, 1).unwrap().set_text("Project Beta");
239 tbl.cell(0, 1).unwrap().shading("2E75B6");
240
241 {
243 let mut cell = tbl.cell(1, 0).unwrap();
244 cell.set_text("Milestones:");
245 let mut inner = cell.add_table(3, 2);
246 inner = inner.borders(BorderStyle::Single, 2, "70AD47");
247 inner.cell(0, 0).unwrap().set_text("Phase");
248 inner.cell(0, 0).unwrap().shading("E2EFDA");
249 inner.cell(0, 1).unwrap().set_text("Status");
250 inner.cell(0, 1).unwrap().shading("E2EFDA");
251 inner.cell(1, 0).unwrap().set_text("Design");
252 inner.cell(1, 1).unwrap().set_text("Complete");
253 inner.cell(2, 0).unwrap().set_text("Build");
254 inner.cell(2, 1).unwrap().set_text("In Progress");
255 }
256
257 {
259 let mut cell = tbl.cell(1, 1).unwrap();
260 cell.set_text("Budget:");
261 let mut inner = cell.add_table(3, 2);
262 inner = inner.borders(BorderStyle::Single, 2, "ED7D31");
263 inner.cell(0, 0).unwrap().set_text("Category");
264 inner.cell(0, 0).unwrap().shading("FCE4D6");
265 inner.cell(0, 1).unwrap().set_text("Amount");
266 inner.cell(0, 1).unwrap().shading("FCE4D6");
267 inner.cell(1, 0).unwrap().set_text("Development");
268 inner.cell(1, 1).unwrap().set_text("$120,000");
269 inner.cell(2, 0).unwrap().set_text("Testing");
270 inner.cell(2, 1).unwrap().set_text("$35,000");
271 }
272 }
273
274 doc.add_paragraph("");
275
276 doc.add_paragraph("5. Form-Style Table").style("Heading2");
280
281 {
282 let mut tbl = doc.add_table(6, 4);
283 tbl = tbl.borders(BorderStyle::Single, 4, "808080");
284 tbl = tbl.width_pct(100.0);
285
286 tbl.cell(0, 0)
288 .unwrap()
289 .set_text("Customer Registration Form");
290 tbl.cell(0, 0).unwrap().grid_span(4);
291 tbl.cell(0, 0).unwrap().shading("404040");
292
293 tbl.cell(1, 0).unwrap().set_text("First Name");
295 tbl.cell(1, 0).unwrap().shading("E8E8E8");
296 tbl.cell(1, 1).unwrap().set_text("John");
297 tbl.cell(1, 2).unwrap().set_text("Last Name");
298 tbl.cell(1, 2).unwrap().shading("E8E8E8");
299 tbl.cell(1, 3).unwrap().set_text("Smith");
300
301 tbl.cell(2, 0).unwrap().set_text("Email");
303 tbl.cell(2, 0).unwrap().shading("E8E8E8");
304 tbl.cell(2, 1).unwrap().set_text("john.smith@example.com");
305 tbl.cell(2, 1).unwrap().grid_span(3);
306
307 tbl.cell(3, 0).unwrap().set_text("Phone");
309 tbl.cell(3, 0).unwrap().shading("E8E8E8");
310 tbl.cell(3, 1).unwrap().set_text("+1 (555) 123-4567");
311 tbl.cell(3, 2).unwrap().set_text("Company");
312 tbl.cell(3, 2).unwrap().shading("E8E8E8");
313 tbl.cell(3, 3).unwrap().set_text("Acme Corp");
314
315 tbl.cell(4, 0).unwrap().set_text("Address");
317 tbl.cell(4, 0).unwrap().shading("E8E8E8");
318 tbl.cell(4, 1)
319 .unwrap()
320 .set_text("123 Business Ave, Suite 400, Portland, OR 97201");
321 tbl.cell(4, 1).unwrap().grid_span(3);
322
323 tbl.cell(5, 0).unwrap().set_text("Notes");
325 tbl.cell(5, 0).unwrap().shading("E8E8E8");
326 tbl.cell(5, 0)
327 .unwrap()
328 .vertical_alignment(VerticalAlignment::Top);
329 {
330 let mut cell = tbl.cell(5, 1).unwrap().grid_span(3);
331 cell.set_text("Premium customer since 2020. Preferred contact method: email.");
332 cell.add_paragraph("Annual review scheduled for March 2026.");
333 }
334 }
335
336 doc.add_paragraph("");
337
338 doc.add_paragraph("6. Comparison Table with Custom Borders")
342 .style("Heading2");
343
344 {
345 let mut tbl = doc.add_table(5, 3);
346 tbl = tbl.borders(BorderStyle::Double, 4, "2E75B6");
347 tbl = tbl.width_pct(100.0);
348
349 tbl.cell(0, 0).unwrap().set_text("Feature");
351 tbl.cell(0, 0).unwrap().shading("2E75B6");
352 tbl.cell(0, 1).unwrap().set_text("Basic Plan");
353 tbl.cell(0, 1).unwrap().shading("2E75B6");
354 tbl.cell(0, 2).unwrap().set_text("Enterprise Plan");
355 tbl.cell(0, 2).unwrap().shading("2E75B6");
356
357 tbl.cell(1, 0).unwrap().set_text("Users");
358 tbl.cell(1, 1).unwrap().set_text("Up to 10");
359 tbl.cell(1, 2).unwrap().set_text("Unlimited");
360 tbl.cell(1, 2).unwrap().shading("E2EFDA");
361
362 tbl.cell(2, 0).unwrap().set_text("Storage");
363 tbl.cell(2, 1).unwrap().set_text("50 GB");
364 tbl.cell(2, 2).unwrap().set_text("5 TB");
365 tbl.cell(2, 2).unwrap().shading("E2EFDA");
366
367 tbl.cell(3, 0).unwrap().set_text("Support");
368 tbl.cell(3, 1).unwrap().set_text("Email only");
369 tbl.cell(3, 2).unwrap().set_text("24/7 Phone + Email");
370 tbl.cell(3, 2).unwrap().shading("E2EFDA");
371
372 tbl.cell(4, 0).unwrap().set_text("Price");
373 tbl.cell(4, 0).unwrap().shading("F2F2F2");
374 tbl.cell(4, 1).unwrap().set_text("$29/month");
375 tbl.cell(4, 1).unwrap().shading("F2F2F2");
376 tbl.cell(4, 2).unwrap().set_text("$199/month");
377 tbl.cell(4, 2).unwrap().shading("C6EFCE");
378 }
379
380 doc.add_paragraph("");
381
382 doc.add_paragraph("7. Fixed Layout Table with Row Height Control")
386 .style("Heading2");
387
388 {
389 let mut tbl = doc.add_table(4, 5);
390 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
391 tbl = tbl.width(Length::inches(7.0));
392 tbl = tbl.layout_fixed();
393
394 for col in 0..5 {
396 tbl.cell(0, col).unwrap().width(Length::inches(1.4));
397 }
398
399 tbl.row(0).unwrap().height_exact(Length::twips(480));
401 tbl.row(0).unwrap().header();
402 tbl.row(0).unwrap().cant_split();
403
404 let headers = ["Mon", "Tue", "Wed", "Thu", "Fri"];
405 for (col, h) in headers.iter().enumerate() {
406 tbl.cell(0, col).unwrap().set_text(h);
407 tbl.cell(0, col).unwrap().shading("404040");
408 tbl.cell(0, col)
409 .unwrap()
410 .vertical_alignment(VerticalAlignment::Center);
411 }
412
413 tbl.row(1).unwrap().height(Length::twips(600));
415 tbl.cell(1, 0).unwrap().set_text("9:00 Standup");
416 tbl.cell(1, 1).unwrap().set_text("9:00 Standup");
417 tbl.cell(1, 2).unwrap().set_text("9:00 Standup");
418 tbl.cell(1, 3).unwrap().set_text("9:00 Standup");
419 tbl.cell(1, 4).unwrap().set_text("9:00 Standup");
420
421 tbl.row(2).unwrap().height(Length::twips(600));
422 tbl.cell(2, 0).unwrap().set_text("10:00 Dev");
423 tbl.cell(2, 0).unwrap().shading("D6E4F0");
424 tbl.cell(2, 1).unwrap().set_text("10:00 Design Review");
425 tbl.cell(2, 1).unwrap().shading("FCE4D6");
426 tbl.cell(2, 2).unwrap().set_text("10:00 Dev");
427 tbl.cell(2, 2).unwrap().shading("D6E4F0");
428 tbl.cell(2, 3).unwrap().set_text("10:00 Sprint Planning");
429 tbl.cell(2, 3).unwrap().shading("E2EFDA");
430 tbl.cell(2, 4).unwrap().set_text("10:00 Dev");
431 tbl.cell(2, 4).unwrap().shading("D6E4F0");
432
433 tbl.row(3).unwrap().height(Length::twips(600));
434 tbl.cell(3, 0).unwrap().set_text("14:00 Code Review");
435 tbl.cell(3, 1).unwrap().set_text("14:00 Dev");
436 tbl.cell(3, 1).unwrap().shading("D6E4F0");
437 tbl.cell(3, 2).unwrap().set_text("14:00 Demo");
438 tbl.cell(3, 2).unwrap().shading("FCE4D6");
439 tbl.cell(3, 3).unwrap().set_text("14:00 Dev");
440 tbl.cell(3, 3).unwrap().shading("D6E4F0");
441 tbl.cell(3, 4).unwrap().set_text("14:00 Retro");
442 tbl.cell(3, 4).unwrap().shading("E2EFDA");
443 }
444
445 doc.set_title("Styled Tables Showcase");
446 doc.set_author("rdocx");
447
448 doc.save(path).unwrap();
449}