easydoc_writer/doc_editor.rs
1//! 文档编辑器 -- 打开已有 DOCX 进行修改。
2//!
3//! 对应 Hutool 的 `Word07Writer(File)` 模式:如果文件存在,打开编辑而非创建新文档。
4
5use std::path::{Path, PathBuf};
6
7use easydoc_core::{DocError, Result};
8use office_oxide::edit::EditableDocument;
9
10/// 已打开的 DOCX 文件,准备进行修改。
11///
12/// 通过门面 `EasyDoc::edit()` 方法创建。包装 `office_oxide` 的 `EditableDocument`
13/// 以支持文本替换和保存。
14///
15/// # 示例
16///
17/// ```ignore
18/// EasyDoc::edit("existing.docx")?
19/// .replace_text("{name}", "Alice")
20/// .replace_text("{date}", "2026-07-21")
21/// .save()?;
22/// ```
23pub struct DocEditor {
24 path: PathBuf,
25 doc: EditableDocument,
26}
27
28impl DocEditor {
29 /// Opens an existing DOCX file for editing.
30 ///
31 /// # Errors
32 ///
33 /// Returns I/O or format errors.
34 pub fn open(path: &Path) -> Result<Self> {
35 let doc = EditableDocument::open(path)
36 .map_err(|e| DocError::Document(format!("cannot open document: {e}")))?;
37 Ok(Self {
38 path: path.to_path_buf(),
39 doc,
40 })
41 }
42
43 /// Replaces all occurrences of `find` with `replace` in the document text.
44 ///
45 /// Corresponds to Hutool's placeholder replacement pattern
46 /// (which Hutool itself does not provide — users must use raw POI).
47 ///
48 /// Returns the number of replacements made.
49 #[must_use]
50 pub fn replace_text(mut self, find: &str, replace: &str) -> Self {
51 self.doc.replace_text(find, replace);
52 self
53 }
54
55 /// Saves the modified document, overwriting the original file.
56 ///
57 /// # Errors
58 ///
59 /// Returns I/O errors.
60 pub fn save(self) -> Result<()> {
61 self.doc
62 .save(&self.path)
63 .map_err(|e| DocError::Document(format!("cannot save document: {e}")))
64 }
65
66 /// Saves the modified document to a new path.
67 ///
68 /// # Errors
69 ///
70 /// Returns I/O errors.
71 pub fn save_as(self, path: impl AsRef<Path>) -> Result<()> {
72 self.doc
73 .save(path.as_ref())
74 .map_err(|e| DocError::Document(format!("cannot save document: {e}")))
75 }
76}