1use std::collections::HashMap;
13use std::path::Path;
14
15use rdocx::{Alignment, BorderStyle, Document, Length};
16
17fn main() {
18 let samples_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
19 .parent()
20 .unwrap()
21 .parent()
22 .unwrap()
23 .join("samples");
24 std::fs::create_dir_all(&samples_dir).unwrap();
25
26 let template_path = samples_dir.join("_template.docx");
28 create_template(&template_path);
29 println!(" Created template: _template.docx");
30
31 let output_path = samples_dir.join("from_template.docx");
33 fill_template(&template_path, &output_path);
34 println!(" Created filled document: from_template.docx");
35
36 std::fs::remove_file(&template_path).ok();
38 println!("\nDone!");
39}
40
41fn create_template(path: &Path) {
44 let mut doc = Document::new();
45 doc.set_page_size(Length::inches(8.5), Length::inches(11.0));
46 doc.set_margins(
47 Length::inches(1.0),
48 Length::inches(1.0),
49 Length::inches(1.0),
50 Length::inches(1.0),
51 );
52
53 doc.set_header("{{company_name}} — Confidential");
54 doc.set_footer("Prepared by {{author_name}} on {{date}}");
55
56 doc.add_paragraph("{{company_name}}")
58 .style("Heading1")
59 .alignment(Alignment::Center);
60
61 doc.add_paragraph("Project Proposal")
62 .alignment(Alignment::Center);
63
64 doc.add_paragraph("");
65
66 doc.add_paragraph("Executive Summary").style("Heading2");
68
69 doc.add_paragraph(
70 "This proposal outlines the {{project_name}} project for {{company_name}}. \
71 The primary contact is {{contact_name}} ({{contact_email}}). \
72 The proposed start date is {{start_date}} with an estimated duration of {{duration}}.",
73 );
74
75 doc.add_paragraph("");
76
77 doc.add_paragraph("Key Details").style("Heading2");
79
80 {
81 let mut p = doc.add_paragraph("");
82 p.add_run("Project: ").bold(true);
83 p.add_run("{{project_name}}");
84 }
85 {
86 let mut p = doc.add_paragraph("");
87 p.add_run("Budget: ").bold(true);
88 p.add_run("{{budget}}");
89 }
90 {
91 let mut p = doc.add_paragraph("");
92 p.add_run("Status: ").bold(true);
93 p.add_run("{{status}}");
94 }
95
96 doc.add_paragraph("");
97
98 doc.add_paragraph("Team Members").style("Heading2");
100
101 {
102 let mut tbl = doc.add_table(4, 3);
103 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
104
105 for col in 0..3 {
107 tbl.cell(0, col).unwrap().shading("2E75B6");
108 }
109 tbl.cell(0, 0).unwrap().set_text("Name");
110 tbl.cell(0, 1).unwrap().set_text("Role");
111 tbl.cell(0, 2).unwrap().set_text("Email");
112
113 tbl.cell(1, 0).unwrap().set_text("{{member1_name}}");
114 tbl.cell(1, 1).unwrap().set_text("{{member1_role}}");
115 tbl.cell(1, 2).unwrap().set_text("{{member1_email}}");
116
117 tbl.cell(2, 0).unwrap().set_text("{{member2_name}}");
118 tbl.cell(2, 1).unwrap().set_text("{{member2_role}}");
119 tbl.cell(2, 2).unwrap().set_text("{{member2_email}}");
120
121 tbl.cell(3, 0).unwrap().set_text("{{member3_name}}");
122 tbl.cell(3, 1).unwrap().set_text("{{member3_role}}");
123 tbl.cell(3, 2).unwrap().set_text("{{member3_email}}");
124 }
125
126 doc.add_paragraph("");
127
128 doc.add_paragraph("Deliverables").style("Heading2");
130
131 doc.add_paragraph("INSERTION_POINT");
132
133 doc.add_paragraph("");
134
135 doc.add_paragraph("Acceptance").style("Heading2");
137
138 doc.add_paragraph(
139 "By signing below, {{company_name}} agrees to the terms outlined in this proposal.",
140 );
141
142 {
143 let mut tbl = doc.add_table(2, 2);
144 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
145 tbl.cell(0, 0)
146 .unwrap()
147 .set_text("Customer: ___________________");
148 tbl.cell(0, 1)
149 .unwrap()
150 .set_text("Provider: ___________________");
151 tbl.cell(1, 0).unwrap().set_text("Date: {{date}}");
152 tbl.cell(1, 1).unwrap().set_text("Date: {{date}}");
153 }
154
155 doc.set_title("{{company_name}} — Project Proposal Template");
156 doc.set_author("Template Generator");
157
158 doc.save(path).unwrap();
159}
160
161fn fill_template(template_path: &Path, output_path: &Path) {
163 let mut doc = Document::open(template_path).unwrap();
164
165 let mut replacements = HashMap::new();
167 replacements.insert("{{company_name}}", "Riverside Medical Center");
168 replacements.insert("{{project_name}}", "Network Security Upgrade");
169 replacements.insert("{{contact_name}}", "Dr. Sarah Chen");
170 replacements.insert("{{contact_email}}", "s.chen@riverside.org");
171 replacements.insert("{{start_date}}", "March 1, 2026");
172 replacements.insert("{{duration}}", "12 weeks");
173 replacements.insert("{{budget}}", "$185,000");
174 replacements.insert("{{status}}", "Pending Approval");
175 replacements.insert("{{author_name}}", "James Wilson");
176 replacements.insert("{{date}}", "February 22, 2026");
177
178 replacements.insert("{{member1_name}}", "James Wilson");
180 replacements.insert("{{member1_role}}", "Project Lead");
181 replacements.insert("{{member1_email}}", "j.wilson@provider.com");
182 replacements.insert("{{member2_name}}", "Maria Garcia");
183 replacements.insert("{{member2_role}}", "Security Architect");
184 replacements.insert("{{member2_email}}", "m.garcia@provider.com");
185 replacements.insert("{{member3_name}}", "David Park");
186 replacements.insert("{{member3_role}}", "Network Engineer");
187 replacements.insert("{{member3_email}}", "d.park@provider.com");
188
189 let count = doc.replace_all(&replacements);
190 println!(" Replaced {} placeholders", count);
191
192 if let Some(idx) = doc.find_content_index("INSERTION_POINT") {
194 doc.remove_content(idx);
196
197 doc.insert_paragraph(idx, "The following deliverables are included:");
199
200 let mut tbl = doc.insert_table(idx + 1, 5, 3);
202 tbl = tbl.borders(BorderStyle::Single, 4, "000000");
203
204 for col in 0..3 {
205 tbl.cell(0, col).unwrap().shading("E2EFDA");
206 }
207 tbl.cell(0, 0).unwrap().set_text("Phase");
208 tbl.cell(0, 1).unwrap().set_text("Description");
209 tbl.cell(0, 2).unwrap().set_text("Timeline");
210
211 tbl.cell(1, 0).unwrap().set_text("1. Discovery");
212 tbl.cell(1, 1)
213 .unwrap()
214 .set_text("Network assessment and asset inventory");
215 tbl.cell(1, 2).unwrap().set_text("Weeks 1-3");
216
217 tbl.cell(2, 0).unwrap().set_text("2. Design");
218 tbl.cell(2, 1)
219 .unwrap()
220 .set_text("Security architecture and policy design");
221 tbl.cell(2, 2).unwrap().set_text("Weeks 4-6");
222
223 tbl.cell(3, 0).unwrap().set_text("3. Implementation");
224 tbl.cell(3, 1)
225 .unwrap()
226 .set_text("Deploy monitoring and access controls");
227 tbl.cell(3, 2).unwrap().set_text("Weeks 7-10");
228
229 tbl.cell(4, 0).unwrap().set_text("4. Validation");
230 tbl.cell(4, 1)
231 .unwrap()
232 .set_text("Testing, training, and handover");
233 tbl.cell(4, 2).unwrap().set_text("Weeks 11-12");
234
235 println!(" Inserted deliverables table at position {}", idx);
236 }
237
238 doc.set_title("Riverside Medical Center — Network Security Upgrade Proposal");
240 doc.set_author("James Wilson");
241 doc.set_subject("Project Proposal");
242 doc.set_keywords("security, network, medical, proposal");
243
244 doc.save(output_path).unwrap();
245}