Java中docx、xlsx、pptx转pdf的方法

hoxiansen

一、Windows环境调用Office或者WPS的COM接口

引入jacob依赖

  1. 下载jacob-1.20依赖包 并解压
  2. 将其中的jar包安装到maven本地仓库(也可以直接在项目中引入jar包依赖)
    1
    2
    3
    4
    5
    mvn install:install-file 
    -Dfile=</your/path/to/jacob.jar>
    -DgroupId=com.jacob
    -DartifactId=jacob
    -Dversion=1.20 -Dpackaging=jar
  3. 把jacob-1.20-x64.dll和jacob-1.20-x86.dll拷贝至%JAVA_HOME%\jre\bin目录

关于jacob的更多使用方式,可以参考MicroSoft的VBA文档

转换代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
public class JacobToPdfUtil {
/**
* 转PDF格式值
*/
private static final int WORD_FORMAT_PDF = 17;
private static final int EXCEL_FORMAT_PDF = 0;
private static final int PPT_FORMAT_PDF = 32;

private static final String PROGRAM_WORD_OFFICE = "Word.Application";
private static final String PROGRAM_WORD_WPS = "KWPS.Application";
private static final String PROGRAM_EXCEL_OFFICE = "Excel.Application";
private static final String PROGRAM_EXCEL_WPS = "KET.Application";
private static final String PROGRAM_PPT_OFFICE = "PowerPoint.Application";
private static final String PROGRAM_PPT_WPS = "KWPP.Application";

public static void wordToPdfByMsOffice(String inputFile, String pdfFile) throws IOException {
wordToPdf(inputFile, pdfFile, PROGRAM_WORD_OFFICE);
}

public static void wordToPdfByWps(String inputFile, String pdfFile) throws IOException {
wordToPdf(inputFile, pdfFile, PROGRAM_WORD_WPS);
}

private static void wordToPdf(String inputFile, String pdfFile, String program) throws IOException {
ActiveXComponent app = null;
Dispatch doc = null;
try {
// 创建一个word对象
app = new ActiveXComponent(program);
// 不可见打开word
app.setProperty("Visible", new Variant(false));
// 禁用宏
app.setProperty("AutomationSecurity", new Variant(3));
// 获取文挡属性
Dispatch docs = app.getProperty("Documents").toDispatch();
// 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document
doc = Dispatch.call(docs, "Open", inputFile).toDispatch();
// word保存为pdf格式宏,值为17
Dispatch.call(doc, "SaveAs", pdfFile, WORD_FORMAT_PDF);
} catch (Throwable t) {
throw new IOException("word转pdf失败", t);
} finally {
if (doc != null) {
Dispatch.call(doc, "Close", false);
}
if (app != null) {
app.invoke("Quit");
}
// 关闭WINWORD.exe进程
ComThread.Release();
}
}

public static void excelToPdfByMsOffice(String inputFile, String pdfFile) throws IOException {
excelToPdf(inputFile, pdfFile, PROGRAM_EXCEL_OFFICE);
}

public static void excelToPdfByWps(String inputFile, String pdfFile) throws IOException {
excelToPdf(inputFile, pdfFile, PROGRAM_EXCEL_WPS);
}

private static void excelToPdf(String inputFile, String pdfFile, String program) throws IOException {
ActiveXComponent app = null;
Dispatch excel = null;
try {
app = new ActiveXComponent(program);
// 不可见打开excel
app.setProperty("Visible", new Variant(false));
// 禁用宏
app.setProperty("AutomationSecurity", new Variant(3));
Dispatch workbooks = app.getProperty("Workbooks").toDispatch();
excel = Dispatch.call(workbooks, "Open", inputFile).toDispatch();
Dispatch.call(excel, "ExportAsFixedFormat", EXCEL_FORMAT_PDF, pdfFile);
} catch (Throwable t) {
throw new IOException("excel转pdf失败", t);
} finally {
if (excel != null) {
Dispatch.call(excel, "Close", false);
}
if (app != null) {
app.invoke("Quit");
}
// 关闭WINWORD.exe进程
ComThread.Release();
}
}

public static void pptToPdfByMsOffice(String inputFile, String pdfFile) throws IOException {
pptToPdf(inputFile, pdfFile, PROGRAM_PPT_OFFICE);
}

public static void pptToPdfByWps(String inputFile, String pdfFile) throws IOException {
pptToPdf(inputFile, pdfFile, PROGRAM_PPT_WPS);
}

private static void pptToPdf(String inputFile, String pdfFile, String program) throws IOException {
ActiveXComponent app = null;
Dispatch ppt = null;
try {
// 创建一个ppt对象
app = new ActiveXComponent(program);
// 不能设置Visible=false。Hiding the application window is not allowed.
// 禁用宏
app.setProperty("AutomationSecurity", new Variant(3));
// 获取文挡属性
Dispatch presentations = app.getProperty("Presentations").toDispatch();
// 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document
// 文档:https://learn.microsoft.com/zh-cn/office/vba/api/powerpoint.presentations.open
ppt = Dispatch.call(presentations, "Open", inputFile,
true, // ReadOnly
false, // Untitled指定文件是否有标题
false // WithWindow指定文件是否可见
).toDispatch();
Dispatch.call(ppt, "SaveAs", pdfFile, PPT_FORMAT_PDF);
} catch (Throwable t) {
throw new IOException("ppt转换pdf失败", t);
} finally {
if (ppt != null) {
Dispatch.call(ppt, "Close");
}
if (app != null) {
app.invoke("Quit");
}
// 关闭WINWORD.exe进程
ComThread.Release();
}
}
}

