论坛首页 综合技术论坛

DOC文档转PDF

浏览 22320 次
锁定老帖子 主题:DOC文档转PDF
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-04-17   最后修改:2011-04-17
最近项目中有用到Word文档转PDF的功能,做了一些尝试,也遇到了一些困难。
下面把尝试的情况记录下来,也希望做过类似工作的童鞋能一起探讨一下。

我尝试过的Word文档转PDF,用过两种方法:
1、使用OpenOffice转PDF;
2、使用MS Office的OLE自动化功能;
OpenOffice的情况稍后补充,下面先说MS Office的转换情况。

Office版本使用2007,因为2007提供了一个加载项:Microsoft Save as PDF 或 XPS,可将文档另存为PDF格式。下载地址:http://www.microsoft.com/downloads/zh-cn/details.aspx?FamilyID=4D951911-3E7E-4AE6-B059-A2E79ED87041,安装即可使用。

Office COM 组件调用使用jacob(Java COM Bridge)
http://sourceforge.net/projects/jacob-project/
Jacob初次使用的人可能会感到比较困惑。题外话,jacob的API设计是有够别扭的,这儿就不多说了。下面说明一下:

我们接触的jacob类主要就3个:ActiveXComponent、Variant、Dispatch;
ActiveXComponent代表COM应用程序:

初始化方法为:
ActiveXComponent app = new ActiveXComponent("Word.Application");

Variant 是与COM通讯的参数或者返回值;
Dispatch代表一个可操作的自动化对象;如果确定返回值是自动化对象的话,可以调用Variant.toDispatch()转换成Dispatch。
获取了Dispatch之后,即可调用该自动化对象的属性或方法,具体的属性和方法要看参考文档,比如:Word开发可在WORD帮助中查看“脱机开发人员帮助WORD对象模型”。
Dispatch.get(dispatch, String name);获取对象属性;
Dispatch.put(dispatch, String name, Object value);设置对象属性;
Dispatch.call(dispatch, String name, Object… args);调用对象方法;
以上都是Dispatch上的静态方法,所以需要传递dispatch本身。

关于jacob-1.15-M4-x86.dll放置的位置,其实很简单,dll的放置位置就是系统参数
System.getProperty("java.library.path");
所指定的,放在路径里的任意一个目录即可,不想污染JDK目录或者windows/system32目录的话,放置项目启动目录下就可以了,Eclipse下我是放在项目目录下。

下面看具体代码:

public class Word2PDF {

static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
static final int wdFormatPDF = 17;// PDF 格式

public static void main(String[] args) {

	String filename = "f:/temp/测试文档.docx";
	String toFilename = filename + ".pdf";
	System.out.println("启动Word...");
	long start = System.currentTimeMillis();
	ActiveXComponent app = null;
	try {
		app = new ActiveXComponent("Word.Application");
		app.setProperty("Visible", false);

		Dispatch docs = app.getProperty("Documents").toDispatch();
		System.out.println("打开文档..." + filename);
		Dispatch doc = Dispatch.call(docs,//
				"Open", //
				filename,// FileName
				false,// ConfirmConversions
				true // ReadOnly
				).toDispatch();

		System.out.println("转换文档到PDF..." + toFilename);
		File tofile = new File(toFilename);
		if (tofile.exists()) {
			tofile.delete();
		}
		Dispatch.call(doc,//
				"SaveAs", //
				toFilename, // FileName
				wdFormatPDF);

		Dispatch.call(doc, "Close", false);
		long end = System.currentTimeMillis();
		System.out.println("转换完成..用时:" + (end - start) + "ms.");
	} catch (Exception e) {
		System.out.println("========Error:文档转换失败:" + e.getMessage());
	} finally {
		if (app != null)
			app.invoke("Quit", wdDoNotSaveChanges);
	}
}
}


已知的情况:
1、转换效果好。(相对于OpenOffice)
2、速度慢
3、CPU占用率高

待解决的问题:
1、安全性问题:是否可禁用WORD宏,以及WORD文档中的ActiveX控件?
这一点我不太清楚,但在WORD选项--安全性设置中看到的:

2、微软知识库中的“服务器端 Office 自动化注意事项”
http://support.microsoft.com/kb/257757/
文档似乎明确了
Microsoft 目前建议不要从任何无人参与的、非交互式客户端应用程序或组件(包括 ASP、DCOM 和 NT Service)中进行 Microsoft Office 应用程序的“自动化”,也不为此提供支持,因为 Office 在这种环境中运行时可能会出现不稳定的现象并且/或者会死锁。

因为我主要的用途就是用来服务器端自动转换。
待仔细研读。
  • 大小: 23.2 KB
  • 大小: 41.5 KB
   发表时间:2011-04-17  
因为使用WORD转PDF的效果是OpenOffice无法比拟的,虽然有诸多问题,还是想要采用。

因为已知的问题:
1、转换速度慢;
2、CPU占用率高(单CPU占用100%)
3、并发情况下WORD可能会死锁(微软知识库)
4、Word宏安全问题;
5、还有一些未知的细节。

目前的打算是采用一个独立服务器,定时扫描需要转换文档的数据库表,
一旦有任务就执行转换,转换完再取下一条数据。
这样的话1/2/3条都不成问题了。
0 请登录后投票
   发表时间:2011-04-18  
1\2\3 跟转换的有关系。

