easypoi导出word换行(easypoi导出数字类型)

2022-07-18,,,,

如果遇到poi读取例如{name}不能识别为一个整体,可以使用word的域操作,如果不太清楚域的使用,可以这么操作,先在text文档中写好,例如{name},然后再整个复制到word中,不要一个一个在word中敲,不然有可能不会被poi识别为一个整体

xwpfdocument对象

poi是apache提供的可以操作word文档的第三方jar。poi能操作word是使用xwpfdocument对象。

  • xwpfdocument对象可以解析docx文件,在xwpfdocument对象通过输入流解析docx的时候,会获取到docx文档中的各种对象,例如表格,段落,图片等,通过操作xwpfdocument对象就可以修改模板内容
  • xwpfdocument api结构org.apache.poi.xwpf.usermodel.xwpfdocument
  • xwpfdocument 提供write(outputstream stream)方法将修改后的对象重新写入xml并生成新的docx

通过xwpfdocument 可以获得的docx中的各种对象

要具体操作通过xwpfdocument 可以获得的docx中的各种对象,我们离不开一个对象为xwpfrun对象,api结构
org.apache.poi.xwpf.usermodel.xwpfrun。其描述为:xwpfrun object defines a region of text with a common set of properties。通过描述我们不难理解其作用为设置文本对象的各种属性。

通过xwpfdocument 获取对象

//解析docx模板并获取document对象
xwpfdocument document = new xwpfdocument(poixmldocument.openpackage(inputurl));
//获取整个文本对象
list<xwpfparagraph> allparagraph = document.getparagraphs();
//获取整个表格对象
list<xwpftable> alltable = document.gettables();
//获取图片对象
xwpfpicturedata pic = document.getpicturedatabyid("picid");

首先建一个很简单的word模板001.docx,我们通过操作对象获取word中的文本内容

下面demo的输出可以看出我们操作文本对象,成功获取了文本内容

@component("xwpruntest")
public class xwpruntest {
    //模板文件地址
    private static string inputurl = "c:\users\zhihe\desktop\demo\001.docx";
    public void runtest(){
        
        try {
            //解析docx模板并获取document对象
            xwpfdocument document = new xwpfdocument(poixmldocument.openpackage(inputurl));
            //获取整个文本对象
            list<xwpfparagraph> allparagraph = document.getparagraphs();
            
            //获取xwpfrun对象输出整个文本内容
            stringbuffer temptext = new stringbuffer();
            for (xwpfparagraph xwpfparagraph : allparagraph) {
                    list<xwpfrun> runlist = xwpfparagraph.getruns();
                    for (xwpfrun xwpfrun : runlist) {
                        temptext.append(xwpfrun.tostring());
                    }
            }
            system.out.println(temptext.tostring());
            
        } catch (ioexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }

}

测试

@runwith(springjunit4classrunner.class)
@contextconfiguration("classpath:applicationcontext.xml")
public class runtest {
    
    @resource
    private xwpruntest xwpruntest;
    
    @test
    public void runtest(){
        xwpruntest.runtest();
    }

}

控制台输出结果

在这里发现操作文本对象的时候并没有获取到表格文本,所以如果我们需要获取到表格文本还需要另外的操作

@component("xwpruntabletest")
public class xwpruntabletest {
    
    //模板文件地址
    private static string inputurl = "c:\users\zhihe\desktop\demo\001.docx";
    
    public void tabletest(){
        
        try {
            
            stringbuffer tabletext = new stringbuffer();
            
            //解析docx模板并获取document对象
            xwpfdocument document = new xwpfdocument(poixmldocument.openpackage(inputurl));
            //获取全部表格对象
            list<xwpftable> alltable = document.gettables();
            
            for (xwpftable xwpftable : alltable) {
                //获取表格行数据
                list<xwpftablerow> rows = xwpftable.getrows();
                for (xwpftablerow xwpftablerow : rows) {
                    //获取表格单元格数据
                    list<xwpftablecell> cells = xwpftablerow.gettablecells();
                    for (xwpftablecell xwpftablecell : cells) {
                        list<xwpfparagraph> paragraphs = xwpftablecell.getparagraphs();
                        for (xwpfparagraph xwpfparagraph : paragraphs) {
                            list<xwpfrun> runs = xwpfparagraph.getruns();
                            for(int i = 0; i < runs.size();i++){
                                xwpfrun run = runs.get(i);
                                tabletext.append(run.tostring());
                            }
                        }
                    }
                }
            }
            
            system.out.println(tabletext.tostring());
            
        } catch (ioexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }

}

测试
成功获取表格

下面我们来对一个wrod进行简单的修改,首先有个模板word,里面只有几个字

代码

public class firstwordtest {
    
        //模板文件地址
        private static string inputurl = "c:\users\zhihe\desktop\demo\001.docx";
        //新生产的模板文件
        private static string outputurl = "c:\users\zhihe\desktop\demo\test.docx";
        
        /**
         * 
         * @param inputurl 模板路径
         * @param outputurl 模板保存路径
         */
        public static void changeword(string inputurl, string outputurl ){
            
            try {
                //获取word文档解析对象
                xwpfdocument doucument = new xwpfdocument(poixmldocument.openpackage(inputurl));
                //获取段落文本对象
                list<xwpfparagraph> paragraph = doucument.getparagraphs();
                //获取首行run对象
                xwpfrun run = paragraph.get(0).getruns().get(0);
                //设置文本内容
                run.settext("修改了的word");
                //生成新的word
                file file = new file(outputurl);
                
                fileoutputstream stream = new fileoutputstream(file);
                doucument.write(stream);
                stream.close();
                
            } catch (ioexception e) {
                // todo auto-generated catch block
                e.printstacktrace();
            }
        }

        public static void main(string[] args) {
            changeword(inputurl,outputurl);
        }
}

测试
运行后生成新的word

但是在实际项目中并没有这么简单,模板文档中可能需要替换文本中的文字,也可能需要替换表格对象中的文字,或者在指定表格中插入数据,下面我们就仿照实际情况来做个简单的模板。

首先创建一个word的模板

工具类

package com.lovo.utils.wordtopdf;

import java.io.file;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import java.util.map.entry;
import java.util.set;
import org.apache.poi.poixmldocument;
import org.apache.poi.xwpf.usermodel.xwpfdocument;
import org.apache.poi.xwpf.usermodel.xwpfparagraph;
import org.apache.poi.xwpf.usermodel.xwpfrun;
import org.apache.poi.xwpf.usermodel.xwpftable;
import org.apache.poi.xwpf.usermodel.xwpftablecell;
import org.apache.poi.xwpf.usermodel.xwpftablerow;

/**
 * 通过word模板生成新的word工具类
 * 
 * @author zhiheng
 * 
 */
public class wordertonewwordutils {

    /**
     * 根据模板生成新word文档
     * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
     * @param inputurl 模板存放地址
     * @param outputurl 新文档存放地址
     * @param textmap 需要替换的信息集合
     * @param tablelist 需要插入的表格信息集合
     * @return 成功返回true,失败返回false
     */
    public static boolean changword(string inputurl, string outputurl,
            map<string, string> textmap, list<string[]> tablelist) {
        
        //模板转换默认成功
        boolean changeflag = true;
        try {
            //获取docx解析对象
            xwpfdocument document = new xwpfdocument(poixmldocument.openpackage(inputurl));
            //解析替换文本段落对象
            wordertonewwordutils.changetext(document, textmap);
            //解析替换表格对象
            wordertonewwordutils.changetable(document, textmap, tablelist);
            
            //生成新的word
            file file = new file(outputurl);
            fileoutputstream stream = new fileoutputstream(file);
            document.write(stream);
            stream.close();
            
        } catch (ioexception e) {
            e.printstacktrace();
            changeflag = false;
        }
        
        return changeflag;

    }

    /**
     * 替换段落文本
     * @param document docx解析对象
     * @param textmap 需要替换的信息集合
     */
    public static void changetext(xwpfdocument document, map<string, string> textmap){
        //获取段落集合
        list<xwpfparagraph> paragraphs = document.getparagraphs();
        
        for (xwpfparagraph paragraph : paragraphs) {
            //判断此段落时候需要进行替换
            string text = paragraph.gettext();
            if(checktext(text)){
                list<xwpfrun> runs = paragraph.getruns();
                for (xwpfrun run : runs) {
                    //替换模板原来位置
                    run.settext(changevalue(run.tostring(), textmap),0);
                }
            }
        }
        
    }
    
    /**
     * 替换表格对象方法
     * @param document docx解析对象
     * @param textmap 需要替换的信息集合
     * @param tablelist 需要插入的表格信息集合
     */
    public static void changetable(xwpfdocument document, map<string, string> textmap,
            list<string[]> tablelist){
        //获取表格对象集合
        list<xwpftable> tables = document.gettables();
        for (int i = 0; i < tables.size(); i++) {
            //只处理行数大于等于2的表格,且不循环表头
            xwpftable table = tables.get(i);
            if(table.getrows().size()>1){
                //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
                if(checktext(table.gettext())){
                    list<xwpftablerow> rows = table.getrows();
                    //遍历表格,并替换模板
                    eachtable(rows, textmap);
                }else{
//                  system.out.println("插入"+table.gettext());
                    inserttable(table, tablelist);
                }
            }
        }
    }
    

    
    
    
    /**
     * 遍历表格
     * @param rows 表格行对象
     * @param textmap 需要替换的信息集合
     */
    public static void eachtable(list<xwpftablerow> rows ,map<string, string> textmap){
        for (xwpftablerow row : rows) {
            list<xwpftablecell> cells = row.gettablecells();
            for (xwpftablecell cell : cells) {
                //判断单元格是否需要替换
                if(checktext(cell.gettext())){
                    list<xwpfparagraph> paragraphs = cell.getparagraphs();
                    for (xwpfparagraph paragraph : paragraphs) {
                        list<xwpfrun> runs = paragraph.getruns();
                        for (xwpfrun run : runs) {
                            run.settext(changevalue(run.tostring(), textmap),0);
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 为表格插入数据,行数不够添加新行
     * @param table 需要插入数据的表格
     * @param tablelist 插入数据集合
     */
    public static void inserttable(xwpftable table, list<string[]> tablelist){
        //创建行,根据需要插入的数据添加新行,不处理表头
        for(int i = 1; i < tablelist.size(); i++){
            xwpftablerow row =table.createrow();
        }
        //遍历表格插入数据
        list<xwpftablerow> rows = table.getrows();
        for(int i = 1; i < rows.size(); i++){
            xwpftablerow newrow = table.getrow(i);
            list<xwpftablecell> cells = newrow.gettablecells();
            for(int j = 0; j < cells.size(); j++){
                xwpftablecell cell = cells.get(j);
                cell.settext(tablelist.get(i-1)[j]);
            }
        }
        
    }
    
    
    
    /**
     * 判断文本中时候包含$
     * @param text 文本
     * @return 包含返回true,不包含返回false
     */
    public static boolean checktext(string text){
        boolean check  =  false;
        if(text.indexof("$")!= -1){
            check = true;
        }
        return check;
        
    }
    
    /**
     * 匹配传入信息集合与模板
     * @param value 模板需要替换的区域
     * @param textmap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static string changevalue(string value, map<string, string> textmap){
        set<entry<string, string>> textsets = textmap.entryset();
        for (entry<string, string> textset : textsets) {
            //匹配模板与替换值 格式${key}
            string key = "${"+textset.getkey()+"}";
            if(value.indexof(key)!= -1){
                value = textset.getvalue();
            }
        }
        //模板未匹配到区域替换为空
        if(checktext(value)){
            value = "";
        }
        return value;
    }
    
    
    
    
    public static void main(string[] args) {
        //模板文件地址
        string inputurl = "c:\users\zhihe\desktop\demo\001.docx";
        //新生产的模板文件
        string outputurl = "c:\users\zhihe\desktop\demo\test.docx";
        
        map<string, string> testmap = new hashmap<string, string>();
        testmap.put("name", "小明");
        testmap.put("sex", "男");
        testmap.put("address", "软件园");
        testmap.put("phone", "88888888");
        
        list<string[]> testlist = new arraylist<string[]>();
        testlist.add(new string[]{"1","1aa","1bb","1cc"});
        testlist.add(new string[]{"2","2aa","2bb","2cc"});
        testlist.add(new string[]{"3","3aa","3bb","3cc"});
        testlist.add(new string[]{"4","4aa","4bb","4cc"});
        
        wordertonewwordutils.changword(inputurl, outputurl, testmap, testlist);
    }
}

测试

这么我们就实现了个简单的poi操作模板完成替换和插入的功能,本来还准备实现固定位置插入图片的功能,不过发现这是个巨坑,暂时未实现其功能,等以后有空再进行完善,此代码以docx格式进行演示操作

如果遇到poi读取例如{name}不能识别为一个整体,可以使用word的域操作,如果不太清楚域的使用,可以这么操作,先在text文档中写好,例如{name},然后再整个复制到word中,不要一个一个在word中敲,不然有可能不会被poi识别为一个整体

《easypoi导出word换行(easypoi导出数字类型).doc》

下载本文的Word格式文档,以方便收藏与打印。