二、Linux环境调用LibreOffice

安装LibreOffice

  1. LibreOffice下载页 下载对应Linux发行版的LibreOffice。
  2. 解压后安装。
    1
    sudo dpkg -i DEBS/*.deb
    或者
    1
    sudo yum install /RPMS/*.rpm
  3. 增加中文字体,不然转换时中文会乱码。

    1
    2
    # 检查系统中是否有中文字体
    fc-list :lang=zh
    如果返回空,请按照这个文档 去安装中文字体。
  4. 安装完成之后运行一下libreoffice7.3 --help,可能会提示库找不到。我在CentOS7系统安装时就遇到了libcairo.so.2,libcups.so.2,libSM.so.6这三个库找不到的问题,执行下面几条命令安装需要的库:
    1
    2
    3
    yum install cairo -y
    yum install cups-libs -y
    yum install libSM -y
    如果遇到其他库找不到的问题可以参考上面解决。

转换代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class LibreOfficeToPdfUtil {
public static void toPdf(String inputFile, String pdfFile) throws BootstrapException, Exception {
XComponentContext context = Bootstrap.bootstrap();
XMultiComponentFactory serviceManager = context.getServiceManager();
Object desktop = serviceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context);
XDesktop xDesktop = UnoRuntime.queryInterface(XDesktop.class, desktop);

XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, xDesktop);
PropertyValue hidden = new PropertyValue();
hidden.Name = "Hidden";
hidden.Value = Boolean.TRUE;
XComponent xComponent = xComponentLoader.loadComponentFromURL("file:///" + inputFile, "_blank", 0, new PropertyValue[]{hidden});


XStorable xStorable = UnoRuntime.queryInterface(XStorable.class, xComponent);
PropertyValue overwrite = new PropertyValue();
overwrite.Name = "Overwrite";
overwrite.Value = Boolean.TRUE;
PropertyValue filterName = new PropertyValue();
filterName.Name = "FilterName";
filterName.Value = "writer_pdf_Export";
xStorable.storeToURL("file:///" + pdfFile, new PropertyValue[]{overwrite, filterName});


xDesktop.terminate();
}
}

运行时报错解决

  1. com.sun.star.comp.helper.BootstrapException: no office executable found!
    解决办法:添加java参数-Xbootclasspath/a:/opt/libreoffice7.3/program/
    原因:启动时会从classpath中寻找soffice文件,所以得把soffice所在目录加到classpath中。

    可以通过readlink `which libreoffice7.3`看libreoffice安装在哪个目录。

  2. 点运行后一直等待,5分钟后抛出BootstrapException异常
    原因:libreoffice进程启动失败。
    解决办法:可以在命令行运行一下libreoffice看看是否缺少库,然后参考上面安装步骤解决。

  3. 转换之后的pdf中文显示方框
    原因:系统中缺少中文字体。
    解决办法:参考安装步骤添加中文字体。

参考文档:

  1. linux安装libreOffice
  2. Convert Microsoft Word to PDF - using Java and LibreOffice (UNO API)
  3. Java中常用的几种DOCX转PDF方法
  • 标题: Java中docx、xlsx、pptx转pdf的方法
  • 作者: hoxiansen
  • 创建于: 2023-01-08 13:13:58
  • 更新于: 2023-06-15 11:00:59
  • 链接: https://hoxiansen.top/2023/01/08/Java中docx、xlsx、pptx转pdf的方法/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论