利用 Jacob 实现 office 文档格式转换

本贴最后更新于 2291 天前,其中的信息可能已经沧海桑田

在做文件在线预览的时候,由于用 OpenOffice、LibreOffice 转换 Office 文档成 pdf 都会存在一定不可避免的失真,为了解决这个问题,又用了 Jacob 来对文档进行转换,测试后发现这个工具转换出来的文档效果和原文件基本相同,所以在这边做个记录,仅供大家参考。


一、安装 Office/WPS

因为文档转换需要用到 Office/WPS 软件,所以需要提前在机子上装好,这里我用的是 Office2016 全家桶。

二、下载 Jacob

下载 Jacob,建议去 Jacob 官网 下载,我下载的是最新的版本 1.19,压缩包内包含的文件如下:
imagepng

三、配置 JDK

这里根据系统的版本,需要把 dll 文件放到 JDK 的 bin 目录下,我机子的路径如下:
imagepng
注意:因为 Linux 不识别 dll 文件,所以这个应该只能在 Windows 系统上跑

四、导入 jar 包

这里我创建的是 SpringBoot 项目,因为 maven 中央仓库找不到 Jacob 的包,所以这里我先把 jacob.jar 导入本地 maven 仓库;
打开 CMD 先进入刚才下载的压缩包的解压缩目录,就是 jacob.jar 的文件目录下执行:
mvn install:install-file -Dfile=jacob.jar -DgroupId=com.jacob -DartifactId=jacob -Dversion=1.19 -Dpackaging=jar

成功后 pom 文件下引入依赖:

<dependency> <groupId>com.jacob</groupId> <artifactId>jacob</artifactId> <version>1.19</version> </dependency>

五、转换实现

这里我只用到了 word 类文档转 pdf、ppt 类文档转 pdf、excel 类文档转 html,下面贴上代码:

/** * word文件转pdf * @param source * @param target */ public static void word2pdf(String source, String target) throws Exception { ComThread.InitSTA(); ActiveXComponent app = null; Dispatch doc = null; try { //创建一个Word对象 app = new ActiveXComponent("Word.Application"); app.setProperty("Visible", false); Dispatch docs = app.getProperty("Documents").toDispatch(); /* * 打开激活文档 * param 4: ReadOnly * param 5: Untitled指定文件是否有标题 * param 6: WithWindow指定文件是否可见 * */ doc = Dispatch.call(docs, "Open", source, false, true).toDispatch(); File tofile = new File(target); if (tofile.exists()) { tofile.delete(); } //word保存为pdf的宏值为17 Dispatch.call(doc, "SaveAs", target, 17); } finally { if(doc != null) { Dispatch.call(doc, "Close", false); } if (app != null) { app.invoke("Quit", new Variant[] {}); } ComThread.Release(); } } /** * ppt转pdf * @param source * @param target * @throws Exception */ public static void ppt2pdf(String source, String target) throws Exception { ComThread.InitSTA(); ActiveXComponent app = null; Dispatch ppt = null; try { app = new ActiveXComponent("PowerPoint.Application"); app.setProperty("Visible", true); Dispatch ppts = app.getProperty("Presentations").toDispatch(); ppt = Dispatch.call(ppts, "Open", source, false, false).toDispatch(); File tofile = new File(target); if (tofile.exists()) { tofile.delete(); } //ppt转pdf的宏值为32 Dispatch.invoke(ppt, "SaveAs", Dispatch.Method, new Object[]{ target, 32},new int[1]); } finally { if(ppt != null) { Dispatch.call(ppt, "Close"); } if(app != null) { app.invoke("Quit", new Variant[] {}); } ComThread.Release(); } } /** * excel转html * @param source * @param target */ public static void excel2html(String source, String target) throws Exception { ComThread.InitSTA(); ActiveXComponent app = null; Dispatch excel = null; try { app = new ActiveXComponent("Excel.Application"); app.setProperty("Visible", false); Dispatch excels = app.getProperty("Workbooks").toDispatch(); excel = Dispatch.invoke( excels, "Open", Dispatch.Method, new Object[] { source, false, true}, new int[1]).toDispatch(); File tofile = new File(target); if (tofile.exists()) { tofile.delete(); } //excel转Html的宏值为44 Dispatch.invoke(excel, "SaveAs", Dispatch.Method, new Object[] { target, 44}, new int[1]); //Excel转换后需要转码成UTF-8,否则预览可能会乱码 html2utf(target); html2utfForJacob(target); } finally { if(excel != null) { Dispatch.call(excel, "Close", false); } if(app != null) { app.invoke("Quit", new Variant[] {}); } ComThread.Release(); } } public static void html2utf(String filePath) throws Exception { String content = "charset=utf-8"; String templateContent = ""; FileInputStream fileinputstream = new FileInputStream(filePath);// 读取模板文件 //获得输入流的长度,然后建一个该长度的数组,然后把输入流中的数据以字节的形式读入到数组中,然后关闭流 int lenght = fileinputstream.available(); byte bytes[] = new byte[lenght]; fileinputstream.read(bytes); fileinputstream.close(); //因为原来的html文件是gb2312格式,所以转为string时也要以GBK格式读取,不然依旧是乱码 templateContent = new String(bytes, "GBK"); templateContent = templateContent.replaceFirst("charset=gb2312", content); // 因为已经替换字符串了,所以使用UTF-8字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 byte tag_bytes[] = templateContent.getBytes("UTF-8"); FileOutputStream fileoutputstream = new FileOutputStream(filePath);// 建立文件输出流 fileoutputstream.write(tag_bytes); fileoutputstream.close(); } public static void html2utfForJacob(String filePath) throws Exception { filePath = filePath.replace(".html", ".files"); File dir = new File(filePath); File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组 if (files != null) { for (int i = 0; i < files.length; i++) { String fileName = files[i].getName(); if (files[i].isDirectory()) { // 判断是文件还是文件夹 html2utfForJacob(files[i].getAbsolutePath()); // 获取文件绝对路径 } else if (fileName.endsWith("html")) { // 判断文件名是否以.html结尾 String strFileName = files[i].getAbsolutePath(); html2utf(strFileName) ; } else { continue; } } } } public static void main(String[] args) { Long a = System.currentTimeMillis(); try { word2pdf("E:\\conventor\\1.docx", "E:\\conventor\\1.pdf"); //ppt2pdf("E:\\conventor\\2.ppt", "E:\\conventor\\2.pdf"); //excel2html("E:\\conventor\\3.xlsx", "E:\\conventor\\3.html"); } catch(Exception e) { e.printStackTrace(); } Long b = System.currentTimeMillis(); Long q = (b-a)/1000; System.out.println("===转换成功===, 耗时" + q + "s"); }

问题:在 main 函数中能够运行 ppt2pdf 函数转换文档,但是在项目中调用这个函数就会报错:
imagepng
稍微调大了 JDK 内存也仍然报错,不知道什么原因,希望有懂的大神可以不吝赐教 ^^

  • Jacob
    1 引用
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3195 引用 • 8215 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...