1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > java poi操作word模版 导出word文档(附工具类)

java poi操作word模版 导出word文档(附工具类)

时间:2021-01-01 19:00:22

相关推荐

java poi操作word模版 导出word文档(附工具类)

模板格式

合同编号:{ contractNumber},合同序号:{ contractSequence}

买家: { buyerName}

卖家:{ sellerName}

业务员: { salesName}

项目名:{ projectName}

生效时间:{ effectiveTime}

生效时间:{ createTime }

3,本通知与前述通知有抵触之处,以本通知为准。

{sellerName}

{createTime}

语法

普通文本 {}空值处理 {field!}行内文本循环 {$(children({ itemName },))}条件判断 {!flag(为true的时候)else(为false的时候={ shipPrice! }元/{unit})}换行符 \\n表格行循环 (支持同一表格多次循环)不支持嵌套$begin{field}{name} | {age}$end

maven依赖

<!-- 只要这一个依赖即可 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency>

解析代码

import mons.beanutils.BeanUtilsBean;import mons.collections.CollectionUtils;import org.apache.poi.util.Units;import org.apache.poi.xwpf.usermodel.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.*;import java.lang.reflect.InvocationTargetException;import java.math.BigDecimal;import java.math.RoundingMode;import java.text.SimpleDateFormat;import java.util.*;import java.util.regex.Matcher;import java.util.regex.Pattern;/*** @author zhenx* @date /7/29 15:15* @description** 普通文本 {}* 空值处理 {field!}* 文本循环 {$(children({ itemName },))}* 条件判断 {!flag(为true的时候)else(为false的时候={ shipPrice! }元/{unit})}* 换行符 \\n** 表格行循环 (支持同一表格多次循环)不支持嵌套* $begin{field}* {name} | {age}* $end*/public class WordTemplateUtils {private static final Logger log = LoggerFactory.getLogger(WordTemplateUtils.class);// 行内循环private static final Pattern FOREACH_TEXT = pile("\\{\\$\\(.+?\\([\\d\\D]+?\\)\\)}");// 条件语句private static final Pattern BOOL_TEXT = pile("\\{!.+?\\(.+?\\)else\\(.+?\\)}");// 普通文本private static final Pattern PAIN_TEXT = pile("\\{.+?}");// 日期格式private static final String DATE_FORMAT = "yyyy-MM-dd";/*** 处理方法* @param docxFile 模版文件* @param model 填充模版的参数*/public static byte[] process(File docxFile, Object model) throws Exception {if (!docxFile.exists() || !docxFile.isFile()) {throw new IllegalArgumentException("文件为空");}return process(new FileInputStream(docxFile), model);}/*** @param input 模版文件* @param model 填充模版的参数*/public static byte[] process(InputStream input, Object object) throws Exception {XWPFDocument doc = new XWPFDocument(input);List<XWPFParagraph> paragraphs = doc.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {replaceParagraph(paragraph, object);}for (XWPFTable table : doc.getTables()) {try {handleTable(table, object);} catch (IllegalArgumentException e) {log.error("操作表格失败, 删除表格: {}", e.getMessage());deleteTable(table);}}ByteArrayOutputStream outputStream = new ByteArrayOutputStream();doc.write(outputStream);byte[] bytes = outputStream.toByteArray();doc.close();return bytes;}/*** 处理表格* @param table* @param param* @throws IllegalArgumentException*/private static void handleTable(XWPFTable table, Object param) throws Exception {// 处理表格内循环Set<Integer> deleteRows = new HashSet<>();handleTableEach(0, table, param, deleteRows);deleteRow(table, deleteRows);// 处理表格内普通文本handleTableText(table, param);}private static void deleteTable(XWPFTable table){List<XWPFTableRow> rows = table.getRows();int rowLength = rows.size();for (int i = 0; i < rowLength; i++) {table.removeRow(0);}}/*** 处理段落* @param paragraph* @param object*/private static void replaceParagraph(XWPFParagraph paragraph, Object object) {List<XWPFRun> runs = paragraph.getRuns();String text = paragraph.getText();Matcher matcher = PAIN_TEXT.matcher(text);if (!matcher.find()) {return;}for (XWPFRun run : runs) {run.setText("", 0);}XWPFRun targetRun = runs.get(0);String result = handleForeachText(text, object);if (result.contains("\\n")) {String[] split = result.split("\\\\n");for (String s : split) {XWPFRun run = paragraph.createRun();copyRun(run, targetRun);run.setText(s);run.addBreak();}} else {targetRun.setText(result, 0);}}/*** 删除行* @param table* @param deleteRows*/private static void deleteRow(XWPFTable table, Set<Integer> deleteRows) {Integer[] array = deleteRows.toArray(new Integer[]{});Arrays.sort(array);int i = 0;for (Integer r: array) {if(i == 0) {table.removeRow(r);i++;}else{table.removeRow(r - i);i++;}}}/*** 表格内循环* @param pos* @param table* @param param* @param deleteRows* @throws IllegalArgumentException*/private static void handleTableEach(int pos, XWPFTable table, Object param, Set<Integer> deleteRows) throws Exception {List<XWPFTableRow> rows = table.getRows();Set<Integer> tplListRows = new HashSet<>();List currentIterator = null;int start = -1;int end = -1;int i = pos;row:for (; i < rows.size(); i++) {XWPFTableRow row = rows.get(i);List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {String text = cell.getText().trim();if(text.matches("^\\$begin\\{.+?}$")) {if (currentIterator != null) {log.error("循环嵌套了: row {}", i);throw new RuntimeException("不允许循环嵌套");}start = i;String listKey = text.substring(7, text.length()-1).trim();boolean emptyFlag = listKey.endsWith("!");if (emptyFlag) {listKey = listKey.substring(0, listKey.length() - 1);}currentIterator = (List) getField(param, listKey);if (CollectionUtils.isEmpty(currentIterator)) {if (emptyFlag) {currentIterator = new ArrayList();} else {log.error("循环字段 {} 为空", listKey);throw new IllegalArgumentException();}}continue row;}else if (text.matches("^\\$end$")) {end = i;tplListRows.remove(i);break row;}else if (start != -1) {tplListRows.add(i);}}}if (start == -1 || end == -1 || CollectionUtils.isEmpty(tplListRows)) {return;}int insertRow = end + 1;for (Object o : currentIterator) {for (Integer r : tplListRows) {XWPFTableRow tplRow = table.getRow(r);XWPFTableRow row = table.insertNewTableRow(insertRow);row.getCtRow().setTrPr(tplRow.getCtRow().getTrPr());replaceRow(row, tplRow, o);insertRow++;}}for (int j = start; j <= end; j++) {deleteRows.add(j);}if (i < rows.size() - 1) {handleTableEach((i + 1), table, param, deleteRows);}}/*** 表格普通文本* @param table* @param param* @throws Exception*/private static void handleTableText(XWPFTable table, Object param) throws Exception {List<XWPFTableRow> rows = table.getRows();for (XWPFTableRow row : rows) {List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {// 处理图片if (handleCellImage(cell, param)) {continue;}handleCellText(cell, param);}}}/*** 处理表格内图片*/private static boolean handleCellImage(XWPFTableCell cell, Object param) throws Exception {String text = cell.getText().trim();if(text.matches("^\\$img\\{.+?}$")) {String key = text.substring(5, text.length() - 1).trim();Object field = getField(param, key);InputStream in = null;if (field instanceof InputStream) {in = (InputStream) field;}else if (field instanceof File) {in = new FileInputStream(((File) field));}else if (field instanceof byte[]) {in = new ByteArrayInputStream((byte[]) field);}if (in == null) {return false;}XWPFRun targetRun = null;for (XWPFParagraph paragraph : cell.getParagraphs()) {for (XWPFRun run : paragraph.getRuns()) {if (targetRun == null) {targetRun = run;}run.setText("", 0);}}if (targetRun == null) {return false;}targetRun.addPicture(in, XWPFDocument.PICTURE_TYPE_PNG, key + ".png", Units.toEMU(80), Units.toEMU(100));return true;}return false;}/*** 处理表格行* @param row* @param tplRow* @param param*/private static void replaceRow(XWPFTableRow row, XWPFTableRow tplRow, Object param) throws Exception {List<XWPFTableCell> cells = tplRow.getTableCells();for (XWPFTableCell tplCell : cells) {XWPFTableCell cell = row.createCell();copyTableCell(cell, tplCell);// 处理图片if (handleCellImage(cell, param)) {continue;}handleCellText(cell, param);}}private static void handleCellText(XWPFTableCell cell, Object param) {String text = cell.getText();Matcher matcher = PAIN_TEXT.matcher(text);if (!matcher.find()) {return;}for (XWPFParagraph paragraph : cell.getParagraphs()) {replaceParagraph(paragraph, param);}}/*** 复制单元格(列) 从sourceCell到targetCell* @param targetCell* @param sourceCell*/private static void copyTableCell(XWPFTableCell targetCell, XWPFTableCell sourceCell) {//表格属性if(sourceCell.getCTTc() != null) {targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());}//删除段落for(int pos = 0; pos < targetCell.getParagraphs().size(); pos++) {targetCell.removeParagraph(pos);}//添加段落for(XWPFParagraph sourceParag : sourceCell.getParagraphs()) {XWPFParagraph targetParag = targetCell.addParagraph();copyParagraph(targetParag, sourceParag);}}/*** 复制段落,从sourceParag到targetParag* @param targetParag* @param sourceParag*/private static void copyParagraph(XWPFParagraph targetParag, XWPFParagraph sourceParag) {targetParag.getCTP().setPPr(sourceParag.getCTP().getPPr()); //设置段落样式//移除所有的runfor(int pos = targetParag.getRuns().size() - 1; pos >= 0; pos-- ) {targetParag.removeRun(pos);}//copy新的runfor(XWPFRun sRun : sourceParag.getRuns()) {XWPFRun tarRun = targetParag.createRun();copyRun(tarRun, sRun);}}/*** 复制XWPFRun 从sourceRun到targetRun* @param targetRun* @param sourceRun*/private static void copyRun(XWPFRun targetRun, XWPFRun sourceRun) {//设置targetRun属性targetRun.getCTR().setRPr(sourceRun.getCTR().getRPr());targetRun.setText(sourceRun.text());//设置文本}private static Object getField(Object object, String field) {if (field.contains(".")) {String[] split = field.split("\\.");if (split.length > 1) {Object obj = getField(object, split[0]);if (obj == null) {return null;}return getField(obj, field.substring(field.indexOf(".") + 1));}}try {return BeanUtilsBean.getInstance().getPropertyUtils().getProperty(object, field.trim());} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {log.info(" getField[{}] fail", field);}return null;}private static String getProperty(Object object, String property) {String res = "";try {Object field = getField(object, property);if (field == null) {return "";}if (field instanceof Date) {res = new SimpleDateFormat(DATE_FORMAT).format(field);}else if (field instanceof BigDecimal){BigDecimal d = (BigDecimal) field;d = d.setScale(2, RoundingMode.HALF_UP);res = d.toPlainString();} else {res = BeanUtilsBean.getInstance().getConvertUtils().convert(field);}} catch (Exception e) {log.info(" getProperty[{}] fail", property);}return res == null ? "" : res;}private static String handleForeachText(String tpl, Object param) {Matcher rMatcher = FOREACH_TEXT.matcher(tpl);StringBuffer rSb = new StringBuffer();while (rMatcher.find()) {String group = rMatcher.group().substring(3);String name = group.substring(0, group.indexOf("("));List iterator = (List) getField(param, name);if (iterator == null) {rMatcher.appendReplacement(rSb, "");continue;}String reTpl = group.substring(name.length() + 1, group.length() - 3);StringBuilder builder = new StringBuilder();for (Object o : iterator) {String text = handleBoolText(reTpl, o);builder.append(text);}rMatcher.appendReplacement(rSb, builder.toString());}rMatcher.appendTail(rSb);return handleBoolText(rSb.toString(), param);}private static String handleBoolText(String tpl, Object object) {Matcher matcher = BOOL_TEXT.matcher(tpl);StringBuffer sb = new StringBuffer();while (matcher.find()) {String group = matcher.group();group = group.substring(2, group.length() - 1);String key = group.substring(0, group.indexOf("("));group = group.substring(key.length());String[] split = group.split("else");String pre = split[0].substring(1, split[0].length() - 1);String suf = split[1].substring(1, split[1].length() - 1);Object field = getField(object, key);String target;if (Boolean.TRUE.equals(field)) {target = pre;} else {target = suf;}String text = "";try {text = handlePainText(target, object);} catch (IllegalArgumentException e) {}matcher.appendReplacement(sb, text);}matcher.appendTail(sb);try {return handlePainText(sb.toString(), object);} catch (IllegalArgumentException e) {return "";}}private static String handlePainText(String tpl, Object param) throws IllegalArgumentException {Matcher matcher = PAIN_TEXT.matcher(tpl);StringBuffer sb = new StringBuffer();while (matcher.find()) {String group = matcher.group();String name = group.substring(1, group.length() - 1).trim();boolean emptyFlag = name.endsWith("!");if (emptyFlag) {name = name.substring(0, name.length() - 1);}String value = getProperty(param, name);if (emptyFlag && StringUtils.isEmpty(value)) {throw new IllegalArgumentException();}matcher.appendReplacement(sb, value);}matcher.appendTail(sb);return sb.toString();}}

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