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

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

在做文件在线预览的时候,由于用 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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3165 引用 • 8206 回帖

相关帖子

欢迎来到这里!

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

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