js 请求后端
function exportWord(opId){ location.href=ctx+'/maintainPro/downloadWord?opId='+opId+"&type=0"; }
java后端代码示例
@RequestMapping(value = "/downloadWord") @AdminToolControllerLog(description = "word文档下载") public void downloadTemplate(HttpServletRequest req, HttpServletResponse resp,Long opId,String type) throws Exception { JsonMsg msg = new JsonMsg(); MaintainPro maintainPro = maintainproService.findMaintainPro(opId); String classpath = this.getClass().getResource("/").getPath(); String docRoot = classpath.replaceAll("WEB-INF/classes/", ""); String wordDirUrl = "static/resources/word/"; // String docRoot = classpath.replaceAll("classes/", ""); // String wordDirUrl = "RePlan/static/resources/word/"; String fileName="项目申报书.docx"; //word模板名称 String filePath =docRoot+wordDirUrl+fileName;
Map<String, Object> ini = getIniMap(maintainPro); //获取固定字段信息 List<Map<String, Object>> list1 = getTableList(maintainPro,1L); //获取列表数据 List<Map<String, Object>> list2 = getTableList(maintainPro,2L); List<Map<String, Object>> list3 = getTableList(maintainPro,3L); WordReporter wordReporter = new WordReporter(); wordReporter.setTempLocalPath(filePath); wordReporter.init(ini); //固定字段赋值 wordReporter.replaceTableParams(ini, 0); //对应表格固定字段信息赋值 (0指word模板中第一个表格,依次类推) wordReporter.replaceTableParams(ini, 1); wordReporter.replaceTableParams(ini, 2); wordReporter.replaceTableParams(ini, 3); wordReporter.replaceTableParams(ini, 4); wordReporter.replaceTableParams(ini, 5); //遍历(设备、产品软件、应用软件)表格 wordReporter.export(list1,6,1,1); //需要遍历的列表赋值 (6指word模板中第7个表格,表格从第1行开始,以第1行作为创建行) wordReporter.export(list2,7,1,1); wordReporter.export(list3,8,1,1); int index = fileName.indexOf("."); String prefix = fileName.substring(0,index); fileName = fileName.replace(prefix, maintainPro.getPiName()+"申报书"); //导出文件重新命名 buildWordheader(req, resp, fileName); //刷新缓冲 resp.flushBuffer(); OutputStream ouputStream = resp.getOutputStream(); wordReporter.getXwpfDocument().write(ouputStream); if (ouputStream != null) { ouputStream.close(); } msg.setSuccess(true); }
//将对象中所需字段转map
public Map<String,Object> getIniMap(MaintainPro maintainPro){ Map<String, Object> map = maintainproService.findIniMapById(maintainPro.getOpId()); if(map!=null) { if(map.get("PI_NAME")!=null) {//项目名称 map.put("piName", map.get("PI_NAME").toString()); } } return map; }
public void buildWordheader(HttpServletRequest req, HttpServletResponse resp,String filename) throws UnsupportedEncodingException { resp.reset(); String fileNameURL = URLEncoder.encode(filename, "UTF-8"); resp.setCharacterEncoding("UTF-8"); //response.setHeader("Content-disposition", "attachment;filename=" + fileName); resp.setHeader("Content-disposition", "attachment;filename=" + fileNameURL + ";" + "filename*=utf-8''" + fileNameURL); resp.setContentType("application/octet-stream"); }
package com.ustc.base.common.util; import org.apache.commons.lang.StringUtils; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; 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; /** * Created by lzx on 2018/8/12 */ public class WordReporter { private String tempLocalPath; private XWPFDocument xwpfDocument = null; private FileInputStream inputStream = null; private OutputStream outputStream = null; public WordReporter(){ } public WordReporter(String tempLocalPath){ this.tempLocalPath = tempLocalPath; } /** * 设置模板路径 * @param tempLocalPath */ public void setTempLocalPath(String tempLocalPath) { this.tempLocalPath = tempLocalPath; } /** * 初始化 * @throws IOException */ public void init(Map<String,Object> params) throws IOException{ inputStream = new FileInputStream(new File(this.tempLocalPath)); xwpfDocument = new XWPFDocument(inputStream); replaceParams(xwpfDocument, params); } /** * 替换段落里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ private static void replaceParams(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); XWPFParagraph paragraph; while (iterator.hasNext()) { paragraph = iterator.next(); replaceParam(paragraph, params); } } /** * 替换段落里面的变量 * * @param paragraph 要替换的段落 * @param params 参数 */ private static void replaceParam(XWPFParagraph paragraph, Map<String, Object> params) { List<XWPFRun> runs; Matcher matcher; String runText = ""; if (matcher(paragraph.getParagraphText()).find()) { runs = paragraph.getRuns(); int j = runs.size(); for (int i = 0; i < j; i++) { runText += runs.get(0).toString(); //保留最后一个段落,在这段落中替换值,保留段落样式 if (!((j - 1) == i)) { paragraph.removeRun(0); } } matcher = matcher(runText); if (matcher.find()) { while ((matcher = matcher(runText)).find()) { runText = matcher.replaceFirst(params.get(matcher.group(1))==null?"":params.get(matcher.group(1)).toString()); // runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1)))); } runs.get(0).setText(runText, 0); } } } /** * 正则匹配字符串 * * @param str * @return */ private static Matcher matcher(String str) { Pattern pattern = Pattern.compile("\$\{(.+?)\}", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); return matcher; } /** * @param doc docx解析对象 * @param params 需要替换的信息集合 * @param tableIndex 第几个表格 * @param tableList 需要插入的表格信息集合 */ public static void changeTable(XWPFDocument doc, Map<String, Object> params, int tableIndex, List<String[]> tableList) { //获取表格对象集合 List<XWPFTable> tables = doc.getTables(); //获取第一个表格 根据实际模板情况 决定去第几个word中的表格 XWPFTable table = tables.get(tableIndex); //替换表格中的参数 // replaceTableParams(params,0); //在表格中插入数据 insertTable(table, tableList); } /** * 为表格插入行数,此处不处理表头,所以从第二行开始 * * @param table 需要插入数据的表格 * @param tableList 插入数据集合 */ private static void insertTable(XWPFTable table, List<String[]> tableList) { //创建与数据一致的行数 for (int i = 0; i < tableList.size(); i++) { table.createRow(); } int length = table.getRows().size(); for (int i = 1; i < length; 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 doc 要替换的文档 * @param params 参数 */ public void replaceTableParams( Map<String, Object> params,int tableIndex) { List<XWPFTable> tableList = xwpfDocument.getTables(); XWPFTable table =tableList.get(tableIndex);; List<XWPFTableRow> rows; List<XWPFTableCell> cells; List<XWPFParagraph> paras; //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 if (matcher(table.getText()).find()) { rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); for (XWPFParagraph para : paras) { replaceParam(para, params); } } } } } /** * 导出方法 * @param params * @param tableIndex word的表格索引 * @param rownum 从第几行开始 * @param createrowindex 以第几行作为创建行 * @return * @throws Exception */ public boolean export(List<Map<String,Object>> params, int tableIndex,int rownum,int createrowindex) throws Exception{ this.insertValueToTable(xwpfDocument,params,tableIndex,rownum,createrowindex); return true; } /** * 循环填充表格内容 * @param xwpfDocument * @param params * @param tableIndex * @throws Exception */ private void insertValueToTable(XWPFDocument xwpfDocument, List<Map<String,Object>> params, int tableIndex,int rownum,int createrowindex) throws Exception { List<XWPFTable> tableList = xwpfDocument.getTables(); if(tableList.size()<=tableIndex){ throw new Exception("tableIndex对应的表格不存在"); } XWPFTable table = tableList.get(tableIndex); List<XWPFTableRow> rows = table.getRows(); if(rows.size()<2){ throw new Exception("tableIndex对应表格应该为2行"); } //模板的那一行 XWPFTableRow tmpRow = rows.get(rownum); List<XWPFTableCell> tmpCells = null; List<XWPFTableCell> cells = null; XWPFTableCell tmpCell = null; tmpCells = tmpRow.getTableCells(); table.getCTTbl(); String cellText = null; String cellTextKey = null; Map<String,Object> totalMap = null; for (int i = 0, len = params.size(); i < len; i++) { Map<String,Object> map = params.get(i); // 创建新的一行 // XWPFTableRow row = table.createRow(); XWPFTableRow row = createRow(table.getCTTbl(),table,createrowindex); // 获取模板的行高 设置为新一行的行高 row.setHeight(tmpRow.getHeight()); cells = row.getTableCells(); for (int k = 0, klen = cells.size(); k < klen; k++) { tmpCell = tmpCells.get(k); XWPFTableCell cell = cells.get(k); cellText = tmpCell.getText(); if (StringUtils.isNotBlank(cellText)) { //转换为mapkey对应的字段 cellTextKey = cellText.replace("$", "").replace("{", "").replace("}", "").replaceAll("[^a-zA-Z0-9_\u4E00-\u9FA5]", ""); if (map.containsKey(cellTextKey)) { // 填充内容 并且复制模板行的属性 setCellText(tmpCell,cell,map.get(cellTextKey)==null?"":map.get(cellTextKey).toString()); } } } } // 删除模版行 table.removeRow(rownum); } private XWPFTableRow createRow(CTTbl ctTbl,XWPFTable table,int i){ int sizeCol = ctTbl.sizeOfTrArray() > 0 ? ctTbl.getTrArray(i) .sizeOfTcArray() : 0; XWPFTableRow tabRow = new XWPFTableRow(ctTbl.addNewTr(), table); addColumn(tabRow, sizeCol); //tableRows.add(tabRow); return tabRow; } private void addColumn(XWPFTableRow tabRow, int sizeCol) { if (sizeCol > 0) { for (int i = 0; i < sizeCol; i++) { tabRow.createCell(); } } } /** * 复制模板行的属性 * @param tmpCell * @param cell * @param text * @throws Exception */ private void setCellText(XWPFTableCell tmpCell, XWPFTableCell cell,String text) throws Exception { CTTc cttc2 = tmpCell.getCTTc(); CTTcPr ctPr2 = cttc2.getTcPr(); CTTc cttc = cell.getCTTc(); CTTcPr ctPr = cttc.addNewTcPr(); if (ctPr2.getTcW() != null) { ctPr.addNewTcW().setW(ctPr2.getTcW().getW()); } if (ctPr2.getVAlign() != null) { ctPr.addNewVAlign().setVal(ctPr2.getVAlign().getVal()); } if (cttc2.getPList().size() > 0) { CTP ctp = cttc2.getPList().get(0); if (ctp.getPPr() != null) { if (ctp.getPPr().getJc() != null) { cttc.getPList().get(0).addNewPPr().addNewJc() .setVal(ctp.getPPr().getJc().getVal()); } } } if (ctPr2.getTcBorders() != null) { ctPr.setTcBorders(ctPr2.getTcBorders()); } XWPFParagraph tmpP = tmpCell.getParagraphs().get(0); XWPFParagraph cellP = cell.getParagraphs().get(0); XWPFRun tmpR = null; if (tmpP.getRuns() != null && tmpP.getRuns().size() > 0) { tmpR = tmpP.getRuns().get(0); } XWPFRun cellR = cellP.createRun(); cellR.setText(text); // 复制字体信息 if (tmpR != null) { if(!cellR.isBold()){ cellR.setBold(tmpR.isBold()); } cellR.setItalic(tmpR.isItalic()); cellR.setUnderline(tmpR.getUnderline()); cellR.setColor(tmpR.getColor()); cellR.setTextPosition(tmpR.getTextPosition()); if (tmpR.getFontSize() != -1) { cellR.setFontSize(tmpR.getFontSize()); } if (tmpR.getFontFamily() != null) { cellR.setFontFamily(tmpR.getFontFamily()); } if (tmpR.getCTR() != null) { if (tmpR.getCTR().isSetRPr()) { CTRPr tmpRPr = tmpR.getCTR().getRPr(); if (tmpRPr.isSetRFonts()) { CTFonts tmpFonts = tmpRPr.getRFonts(); CTRPr cellRPr = cellR.getCTR().isSetRPr() ? cellR .getCTR().getRPr() : cellR.getCTR().addNewRPr(); CTFonts cellFonts = cellRPr.isSetRFonts() ? cellRPr .getRFonts() : cellRPr.addNewRFonts(); cellFonts.setAscii(tmpFonts.getAscii()); cellFonts.setAsciiTheme(tmpFonts.getAsciiTheme()); cellFonts.setCs(tmpFonts.getCs()); cellFonts.setCstheme(tmpFonts.getCstheme()); cellFonts.setEastAsia(tmpFonts.getEastAsia()); cellFonts.setEastAsiaTheme(tmpFonts.getEastAsiaTheme()); cellFonts.setHAnsi(tmpFonts.getHAnsi()); cellFonts.setHAnsiTheme(tmpFonts.getHAnsiTheme()); } } } } // 复制段落信息 cellP.setAlignment(tmpP.getAlignment()); cellP.setVerticalAlignment(tmpP.getVerticalAlignment()); cellP.setBorderBetween(tmpP.getBorderBetween()); cellP.setBorderBottom(tmpP.getBorderBottom()); cellP.setBorderLeft(tmpP.getBorderLeft()); cellP.setBorderRight(tmpP.getBorderRight()); cellP.setBorderTop(tmpP.getBorderTop()); cellP.setPageBreak(tmpP.isPageBreak()); if (tmpP.getCTP() != null) { if (tmpP.getCTP().getPPr() != null) { CTPPr tmpPPr = tmpP.getCTP().getPPr(); CTPPr cellPPr = cellP.getCTP().getPPr() != null ? cellP .getCTP().getPPr() : cellP.getCTP().addNewPPr(); // 复制段落间距信息 CTSpacing tmpSpacing = tmpPPr.getSpacing(); if (tmpSpacing != null) { CTSpacing cellSpacing = cellPPr.getSpacing() != null ? cellPPr .getSpacing() : cellPPr.addNewSpacing(); if (tmpSpacing.getAfter() != null) { cellSpacing.setAfter(tmpSpacing.getAfter()); } if (tmpSpacing.getAfterAutospacing() != null) { cellSpacing.setAfterAutospacing(tmpSpacing .getAfterAutospacing()); } if (tmpSpacing.getAfterLines() != null) { cellSpacing.setAfterLines(tmpSpacing.getAfterLines()); } if (tmpSpacing.getBefore() != null) { cellSpacing.setBefore(tmpSpacing.getBefore()); } if (tmpSpacing.getBeforeAutospacing() != null) { cellSpacing.setBeforeAutospacing(tmpSpacing .getBeforeAutospacing()); } if (tmpSpacing.getBeforeLines() != null) { cellSpacing.setBeforeLines(tmpSpacing.getBeforeLines()); } if (tmpSpacing.getLine() != null) { cellSpacing.setLine(tmpSpacing.getLine()); } if (tmpSpacing.getLineRule() != null) { cellSpacing.setLineRule(tmpSpacing.getLineRule()); } } // 复制段落缩进信息 CTInd tmpInd = tmpPPr.getInd(); if (tmpInd != null) { CTInd cellInd = cellPPr.getInd() != null ? cellPPr.getInd() : cellPPr.addNewInd(); if (tmpInd.getFirstLine() != null) { cellInd.setFirstLine(tmpInd.getFirstLine()); } if (tmpInd.getFirstLineChars() != null) { cellInd.setFirstLineChars(tmpInd.getFirstLineChars()); } if (tmpInd.getHanging() != null) { cellInd.setHanging(tmpInd.getHanging()); } if (tmpInd.getHangingChars() != null) { cellInd.setHangingChars(tmpInd.getHangingChars()); } if (tmpInd.getLeft() != null) { cellInd.setLeft(tmpInd.getLeft()); } if (tmpInd.getLeftChars() != null) { cellInd.setLeftChars(tmpInd.getLeftChars()); } if (tmpInd.getRight() != null) { cellInd.setRight(tmpInd.getRight()); } if (tmpInd.getRightChars() != null) { cellInd.setRightChars(tmpInd.getRightChars()); } } } } } /** * 收尾方法 * @param outDocPath * @return * @throws IOException */ public boolean generate(String outDocPath) throws IOException{ outputStream = new FileOutputStream(outDocPath); xwpfDocument.write(outputStream); this.close(outputStream); this.close(inputStream); return true; } /** * 关闭输入流 * @param is */ private void close(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 关闭输出流 * @param os */ private void close(OutputStream os) { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } public XWPFDocument getXwpfDocument() { return xwpfDocument; } public OutputStream getOutputStream() { return outputStream; } }
word模板示例: