持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情
jacob的简单使用
前言
操作word文档的需求在工作中很常见, 我们之前也介绍了很多工具, 但是他们对更新目录等功能的支持都不是很友好 像poi-tl暂不支持, spire.doc免费版的有限制等, 我们来尝试下使用jacob操作word完成相关功能
ps: 其原理就是用代码调用word提供的api, 所以jocb只能在windows上使用
环境
下载 免费下载地址
结构 将
jacob-1.20-x64.dll拷贝到C:\Windows\System32中
maven 本地引入
jacob.jar
<dependency>
<groupId>com.jacob</groupId>
<artifactId>jacob</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jacob.jar</systemPath>
</dependency>
代码
格式枚举
/**
* word格式枚举
*/
@Getter
@AllArgsConstructor
public enum WordType {
DOC(0, "doc"),
DOCT(1, "dot"),
TXT(2, "txt"),
RTF(6, "rtf"),
HTM(8, "htm"),
MHT(9, "mht"),
XML(11, "xml"),
DOCX(12, "docx"),
DOCM(13, "docm"),
DOTX(14, "dotx"),
DOTM(15, "dotm"),
PDF(17, "pdf"),
XPS(18, "xps"),
ODT(23, "odt"),
WTF(24, "wtf"),;
private int code;
private String type;
public static String getTypeByCode(int code) {
return Arrays.stream(values()).filter(e -> Objects.equals(code, e.getCode())).findFirst().map(WordType::getType).orElse(null);
}
}
封装操作工具
public class WordUtil {
/**
* 源文件
*/
private String docFile;
/**
* Word应用
*/
private ActiveXComponent word;
/**
* 打开的文档
*/
private Dispatch doc;
/**
* 构造
*/
public WordUtil(String docFile) {
this.docFile = docFile;
ComThread.InitSTA();
// 打开一个word应用
word = new ActiveXComponent("Word.Application");
word.setProperty("Visible", new Variant(false));
// 打开一个word文档
doc = Dispatch.invoke(word.getProperty("Documents").toDispatch(), "Open", Dispatch.Method,
new Object[]{docFile, new Variant(false), new Variant(true)}, new int[1]).toDispatch();
}
/**
* 更新目录并另存为
*/
public void updateCatalogue(int fmt) {
Dispatch activeDocument = word.getProperty("ActiveDocument").toDispatch();
Dispatch tablesOfContents = Dispatch.get(activeDocument, "TablesOfContents").toDispatch();
// 更新目录,有两个方法:Update 更新域,UpdatePageNumbers 只更新页码
Dispatch toc = Dispatch.call(tablesOfContents, "Item", new Variant(1)).toDispatch();
Dispatch.call(toc, "Update");
convertDocFmt(fmt);
}
/**
* 另存为
*
* @param fmt 另存为文档格式
*/
public void convertDocFmt(int fmt) {
String targetPath = StrUtil.replace(this.docFile, "." + FileUtil.getSuffix(this.docFile), "." + WordType.getTypeByCode(fmt));
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[]{targetPath, new Variant(fmt)}, new int[1]);
new File(targetPath);
}
/**
* 封装一下调用, 方便关闭
*/
public void call(VoidFunc0 voidFunc0) {
try {
voidFunc0.callWithRuntimeException();
} finally {
if (doc != null) {
// 关闭文档
Dispatch.call(doc, "Close", new Variant(false));
}
if (word != null) {
// 退出word应用
word.invoke("Quit", new Variant[]{});
}
ComThread.Release();
}
}
}
使用
public static void main(String[] args) {
String docFile = "F:\\ff.doc";
WordUtil wordUtil = new WordUtil(docFile);
// 另存为
// wordUtil.call(() -> wordUtil.convertDocFmt(WordType.DOCX.getCode()));
// 更新目录然后另存为
wordUtil.call(() -> wordUtil.updateCatalogue(WordType.DOCX.getCode()));
}