在合同、申请表、报告模板等 Word 文档中,经常需要限制用户修改某些内容。例如,可以将整份文档设为只读,只允许添加批注或修订,也可以锁定大部分正文,仅保留指定区域供用户填写。
这类限制不同于文档打开密码。打开密码用于控制谁可以打开文件,而编辑限制是在文档已经打开的情况下控制允许执行的编辑操作。
下面介绍如何使用 Java 设置 Word 文档的编辑限制,以及如何在受保护的文档中保留指定区域可编辑。
添加依赖
下面的示例通过 Spire.Doc for Java 处理 Word 文档。使用 Maven 时,可在 pom.xml 中添加其 Maven 仓库和依赖:
xml
代码解读
复制代码
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>14.7.4</version>
</dependency>
</dependencies>
使用 Java 设置 Word 文档编辑限制
可以通过 Document.protect() 为 Word 文档设置编辑限制,并使用 ProtectionType 指定允许的操作。
常用的限制类型包括:
| ProtectionType | 允许的操作 |
|---|---|
Allow_Only_Reading | 仅查看,不允许修改 |
Allow_Only_Revisions | 可以修改,但修改内容以修订形式记录 |
Allow_Only_Comments | 只允许添加或修改批注 |
Allow_Only_Form_Fields | 只允许填写表单域 |
No_Protection | 不设置编辑限制 |
下面的示例将 Word 文档设置为只读:
typescript
代码解读
复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.ProtectionType;
public class RestrictWordEditing {
public static void main(String[] args) {
// 加载 Word 文档
Document doc = new Document();
doc.loadFromFile("合同.docx");
// 设置为只读,并设置解除限制所需的密码
doc.protect(
ProtectionType.Allow_Only_Reading,
"123456"
);
// 保存文档
doc.saveToFile("合同_限制编辑.docx", FileFormat.Docx_2019);
doc.close();
}
}
如果需要更换限制方式,只需修改传入的 ProtectionType。例如,仅允许用户添加批注:
arduino
代码解读
复制代码
doc.protect(
ProtectionType.Allow_Only_Comments,
"123456"
);
如果文档需要由多人审核,Allow_Only_Revisions 会更合适。用户仍然可以修改正文,但这些修改会作为修订保留下来,便于后续接受或拒绝。
对于包含文本表单域、复选框等可填写控件的模板,可以使用 Allow_Only_Form_Fields,限制用户只能操作这些表单域。
需要注意,protect() 中的密码用于解除编辑限制,并不是打开文档所需的密码。如果需要用户输入密码才能打开文件,应使用文档加密功能,而不是编辑限制。
使用 Java 设置 Word 文档指定区域可编辑
整篇文档设为只读并不总是够用。更常见的一种情况是:合同条款、说明文字等内容不能修改,但需要保留部分位置供用户填写。
Spire.Doc 可以通过 PermissionStart 和 PermissionEnd 标记一个不受编辑限制影响的区域。
下面的示例将文档设置为只读,同时允许第 1 到第 6 个段落继续编辑:
java
代码解读
复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.PermissionEnd;
import com.spire.doc.PermissionStart;
import com.spire.doc.ProtectionType;
import com.spire.doc.Section;
public class AllowEditingInSpecifiedRange {
public static void main(String[] args) {
// 加载 Word 文档
Document doc = new Document();
doc.loadFromFile("合同模板.docx");
// 创建一对权限区域标记
PermissionStart start =
new PermissionStart(doc, "EditableRange1");
PermissionEnd end =
new PermissionEnd(doc, "EditableRange1");
// 获取目标节
Section section = doc.getSections().get(0);
// 在第一个段落开头插入起始标记
section.getParagraphs()
.get(0)
.getChildObjects()
.insert(0, start);
// 在第六个段落末尾插入结束标记
section.getParagraphs()
.get(5)
.getChildObjects()
.add(end);
// 将其他内容设置为只读
doc.protect(
ProtectionType.Allow_Only_Reading,
"123456"
);
// 保存结果
doc.saveToFile(
"合同模板_限制编辑.docx",
FileFormat.Docx_2019
);
doc.close();
}
}
PermissionStart 和 PermissionEnd 需要使用相同的权限 ID:
arduino
代码解读
复制代码
new PermissionStart(doc, "EditableRange1");
new PermissionEnd(doc, "EditableRange1");
这样 Word 才能把两个标记之间的内容识别为同一个可编辑区域。
上面的代码把起始标记放在第一个段落的第一个子对象之前,把结束标记放在第六个段落的末尾,因此这几个段落之间的内容都属于例外区域。
如果只需要开放段落中的一部分内容,也可以把标记插入到具体的 TextRange 前后,而不是直接以整个段落作为边界。实际项目中,最好根据模板中稳定的书签、占位文本或其他可识别对象定位编辑区域,而不是长期依赖固定的段落索引。
设置多个可编辑区域时注意权限 ID
一份文档可以包含多个可编辑区域,例如分别开放“客户信息”“合同金额”和“备注”。
每个区域应使用自己的权限 ID:
代码解读
复制代码
CustomerInfo
ContractAmount
Remarks
起始标记和结束标记必须一一对应。
如果多个区域误用了不匹配的 ID,或者只插入了 PermissionStart 而没有正确插入对应的 PermissionEnd,生成的文档可能出现编辑范围与预期不一致的问题。
因此,如果编辑区域是根据业务配置动态生成的,建议为每组标记生成明确且唯一的 ID,而不要在所有位置都硬编码同一个名称。
使用 Java 移除 Word 文档编辑限制
如果需要恢复文档的正常编辑状态,可以将保护类型设置为 No_Protection:
typescript
代码解读
复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.ProtectionType;
public class RemoveEditingRestriction {
public static void main(String[] args) {
// 加载受限制的 Word 文档
Document doc = new Document();
doc.loadFromFile("合同_限制编辑.docx");
// 移除编辑限制
doc.protect(ProtectionType.No_Protection);
// 保存结果
doc.saveToFile(
"合同_解除限制.docx",
FileFormat.Docx_2019
);
doc.close();
}
}
如果文档之前只设置了整体编辑限制,这样处理即可。
但如果文档中使用过 PermissionStart 和 PermissionEnd 创建例外区域,这些标记属于文档内容结构的一部分。取消保护并不会自动意味着程序后续不再需要这些标记。
如果希望输出一份完全清理后的普通文档,可以同时删除这些对象:
ini
代码解读
复制代码
import com.spire.doc.Document;
import com.spire.doc.DocumentObject;
import com.spire.doc.FileFormat;
import com.spire.doc.PermissionEnd;
import com.spire.doc.PermissionStart;
import com.spire.doc.ProtectionType;
import com.spire.doc.Section;
import com.spire.doc.documents.Paragraph;
public class RemoveEditingRestrictionAndPermissions {
public static void main(String[] args) {
Document doc = new Document();
doc.loadFromFile("合同模板_限制编辑.docx");
// 移除编辑限制
doc.protect(ProtectionType.No_Protection);
// 删除权限区域标记
for (int s = 0; s < doc.getSections().getCount(); s++) {
Section section = doc.getSections().get(s);
for (int p = 0; p < section.getParagraphs().getCount(); p++) {
Paragraph paragraph = section.getParagraphs().get(p);
for (int i = 0;
i < paragraph.getChildObjects().getCount();) {
DocumentObject obj =
paragraph.getChildObjects().get(i);
if (obj instanceof PermissionStart
|| obj instanceof PermissionEnd) {
paragraph.getChildObjects().remove(obj);
} else {
i++;
}
}
}
}
doc.saveToFile(
"合同模板_解除限制.docx",
FileFormat.Docx_2019
);
doc.close();
}
}
这里删除对象时没有在 for 循环末尾固定执行 i++。原因是删除当前对象以后,后面的对象会移动到当前索引;如果此时继续递增索引,就可能跳过紧邻的下一个权限标记。
编辑限制和文档加密不要混用概念
编辑限制控制的是文档打开以后可以进行哪些操作:
arduino
代码解读
复制代码
doc.protect(ProtectionType.Allow_Only_Reading, "123456");
而文档加密控制的是没有密码能否打开文件。
因此,“只能看不能改”和“没有密码不能打开”是两个不同的需求。项目中如果同时需要这两层控制,可以分别设置,但不应把 protect() 当作文件访问权限。
另外,Word 的编辑限制主要用于规范正常的文档编辑行为,并不适合作为高强度的数据安全机制。如果真正需要防止未经授权的人员访问内容,仍然应该使用加密、访问控制或其他安全措施。
使用时需要注意的几点
对于固定 Word 模板,可以直接根据段落、表格单元格等结构插入权限标记。但模板一旦经常调整,硬编码类似: https://0571fp.wordpress.com/ https://0571hyfp.wordpress.com/ https://0571clfp.wordpress.com/ https://0571lwfp.wordpress.com/ https://0571zlfp.wordpress.com/ https://0571zxfp.wordpress.com/ https://hzkfp.wordpress.com/ https://0571qcfp.wordpress.com/ https://hzjxfp.wordpress.com/ https://hzypfp.wordpress.com/
scss
代码解读
复制代码
section.getParagraphs().get(5)
这样的索引会比较脆弱。新增一个标题或说明段落,就可能让原来的编辑区域落到错误位置。
更稳妥的做法是先通过书签、特定占位文本或其他稳定标识找到目标位置,再插入 PermissionStart 和 PermissionEnd。
如果文档中已经存在编辑限制或权限区域,在重新设置保护前也应先检查原来的结构,避免重复加入权限标记。
结语
对于需要长期维护的 Word 模板,真正值得固定下来的不是段落序号,而是“哪些业务内容允许编辑”的定位规则。只要编辑区域能够通过稳定的书签、占位符或其他结构标识找到,后续模板增加说明文字或调整排版时,权限设置代码通常不需要跟着频繁修改。
