java POI对word中的表格动态插入固定数据,以及插入不具体的数据

遇到个项目本来是用Execl导出的,相对简单,客户要求用Word导出,并按照他们给的模板进行导出;
从网上百度了一下,然后自己修改下,实现了对word中的同一张表格同时进行通过key替换操作,以及从特定的行开始插入数据,根据是需要插入的数据自动增加行等;下面直接上主要代码,都有注释。

maven依赖包引入

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
</dependency>

工具类

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;

public class WordUtil {
	
	
    /**
     * 根据模板生成新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));
            //解析替换文本段落对象
            WordUtil.changeText(document, textMap);
            //解析替换表格对象
            WordUtil.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();
        //获取第一个表格   根据实际模板情况 决定去第几个word中的表格
        XWPFTable table = tables.get(0);
        
        //表格中的内容替换
        List<XWPFTableRow> rows = table.getRows();
        eachTable(rows, textMap);//遍历表格,并替换模板
        
        //向特定位置 行插入数据
        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){
        //创建行,根据需要插入的数据添加新行,不处理表头
    	//判断需要插入的数量
    	if (tableList.size() > 5) {//我的模板预留了五行
    		for (int i=0;i<tableList.size()-4;i++) {
    			insertRow(table,10,14);
    		}
		} 
        //遍历表格插入数据
        List<XWPFTableRow> rows = table.getRows();
        for(int i = 9; i < tableList.size() + 9; 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-9)[j]);
            }
        }
        
    }
    
    /**
     * 判断文本中时候包含$
     * @param text 文本
     * @return 包含返回true,不包含返回false
     */
    public static boolean checkText(String text){
        boolean check  =  false;
        if(text.indexOf("$")!= -1){
            check = true;
        }
        return check;
        
    }
	/**
	 * insertRow 在word表格中指定位置插入一行,并将某一行的样式复制到新增行
	 * @param copyrowIndex 需要复制的行位置
	 * @param newrowIndex 需要新增一行的位置
	 * */
	public static void insertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {
		// 在表格中指定的位置新增一行
		XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
		// 获取需要复制行对象
		XWPFTableRow copyRow = table.getRow(copyrowIndex);
		//复制行对象
		targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
		//或许需要复制的行的列
		List<XWPFTableCell> copyCells = copyRow.getTableCells();
		//复制列对象
		XWPFTableCell targetCell = null;
		for (int i = 0; i < copyCells.size(); i++) {
			XWPFTableCell copyCell = copyCells.get(i);
			targetCell = targetRow.addNewTableCell();
			targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
			if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
				targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
				if (copyCell.getParagraphs().get(0).getRuns() != null
						&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {
					XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
					cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
				} 
			} 
		}
		
	}
    /**
     * 匹配传入信息集合与模板
     * @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 = "E:\\beian\\demo1.docx";
        //新生产的模板文件
        String outputUrl = "E:\\beian\\demo3.docx";
        
        Map<String, String> testMap = new HashMap<String, String>();
        testMap.put("type0", "注销");
        testMap.put("application", "票据系统");
        testMap.put("dept", "信息中心");
        testMap.put("unit", "111111");
        testMap.put("type1", "2");
        testMap.put("type2", "3");
        testMap.put("type3", "4");
        testMap.put("type4", "5");
        
        List<String[]> testList = new ArrayList<String[]>();
        testList.add(new String[]{"1","Q1","W1","E1","R1","T1"});
        testList.add(new String[]{"2","Q2","W2","E2","R2","T2"});
        testList.add(new String[]{"3","Q3","W3","E3","R3","T3"});
        testList.add(new String[]{"4","Q4","W4","E4","R4","T4"});
        testList.add(new String[]{"5","Q5","W5","E5","R5","T5"});
        testList.add(new String[]{"6","Q6","W6","E6","R6","T6"});
        testList.add(new String[]{"7","Q7","W7","E7","R7","T7"});
        
        WordUtil.changWord(inputUrl, outputUrl, testMap, testList);
    }

}

模板

java JodConverter openoffice模板填充 java word 动态填充_apache

${type0}中的内容 为要替换的部分,用text写,然后复制进来, 不然可能无法替换,直接在word中写,会可能被认为一整个对象,无法替换成功

结果:

java JodConverter openoffice模板填充 java word 动态填充_List_02