docx4j
三丰 soft张三丰
docx4j介绍
官方网站:http://www.docx4java.org/trac/docx4j
下载地址:http://www.docx4java.org/downloads.html
入门指南:Getting Started guide(PDF)(HTML)
得益于天朝伟大的GFW,docx4j的官方站点有时可能需要挂代理才能访问。
官方介绍:
docx4j is a Java library for creating and manipulating Microsoft Open XML (Word docx, Powerpoint pptx, and Excel xlsx) files.
It is similar to Microsoft's OpenXML SDK, but for Java.
docx4j uses JAXB to create the in-memory object representation.
It is available under the Apache License (v2).
docx4j was created by Plutext Pty Ltd in 2008 - using OpenXML4J for the OPC piece. Plutext still drives the project, but since then docx4j has benefited from contributions from many individuals. The contributors are listed in docx4j's pom.xml.
docx4j能做什么
-
打开已存在docx(从文件系统、SMB/CIFS、使用VFS的WebDAV),pptx,xlsx
-
创建新的docx、pptx、xlsx
-
编程式地操作上面打开的文档(很显示) docx4j特殊的功能支持:
-
模版替换;CustomXML绑定
-
生产/消费Word2007的xmlPackage(pkg)格式
-
作为docx保存docx到文件系统(zipped)或者保存到JCR(unzipped)
-
应用转换,包括常见过滤器
-
作为HTML或者PDF导出
-
比较文档、段落或者sdt(内容控件)之间的差异
-
字体支持(字体替换及使用任何文档中嵌入的字体) 具体的使用技巧请看前面提到的几篇博客以及docx4j的入门指南,这里仅列出几个自己了解而前面博客没有提到的使用技巧:合并docx文档和转换PDF。
合并多个docx文档
现在所做的项目中,需要合并多个docx文档,这让我纠结了很长一段时间;其实在docx4j的基础上,作者还提供了合并多个docx文档的lib,但那是需要商业授权的,所以没法使用,但后来在docx4j的forum中看到了其他人提供的解决方案,详情如下:
public InputStream mergeDocx(final List<InputStream> streams)
throws Docx4JException, IOException {
WordprocessingMLPackage target = null;
final File generated = File.createTempFile("generated", ".docx");
int chunkId = 0;
Iterator<InputStream> it = streams.iterator();
while (it.hasNext()) {
InputStream is = it.next();
if (is != null) {
if (target == null) {
// Copy first (master) document
OutputStream os = new FileOutputStream(generated);
os.write(IOUtils.toByteArray(is));
os.close();
target = WordprocessingMLPackage.load(generated);
} else {
// Attach the others (Alternative input parts)
insertDocx(target.getMainDocumentPart(),
IOUtils.toByteArray(is), chunkId++);
}
}
}
if (target != null) {
target.save(generated);
return new FileInputStream(generated);
} else {
return null;
}
}
// 插入文档
private void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) {
try {
AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(
new PartName("/part" + chunkId + ".docx"));
afiPart.setContentType(new ContentType(CONTENT_TYPE));
afiPart.setBinaryData(bytes);
Relationship altChunkRel = main.addTargetPart(afiPart);
CTAltChunk chunk = Context.getWmlObjectFactory().createCTAltChunk();
chunk.setId(altChunkRel.getId());
main.addObject(chunk);
} catch (Exception e) {
e.printStackTrace();
}
}
docx文档转换为PDF
在做docx转换PDF时让我为难了好长一阵子,因为中文导致乱码,官方示例中是有这一部分内容的,但由于注释太少,所以一直没有注意到,后来才发现示例的作者将字体相关的两句代码注释掉了:
// Set up font mapper
// Mapper fontMapper = new BestMatchingMapper();
// wordMLPackage.setFontMapper(fontMapper);
在将这段代码加上之后,中文乱码没有了,但是好像除了“宋体”以外的其它字体还会乱码,比如:华文行楷、隶书之类的,要解决这些问题,需要多做点工作:
Mapper fontMapper = new IdentityPlusMapper();
fontMapper.getFontMappings().put("华文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));
// 其它中文字体
mlPackage.setFontMapper(fontMapper);
// 然后再创建转换器
PdfConversion conversion = new Conversion(mlPackage);
完整方法代码:
/**
* docx文档转换为PDF
* @param docx docx文档
* @param pdfPath PDF文档存储路径
* @throws Exception 可能为Docx4JException, FileNotFoundException, IOException等
*/
public void convertDocxToPDF(File docx, String pdfPath) throws Exception {
OutputStream os = null;
try {
WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(docx);
// Mapper fontMapper = new BestMatchingMapper();
Mapper fontMapper = new IdentityPlusMapper();
fontMapper.getFontMappings().put("华文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));
fontMapper.getFontMappings().put("华文仿宋", PhysicalFonts.getPhysicalFonts().get("STFangsong"));
fontMapper.getFontMappings().put("隶书", PhysicalFonts.getPhysicalFonts().get("LiSu"));
mlPackage.setFontMapper(fontMapper);
PdfConversion conversion = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(mlPackage);
os = new FileOutputStream(pdfPath);
conversion.output(os, new PdfSettings());
} finally {
IOUtils.closeQuietly(os);
}
}
另外,docx4j还支持通过iTtext将docx文档转换为PDF,不过好像只能支持iText2.X版本,新版本不能用!
其实这样转换好像还不够完美,比如页眉页脚、目录什么的,都会出乱子;由于项目中word文档较为复杂,最终没有采用docx4j做PDF转换,换成了jacob......