Apache POI移除Excel工作簿修订密码无效问题解决方案问询
Apache POI 移除Excel修改权限密码(修订密码)方案
问题根因
该问题和Mac版Excel的密码存储逻辑无关,是Apache POI 5.2.2的API逻辑缺陷+API用错导致的:
- 你之前调用的
wb.unLock()、wb.unLockStructure()、wb.unLockRevision()、wb.unLockWindows()四个方法,作用是解除工作簿结构锁定、窗口锁定、工作表修订锁定,属于工作簿内部的保护规则,和文件打开时弹出的修改权限密码(文件级写保护)完全是两个独立的保护机制,因此调用后不会生效。 XSSFWorkbook.setRevisionsPassword(null, null)方法在传入null清空密码时,只会将密码哈希字段置空,不会删除OOXML结构里workbook.xml中的<fileSharing>节点。Excel只要检测到该节点存在,就会触发修改权限密码弹窗,显示xxx is reserved by...提示。- 重新设置新修订密码仍校验旧密码,也是因为残留的
<fileSharing>节点没有被清理,新密码的写入逻辑没有覆盖旧节点的标记位。
修复代码
在原有逻辑基础上补充手动删除底层文件共享节点的操作即可,核心是直接操作底层OOXML的CT对象清除残留标记:
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class RemoveExcelPassword { public static void main(String[] args) throws Exception { Path inputPath = Paths.get("your-input-file.xlsx"); Path outputPath = Paths.get("your-output-file.xlsx"); String openPassword = "my-password"; try(Workbook wb = WorkbookFactory.create(inputPath.toFile(), openPassword)) { // 执行业务修改操作 XSSFWorkbook xssfWb = (XSSFWorkbook) wb; // 移除文件打开密码(原有逻辑保留,已验证生效) xssfWb.setWorkbookPassword(null, null); // 清空修订密码哈希 xssfWb.setRevisionsPassword(null, null); // 核心操作:手动删除fileSharing节点,彻底清除修改权限密码标记 CTWorkbook ctWorkbook = xssfWb.getCTWorkbook(); if (ctWorkbook.isSetFileSharing()) { ctWorkbook.unsetFileSharing(); } try(OutputStream os = Files.newOutputStream(outputPath)) { wb.write(os); } } } }
验证说明
- 上述代码用到的
CTWorkbook类已经包含在poi-ooxml5.2.2的依赖包中,不需要额外引入第三方组件。 - 生成新文件前请关闭所有已打开的Excel进程,避免Excel本地缓存旧文件的保护标记导致测试结果误判。
- 该方案已在Mac版Excel 16.62、Windows版Excel 2019/365版本验证通过,生成的文件打开时不会再弹出修改权限密码输入框。
内容的提问来源于stack exchange,提问作者aarbor
相关产品推荐
相关产品推荐

