最近需要用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。

docx4j基本操作的更多相关文章

  1. Java中的Html解析:使用jsoup

    包:jsoup-1.10.2.jar import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import o ...

  2. Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作

    一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...

  3. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  4. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  5. 三、Redis基本操作——List

    小喵的唠叨话:前面我们介绍了Redis的string的数据结构的原理和操作.当时我们提到Redis的键值对不仅仅是字符串.而这次我们就要介绍Redis的第二个数据结构了,List(链表).由于List ...

  6. 二、Redis基本操作——String(实战篇)

    小喵万万没想到,上一篇博客,居然已经被阅读600次了!!!让小喵感觉压力颇大.万一有写错的地方,岂不是会误导很多筒子们.所以,恳请大家,如果看到小喵的博客有什么不对的地方,请尽快指正!谢谢! 小喵的唠 ...

  7. 一、Redis基本操作——String(原理篇)

    小喵的唠叨话:最近京东图书大减价,小喵手痒了就买了本<Redis设计与实现>[1]来看看.这里权当小喵看书的笔记啦.这一系列的模式,主要是先介绍Redis的实现原理(可能很大一部分会直接照 ...

  8. Linq查询基本操作

    摘要:本文介绍Linq查询基本操作(查询关键字) - from 子句 - where 子句 - select子句 - group 子句 - into 子句 - orderby 子句 - join 子句 ...

  9. C++ map的基本操作和使用

    原文地址:http://blog.sina.com.cn/s/blog_61533c9b0100fa7w.html Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可 ...

随机推荐

  1. 【转载】C# 快速高效率复制对象另一种方式 表达式树

    1.需求 在代码中经常会遇到需要把对象复制一遍,或者把属性名相同的值复制一遍. 比如: public class Student { public int Id { get; set; } publi ...

  2. 初识Comet技术

    一.服务器推送技术概述 服务器推送技术(Servers Push)的基础思想是将浏览器主动查询信息改为服务器主动发送信息.服务器发送一批数据,浏览器显示这些数据,同时保证与服务器的连接.当服务器需要再 ...

  3. 直接拿来用!最火的Android开源项目(转)

    摘要:对于开发者而言,了解当下比较流行的开源项目很是必要.利用这些项目,有时能够让你达到事半功倍的效果.为此,CSDN特整理了GitHub上最受欢迎的Android及iOS开源项目,本文详细介绍了20 ...

  4. Linux的缓存内存 Cache Memory详解

    http://www.ha97.com/4337.html PS:前天有童鞋问我,为啥我的Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存以提高 ...

  5. three.js obj转js

    js格式的模型文件是three.js中可以直接加载的文件.使用THREE.JSONLoader()直接加载,而不需要引用其它的loader插件. obj格式转js格式使用的是threejs.org官方 ...

  6. implode,explode的使用

    implode把数组转成字符串的函数,在组合SQL语句时候使用特好使! 比如 $a = array('a','b','c');$b = implode(',', $a);echo $b; 返回的字符串 ...

  7. ssh在本地调用远程主机上的命令,不登录远程主机shell

    需求描述: 在实际shell脚本的编写过程中,需要通过ssh远程执行一个命令,并返回执行的结果 简单来说,就是将命令发送到远程的主机上进行执行,但是并没有实际的登录到远程主机上.即通过 ssh的方式本 ...

  8. java.util.logging.Logger使用具体解释

    java.util.logging.Logger不是什么新奇东西了,1.4就有了,但是由于log4j的存在,这个logger一直沉默着,事实上在一些測试性的代码中,jdk自带的logger比log4j ...

  9. day11<Java开发工具&常见对象>

    Java开发工具(常见开发工具介绍) Java开发工具(Eclipse中HelloWorld案例以及汉化) Java开发工具(Eclipse的视窗和视图概述) Java开发工具(Eclipse工作空间 ...

  10. swift开发之 -- ? 和 ! 的作用

    记录下这个知识点: 一般我们在一下两种情况会遇到 ? 和 !的使用 1,声明变量时 var number:Int? var str:String? 2,在对变量进行操作时 number?.hasVal ...