最近项目中遇到很多对word/excel/pdf等文件的操作,解决方案有好多,开源免费有:利用openoffice组件(需要安装openoffice软件),poi,itext等。也有收费的服务:aspose(特别好用,也有点贵)。
我项目中需求可以概括为导出word(包括文字,表格,图片),把pdf插入到word,word之间的合并。
这里按需求介绍一下我走通的技术方案:
导出word 可以使用poi,aspose。(其实poi操作word还是有些不方便的,用itext好一些,当然aspose都可以干,只不过要花钱!!)
关于这方面的资料挺少的,api都挺好使用的,只不过一开始面对忙忙多的类,会有无从下手的感觉,特再此说明一些关键操作类。
无论采用哪种类库,他们大致步奏是一样的。一般都是新建一个段落,获取画笔。(由于本文主要提供技术方案及操作步奏,具体代码就不提供了,读者可以根据作者思路及官方api进行操作)
poi操作word:poi操作word把doc/docx是分开的,创建word对象后,便可create paragraph(段落)了,在从paragraph.createRun(),获取画笔XWPFRun(我称为画笔),便可run设置文字字体,大小,通过setText()方法,变可以写入文字。
生成表格,paragraph.createTable(),可以在create时声称table的大小,也可以动态添加行和列。
插入图片:poi插入图片有点问题,下面重写了XWPFDocuemnt的插入图片方法,读者可以使用自己类代替自带的XWPFDocument进行docx的操作
public class CustomXWPFDocument extends XWPFDocument {
public CustomXWPFDocument(InputStream in) throws IOException {
super(in);
}
/**
*
*/
public CustomXWPFDocument() {
super();
// TODO Auto-generated constructor stub
}
/**
* @param pkg
* @throws IOException
*/
public CustomXWPFDocument(OPCPackage pkg) throws IOException {
super(pkg);
// TODO Auto-generated constructor stub
} // picAttch 图片后面追加的字符串 可以是空格
public void createPicture(XWPFParagraph paragraph,int id, int width, int height,String picAttch) {
final int EMU = 9525;
width *= EMU;
height *= EMU;
String blipId = getAllPictures().get(id).getPackageRelationship()
.getId();
CTInline inline = paragraph.createRun().getCTR()
.addNewDrawing().addNewInline();
paragraph.createRun().setText(picAttch);
String picXml = ""
+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
+ " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ " <pic:nvPicPr>" + " <pic:cNvPr id=\""
+ id
+ "\" name=\"Generated\"/>"
+ " <pic:cNvPicPr/>"
+ " </pic:nvPicPr>"
+ " <pic:blipFill>"
+ " <a:blip r:embed=\""
+ blipId
+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
+ " <a:stretch>"
+ " <a:fillRect/>"
+ " </a:stretch>"
+ " </pic:blipFill>"
+ " <pic:spPr>"
+ " <a:xfrm>"
+ " <a:off x=\"0\" y=\"0\"/>"
+ " <a:ext cx=\""
+ width
+ "\" cy=\""
+ height
+ "\"/>"
+ " </a:xfrm>"
+ " <a:prstGeom prst=\"rect\">"
+ " <a:avLst/>"
+ " </a:prstGeom>"
+ " </pic:spPr>"
+ " </pic:pic>"
+ " </a:graphicData>" + "</a:graphic>";
// CTGraphicalObjectData graphicData =
inline.addNewGraphic().addNewGraphicData();
XmlToken xmlToken = null;
try {
xmlToken = XmlToken.Factory.parse(picXml);
} catch (XmlException xe) {
xe.printStackTrace();
}
inline.set(xmlToken);
// graphicData.set(xmlToken);
inline.setDistT(0);
inline.setDistB(0);
inline.setDistL(0);
inline.setDistR(0);
CTPositiveSize2D extent = inline.addNewExtent();
extent.setCx(width);
extent.setCy(height);
CTNonVisualDrawingProps docPr = inline.addNewDocPr();
docPr.setId(id);
docPr.setName("图片" + id);
docPr.setDescr("");
}
}
使用createPicture方法便可以插入图片了。
存储word:XWPFDocument有write方法,我们可以提供了FileOutputStream,便可直接保存了。
aspose操作word:aspose真心好用,毕竟收费还这么贵,首先通过Document实例化一个word对象(doc/docx)都可以,然后获取DocumentBuilder(我称之为画笔),接下来所有的操作,包括画表格都有它来完成,跟poi的使用还有点不一样的,写入文字,表格,图片都是基于builder完成的,write是写入文字的做法。
这里跟poi有一个很大的不同,假设我们需要有个文字加黑操作,poi在加黑和不加黑就需要两个run来处理,而aspose只需要用同一个builder来处理就好,builder.setBlod(),完全不影响该builder画出的全部数据。
下面在来讲讲pdf插入word,合并word的操作。
很遗憾,poi/aspose.word是不支持直接插入pdf的,我这里采用了pdfbox库先将pdf转为图片,然后将图片插入到word中。
word合并:aspose是直接支持合并word的,Document.append()方法直接合并。