Skip to main content

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}