4、可以对宏进行签名,解决安全问题。
-----------------------------------
你可以咨询我任何office dev相关的问题。

另外,对你的几个建议
1、office不支持ole,可以通过dsoframer来做
2、office在com方式下使用,容易出现无法release的问题。特别是excel,
因为excel的进程模型跟其他的不太一样。
这个有办法处理强制解决。

还有一个转换办法:
使用office的print功能,而不是saveaspdf插件。
然后指定pdf reader自带的pdf打印机来生成文档。


当然,这些方式,都依赖了office。
0 请登录后投票
   发表时间:2011-04-18  
TO kimmking:
非常感谢。
OLE是我前面写错了,目前暂不需要嵌入编辑界面,只需要后台运行Office就可以了。

如果用Office做后台转换的话,转换速度慢、CPU占用100%的问题还有什么好的办法来应对吗?

宏的问题,我主要担心恶意的宏对系统安全造成危害。
有什么办法来解决吗?Office我的使用还比较初级,呵呵

使用office的print功能,比使用saveas有哪些优势吗?
使用saveas只需要依赖office,使用print,依赖的环境不是更多了吗?

另外,关于你说的:
kimmking 写道

2、office在com方式下使用,容易出现无法release的问题。特别是excel,
因为excel的进程模型跟其他的不太一样。
这个有办法处理强制解决。


非常有兴趣知道,期待你的分享。
0 请登录后投票
   发表时间:2011-06-09  
在ppt转换为pdf时,visible可否有什么方法设置为false?
用setProperty尝试了下,提示不允许:Hiding the application window is not allowed。
0 请登录后投票
   发表时间:2011-06-09  
xiangziwade 写道
在ppt转换为pdf时,visible可否有什么方法设置为false?
用setProperty尝试了下,提示不允许:Hiding the application window is not allowed。


app = new ActiveXComponent("Powerpoint.Application");
// app.setProperty("Visible", true);
System.out.println(app.getProperty("Visible"));


new一个Powerpoint.Application时,Visible已经是false了。
MsoTriState 枚举.msoFalse的值是0,和打印出来的相同。
反而是如果调用setProperty("Visible", true);Powerpoint的窗口才会显示出来。

不过一个问题是 另存的时候,还是会有一个发布的进度框显示出来,还不知道该怎样把它隐藏掉。
public class Test {
static final int ppSaveAsPDF = 32;// PDF 格式

public static void main(String[] args) {

	String filename = "f:/aaaaa.ppt";
	String toFilename = filename + ".pdf";
	System.out.println("启动...");
	long start = System.currentTimeMillis();
	ActiveXComponent app = null;
	try {
		app = new ActiveXComponent("Powerpoint.Application");
		// app.setProperty("Visible", true);
		System.out.println(app.getProperty("Visible"));

		Dispatch presentations = app.getProperty("Presentations").toDispatch();
		System.out.println("打开文档..." + filename);
		Dispatch presentation = Dispatch.call(presentations,//
				"Open", //
				filename,// FileName
				true,// ReadOnly
				true,// Untitled 指定文件是否有标题。
				false // WithWindow 指定文件是否可见。
				).toDispatch();

		System.out.println("转换文档到PDF..." + toFilename);
		File tofile = new File(toFilename);
		if (tofile.exists()) {
			tofile.delete();
		}
		Dispatch.call(presentation,//
				"SaveAs", //
				toFilename, // FileName
				ppSaveAsPDF);

		Dispatch.call(presentation, "Close");
		long end = System.currentTimeMillis();
		System.out.println("转换完成..用时:" + (end - start) + "ms.");
	} catch (Exception e) {
		System.out.println("========Error:文档转换失败:" + e.getMessage());
	} finally {
		if (app != null) app.invoke("Quit");
	}
}

0 请登录后投票
   发表时间:2011-06-09  
装个PDF打印机就可以了,win7默认有XPS打印机,win8应该同时支持xps和PDF
0 请登录后投票
   发表时间:2011-06-09  
原来如此啊,非常感谢!
Dispatch.call()的情况好复杂。。。

另外,这些常数是如何定义的呢?
static final int wdFormatPDF = 17;// PDF 格式
static final int ppSaveAsPDF = 32;// PDF 格式

对于ppt貌似设置成16到19之间,可以直接转换成图片。
不知对于word有没有类似的情况?
0 请登录后投票
   发表时间:2011-06-10  
xiangziwade 写道
原来如此啊,非常感谢!
Dispatch.call()的情况好复杂。。。

另外,这些常数是如何定义的呢?
static final int wdFormatPDF = 17;// PDF 格式
static final int ppSaveAsPDF = 32;// PDF 格式

对于ppt貌似设置成16到19之间,可以直接转换成图片。
不知对于word有没有类似的情况?


sswh 写道
获取了Dispatch之后,即可调用该自动化对象的属性或方法,具体的属性和方法要看参考文档,比如:Word开发可在WORD帮助中查看“脱机开发人员帮助WORD对象模型”。






  • 大小: 44.8 KB
  • 大小: 106.4 KB
0 请登录后投票
   发表时间:2011-06-10  
再次感谢您不吝赐教!!!

查看了一下,word貌似还真没有控制直接存为图片的参数。。。

另外,有没有什么 不依赖于office2007 来转换word2003到pdf(或者图片)的方法?
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics