700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 利用poi读取word模板文件生成新的word文档

利用poi读取word模板文件生成新的word文档

时间:2019-10-27 13:52:49

相关推荐

利用poi读取word模板文件生成新的word文档

利用poi读取word模板文件生成新的word文档

利用poi读取word模板文件,并回填逻辑数据,生成并导出需要的word文档源码。解决模板读取异常问题,提供wordUtils工具类(各种功能实现)

第一步:

项目结构见下图:

第二步:

前端界面见下

第三步:

模板样式

第四步:

输出结果

核心代码如下:

package com.word.poi.demo.controller;import com.word.poi.demo.service.WordService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.MediaType;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;import java.io.InputStream;import java.io.OutputStream;import java.text.SimpleDateFormat;import java.util.Date;@RestController@RequestMapping("/word")@CrossOrigin(origins = "*", maxAge = 3600)@Api(tags = "word文档处理")public class WordController {@Autowiredprivate WordService wordService;@RequestMapping(value = "/exportWord",method = RequestMethod.GET)@ApiOperation(value = "生成并导出word文档", httpMethod = "GET", notes = "生成并导出word文档", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)public void exportFDDBrief(HttpServletResponse response) throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HHmmss");//获取统计时间段String time = "10.09-10.19";String wordName = "Word版-("+time+")"+sdf.format(new Date());// 告诉浏览器用什么软件可以打开此文件response.reset();// 清空输出流response.setHeader("content-Type", "application/msword");// 下载文件的默认名称response.setHeader("Content-Disposition", "attachment;filename="+new String(wordName.getBytes("GB2312"), "8859_1") + ".docx");OutputStream out = response.getOutputStream();//读取word模板InputStream in = this.getClass().getResourceAsStream("/templates/wordTemplate.docx");wordService.exportWord(in,out,"全球");}}

package com.word.poi.demo.util;import mons.collections4.CollectionUtils;import mons.lang3.StringUtils;import org.apache.poi.xwpf.usermodel.*;import java.io.IOException;import java.io.InputStream;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;/*** 通过word模板生成新的word工具类* */public class WorderToNewWordUtils {/*** 根据模板生成新word文档* 判断表格是需要替换还是需要插入,判断逻辑有${}为替换,表格无${}为插入* @param textMap 需要替换的信息集合* @return 成功返回true,失败返回false*/public static XWPFDocument changWordForcommon(InputStream in,Map<String, String> textMap) {XWPFDocument document = null;try {//第一步:获取docx解析对象document = new XWPFDocument(in);//第二步:重构XWPFDocument中 不合格的 占位符 比如:${abcd}分开为${a,b..,cd}refactorXWPFDocument(document);//第三步:解析替换文本段落对象changeText(document, textMap);//第四步:解析替换表格对象changeTableCity(document, textMap);} catch (IOException e) {e.printStackTrace();}return document;}/*** 根据模板生成新word文档* 判断表格是需要替换还是需要插入,判断逻辑有${}为替换,表格无${}为插入* @param textMap 需要替换的信息集合* @param extendTableMap 需要插入的表格信息集合* @param colorMapForCell* @return 成功返回true,失败返回false*/public static XWPFDocument changWordForComplex(InputStream in,Map<String, String> textMap, Map<String, List<List<String>>> extendTableMap,Map<String, List<String>> colorMapForCell) {XWPFDocument document = null;try {//第一步:获取docx解析对象document = new XWPFDocument(in);//第二步:重构XWPFDocument中 不合格的 占位符 比如:${abcd}分开为${a,b..,cd}refactorXWPFDocument(document);//第三步:解析替换文本段落对象changeText(document, textMap);//第四步:解析替换表格对象changeTableProvince(document, textMap, extendTableMap);//第五步:根据逻辑设置表格cell的背景颜色setColorForCell(document,colorMapForCell);} catch (IOException e) {e.printStackTrace();}return document;}private static void setColorForCell(XWPFDocument document, Map<String, List<String>> colorMapForCell) {List<XWPFTable> tables = document.getTables();for (int i = 0; i <tables.size() ; i++) {List<String> placeList = colorMapForCell.get("table" + i);//获取表格坐标listif (CollectionUtils.isNotEmpty(placeList)){for (String palce:placeList) {String[] split = palce.split(",");int x = Integer.parseInt(split[0]);int y = Integer.parseInt(split[1]);tables.get(i).getRow(x).getCell(y).setColor("FF0000");}}}}/*** 替换段落文本* @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();//重构段落 不合格的 占位符 比如:${abcd}分开为${a,b..,cd}// refactorParagraph(paragraph);if(checkText(text)){List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {//替换模板原来位置run.setText(changeValue(run.toString(), textMap),0);}}}}/*** 替换表格对象方法* @param document docx解析对象* @param textMap 需要替换的信息集合*/public static void changeTableCity(XWPFDocument document, Map<String, String> textMap){//获取表格对象集合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);}}}}/*** 替换表格对象方法* @param document docx解析对象* @param textMap 需要替换的信息集合* @param extendTableMap 需要插入的表格信息集合*/public static void changeTableProvince(XWPFDocument document, Map<String, String> textMap,Map<String, List<List<String>>> extendTableMap){//获取表格对象集合List<XWPFTable> tables = document.getTables();int tableNo = 0;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);tableNo++;}else{List<List<String>> tableList = extendTableMap.get("table" + tableNo);insertTable(table, tableList);tableNo++;}}}}/*** 遍历表格* @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<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).get(j));XWPFParagraph xwpfParagraph = cell.getParagraphs().get(0);//获取cell中的第一个段落第一个ruan并设置字体样式和内容XWPFRun run = xwpfParagraph.createRun();run.setFontSize(9);run.setFontFamily("宋体");run.setText(tableList.get(i-1).get(j));}}}/*** 判断文本中时候包含{{* @param text 文本* @return 包含返回true,不包含返回false*/public static boolean checkText(String text){boolean check = false;if(null != text && 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(null != value && value.indexOf(key)!= -1){String s = textSet.getValue();value = s;}}//模板未匹配到区域替换为空if(checkText(value)){value = "NULL";}return value;}public static void refactorXWPFDocument(XWPFDocument doc) {try {buildParagraph(doc);buildTable(doc);/*List<XWPFParagraph> paragraphs = doc.getParagraphs();for (XWPFParagraph paragraph : paragraphs){List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs){System.out.println(run.toString());}}*/} catch (Exception e) {e.printStackTrace();}//return doc;}public static void refactorParagraph(XWPFParagraph paragraph) {int start = -1;int end = -1;List<XWPFRun> runs = paragraph.getRuns();for (int i = 0; i < runs.size() ; i++) {String runText = runs.get(i).toString();if ('$' == runText.charAt(0)&&'}' == runText.charAt(runText.length() - 1)){continue;}if ('$' == runText.charAt(0)){start = i;}if ('}' == runText.charAt(runText.length() - 1)){end = i;break;}}if (start != -1){mergeRun(paragraph,start,end);refactorParagraph(paragraph);}}/* public static void main(String[] args) {String runText ="";char c = runText.charAt(0);System.out.println(c);}*/public static void mergeRun(XWPFParagraph paragraph, int start, int end) {int removeCount = end-start;//删除次数int removeIndex = start+1;//删除开始位置List<XWPFRun> runs = paragraph.getRuns();for (int i = 0; i <runs.size() ; i++) {System.out.println(runs.get(i).toString());}StringBuilder sb = new StringBuilder();sb.append(runs.get(start).toString());for (int i = 0; i < removeCount; i++){sb.append(runs.get(removeIndex).toString());paragraph.removeRun(removeIndex);}runs.get(start).setText(sb.toString(),0);}public static Matcher matcher(String str) {Pattern pattern = pile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);Matcher matcher = pattern.matcher(str);return matcher;}public static void buildParagraph(XWPFDocument document){for (XWPFParagraph paragraph : document.getParagraphs()) {if (matcher(paragraph.getText()).find()) {removeEmptyRun(paragraph);refactorParagraph(paragraph);}}}public static void buildTable(XWPFDocument document){List<XWPFTable> tables = document.getTables();for (XWPFTable xwpfTable : tables) {List<XWPFTableRow> rows = xwpfTable.getRows();for (XWPFTableRow row :rows){List<XWPFTableCell> tableCells = row.getTableCells();for (XWPFTableCell tableCell : tableCells){List<XWPFParagraph> paragraphs = tableCell.getParagraphs();for (XWPFParagraph paragraph : paragraphs){if (matcher(paragraph.getText()).find()) {removeEmptyRun(paragraph);refactorParagraph(paragraph);}}}}}}private static void removeEmptyRun(XWPFParagraph paragraph) {List<XWPFRun> runsq = paragraph.getRuns();for (int i = 0; i <runsq.size() ; i++) {String runText = runsq.get(i).toString();if (StringUtils.isEmpty(runText)){paragraph.removeRun(i);break;}}for (int i = 0; i <runsq.size() ; i++) {String runText = runsq.get(i).toString();if (StringUtils.isEmpty(runText)){removeEmptyRun(paragraph);break;}}}}

具体源码详见:/download/qq_36244155/10805107

源码下载后,用idea打开,maven加载依赖即可运行。

也可以打包成demo-0.0.1-SNAPSHOT.jar后,

用命令 java -jar demo-0.0.1-SNAPSHOT.jar 运行。

访问地址:http://localhost:8080/#

swagger访问地址:http://localhost:8080/swagger-ui.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。