精华内容
下载资源
问答
  • Aspose Java for Docx4j是一个提供比较源代码示例的项目,该示例使用Aspose for Java API和Docx4j来执行相同的文件处理任务。 此外,该项目提供了Aspose提供的高级功能的源代码示例,而Docx4j中缺少这些功能。 ...
  • 最近需要用docx4j来对docx进行一些操作,用到的技术是docx4j,这个技术在国内其实用的不是很多,看了一些博主的文章,有些感悟,做了一些总结,如果有疑问或错误之处欢迎交流。创建包:WordprocessingMLPackage ...

    最近需要用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 getAllElementFromObject(Object obj, Class> toSearch) {

    List result = new ArrayList();

    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。

    展开全文
  • at org.docx4j.Docx4J.toFO(Docx4J.java:711) at com.komunitas.tester.docx.DefaultDocxToFo.main(DefaultDocxToFo.java:123) org.docx4j.convert.out.common.AbstractExporter.export(AbstractExporter.java:106...
  • DOCX4J jar包

    2018-05-21 14:33:27
    docx4j 用的jar包,docx4j学习网址:http://www.docx4java.org/trac/docx4j
  • #docx4j介绍docx4j是一个用于创建和操作Microsoft Open XML (Word docx, Powerpoint pptx, 和 Excel xlsx)文件的Java类库。#开发环境笔记仅供参考,具体开发环境可能存在版本差异。OS:Windows 10JDK:SUN 1.8Eclipse:...

    #docx4j介绍

    docx4j是一个用于创建和操作Microsoft Open XML (Word docx, Powerpoint pptx, 和 Excel xlsx)文件的Java类库。

    #开发环境

    笔记仅供参考,具体开发环境可能存在版本差异。

    OS:Windows 10

    JDK:SUN 1.8

    Eclipse:4.5[STS Spring定制版]

    Maven:3.3.9

    #使用介绍

    这个问题之前是用卓正office解决的文档合成,我个人不是很满意效果。现在找到了新的方案感觉挺不错的,所以只是演示合成。我感觉poi也是可以的,但是我并没发现有合并文档的方法。也许是我不够深入吧。

    #添加依赖

    org.docx4j

    docx4j

    3.3.1

    org.docx4j

    docx4j-ImportXHTML

    3.3.1

    org.docx4j.org.capaxit.textimage

    TextImageGen

    1.9

    org.plutext

    jaxb-xmldsig-core

    1.0.0

    #代码用例

    import java.io.Closeable;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.util.ArrayList;

    import java.util.Iterator;

    import java.util.List;

    import org.apache.commons.io.IOUtils;

    import org.docx4j.jaxb.Context;

    import org.docx4j.openpackaging.exceptions.Docx4JException;

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    import org.docx4j.openpackaging.parts.PartName;

    import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart;

    import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;

    import org.docx4j.relationships.Relationship;

    import org.docx4j.wml.CTAltChunk;

    public class MargeDoc {

    public static final int BUFFER_LENGTH = 10240; //缓冲

    public void mergeDocx(List list, File file) {

    List inList = new ArrayList();

    for (int i = 0; i < list.size(); i++)

    try {

    inList.add(new FileInputStream(list.get(i)));

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    }

    try {

    InputStream inputStream = mergeDocx(inList);

    write(inputStream, file);

    } catch (Docx4JException | IOException e) {

    e.printStackTrace();

    }

    }

    public InputStream mergeDocx(final List streams) throws Docx4JException, IOException {

    WordprocessingMLPackage target = null;

    final File generated = File.createTempFile("generated", ".docx");

    int chunkId = 0;

    Iterator 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 {

    insertDocx(target.getMainDocumentPart(), IOUtils.toByteArray(is), chunkId++);

    }

    }

    }

    if (target != null) {

    target.save(generated);

    return new FileInputStream(generated);

    } else {

    return null;

    }

    }

    /**

    * 插入单个文档

    * @param main

    * @param bytes

    * @param chunkId

    */

    private void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) {

    try {

    AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(

    new PartName("/part" + chunkId + ".docx"));

    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();

    }

    }

    /**

    * 写入文件

    * @param req

    * @return

    * @throws IOException

    */

    public static boolean write(InputStream content,File file) {

    OutputStream out = null;

    int read = 0;

    final byte[] bytes = new byte[BUFFER_LENGTH];

    try {

    out = new FileOutputStream(file, true);

    while ((read = content.read(bytes)) != -1){

    out.write(bytes, 0, read);

    }

    } catch (IOException e) {

    return false;

    }finally {

    close(out);

    close(content);

    }

    return true;

    }

    /**

    * 关闭流

    * @param stream

    */

    public static void close(Closeable stream) {

    try {

    if (stream != null)

    stream.close();

    } catch (IOException e) {

    }

    }

    public static void main(String[] args) throws Docx4JException, IOException{

    MargeDoc wordUtil=new MargeDoc();

    String template="D:/import/docx";

    List list=new ArrayList();

    list.add(template+"/1.docx");

    list.add(template+"/2.docx");

    list.add(template+"/3.docx");

    wordUtil.mergeDocx(list, new File(template+"/out.docx"));

    }

    }

    #测试数据

    0818b9ca8b590ca3270a3433284dd417.png

    0818b9ca8b590ca3270a3433284dd417.png

    0818b9ca8b590ca3270a3433284dd417.png

    #测试结果

    图片文字样式都可以合成,唯独插入的表单是个合成的时候位置不对。有待研究用法。

    0818b9ca8b590ca3270a3433284dd417.png

    展开全文
  • 一、前言工作中,经常会碰到需要对word的处理操作,最最最常用的是word文档的导出,而且经常碰到各种抓脑壳的复杂格式的word,最开始我用的是poi,但是挣扎了一段时间,莫得法,换成了用docx4j,很强大,嗯,我喜欢...

    一、前言

    工作中,经常会碰到需要对word的处理操作,最最最常用的是word文档的导出,而且经常碰到各种抓脑壳的复杂格式的word,最开始我用的是poi,但是挣扎了一段时间,莫得法,换成了用docx4j,很强大,嗯,我喜欢,用了好长一段时间,发现网上关于docx4j的中文文档还是太少了,大家都是零零碎碎的一些博客文章。觉得,应该整理共享一下,让更多的人,享受到docx4j的便利。

    引用官网上的一段话:docx4j是一个开源(ASLv2)Java库,用于创建和处理Microsoft Open XML(Word docx,Powerpoint pptx和Excel xlsx)文件。

    二、理解docx文件

    1.认识Open XML

    docx4j主要是针对docx文件进行操作,操作的对象的Microsoft Open XML文件。

    什么是Microsoft Open XML?

    Office Open XML,也称为OpenXML或OOXML,是Office文档的基础XML的格式,应用于word,execl,ppt,图表等。该规范由Microsoft开发,被ISO和IEC采纳。现在是所有Microsoft Office文档(.docx,.xlsx和.pptx)的默认格式。

    2.docx文件的结构

    docx我们可以理解为一个前端项目的压缩包,里面有样式文件,dom格式的xml文件,我们解压一个docx的文件看一下它的目录结构:

    d7f604303bd16562a161ee6fb623e53a.png

    我们先看根目录下的[Content_Types] .xml文件,这个是整个docx文件的内容组件的配置文件,整个压缩包中用到的文件都在里面配置,可以简单理解为,我们写前端时html文件的head部分关于js,css引用的部分,但这样理解有点不明确,想象一下,jsp文件include各部分的总页面,有点类似。

    _rels这个目录是配置定义各部分间的关系,了解就行,

    看里面的核心word目录,可以看到,这个目录结构跟我们前端项目的html、css结构很相似,

    media目录下放多媒体元素,图片之类的,了解就行

    theme目录,顾名思义,word的主题,了解就行

    word目录下最重要的是里面的document.xml文件

    其他的word部分文件,settings.xml和styles.xml是docx文件都有的配置和样式文件,footTable是字体表,footnotes是词汇表,其他的还有foot开头的脚表,head开头的是页眉文件之类的文件

    3.docx的核心OpenXML文件格式

    我们主要看document.xml文件,这个文件是整个docx的骨架,类似于前端页面的html文件,是最基础、也是最重要的文件。

    理解document.xml的文本结构,这个文本结构类似html格式

    (写到这突然有点不想写了.....,下面就随便记录哈了)

    三、使用docx4j

    1.使用的jar

    maven导入

    org.docx4j

    docx4j

    6.1.2

    2.工具类

    package com.zb.hello.util;

    import java.io.ByteArrayOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.util.ArrayList;

    import java.util.HashMap;

    import java.util.Iterator;

    import java.util.List;

    import java.util.Map;

    import java.util.Map.Entry;

    import java.util.regex.Matcher;

    import java.util.regex.Pattern;

    import javax.xml.bind.JAXBElement;

    import javax.xml.bind.JAXBException;

    import org.docx4j.XmlUtils;

    import org.docx4j.dml.wordprocessingDrawing.Inline;

    import org.docx4j.jaxb.XPathBinderAssociationIsPartialException;

    import org.docx4j.openpackaging.exceptions.Docx4JException;

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;

    import org.docx4j.wml.ContentAccessor;

    import org.docx4j.wml.Drawing;

    import org.docx4j.wml.ObjectFactory;

    import org.docx4j.wml.P;

    import org.docx4j.wml.R;

    import org.docx4j.wml.Tbl;

    import org.docx4j.wml.Tc;

    import org.docx4j.wml.Text;

    import org.docx4j.wml.Tr;

    public class Docx4jUtil {

    public static Builder Builder;

    public static Builder of(String path) throws FileNotFoundException, Docx4JException {

    return new Builder(path);

    }

    public static class Builder {

    private WordprocessingMLPackage template = null;

    private Iterator texts = null;

    // 占位符参数map

    private Map params = new HashMap<>();

    private Builder(String path) throws FileNotFoundException, Docx4JException {

    if (path != null && !path.isEmpty()) {

    this.template = WordprocessingMLPackage.load(new FileInputStream(new File(path)));

    this.texts = getAllPlaceholderElementFromObject(template.getMainDocumentPart()).iterator();

    }

    }

    /**

    * 增加文本占位符参数(一个)

    *

    * @param key 键

    * @param value 值

    * @return Builder对象

    */

    public Builder addParam(String key, String value) {

    Builder builder = this;

    if (key != null && !key.isEmpty()) {

    /*while (texts.hasNext()) {

    Text text = texts.next();

    String temp = text.getValue();

    if (temp.equals("${" + key + "}")) {

    text.setValue(value);

    texts.remove();

    return builder;

    }

    }*/

    params.put(key, value);

    }

    return builder;

    }

    /**

    * 增加参数(多个)

    *

    * @param params 多个参数的map

    * @return Builder对象

    */

    public Builder addParams(Map params) {

    this.params = params;

    return this;

    }

    /**

    * 增加一个表格

    *

    * @param tablePlaceholder 寻找表格的占位符

    * @param placeholderRows 模板行所占行数

    * @param list 替换模板占位符的数据

    * @return Builder对象

    * @throws JAXBException JAXBException

    * @throws Docx4JException Docx4JException

    */

    public Builder addTable(String tablePlaceholder, int placeholderRows, List> list)

    throws Docx4JException, JAXBException {

    List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

    Tbl tempTable = getTemplateTable(tables, tablePlaceholder);

    if (tempTable != null && list != null && !list.isEmpty()) {

    List trs = getAllElementFromObject(tempTable, Tr.class);

    int rows = trs.size();

    if (rows > placeholderRows) {

    List

    tempTrs = new ArrayList<>();

    for (int i = rows - placeholderRows; i < rows; i++) {

    tempTrs.add((Tr) trs.get(i));

    }

    for (Map trData : list) {

    for (Tr tempTr : tempTrs) {

    addRowToTable(tempTable, tempTr, trData);

    }

    }

    for (Tr tempTr : tempTrs) {

    tempTable.getContent().remove(tempTr);

    }

    }

    }

    return this;

    }

    private void loadImg(Tbl tempTable, byte[] decodeBuffer, int maxWidth) {

    Inline inline = createInlineImage(template, decodeBuffer, maxWidth);

    P paragraph = addInlineImageToParagraph(inline);

    List rows = getAllElementFromObject(tempTable, Tr.class);

    Tr tr = (Tr) rows.get(0);

    List cells = getAllElementFromObject(tr, Tc.class);

    Tc tc = (Tc) cells.get(0);

    tc.getContent().clear();

    tc.getContent().add(paragraph);

    }

    /**

    * 通过站位符确定加载图片的位置,图片的位置为表格

    *

    * @param placeholder 占位符

    * @param decodeBuffer 图片的字节流

    * @return 当前对象

    * @throws Docx4JException Docx4JException

    * @throws JAXBException JAXBException

    */

    public Builder addImg(String placeholder, byte[] decodeBuffer) throws Docx4JException, JAXBException {

    addImg(placeholder, decodeBuffer, 0);

    return this;

    }

    /**

    * 通过站位符确定加载图片的位置,图片的位置为表格

    *

    * @param placeholder 占位符

    * @param decodeBuffer 图片的字节流

    * @param maxWidth 图片的最多宽度,不传默认写入图片原始宽度

    * @return 当前对象

    * @throws Docx4JException Docx4JException

    * @throws JAXBException JAXBException

    */

    public Builder addImg(String placeholder, byte[] decodeBuffer, int maxWidth) throws Docx4JException, JAXBException {

    List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

    Tbl tempTable = getTemplateTable(tables, placeholder);

    loadImg(tempTable, decodeBuffer, maxWidth);

    return this;

    }

    /**

    * 通过int的位置数组确定加载图片的位置,图片的位置为表格(以主界面为基准)

    *

    * @param wz int型数组,长度必须为3 ,第一个值为第几个表格,第二个值为第几行,第三个参数为第几个单元格

    * @param decodeBuffer 图片的字节流

    * @param maxWidth 图片的最多宽度,不传默认写入图片原始宽度

    * @return 当前对象

    */

    public Builder addImg(int[] wz, byte[] decodeBuffer, int maxWidth) {

    Tc tc = getTcByWz(wz);

    Tbl tempTable = (Tbl) getAllElementFromObject(tc, Tbl.class).get(0);

    loadImg(tempTable, decodeBuffer, maxWidth);

    return this;

    }

    /**

    * 通过int的位置数组确定加载图片的位置,图片的位置为表格(以主界面为基准)

    *

    * @param wz int型数组,长度必须为3 ,第一个值为第几个表格,第二个值为第几行,第三个参数为第几个单元格

    * @param decodeBuffer 图片的字节流

    * @return 当前对象

    */

    public Builder addImg(int[] wz, byte[] decodeBuffer) {

    addImg(wz, decodeBuffer, 0);

    return this;

    }

    /**

    * 添加段落

    *

    * @param list 数据集合

    * @param wz 模板段落所在的位置,长度为三(第几个表格,第几行,第几个单元格)

    * @return Builder对象

    */

    public Builder addParagrash(List> list, int[] wz) {

    Tc tc = getTcByWz(wz);

    List paraList = getAllElementFromObject(tc, P.class);

    tc.getContent().clear();

    for (Map item : list) {

    paraList.forEach((tempPara) -> {

    P workingPara = (P) XmlUtils.deepCopy(tempPara);

    repaleTexts(workingPara, item);

    tc.getContent().add(workingPara);

    });

    }

    return this;

    }

    /**

    * 移除含有占位符的Tr

    * @param placeholder 占位符

    * @return Builder对象

    */

    public Builder removeTrByPlaceholder(String placeholder) {

    //这种方式获取是正常的,但是get()方法操作的时候不能正常替换文本了。

    //List trs = template.getMainDocumentPart().getJAXBNodesViaXPath("//w:tr", true);

    List trs = getAllElementFromObject(template.getMainDocumentPart(), Tr.class);

    Tr tr = (Tr) getTemplateObj(trs,placeholder,false);

    if(tr != null){

    Tbl tbl = (Tbl) tr.getParent();

    tbl.getContent().remove(tr);

    }

    return this;

    }

    /**

    * 移除含有占位符的Tr

    * @param placeholders 占位符的集合

    * @return Builder对象

    */

    public Builder removeTrByPlaceholder(List placeholders) {

    /* List trs = template.getMainDocumentPart().getJAXBNodesViaXPath("//w:tr", true);*/

    List trs = getAllElementFromObject(template.getMainDocumentPart(), Tr.class);

    List list = getTemplateObjs(trs,placeholders);

    for (Object o:list) {

    Tr tr = (Tr) o;

    if(tr != null){

    Tbl tbl = (Tbl) tr.getParent();

    tbl.getContent().remove(tr);

    }

    }

    return this;

    }

    /**

    * 获取文件字节流

    *

    * @return 文件字节流

    * @throws Docx4JException docx异常

    */

    public byte[] get() throws Docx4JException {

    if (!params.isEmpty()) {

    while (texts.hasNext()) {

    Text text = texts.next();

    String temp = text.getValue();

    for (Entry param : params.entrySet()) {

    if (temp.equals("${" + param.getKey() + "}")) {

    text.setValue(param.getValue());

    }

    }

    }

    }

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

    template.save(outputStream);

    return outputStream.toByteArray();

    }

    /**

    * 获取指定单元格

    *

    * @param temp 模板段落所在的位置,长度为三(第几个表格,第几行,第几个单元格)

    * @return tc

    */

    private Tc getTcByWz(int[] temp) {

    List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

    Tbl wzTable = (Tbl) tables.get(temp[0]);

    Tr tr = (Tr) getAllElementFromObject(wzTable, Tr.class).get(temp[1]);

    return (Tc) getAllElementFromObject(tr, Tc.class).get(temp[2]);

    }

    }

    /**

    * 创建包含图片的一个内联对象

    *

    * @param wordMLPackage WordprocessingMLPackage

    * @param bytes 图片字节流

    * @param maxWidth 最大宽度

    * @return 图片的内联对象

    */

    private static Inline createInlineImage(WordprocessingMLPackage wordMLPackage, byte[] bytes, int maxWidth) {

    Inline inline = null;

    try {

    BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

    int docPrId = 1;

    int cNvPrId = 2;

    if (maxWidth > 0) {

    inline = imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false, maxWidth);

    } else {

    inline = imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false);

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    return inline;

    }

    /**

    * 创建一个对象工厂并用它创建一个段落和一个可运行块R. 然后将可运行块添加到段落中. 接下来创建一个图画并将其添加到可运行块R中. 最后我们将内联

    * 对象添加到图画中并返回段落对象.

    *

    * @param inline 包含图片的内联对象.

    * @return 包含图片的段落

    */

    private static P addInlineImageToParagraph(Inline inline) {

    // 添加内联对象到一个段落中

    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);

    return paragraph;

    }

    // 发现docx文档包含占位符的文本节点

    private static List getAllPlaceholderElementFromObject(Object obj) {

    List result = new ArrayList<>();

    Class toSearch = Text.class;

    Text textPlaceholder;

    if (obj instanceof JAXBElement) {

    obj = ((JAXBElement>) obj).getValue();

    }

    if (obj.getClass().equals(toSearch)) {

    textPlaceholder = (Text) obj;

    if (isPlaceholder(textPlaceholder.getValue())) {

    result.add((Text) obj);

    }

    } else if (obj instanceof ContentAccessor) {

    List> children = ((ContentAccessor) obj).getContent();

    for (Object child : children) {

    result.addAll(getAllPlaceholderElementFromObject(child));

    }

    }

    return result;

    }

    // 发现docx文档中的节点

    private static List getAllElementFromObject(Object obj, Class> toSearch) {

    List result = new ArrayList<>();

    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;

    }

    // 这个方法只是查看表格是否含有我们的占位符,如果有则返回表格

    private static Tbl getTemplateTable(List tables, String templateKey) {

    return (Tbl) getTemplateObj(tables,templateKey,false);

    }

    /**

    * 这个方法只是查看dom是否含有我们的占位符,如果有则返回dom

    *

    * @param objects 需要查找的dom元素

    * @param placeholder 占位符

    * @param f 是否全部查找,为ture时全部查找,返回的是list,为false时一找到元素就返回,只是单个元素

    * @return 找到的元素

    */

    private static Object getTemplateObj(List objects, String placeholder, boolean f) {

    List objectList = new ArrayList<>();

    for (Object o : objects) {

    List> textElements = getAllElementFromObject(o, Text.class);

    for (Object text : textElements) {

    Text textElement = (Text) text;

    if (textElement.getValue() != null && textElement.getValue().equals("${" + placeholder + "}")) {

    if (!f) {

    return o;

    } else {

    objectList.add(o);

    }

    }

    }

    }

    return objectList.isEmpty()?null:objectList;

    }

    /**

    * 这个方法只是查看dom是否含有我们的占位符,如果有则返回dom

    * @param objects 需要查找的dom元素的集合

    * @param placeholders 占位符集合

    * @return 找到的元素的集合

    */

    private static List getTemplateObjs(List objects, List placeholders) {

    List objectList = new ArrayList<>();

    for (Object o : objects) {

    List> textElements = getAllElementFromObject(o, Text.class);

    for (Object text : textElements) {

    Text textElement = (Text) text;

    if (textElement.getValue() != null && placeholders.contains(getPlaceholderStr(textElement.getValue()))) {

    objectList.add(o);

    }

    }

    }

    return objectList;

    }

    /**

    * 复制模板行

    *

    * @param reviewtable 表格

    * @param templateRow 模板行

    * @param replacements 填充模板行的数据

    */

    private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map replacements) {

    Tr workingRow = XmlUtils.deepCopy(templateRow);

    repaleTexts(workingRow, replacements);

    reviewtable.getContent().add(workingRow);

    }

    /**

    * 把工作对象中的全部占位符都替换掉

    *

    * @param working 工作对象

    * @param replacements map数据对象

    */

    private static void repaleTexts(Object working, Map replacements) {

    List> textElements = getAllElementFromObject(working, Text.class);

    for (Object object : textElements) {

    Text text = (Text) object;

    String keyStr = getPlaceholderStr(text.getValue());

    if (keyStr != null && !keyStr.isEmpty()) {

    String replacementValue = replacements.get(keyStr);

    if (replacementValue != null) {

    text.setValue(replacementValue);

    } else {

    text.setValue("--");

    }

    }

    }

    }

    /**

    * 判断字符串是否有${}占位符

    *

    * @param str 需要判断的字符串

    * @return 是否字符串是否有${}占位符

    */

    private static boolean isPlaceholder(String str) {

    if (str != null && !str.isEmpty()) {

    Pattern pattern = Pattern.compile("([$]\\{\\w+\\})");

    Matcher m = pattern.matcher(str);

    return m.find();

    }

    return false;

    }

    /**

    * 得到占位符${}中的文本

    *

    * @param str 需要判断的字符串

    * @return 占位符${}中的文本

    */

    private static String getPlaceholderStr(String str) {

    if (str != null && !str.isEmpty()) {

    Pattern p = Pattern.compile("\\$\\{(.*?)\\}");

    Matcher m = p.matcher(str);

    if (m.find()) {

    return m.group(1);//m.group(0)包括这两个字符

    }

    }

    return null;

    }

    }

    3.导出word文件使用

    public byte[] downloadWord() throws Docx4JException, JAXBException, FileNotFoundException {

    //模板文件路径

    String path = this.getClass().getClassLoader().getResource("template/test.docx").getPath();

    //模板中要生成表格的数据

    List> list = new ArrayList<>();

    for (int i = 0; i < 3; i++) {

    Map m = new HashMap<>();

    m.put("name", "姓名"+i);

    m.put("sex", "性别"+i);

    m.put("age", "年龄"+i);

    m.put("bz", "备注"+i);

    m.put("xx", "详细"+i);

    list.add(m);

    }

    list.stream();

    //模板中要插入图片的数据

    byte[] img = null;

    try (InputStream input = new FileInputStream(this.getClass().getClassLoader().getResource("template/timg.jpg").getPath())){

    img = new byte[input.available()];

    input.read(img);

    } catch (Exception e) {

    e.printStackTrace();

    }

    //要插入的map数据

    Map m = new HashMap<>();

    m.put("today", LocalDate.now().toString());

    m.put("active", "游泳");

    //处理好数据后就是超级简单的调用

    return Docx4jUtil.of(path)

    .addParam("title", "测试文档标题")

    .addParam("user", "测试人")

    .addParams(m)

    .addTable("name", 2, list)

    .addImg("img", img)

    .get();

    }

    四、扩展

    1.word转html

    使用poi的maven

    fr.opensagres.xdocreport

    xdocreport

    2.0.2

    org.apache.poi

    poi

    ${poi-version}

    org.apache.poi

    poi-scratchpad

    ${poi-version}

    org.apache.poi

    poi-ooxml

    ${poi-version}

    org.apache.poi

    poi-ooxml-schemas

    ${poi-version}

    org.apache.poi

    ooxml-schemas

    1.4

    org.apache.commons

    commons-compress

    1.18

    2.工具类

    package com.zb.hello.util;

    import fr.opensagres.poi.xwpf.converter.xhtml.Base64EmbedImgManager;

    import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;

    import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;

    import org.apache.commons.codec.binary.Base64;

    import org.apache.poi.hwpf.HWPFDocumentCore;

    import org.apache.poi.hwpf.converter.PicturesManager;

    import org.apache.poi.hwpf.converter.WordToHtmlConverter;

    import org.apache.poi.hwpf.converter.WordToHtmlUtils;

    import org.apache.poi.xwpf.usermodel.XWPFDocument;

    import org.w3c.dom.Document;

    import javax.xml.parsers.DocumentBuilderFactory;

    import javax.xml.parsers.ParserConfigurationException;

    import javax.xml.transform.OutputKeys;

    import javax.xml.transform.Transformer;

    import javax.xml.transform.TransformerException;

    import javax.xml.transform.TransformerFactory;

    import javax.xml.transform.dom.DOMSource;

    import javax.xml.transform.stream.StreamResult;

    import java.io.ByteArrayOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.IOException;

    public class WordHtmlUtil {

    //doc转换html

    public static String docToHtml(File file) throws IOException, ParserConfigurationException, TransformerException {

    HWPFDocumentCore wordDocument = WordToHtmlUtils.loadDoc(new FileInputStream(file));

    WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(

    DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()

    );

    PicturesManager pictureRunMapper = (bytes, pictureType, s, v, v1) -> "data:image/png;base64,"+Base64.encodeBase64String(bytes);

    wordToHtmlConverter.setPicturesManager(pictureRunMapper);

    wordToHtmlConverter.processDocument(wordDocument);

    Document htmlDocument = wordToHtmlConverter.getDocument();

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    DOMSource domSource = new DOMSource(htmlDocument);

    StreamResult streamResult = new StreamResult(out);

    TransformerFactory transformerFactory = TransformerFactory.newInstance();

    Transformer serializer = transformerFactory.newTransformer();

    serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

    serializer.setOutputProperty(OutputKeys.INDENT, "yes");

    serializer.setOutputProperty(OutputKeys.METHOD, "html");

    serializer.transform(domSource, streamResult);

    out.close();

    return new String(out.toByteArray());

    }

    //docx转换html

    public static String docxToHtml(File file) throws IOException {

    XWPFDocument docxDocument = new XWPFDocument(new FileInputStream(file));

    XHTMLOptions options = XHTMLOptions.create();

    //图片转base64

    options.setImageManager(new Base64EmbedImgManager());

    // 转换htm11

    ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();

    XHTMLConverter.getInstance().convert(docxDocument, htmlStream, options);

    htmlStream.close();

    return new String(htmlStream.toByteArray());

    }

    }

    展开全文
  • docx4j

    2017-12-16 11:21:57
    docx4j所需要的包
  • 原文标题:Creating Word documents with Docx4j发表时间:2012年9月6日注:第一次翻译博客;由于个人水平不高,而且英语仅有四级水平,所以错误很多,请大家见谅!!!只是国内关于docx4j的博客极少,感觉这篇入门...

    原文标题:Creating Word documents with Docx4j

    发表时间:2012年9月6日

    注:第一次翻译博客;由于个人水平不高,而且英语仅有四级水平,所以错误很多,请大家见谅!!!只是国内关于docx4j的博客极少,感觉这篇入门博客挺不错,勉强翻译过来,希望对大家有所帮助。

    一段时间之前,我为一个想要在word和excel中作报表的客户提供服务。我以前的项目中生成过PDF文件和CSV文件,但从来没有处理过docx和xlsx文件。这些天了解到MS Office是基于XML的。我不禁想知道是否有一些库来帮助我生成这些文件。经过一番在线搜索,结果表明确实有:Docx4j。我开始去试用这个新库看它能做些什么。

    在官方网站上你可以了解到docx4j可以读取、更新、创建docx、xlsx和pptx文档。我只需要生成文档,所以我没有尝试读取和更新文档,但原理是一样的。Docx4j已经自带了不少示例程序,但我发现其中的一些例子同时展示了多样东西或者没有完全展示我需要了解的。所以有不少东西我不得不自己解决。幸运的是docx4j严格遵循Office Open XML标准,所以还不算太难。总而言这,我对这个库所提供的功能非常满意。

    在这个博客中我会展示一些我试用docx4j生成docx文档时创建的例子:

    一些提示

    在真正示例开始之前有几处提示。首先,在使用docx创建文档的时候,看看你使用word软件创建文档时生成的xml。当你使用一个ZIP压缩工具(例如7zip)打开一个docx文件时会找到这些XML文件。看一下都是些什么样的文件以及它们包含了哪些信息。通常情况下,如果你想得到什么东西,可以通过查看Word软件自己生成了什么而从中得到很多帮助。

    现在让我们来看一些代码。

    用一些文本创建文档

    最简单的例子就是创建一个新word文档并向其中添加一些文本内容。

    运行下面代码:

    WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();

    wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");

    wordMLPackage.save(new java.io.File("src/main/files/HelloWord1.docx"));

    结果生成一个如下所示的文件:

    1364394153_2536.png

    这里发生的就是一个word文档由一个带有文档部件的包组成。Docx4j提供一个创建包的工具方法(第1行);然后你可以从这个包中获取主文档部件并向其中添加一个文本段落(第2行);最后将这个包保存(第3行)。就这么简单,当然,如果你想做不仅仅是向文档中添加一些文本内容,那么你需要做更多的工作。

    添加带样式的文本

    然而即使添加带样式的文本也并不需要做过多的工作,不是向文档添加一个普通的文本段落,而是只需要添加一个带样式的段落。

    WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();

    wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello Word!");

    wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Subtitle","This is a subtitle!");

    wordMLPackage.save(new java.io.File("src/main/files/HelloWord2.docx"));

    1364395341_1812.png

    添加表格

    当我们想添加一个表格时,情况开始变得复杂一些。直到现在我们的代码都如此简单以至于不需要拆分到多个方法中,所以我仅仅只展示了代码中相关的数行。但这个示例我们需要第二个方法,所以我会展示整个类。

    public class AddingATable {

    private static WordprocessingMLPackage  wordMLPackage;

    private static ObjectFactory factory;

    public static void main (String[] args) throws Docx4JException {

    wordMLPackage = WordprocessingMLPackage.createPackage();

    factory = Context.getWmlObjectFactory();

    Tbl table = factory.createTbl();

    Tr tableRow = factory.createTr();

    addTableCell(tableRow, "Field 1");

    addTableCell(tableRow, "Field 2");

    table.getContent().add(tableRow);

    wordMLPackage.getMainDocumentPart().addObject(table);

    wordMLPackage.save(new java.io.File("src/main/files/HelloWord4.docx"));

    }

    private static void addTableCell(Tr tableRow, String content) {

    Tc tableCell = factory.createTc();

    tableCell.getContent().add(

    wordMLPackage.getMainDocumentPart().createParagraphOfText(content));

    tableRow.getContent().add(tableCell);

    }

    }

    我们再一次创建了word包,只是这一次我们将其保存为一个属性,从而我们可以在第二个方法中访问它。然后我们同样创建了一个对象工厂(ObjectFactory),这是一个帮助我们创建本例中所需要的具体对象的工具类,例如表格、表格行及表格列等具体对象。

    然后我们创建了表格,创建了行并且在行中添加了两个单元格。最后我们将行添加到表格中,将表格添加到主文档部件并且将包保存。

    1364439449_7397.png

    给表格添加边框

    现在我们拥有了一个表格,让我们给它添加一些边框。这需要深入研究一下表格的结构。

    1364439567_4989.png

    public class TableWithBorders {

    private static WordprocessingMLPackage  wordMLPackage;

    private static ObjectFactory factory;

    public static void main (String[] args) throws Docx4JException {

    wordMLPackage = WordprocessingMLPackage.createPackage();

    factory = Context.getWmlObjectFactory();

    Tbl table = createTableWithContent();

    addBorders(table);

    wordMLPackage.getMainDocumentPart().addObject(table);

    wordMLPackage.save(new java.io.File(

    "src/main/files/HelloWord5.docx") );

    }

    private static void addBorders(Tbl table) {

    table.setTblPr(new TblPr());

    CTBorder border = new CTBorder();

    border.setColor("auto");

    tborder.setSz(new BigInteger("4"));

    border.setSpace(new BigInteger("0"));

    border.setVal(STBorder.SINGLE);

    TblBorders borders = new TblBorders();

    borders.setBottom(border);

    borders.setLeft(border);

    borders.setRight(border);

    borders.setTop(border);

    borders.setInsideH(border);

    borders.setInsideV(border);

    table.getTblPr().setTblBorders(borders);

    }

    private static Tbl createTableWithContent() {

    Tbl table = factory.createTbl();

    Tr tableRow = factory.createTr();

    addTableCell(tableRow, "Field 1");

    addTableCell(tableRow, "Field 2");

    table.getContent().add(tableRow);

    return table;

    }

    private static void addTableCell(Tr tableRow, String content) {

    Tc tableCell = factory.createTc();

    tableCell.getContent().add(

    wordMLPackage.getMainDocumentPart().

    createParagraphOfText(content));

    tableRow.getContent().add(tableCell);

    }

    }

    首先我们创建了一个默认颜色(黑色)、粗细尺寸为4、间距为0的单线边框的边框组件(Border component),然后边框被应用到表格的四周以及表格内部水平和垂直的边框。随后我们将边框应用到表格;所有其它的代码与前面的示例一样。

    给表格添加样式

    接下来的问题--给表格添加样式让我忙活了一阵子,我们的客户想要在表格中使用粗体文本并且需要多种大小的字体。

    1364440581_5884.png

    这个示例程序有点复杂,注释和代码交织在一起。

    public class TableWithStyledContent {

    private static WordprocessingMLPackage  wordMLPackage;

    private static ObjectFactory factory;

    /**

    *  跟前面的做的一样, 我们再一次创建了一个表格, 并添加了三个单元格, 其中有两个

    *  单元带有样式. 在新方法中我们传进表格行, 单元格内容, 是否为粗体及字体大小作

    *  为参数. 你需要注意, 因为the Office Open specification规范定义这个属性是半个

    *  点(half-point)大小, 因此字体大小需要是你想在Word中显示大小的两倍,

    */

    public static void main (String[] args) throws Docx4JException {

    wordMLPackage = WordprocessingMLPackage.createPackage();

    factory = Context.getWmlObjectFactory();

    Tbl table = factory.createTbl();

    Tr tableRow = factory.createTr();

    addRegularTableCell(tableRow, "Normal text");

    addStyledTableCell(tableRow, "Bold text", true, null);

    addStyledTableCell(tableRow, "Bold large text", true, "40");

    table.getContent().add(tableRow);

    addBorders(table);

    wordMLPackage.getMainDocumentPart().addObject(table);

    wordMLPackage.save(new java.io.File("src/main/files/HelloWord6.docx") );

    }

    /**

    *  本方法创建单元格, 添加样式后添加到表格行中

    */

    private static void addStyledTableCell(Tr tableRow, String content,

    boolean bold, String fontSize) {

    Tc tableCell = factory.createTc();

    addStyling(tableCell, content, bold, fontSize);

    tableRow.getContent().add(tableCell);

    }

    /**

    *  这里我们添加实际的样式信息, 首先创建一个段落, 然后创建以单元格内容作为值的文本对象;

    *  第三步, 创建一个被称为运行块的对象, 它是一块或多块拥有共同属性的文本的容器, 并将文本对象添加

    *  到其中. 随后我们将运行块R添加到段落内容中.

    *  直到现在我们所做的还没有添加任何样式, 为了达到目标, 我们创建运行块属性对象并给它添加各种样式.

    *  这些运行块的属性随后被添加到运行块. 最后段落被添加到表格的单元格中.

    */

    private static void addStyling(Tc tableCell, String content, boolean bold, String fontSize) {

    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();

    if (bold) {

    addBoldStyle(runProperties);

    }

    if (fontSize != null && !fontSize.isEmpty()) {

    setFontSize(runProperties, fontSize);

    }

    run.setRPr(runProperties);

    tableCell.getContent().add(paragraph);

    }

    /**

    *  本方法为可运行块添加字体大小信息. 首先创建一个"半点"尺码对象, 然后设置fontSize

    *  参数作为该对象的值, 最后我们分别设置sz和szCs的字体大小.

    *  Finally we'll set the non-complex and complex script font sizes, sz and szCs respectively.

    */

    private static void setFontSize(RPr runProperties, String fontSize) {

    HpsMeasure size = new HpsMeasure();

    size.setVal(new BigInteger(fontSize));

    runProperties.setSz(size);

    runProperties.setSzCs(size);

    }

    /**

    *  本方法给可运行块属性添加粗体属性. BooleanDefaultTrue是设置b属性的Docx4j对象, 严格

    *  来说我们不需要将值设置为true, 因为这是它的默认值.

    */

    private static void addBoldStyle(RPr runProperties) {

    BooleanDefaultTrue b = new BooleanDefaultTrue();

    b.setVal(true);

    runProperties.setB(b);

    }

    /**

    *  本方法像前面例子中一样再一次创建了普通的单元格

    */

    private static void addRegularTableCell(Tr tableRow, String content) {

    Tc tableCell = factory.createTc();

    tableCell.getContent().add(

    wordMLPackage.getMainDocumentPart().createParagraphOfText(

    content));

    tableRow.getContent().add(tableCell);

    }

    /**

    *  本方法给表格添加边框

    */

    private static void addBorders(Tbl table) {

    table.setTblPr(new TblPr());

    CTBorder border = new CTBorder();

    border.setColor("auto");

    border.setSz(new BigInteger("4"));

    border.setSpace(new BigInteger("0"));

    border.setVal(STBorder.SINGLE);

    TblBorders borders = new TblBorders();

    borders.setBottom(border);

    borders.setLeft(border);

    borders.setRight(border);

    borders.setTop(border);

    borders.setInsideH(border);

    borders.setInsideV(border);

    table.getTblPr().setTblBorders(borders);

    }

    }

    纵向合并单元格

    有时你想要一个三列的表格,其中第一列将多行组合在一起。

    1364444616_9924.png

    package com.zyh.sample.docx4j;

    public class TableWithMergedCells {

    private static WordprocessingMLPackage  wordMLPackage;

    private static ObjectFactory factory;

    /**

    *  创建一个带边框的表格并添加四个带内容的行, 然后将表格添加到文档并保存

    */

    public static void main (String[] args) throws Docx4JException {

    wordMLPackage = WordprocessingMLPackage.createPackage();

    factory = Context.getWmlObjectFactory();

    Tbl table = factory.createTbl();

    addBorders(table);

    addTableRowWithMergedCells("Heading 1", "Heading 1.1",

    "Field 1", table);

    addTableRowWithMergedCells(null, "Heading 1.2", "Field 2", table);

    addTableRowWithMergedCells("Heading 2", "Heading 2.1",

    "Field 3", table);

    addTableRowWithMergedCells(null, "Heading 2.2", "Field 4", table);

    wordMLPackage.getMainDocumentPart().addObject(table);

    wordMLPackage.save(new java.io.File(

    "src/main/files/HelloWord9.docx") );

    }

    /**

    *  本方法创建一行, 并向其中添加合并列, 然后添加再两个普通的单元格. 随后将该行添加到表格

    */

    private static void addTableRowWithMergedCells(String mergedContent,

    String field1Content, String field2Content, Tbl table) {

    Tr tableRow1 = factory.createTr();

    addMergedColumn(tableRow1, mergedContent);

    addTableCell(tableRow1, field1Content);

    addTableCell(tableRow1, field2Content);

    table.getContent().add(tableRow1);

    }

    /**

    *  本方法添加一个合并了其它行单元格的列单元格. 如果传进来的内容是null, 传空字符串和一个为null的合并值.

    */

    private static void addMergedColumn(Tr row, String content) {

    if (content == null) {

    addMergedCell(row, "", null);

    } else {

    addMergedCell(row, content, "restart");

    }

    }

    /**

    *  我们创建一个单元格和单元格属性对象.

    *  也创建了一个纵向合并对象. 如果合并值不为null, 将它设置到合并对象中. 然后将该对象添加到

    *  单元格属性并将属性添加到单元格中. 最后设置单元格内容并将单元格添加到行中.

    *

    *  如果合并值为'restart', 表明要开始一个新行. 如果为null, 继续按前面的行处理, 也就是合并单元格.

    */

    private static void addMergedCell(Tr row, String content, String vMergeVal) {

    Tc tableCell = factory.createTc();

    TcPr tableCellProperties = new TcPr();

    VMerge merge = new VMerge();

    if(vMergeVal != null){

    merge.setVal(vMergeVal);

    }

    tableCellProperties.setVMerge(merge);

    tableCell.setTcPr(tableCellProperties);

    if(content != null) {

    tableCell.getContent().add(

    wordMLPackage.getMainDocumentPart().

    createParagraphOfText(content));

    }

    row.getContent().add(tableCell);

    }

    /**

    *  本方法为给定的行添加一个单元格, 并以给定的段落作为内容

    */

    private static void addTableCell(Tr tr, String content) {

    Tc tc1 = factory.createTc();

    tc1.getContent().add(

    wordMLPackage.getMainDocumentPart().createParagraphOfText(content));

    tr.getContent().add(tc1);

    }

    /**

    *  本方法为表格添加边框

    */

    private static void addBorders(Tbl table) {

    table.setTblPr(new TblPr());

    CTBorder border = new CTBorder();

    border.setColor("auto");

    border.setSz(new BigInteger("4"));

    border.setSpace(new BigInteger("0"));

    border.setVal(STBorder.SINGLE);

    TblBorders borders = new TblBorders();

    borders.setBottom(border);

    borders.setLeft(border);

    borders.setRight(border);

    borders.setTop(border);

    borders.setInsideH(border);

    borders.setInsideV(border);

    table.getTblPr().setTblBorders(borders);

    }

    }

    为表格设置列宽

    作为本博客的最后一个示例, 我会展示怎样为表格设置列宽。

    1364445987_6950.png

    public class SettingColumnWidthForTable {

    private static WordprocessingMLPackage  wordMLPackage;

    private static ObjectFactory factory;

    /**

    *  创建一个带边框的表格并添加一行. 然后添加两个带内容的单元格并给定宽度.

    */

    public static void main (String[] args) throws Docx4JException {

    wordMLPackage = WordprocessingMLPackage.createPackage();

    factory = Context.getWmlObjectFactory();

    Tbl table = factory.createTbl();

    addBorders(table);

    Tr tr = factory.createTr();

    addTableCellWithWidth(tr, "Field 1", 2500);

    addTableCellWithWidth(tr, "Field 2", 0);

    table.getContent().add(tr);

    wordMLPackage.getMainDocumentPart().addObject(table);

    wordMLPackage.save(new java.io.File(

    "src/main/files/HelloWord13.docx") );

    }

    /**

    *  本方法创建一个单元格并将给定的内容添加进去.

    *  如果给定的宽度大于0, 将这个宽度设置到单元格.

    *  最后, 将单元格添加到行中.

    */

    private static void addTableCellWithWidth(Tr row, String content, int width){

    Tc tableCell = factory.createTc();

    tableCell.getContent().add(

    wordMLPackage.getMainDocumentPart().createParagraphOfText(

    content));

    if (width > 0) {

    setCellWidth(tableCell, width);

    }

    row.getContent().add(tableCell);

    }

    /**

    *  本方法创建一个单元格属性集对象和一个表格宽度对象. 将给定的宽度设置到宽度对象然后将其添加到

    *  属性集对象. 最后将属性集对象设置到单元格中.

    */

    private static void setCellWidth(Tc tableCell, int width) {

    TcPr tableCellProperties = new TcPr();

    TblWidth tableWidth = new TblWidth();

    tableWidth.setW(BigInteger.valueOf(width));

    tableCellProperties.setTcW(tableWidth);

    tableCell.setTcPr(tableCellProperties);

    }

    /**

    *  本方法为表格添加边框

    */

    private static void addBorders(Tbl table) {

    table.setTblPr(new TblPr());

    CTBorder border = new CTBorder();

    border.setColor("auto");

    border.setSz(new BigInteger("4"));

    border.setSpace(new BigInteger("0"));

    border.setVal(STBorder.SINGLE);

    TblBorders borders = new TblBorders();

    borders.setBottom(border);

    borders.setLeft(border);

    borders.setRight(border);

    borders.setTop(border);

    borders.setInsideH(border);

    borders.setInsideV(border);

    table.getTblPr().setTblBorders(borders);

    }

    }

    总结

    在这篇文章中,我展示了如何创建一个文档、如何为其应用样式以及添加带样式的表格。以后的文章我会展示更多的关于docx文档的示例(比如添加目录、添加图片、添加页眉和页脚等)以及一些关于xlsx文档的示例。

    展开全文
  • docx4J 文件源代码 docx4J source files docx4j is an open source Java library for manipulating OpenXML WordprocessingML documents, released under the Apache software licence. docx is the default file ...
  • docx4j操作word

    2017-12-19 09:02:12
    docx4j操作word,主要使用docx4j对word进行操作,比如chart图表、标签替换、目录等。
  • word转pdf所用docx4j

    2019-03-14 21:31:50
    docx4j 用的jar包,docx4j学习网址:http://www.docx4java.org/trac/docx4j
  • docx4j
  •  word的格式其实可以用xml来表现,docx4j也应该是基于xml来操作docx文档的。xml就比较好理解了。我们都是通过doc树的形式操作docx,只不过对于docx4j来说根节点是一个package,我们可以从根节点...
  • package org.docx4j.samples;import java.io.File;import java.math.BigInteger;import org.docx4j.customxml.ObjectFactory;import org.docx4j.openpackaging.packages.WordprocessingMLPackage;import org.docx4j....
  • docx4j-3.3.6

    2018-01-22 18:28:25
    What is docx4j? docx4j is an open source (Apache v2) library for creating, editing, and saving OpenXML "packages", including docx, pptx, and xslx. It uses JAXB to create the Java representation. ...
  • Docx4j缩放字体

    2020-09-15 15:38:19
    import org.apache.commons.lang...import org.docx4j.Docx4J; import org.docx4j.TraversalUtil; import org.docx4j.finders.ClassFinder; import org.docx4j.openpackaging.exceptions.Docx4JException; import or.
  • docx4j-3.1.0 jar包

    2018-08-02 09:41:48
    docx4j所需jar包和source.jar包,docx4j 是一个解压的docx包(docx本身是zip包)和解析WordprocessingML格式XML的Java库 。 最新版本的 docx4j 也支持PowerPoint pptx文件。
  • docx4j-3.3.3.zip

    2021-02-20 14:14:46
    docx4j-3.3.3 jar包及依赖jar包
  • docx4j API

    热门讨论 2013-11-24 17:54:27
    docx4j API参考 java当中用于操作office(docx/xlsx/ppt)等文件的类库
  • docx4j是一款在java世界处理微软word/ppt/excel文档的强大工具。它其实是一个半开源的产品。虽然它对WORD各种处理在API层 面进行了封装,但是像WORD本身的拆分,合并。其作者(Jason Harrop)是单独提出来了,封装成...
  • docx4j及其依赖包

    2019-01-14 16:04:32
    docx4j支持操作后缀.docx得word文档,替换书签,获取文档内容,稳定资源
  • docx4j全量包.zip

    2021-03-22 16:08:13
    包含60个JAR包,docx4j所有的jar包,涉及到word转换pdf,和他的所有依赖包
  • docx4j所有jar包

    2018-11-07 11:46:06
    docx4j所有的jar包,设计到word转换pdf,和他的所有依赖包
  • docx4j相关jar包

    2018-11-20 15:08:06
    docx4j运行需要的jar包,这里是整理好的所有必须的jar包
  • 通过docx4j完美合并docx

    千次阅读 2017-11-20 14:53:24
    通过docx4j完美合并docx
  • 我能够将文本和段落添加到单词中,并用文本替换任何合并字段,但我需要使用docx4j添加新的合并字段来创建单词模板.我怎样才能做到这一点?我是否使用wordMLPackage.getMainDocumentPart().addTargetPart(targetpart);...
  • docx4j所需jar包全

    2019-12-25 16:48:04
    docx4j所需jar包整合,其中word转pdf,word转html,word中docx转doc,java代码实现,都可以使用,仅限学习参考使用。
  • docx4j-community-6.0.1

    2018-11-28 13:40:55
    docx4j-community-6.0.1 官方原版 包含文档和所有依赖
  • docx4j之word模板

    千次阅读 2018-04-10 01:18:31
    pom.xml 4.0.0 com.hys docx4j 0.0.1-SNAPSHOT org.docx4j docx4j 3.3.6 org.docx4j docx4j-export-fo 3.3.6 org.slf4j slf4j-api 1.7.21

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 754
精华内容 301
热门标签
关键字:

docx4j