docx4j基本操作


最近需要用docx4j来对docx进行一些操作,用到的技术是docx4j,这个技术在国内其实用的不是很多,看了一些博主的文章,有些感悟,做了一些总结,如果有疑问或错误之处欢迎交流。

创建包:

WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(); 

保存包:

wordMLPackage.save(new java.io.File("C://xxx.docx")); 

得到主段落,并且输出/带样式输出:

MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart(); wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!"); wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello Word!"); wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Subtitle"," a subtitle!"); 

创建表格并添加内容:

ObjectFactory factory=Context.getWmlObjectFactory(); Tbl table = factory.createTbl(); Tr tableRow = factory.createTr(); Tc tableCell = factory.createTc(); tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText("Field 1")); tableRow.getContent().add(tableCell); table.getContent().add(tableRow); wordMLPackage.getMainDocumentPart().addObject(table); 

先创建一个工厂,(需要导入的包是org.docx4j.wml,导错的的话下面全错)创建表格,在创建行和单元格(tableCell),在单元格里添加你想要的内容,因为返回值是Object,只能通过这种方式传入数据,最后层层退回去,用add添加,最后在主段落添加。

编辑表格样式:

table.setTblPr(new TblPr()); CTBorder border = new CTBorder(); border.setColor("auto"); border.setSz(new BigInteger("4")); TblBorders borders = new TblBorders(); borders.setBottom(border); borders.setLeft(border); borders.setInsideV(border); table.getTblPr().setTblBorders(borders); 

先创建table样式对象,在用CTBorder对象规定样式规范,用TblBorders对象将样式规范应用进去。

创建 段落/运行块/运行块属性/文本 对象:

ObjectFactory factory=Context.getWmlObjectFactory(); P paragraph = factory.createP(); Text text = factory.createText(); text.setValue(content); R run = factory.createR(); run.getContent().add(text); paragraph.getContent().add(run); RPr runProperties = factory.createRPr(); run.setRPr(runProperties); tableCell.getContent().add(paragraph); 

P是一个段落,Text是文本的值对象,R是一个运行块,负责便于将多个属性相同的Text对象统一操作,RPr是运行块的属性,可以对R对象进行操作。简单的说几个对象之间的关系可以这么理解:Tc tableCell > P paragraph > R run > Text text。其中,run.setRPr(RPr runProperties)可以设置块中属性。个人认为用开始的方法输入内容,在某种程度上是和上述代码做了一样的工作,效果相同。 
加粗字体和调整字体大小:

HpsMeasure size = new HpsMeasure(); size.setVal(new BigInteger("40")); runProperties.setSz(size); runProperties.setSzCs(size); BooleanDefaultTrue b = new BooleanDefaultTrue(); b.setVal(true); runProperties.setB(b); 

思路是先创建各自的对象,设置对象的值为自己想要的情况,再用RPr的对象来set相应的属性。其中注意setVal中的值最后会被现实一半,所以只有字体20大小。

纵向合并单元格:

Tc tableCell = factory.createTc(); TcPr tableCellProperties = new TcPr(); VMerge merge = new VMerge(); merge.setVal("restart"); tableCellProperties.setVMerge(merge); tableCell.setTcPr(tableCellProperties); tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(content)); row.getContent().add(tableCell);

先创建单元格属性,再创建VMerge对象,如果设置merge则为向上合并,如果将merge属性设为restart则重新开始新的单元格。

设置单元格宽度:

TcPr tableCellProperties = new TcPr(); TblWidth tableWidth = new TblWidth(); tableWidth.setW(BigInteger.valueOf("50")); tableCellProperties.setTcW(tableWidth); tableCell.setTcPr(tableCellProperties);

先创建单元格属性对象,创建Tblwidth对象并且设置宽度,用单元格属性对象通过方法调用Tblwidth对象。

添加图片:

File file = new File("c:\\a.jpg"); BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, file); int docPrId = 1; int cNvPrId = 2; Inline inline = imagePart.createImageInline("Filename hint","Alternative text", docPrId, cNvPrId, false); ObjectFactory factory = new ObjectFactory(); P paragraph = factory.createP(); R run = factory.createR(); paragraph.getContent().add(run); Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); wordMLPackage.getMainDocumentPart().addObject(paragraph);

打开文件,通过imagePart将图片读进去,现在图片被转换成二进制,为了能在文件中内联中显示出图片,调用函数将图片存在inline中。之后paragraph,run,drawing,用drawing读inline,方法同上。

加载读入docx文件:

WordprocessingMLPackage template = WordprocessingMLPackage.load(new File("c:\\a.docx"));

获取文档中所有内容(方法):

private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) { List<Object> result = new ArrayList<Object>(); if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue(); if (obj.getClass().equals(toSearch)) result.add(obj); else if (obj instanceof ContentAccessor) { List<?> children = ((ContentAccessor) obj).getContent(); for (Object child : children) { result.addAll(getAllElementFromObject(child, toSearch)); } } return result; } 

通过对类型的判断,将obj的内容分类读到List中,最后将内容按照列表的顺序贮存,如果obj是JAXB的一个实例就将他转型获取值,如果是和第二个参数的类型相同就添加,如果是ContentAccessor的一个对象,就将对象中的内容存到另外的一个列表中,再次调用自己将全部元素添加到原来的List中,返回一个List。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM