docx文件转pdf,使用aspose words 转pdf,并且解决表格格式错乱
最近遇到一个问题,需要将数据动态生成pdf文件。于是我毫不犹豫的使用poi,计划先将数据写入docx文件,然后再实现docx文件转pdf。就这样,当天我的docx文件已经生成,并且把各种格式,字体,颜色,表格,表格边距等等属性调整完毕,下一步就是转换pdf了(注:不是摸板信息回填,而是根据程序中表单的格式,内容,审批流程等等信息自动生成docx文件,然后提供线下备份及打印功能等等。。。。。。)。然而,理想是丰满的,现实是骨感的。使用poi系列工具类转pdf后,格式一下子就爆炸了,百度了一圈最终放弃,只能另选出路了。
之后,陆续选择了几种转换工具,比如:documents4j,expire,aspose,itextpdf。都尝试过,略微说下使用感受。
1,documents4j
依赖于windows系统和office。使用过程中经常出现 FileInputStream 流信息中断异常,这可能是因为我再使用poi生成的doc文件中存在无法解析的字符,导致officeWord无法正常打开文件,解决这个问题让我头发,果断放弃。然而这也不是主要原因,如果使用该工具,那么我后续就得考虑服务器的问题了,windows系统和office呵呵。。。
2,expire
看了官网介绍,免费的版本只能转换3页,大概记得是这样。总之远远不能满足我的需要,直接忽视。
3,itextpdf
转换之后的pdf格式混乱,字体混乱。使用了一次就果断放弃,没有深入探索。
4,aspose
最终选择aspose,主要是使用方便,能满足我的需要,目前功能已上线,在服务器上运行正常,转换之后格式无偏差,字体显示饱满,特别是表格和图片的处理,就是我需要的。
大概介绍了我选择aspose的原因,大多是个人使用感受。当然,会有其他实现pdf转换的方法或者工具,也有大神可以使用itextpdf实现无偏差转换,或者是有其他看法的。我只是自抒己见而已,勿嘲 勿喷。
接下来介绍aspose 的简单使用
一,依赖下载
阿里云仓库无镜像文件,需要手动下载jar包,然后本地mvn引入依赖
该依赖仅限于学习使用。。。。。
其他版本,可至官网下载。
1,下载jar包
下载地址,提取码:buaz
2,pom中引入依赖
<dependency>
<groupId>com.aspose.words</groupId>
<artifactId>aspose-words</artifactId>
<version>19.5</version>
</dependency>
3,mnv导入本地jar包
mvn install:install-file -DgroupId=com.aspose.words -DartifactId=aspose-words -Dversion=19.5 -Dpackaging=jar -Dfile=写入文件所在地址
二,工具类的使用
1,取消水印处理
将如下代码,写入xml文件中,并且存在到resource路径下,具体位置随意,之后引入即可。
<?xml version="1.0" encoding="UTF-8"?>
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
图片:
图片上传失败,懒得弄,自己脑补吧。
写一个方法读取xml信息
public static boolean getLicense() {
boolean result = false;
InputStream is = null;
try {
Resource resource = new ClassPathResource("static/license.xml");
is = resource.getInputStream();
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
2,实现方法
1,调用去水印方法
getLicense()
2,使用document读取docx文件
Document doc = new Document(new FileOutputStream(new File("文件路径")));
3,写出pdf文件
document.save(new FileOutputStream(new File("输出的pdf地址"), SaveFormat.PDF)
大体上就这么简单。。。。。。。。。。。。。
三,解决表格格式错乱
表格格式混乱,我遇到的就三种
1,在docx文件中表格宽度是100%,自动适应页面宽度。然而转换成pdf后宽度变了,不能铺满页面,也许还更窄,懒得去截图了,这里就不上图了,遇到类似问题的朋友,估计你能很快脑补出来,总之就是你的表格缩水了。
解决方法:在docx文件中设置表格的宽度为固定值,这里我是在poi中设置的,如下:
XWPFTable table = doc.createTable(rows, cols);
table.setWidthType(TableWidthType.DXA);
当然,你也可以手动打开文件,然后进行设置。
2,表格的单元格内容过长后会把整个单元格撑爆,然后连锁反应,使得整个表格超出了页面。
解决方法:这里我之前勿以为是单元格的宽度没有固定死导致的,其实是单元格内容自动换行的问题,查找了poi文档,未能找到自动换行属性的设置,因为poi默认就是自动换行的。
在我把所有目光放在使用使用poi调整格式中,我截然忘记了 Document 这个aspose提供给我们的对象,这个对象也是用来操作文档的,呵呵 活该是个死搬代码。。。。。。。。。
<————————————–
这里需要解释一下为什么转pdf后格式会混乱,我个人认为在document对象读取文件后,某些自定义的属性是没有被写在ooxml文件中的,就比如这个单元格内自动换行。这里我百度后有人说在读取文件后,进行一次复制,并且设置全格式复制模式可以解决,我试过,没成功。
Document doc = new Document(inPath); // 使用document打开一个文件对象
Document document = new Document();//新创建一个对象
document.removeAllChildren();
document.appendDocument(doc, ImportFormatMode.USE_DESTINATION_STYLES);//保留样式复制
注意,上面这个方法我使用过,没卵用。。。。。。。。。
往下看
———————–>
我们要相信科学,既然没有设置这个属性,那么没有就是没有,别死撑着,使用document设置一下就有了。
File file = new File(outPath); // 新建一个空白pdf文档
os = new FileOutputStream(file);
Document document = new Document(inPath); // Address是将要被转化的word文档
TableCollection tables = document.getFirstSection().getBody().getTables();
for (Table table : tables) {
RowCollection rows = table.getRows();
table.setAllowAutoFit(false);
for (Row row : rows) {
CellCollection cells = row.getCells();
for (Cell cell : cells) {
CellFormat cellFormat = cell.getCellFormat();
cellFormat.setFitText(false); //设置自适应关闭
cellFormat.setWrapText(true); // 设置自动换行
}
}
}
document.save(os, SaveFormat.PDF);
同理,如果你在使用aspose words进行pdf转换的过程中,遇到的格式错乱。千万别犹豫,使用document对象,盘他。
我呢是由于前期使用了poi导出docx文件,其中涉及的样式及数据整理有些复杂,不愿意切换成document,如果你目前有条件的话,我建议试试使用aspose提供的 document对象直接进行操作,应该不会让你失望。
最后,提供下我的util文件
package com.xxx.xx.xxx.common.utils;
import com.aspose.words.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class WordToPdfUtil {
public static boolean getLicense() {
boolean result = false;
InputStream is = null;
try {
Resource resource = new ClassPathResource("static/license.xml"); // xml文件地址
is = resource.getInputStream();
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public static boolean docxToPdf(String inPath, String outPath) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return false;
}
FileOutputStream os = null;
try {
long old = System.currentTimeMillis();
File file = new File(outPath); // 新建一个空白pdf文档
os = new FileOutputStream(file);
Document document= new Document(inPath); // Address是将要被转化的word文档
TableCollection tables = document.getFirstSection().getBody().getTables();
for (Table table : tables) {
RowCollection rows = table.getRows();
table.setAllowAutoFit(false);
for (Row row : rows) {
CellCollection cells = row.getCells();
for (Cell cell : cells) {
CellFormat cellFormat = cell.getCellFormat();
cellFormat.setFitText(false);
cellFormat.setWrapText(true);
}
}
}
document.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
// EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
} catch (Exception e) {
e.printStackTrace();
return false;
}finally {
if (os != null) {
try {
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
}