Java-POI替换Word模板文档中的变量,生成Word文档

来源:互联网 发布:单片机电流采样电路 编辑:程序博客网 时间:2024/06/06 08:41

第一步:在项目中导入POI的jar包,以及相关的jar包。

所需的jar包列表:

下载地址:http://download.csdn.net/download/qq_34908167/10046670


第二步:建立util工具类。

public class DocxUtil{    /**      * @Description: 将t中的字段转换成替换模板需要的数据${字段}-->字段值*      在word模板中变量为${valuename},为每个值建一个以‘${valuename}’为键,‘value’为值的Map集合,*      利用键去和Word模板中寻找相等的变量     */    public <T> Map<String, String> copyParamFromBean(T t, Map<String, String> params) {        Field[] fields = t.getClass().getDeclaredFields();        String key;        String value;        for (Field field : fields) {            String fieldName = field.getName();            key = "${" + fieldName + "}";            String name = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);            try {                value = String.valueOf(t.getClass().getMethod(name).invoke(t));                params.put(key, value);            } catch (Exception e) {                e.printStackTrace();            }        }        return params;    }/****替换Word模板中的对应变量。*两种情况:1-段落中的变量。 2-表格中的变量*/ public static void searchAndReplace(XWPFDocument document,Map<String, String> map) {        try {            // 替换段落中的指定文字            Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();//获得word中段落            while (itPara.hasNext()) {       //遍历段落                XWPFParagraph paragraph = (XWPFParagraph) itPara.next();                Set<String> set = map.keySet();                Iterator<String> iterator = set.iterator();                while (iterator.hasNext()) {                    String key = iterator.next();                    List<XWPFRun> run=paragraph.getRuns();                    for(int i=0;i<run.size();i++)                    {                        if(run.get(i).getText(run.get(i).getTextPosition())!=null &&                                run.get(i).getText(run.get(i).getTextPosition()).equals(key))                        {                            /**                             * 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始                             * 就可以把原变量替换掉                             */                            run.get(i).setText(map.get(key),0);                        }                    }                }            }                     // 替换表格中的指定文字            Iterator<XWPFTable> itTable = document.getTablesIterator();//获得Word的表格            while (itTable.hasNext()) { //遍历表格                XWPFTable table = (XWPFTable) itTable.next();                int count = table.getNumberOfRows();//获得表格总行数                for (int i = 0; i < count; i++) { //遍历表格的每一行                    XWPFTableRow row = table.getRow(i);//获得表格的行                    List<XWPFTableCell> cells = row.getTableCells();//在行元素中,获得表格的单元格                    for (XWPFTableCell cell : cells) {   //遍历单元格                        for (Entry<String, String> e : map.entrySet()) {                            if (cell.getText().equals(e.getKey())) {//如果单元格中的变量和‘键’相等,就用‘键’所对应的‘值’代替。                                cell.removeParagraph(0);//所以这里就要求每一个单元格只能有唯一的变量。                                cell.setText(e.getValue());                            }                        }                    }                }            }        } catch (Exception e) {            e.printStackTrace();        }    }/**     * 关闭输出流     *     * @param os     */    public void close(OutputStream os) {        if (os != null) {            try {                os.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}


第三步:在项目的对应目录下放入Word模板。

这里给出我的Word模板:http://download.csdn.net/download/qq_34908167/10046772

第四步:导出Word的实现。

public String exportDoc(){        XWPFDocument doc = null;        OutputStream out = null;        FileInputStream in = null;        DocxUtil docxUtil = null;        try {            String rootPath = "";            ServletContext context = servletRequest.getSession().getServletContext();            String studentId = this.servletRequest.getParameter("studentid");//得到页面的参数            RankExportDocVO docVo=null;            if (studentId!=null) {                rootPath = context.getRealPath("/docmodel/PG/RankPrintAll_WordTemplate.docx");//Word模板所在的路径                docVo = rankPrintService.queryStudentInfo((studentId);//调用service得到对应的VO类            }else{                throw new Exception("传输字段为空!");            }            Map<String, String> params = new HashMap<String, String>();            docxUtil = new DocxUtil();            XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(rootPath));//读取Word模板            docxUtil.copyParamFromBean(docVo, params);//调用DocxUtil中的copyParamFromBean方法,为VO的每个值建立“${valuename}”键            docxUtil.searchAndReplace(document, params);//替换模板中的对应变量。            // 清空response            this.servletResponse.reset();            // 设置response的Header            String userAgent = this.servletRequest.getHeader("User-Agent");            String realname = "学生信息文档_"+docVo.getXm()+".docx";//最终导出文档的新文档名            if (userAgent.contains("Firefox")) {                // 采用BASE64编码                realname = "=?UTF-8?B?" + new BASE64Encoder().encode(realname.getBytes("utf-8")) + "?=";            } else {                // 其它浏览器 IE 、google 采用URL编码                realname = URLEncoder.encode(realname, "utf-8");                realname = realname.replace("+", " ");            }            servletResponse.setHeader("Content-Disposition", "attachment;filename=" + realname);            String minitype = ServletActionContext.getServletContext().getMimeType(realname);            servletResponse.setContentType(minitype);            out = this.servletResponse.getOutputStream();            document.write(out);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != docxUtil) {                docxUtil.close(out);//关闭流            }        }        return null;    }


这就是利用Java-poi技术导出Word文档的全部步骤。

这样的好处,就在于我们可以根据需求制定我们需要的Word样式。

注意事项:

1:Word模板中,表格的单元格的变量必须是唯一的,如果需要多个变量,我们可以利用word的隐藏表格功能,

来实现视觉上的一个单元格有多个变量的效果。

2:Word模板中的变量左右不能有空格,不然不能识别。