Word 模板动态数据合成

/*
 * Copyright (c) 2017 西安才多信息技术有限责任公司。
 * 项目名称:dev
 * 文件名称:DocxTemplateUtils.java
 * 日期:17-10-11 下午2:18
 * 作者:yangyan
 *
 */

package com.deyatong.common.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * WORD DOCX 文件变量替换输出工具类
 */
public class DocxTemplateUtils {

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 变量替换符号的正则,用来找到 ${xxx} 这样的内容,并实现替换
     */
    Pattern compile = Pattern.compile("(\\$\\{([^\\}]*)\\})");
    private final Map<String, ?> params;  //数据填充对象
    InputStream is;    //读入模板文件的流
    XWPFDocument doc;  //内存中构建的文档对象

    /**
     * 使用文件路径和变量集合创建
     *
     * @param templateDocxFile
     * @param params
     */
    public DocxTemplateUtils(String templateDocxFile, Map<String, ?> params) {
        this.params = params;
        try {
            is = new FileInputStream(templateDocxFile);
            doc = new XWPFDocument(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用文件和和变量集合创建
     *
     * @param templateDocxFile
     * @param params
     */
    public DocxTemplateUtils(File templateDocxFile, Map<String, ?> params) {
        this.params = params;
        try {
            is = new FileInputStream(templateDocxFile);
            doc = new XWPFDocument(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用模板读入的流和变量集合创建
     *
     * @param templateDocxFileInputStream
     * @param params
     */
    public DocxTemplateUtils(InputStream templateDocxFileInputStream, Map<String, ?> params) {
        this.params = params;
        try {
            is = templateDocxFileInputStream;
            doc = new XWPFDocument(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 此类为poi操作word模板的工具类
     **/
    public XWPFDocument getDoc() {
        return doc;
    }

    /**
     * 替换所有段落中的变量
     */
    public void replaceInPara() {
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
        XWPFParagraph para;
        while (iterator.hasNext()) {
            para = iterator.next();
            this.replaceInPara(para);
        }
    }

    /**
     * 替换传入段落里面的变量
     *
     * @param para 要替换的段落
     */
    private void replaceInPara(XWPFParagraph para) {
        String paragraphText = para.getParagraphText();
        int start = paragraphText.indexOf("${");
        int end = paragraphText.indexOf("}");
        if (start == -1 && end == -1) { //段落中没有变量直接跳过
            logger.warn("没开始,没结束,直接跳过:" + paragraphText);
            return;
        }
        boolean isStart = false;
        boolean isEnd = false;
        StringBuilder varName = null;
        List<XWPFRun> runs;
        Matcher matcher;
        runs = para.getRuns(); //不同的文字片段可能有不同的样式
        logger.info("整段:" + paragraphText);

//        for (int i = 0; i < runs.size(); i++) {
//            XWPFRun run = runs.get(i);
//            String runText = run.toString().trim();
//            System.out.println(runText);
//        }

        for (int i = 0; i < runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runText = run.toString().trim();
            logger.debug(">>>处理文字片段:" + runText);
            String tail = "";
            if (runText.trim().length() == 0) {
                continue;
            }
            if (varName == null) {
                varName = new StringBuilder();
            }
            int s = runText.indexOf("${");
            if (s > -1) { //有开始
                int n = runText.indexOf("}", s);
                if (n != -1) { //有结束
                    varName.append(runText.substring(s, n + 1));
                    isEnd = true;
                    if (runText.indexOf("${", n) != -1) { //一行内是否有第二个变量开启
                        isStart = true;
                    }
                    tail = runText.substring(n + 1);
                } else { //没结束
                    isStart = true;
                    isEnd = false;
                    varName.append(runText.substring(s));
                    run.setText("", 0);
                }
            } else { //没开始
                if (isStart) { //之前开始了
                    int n = runText.indexOf("}");
                    if (n == -1) { //没结束
                        varName.append(runText);
                        run.setText("", 0);
                    } else { //结束
                        isStart = false;
                        varName.append(runText.substring(0, n + 1));
                        if (runText.indexOf("${", n) != -1) { //一行内是否有第二个变量开启
                            isStart = true;
                            tail = runText.substring(n + 1);
                        }
                        isEnd = true;
                    }
                }
            }
            if (isEnd) {
                String s1 = varName.toString();
                logger.warn("拼接结果:" + s1);
                Object o = params.get(s1);
                String value = o == null ? "" : o.toString();
                run.setText(value + tail, 0);
                varName = null;
                isEnd = false;
            }
//            if (s == -1) { //如果没有开始标记后面的就不用执行了
//                break;
//            }
            //文字替换处理
            matcher = compile.matcher(runText);
            while (matcher.find()) {
                String group = matcher.group(1);
                logger.debug("----找到变量:" + group + String.format(",文字片段内位置:(%s-%s)", matcher.start(), matcher.end()));
                Object o = params.get(group);
                String replacement = "";
                if (o != null) {
                    if (o instanceof List) {
                        //替换的内容
                        logger.debug("----变量替换成为:" + StringUtils.join(o));
                        run.setText("", 0);
                        List list = (List) o;
                        for (Object o1 : list) {
                            run.addCarriageReturn();
                            run.setText(o1.toString());
                        }
                        break;
                    } else {
                        replacement = o.toString();
                        //替换的内容
                        runText = matcher.replaceFirst(replacement);
                        logger.debug("----变量替换成为:" + replacement);
                        run.setText(runText, 0);
                        logger.debug(">>>片段替换成为:" + runText);
                    }
                }
            }
        }
    }


    /**
     * 替换表格里面的变量
     */
    public void replaceInTable() {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        while (iterator.hasNext()) {
            table = iterator.next();
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    paras = cell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                        this.replaceInPara(para);
                    }
                }
            }
        }
    }

    /**
     * 关闭输入流
     */
    public void closeInputStream() {
        if (is != null) {
            try {
                is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭输出流
     *
     * @param os
     */
    public void closeOutputStream(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void addTablesRows(List<List<String>> data, int tableIndex, int rowIndex) {
        List<XWPFTable> list = doc.getTables();
        System.out.println("----" + list.size());
        XWPFTable xt = list.get(tableIndex);
        if (rowIndex < 0 || (rowIndex + 1) > xt.getNumberOfRows()) {
            rowIndex = xt.getNumberOfRows() - 1;
        }
        XWPFTableRow row1 = xt.getRow(rowIndex + 1);
        if (row1 == null) {
            row1 = xt.createRow();
            addTablesRows(data, tableIndex, rowIndex);
            return;
        }
        for (int i = 0; i < data.size(); i++) {
            XWPFTableRow row2 = xt.getRow(rowIndex + i);
            if (row2 == null) {
                row2 = xt.createRow();
            }
            List<XWPFTableCell> cells = row2.getTableCells();
            List<String> clist = data.get(i);
            for (int k = 0; k < clist.size(); k++) {
                XWPFTableCell cell = row2.getCell(k);
                cell.setText(clist.get(k));
            }
        }
    }
}

 

Leave a Comment

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据