diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java index 4f51443..4d52207 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java @@ -66,6 +66,8 @@ public class TemplateExportParams extends ExcelBaseParams { * FOR EACH 用到的局部变量 */ private String tempParams = "t"; + + private boolean colForEach = false; /** * 默认构造器 @@ -195,4 +197,12 @@ public class TemplateExportParams extends ExcelBaseParams { this.tempParams = tempParams; } + public boolean isColForEach() { + return colForEach; + } + + public void setColForEach(boolean colForEach) { + this.colForEach = colForEach; + } + } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java index 603e278..191cef3 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java @@ -74,6 +74,10 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { * 模板参数,全局都用到 */ private TemplateExportParams teplateParams; + /** + * 单元格合并信息 + */ + private MergedRegionHelper mergedRegionHelper; /** * 往Sheet 填充正常数据,根据表头信息 使用导入的部分逻辑,坐对象映射 @@ -184,7 +188,7 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { wb.setSheetName(i, params.getSheetName()[i]); } tempCreateCellSet.clear(); - parseTemplate(wb.getSheetAt(i), map); + parseTemplate(wb.getSheetAt(i), map,params.isColForEach()); } if (dataSet != null) { // step 4. 正常的数据填充 @@ -239,8 +243,11 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { } - private void parseTemplate(Sheet sheet, Map map) throws Exception { + private void parseTemplate(Sheet sheet, Map map, boolean colForeach) throws Exception { deleteCell(sheet, map); + if(colForeach){ + colForeach(sheet, map); + } Row row = null; int index = 0; while (index <= sheet.getLastRowNum()) { @@ -258,6 +265,69 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { } /** + * 先进行列的循环,因为涉及很多数据 + * @param sheet + * @param map + */ + private void colForeach(Sheet sheet, Map map) throws Exception { + Row row = null; + Cell cell = null; + int index = 0; + mergedRegionHelper = new MergedRegionHelper(sheet); + while (index <= sheet.getLastRowNum()) { + row = sheet.getRow(index++); + if (row == null) { + continue; + } + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) { + cell = row.getCell(i); + if (row.getCell(i) != null && (cell.getCellType() == Cell.CELL_TYPE_STRING + || cell.getCellType() == Cell.CELL_TYPE_NUMERIC)) { + cell.setCellType(Cell.CELL_TYPE_STRING); + String text = cell.getStringCellValue(); + if (text.contains(FOREACH_COL) || text.contains(FOREACH_COL_VALUE)) { + foreachCol(cell,map,text); + } + } + } + } + } + + /** + * 循环列表 + * @param cell + * @param map + * @param name + * @throws Exception + */ + private void foreachCol(Cell cell, Map map, + String name) throws Exception { + boolean isCreate = name.contains(FOREACH_COL_VALUE); + name = name.replace(FOREACH_COL_VALUE, EMPTY).replace(FOREACH_COL, EMPTY).replace(START_STR, EMPTY); + String[] keys = name.replaceAll("\\s{1,}", " ").trim().split(" "); + Collection datas = (Collection) PoiPublicUtil.getParamsValue(keys[0], map); + Object[] columnsInfo = getAllDataColumns(cell, name.replace(keys[0], EMPTY), + mergedRegionHelper); + if (datas == null) { + return; + } + Iterator its = datas.iterator(); + int rowspan = (Integer) columnsInfo[0], colspan = (Integer) columnsInfo[1]; + @SuppressWarnings("unchecked") + List columns = (List) columnsInfo[2]; + while (its.hasNext()) { + Object t = its.next(); + setForEeachRowCellValue(true, cell.getRow(), cell.getColumnIndex(), t, columns, map, rowspan, + colspan, mergedRegionHelper); + cell = cell.getRow().getCell(cell.getColumnIndex()+colspan); + } + if(isCreate) { + cell = cell.getRow().getCell(cell.getColumnIndex()-1); + cell.setCellValue(cell.getStringCellValue()+END_STR); + } + } + + /** * 先判断删除,省得影响效率 * @param sheet * @param map @@ -331,7 +401,7 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { } //判断foreach 这种方法 if (oldString != null && oldString.contains(FOREACH)) { - addListDataToExcel(cell, map, oldString.trim()); + addListDataToExcel(cell, map, oldString.trim()); } } @@ -356,7 +426,6 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { .replace(FOREACH, EMPTY).replace(START_STR, EMPTY); String[] keys = name.replaceAll("\\s{1,}", " ").trim().split(" "); Collection datas = (Collection) PoiPublicUtil.getParamsValue(keys[0], map); - MergedRegionHelper mergedRegionHelper = new MergedRegionHelper(cell.getSheet()); Object[] columnsInfo = getAllDataColumns(cell, name.replace(keys[0], EMPTY), mergedRegionHelper); if (datas == null) { @@ -668,7 +737,7 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { wb.setSheetName(i, params.getSheetName()[i]); } tempCreateCellSet.clear(); - parseTemplate(wb.getSheetAt(i), map.get(i)); + parseTemplate(wb.getSheetAt(i), map.get(i),params.isColForEach()); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/pdf/export/PdfExportServer.java b/easypoi-base/src/main/java/org/jeecgframework/poi/pdf/export/PdfExportServer.java index eb6216c..ab57cff 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/pdf/export/PdfExportServer.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/pdf/export/PdfExportServer.java @@ -25,7 +25,6 @@ import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.apache.poi.util.IOUtils; import org.jeecgframework.poi.cache.ImageCache; import org.jeecgframework.poi.excel.annotation.ExcelTarget; import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity; diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiElUtil.java b/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiElUtil.java index 9b9d0c4..fd7159d 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiElUtil.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiElUtil.java @@ -26,215 +26,217 @@ import org.jeecgframework.poi.exception.excel.ExcelExportException; */ public final class PoiElUtil { - public static final String LENGTH = "le:"; - public static final String FOREACH = "fe:"; - public static final String FOREACH_NOT_CREATE = "!fe:"; - public static final String FOREACH_AND_SHIFT = "$fe:"; - public static final String START_STR = "{{"; - public static final String END_STR = "}}"; - public static final String WRAP = "]]"; - public static final String NUMBER_SYMBOL = "n:"; - public static final String FORMAT_DATE = "fd:"; - public static final String FORMAT_NUMBER = "fn:"; - public static final String IF_DELETE = "!if:"; - public static final String EMPTY = ""; - public static final String CONST = "'"; - public static final String NULL = "&NULL&"; - public static final String LEFT_BRACKET = "("; - public static final String RIGHT_BRACKET = ")"; - - private PoiElUtil() { - } - - /** - * 解析字符串,支持 le,fd,fn,!if,三目 - * @param text - * @param map - * @return - * @throws Exception - */ - public static Object eval(String text, Map map) throws Exception { - String tempText = new String(text); - Object obj = innerEval(text, map); - //如果没有被处理而且这个值找map中存在就处理这个值 - if (tempText.equals(obj.toString()) && map.containsKey(tempText.split("\\.")[0])) { - return PoiPublicUtil.getParamsValue(tempText, map); - } - return obj; - } - - /** - * 解析字符串,支持 le,fd,fn,!if,三目 - * @param text - * @param map - * @return - * @throws Exception - */ - public static Object innerEval(String text, Map map) throws Exception { - if (text.indexOf("?") != -1 && text.indexOf(":") != -1) { - return trinocular(text, map); - } - if (text.indexOf(LENGTH) != -1) { - return length(text, map); - } - if (text.indexOf(FORMAT_DATE) != -1) { - return formatDate(text, map); - } - if (text.indexOf(FORMAT_NUMBER) != -1) { - return formatNumber(text, map); - } - if (text.indexOf(IF_DELETE) != -1) { - return ifDelete(text, map); - } - if (text.startsWith("'")) { - return text.replace("'", ""); - } - return text; - } - - /** - * 是不是删除列 - * @param text - * @param map - * @return - * @throws Exception - */ - private static Object ifDelete(String text, Map map) throws Exception { - //把多个空格变成一个空格 - text = text.replaceAll("\\s{1,}", " ").trim(); - String[] keys = getKey(IF_DELETE, text).split(" "); - text = text.replace(IF_DELETE, EMPTY); - return isTrue(keys, map); - } - - /** - * 是不是真 - * @param keys - * @param map - * @return - * @throws Exception - */ - private static Boolean isTrue(String[] keys, Map map) throws Exception { - if (keys.length == 1) { - String constant = null; - if ((constant = isConstant(keys[0])) != null) { - return Boolean.valueOf(constant); - } - return Boolean.valueOf(PoiPublicUtil.getParamsValue(keys[0], map).toString()); - } - if (keys.length == 3) { - Object first = eval(keys[0], map); - Object second = eval(keys[2], map); - return PoiFunctionUtil.isTrue(first, keys[1], second); - } - throw new ExcelExportException("判断参数不对"); - } - - /** - * 判断是不是常量 - * @param param - * @return - */ - private static String isConstant(String param) { - if (param.indexOf("'") != -1) { - return param.replace("'", ""); - } - return null; - } - - /** - * 格式化数字 - * @param text - * @param map - * @return - * @throws Exception - */ - private static Object formatNumber(String text, Map map) throws Exception { - String[] key = getKey(FORMAT_NUMBER, text).split(";"); - text = text.replace(FORMAT_NUMBER, EMPTY); - return innerEval( - replacinnerEvalue(text, - PoiFunctionUtil.formatNumber(PoiPublicUtil.getParamsValue(key[0], map), key[1])), - map); - } - - /** - * 格式化时间 - * @param text - * @param map - * @return - * @throws Exception - */ - private static Object formatDate(String text, Map map) throws Exception { - String[] key = getKey(FORMAT_DATE, text).split(";"); - text = text.replace(FORMAT_DATE, EMPTY); - return innerEval( - replacinnerEvalue(text, - PoiFunctionUtil.formatDate(PoiPublicUtil.getParamsValue(key[0], map), key[1])), - map); - } - - /** - * 计算这个的长度 - * @param text - * @param map - * @throws Exception - */ - private static Object length(String text, Map map) throws Exception { - String key = getKey(LENGTH, text); - text = text.replace(LENGTH, EMPTY); - Object val = PoiPublicUtil.getParamsValue(key, map); - return innerEval(replacinnerEvalue(text, PoiFunctionUtil.length(val)), map); - } - - private static String replacinnerEvalue(String text, Object val) { - StringBuilder sb = new StringBuilder(); - sb.append(text.substring(0, text.indexOf(LEFT_BRACKET))); - sb.append(" "); - sb.append(val); - sb.append(" "); - sb.append(text.substring(text.indexOf(RIGHT_BRACKET) + 1, text.length())); - return sb.toString().trim(); - } - - private static String getKey(String prefix, String text) { - int leftBracket = 1, rigthBracket = 0, position = 0; - int index = text.indexOf(prefix) + prefix.length(); - while (text.charAt(index) == " ".charAt(0)) { - text = text.substring(0, index) + text.substring(index + 1, text.length()); - } - for (int i = text.indexOf(prefix + LEFT_BRACKET) + prefix.length() + 1; i < text - .length(); i++) { - if (text.charAt(i) == LEFT_BRACKET.charAt(0)) { - leftBracket++; - } - if (text.charAt(i) == RIGHT_BRACKET.charAt(0)) { - rigthBracket++; - } - if (leftBracket == rigthBracket) { - position = i; - break; - } - } - return text.substring(text.indexOf(prefix + LEFT_BRACKET) + 1 + prefix.length(), position) - .trim(); - } - - /** - * 三目运算 - * @return - * @throws Exception - */ - private static Object trinocular(String text, Map map) throws Exception { - //把多个空格变成一个空格 - text = text.replaceAll("\\s{1,}", " ").trim(); - String testText = text.substring(0, text.indexOf("?")); - text = text.substring(text.indexOf("?") + 1, text.length()).trim(); - text = innerEval(text, map).toString(); - String[] keys = text.split(":"); - Object first = eval(keys[0].trim(), map); - Object second = eval(keys[1].trim(), map); - return isTrue(testText.split(" "), map) ? first : second; - } + public static final String LENGTH = "le:"; + public static final String FOREACH = "fe:"; + public static final String FOREACH_NOT_CREATE = "!fe:"; + public static final String FOREACH_AND_SHIFT = "$fe:"; + public static final String FOREACH_COL = "#fe:"; + public static final String FOREACH_COL_VALUE = "v_fe:"; + public static final String START_STR = "{{"; + public static final String END_STR = "}}"; + public static final String WRAP = "]]"; + public static final String NUMBER_SYMBOL = "n:"; + public static final String FORMAT_DATE = "fd:"; + public static final String FORMAT_NUMBER = "fn:"; + public static final String IF_DELETE = "!if:"; + public static final String EMPTY = ""; + public static final String CONST = "'"; + public static final String NULL = "&NULL&"; + public static final String LEFT_BRACKET = "("; + public static final String RIGHT_BRACKET = ")"; + + private PoiElUtil() { + } + + /** + * 解析字符串,支持 le,fd,fn,!if,三目 + * @param text + * @param map + * @return + * @throws Exception + */ + public static Object eval(String text, Map map) throws Exception { + String tempText = new String(text); + Object obj = innerEval(text, map); + //如果没有被处理而且这个值找map中存在就处理这个值 + if (tempText.equals(obj.toString()) && map.containsKey(tempText.split("\\.")[0])) { + return PoiPublicUtil.getParamsValue(tempText, map); + } + return obj; + } + + /** + * 解析字符串,支持 le,fd,fn,!if,三目 + * @param text + * @param map + * @return + * @throws Exception + */ + public static Object innerEval(String text, Map map) throws Exception { + if (text.indexOf("?") != -1 && text.indexOf(":") != -1) { + return trinocular(text, map); + } + if (text.indexOf(LENGTH) != -1) { + return length(text, map); + } + if (text.indexOf(FORMAT_DATE) != -1) { + return formatDate(text, map); + } + if (text.indexOf(FORMAT_NUMBER) != -1) { + return formatNumber(text, map); + } + if (text.indexOf(IF_DELETE) != -1) { + return ifDelete(text, map); + } + if (text.startsWith("'")) { + return text.replace("'", ""); + } + return text; + } + + /** + * 是不是删除列 + * @param text + * @param map + * @return + * @throws Exception + */ + private static Object ifDelete(String text, Map map) throws Exception { + //把多个空格变成一个空格 + text = text.replaceAll("\\s{1,}", " ").trim(); + String[] keys = getKey(IF_DELETE, text).split(" "); + text = text.replace(IF_DELETE, EMPTY); + return isTrue(keys, map); + } + + /** + * 是不是真 + * @param keys + * @param map + * @return + * @throws Exception + */ + private static Boolean isTrue(String[] keys, Map map) throws Exception { + if (keys.length == 1) { + String constant = null; + if ((constant = isConstant(keys[0])) != null) { + return Boolean.valueOf(constant); + } + return Boolean.valueOf(PoiPublicUtil.getParamsValue(keys[0], map).toString()); + } + if (keys.length == 3) { + Object first = eval(keys[0], map); + Object second = eval(keys[2], map); + return PoiFunctionUtil.isTrue(first, keys[1], second); + } + throw new ExcelExportException("判断参数不对"); + } + + /** + * 判断是不是常量 + * @param param + * @return + */ + private static String isConstant(String param) { + if (param.indexOf("'") != -1) { + return param.replace("'", ""); + } + return null; + } + + /** + * 格式化数字 + * @param text + * @param map + * @return + * @throws Exception + */ + private static Object formatNumber(String text, Map map) throws Exception { + String[] key = getKey(FORMAT_NUMBER, text).split(";"); + text = text.replace(FORMAT_NUMBER, EMPTY); + return innerEval( + replacinnerEvalue(text, + PoiFunctionUtil.formatNumber(PoiPublicUtil.getParamsValue(key[0], map), key[1])), + map); + } + + /** + * 格式化时间 + * @param text + * @param map + * @return + * @throws Exception + */ + private static Object formatDate(String text, Map map) throws Exception { + String[] key = getKey(FORMAT_DATE, text).split(";"); + text = text.replace(FORMAT_DATE, EMPTY); + return innerEval( + replacinnerEvalue(text, + PoiFunctionUtil.formatDate(PoiPublicUtil.getParamsValue(key[0], map), key[1])), + map); + } + + /** + * 计算这个的长度 + * @param text + * @param map + * @throws Exception + */ + private static Object length(String text, Map map) throws Exception { + String key = getKey(LENGTH, text); + text = text.replace(LENGTH, EMPTY); + Object val = PoiPublicUtil.getParamsValue(key, map); + return innerEval(replacinnerEvalue(text, PoiFunctionUtil.length(val)), map); + } + + private static String replacinnerEvalue(String text, Object val) { + StringBuilder sb = new StringBuilder(); + sb.append(text.substring(0, text.indexOf(LEFT_BRACKET))); + sb.append(" "); + sb.append(val); + sb.append(" "); + sb.append(text.substring(text.indexOf(RIGHT_BRACKET) + 1, text.length())); + return sb.toString().trim(); + } + + private static String getKey(String prefix, String text) { + int leftBracket = 1, rigthBracket = 0, position = 0; + int index = text.indexOf(prefix) + prefix.length(); + while (text.charAt(index) == " ".charAt(0)) { + text = text.substring(0, index) + text.substring(index + 1, text.length()); + } + for (int i = text.indexOf(prefix + LEFT_BRACKET) + prefix.length() + 1; i < text + .length(); i++) { + if (text.charAt(i) == LEFT_BRACKET.charAt(0)) { + leftBracket++; + } + if (text.charAt(i) == RIGHT_BRACKET.charAt(0)) { + rigthBracket++; + } + if (leftBracket == rigthBracket) { + position = i; + break; + } + } + return text.substring(text.indexOf(prefix + LEFT_BRACKET) + 1 + prefix.length(), position) + .trim(); + } + + /** + * 三目运算 + * @return + * @throws Exception + */ + private static Object trinocular(String text, Map map) throws Exception { + //把多个空格变成一个空格 + text = text.replaceAll("\\s{1,}", " ").trim(); + String testText = text.substring(0, text.indexOf("?")); + text = text.substring(text.indexOf("?") + 1, text.length()).trim(); + text = innerEval(text, map).toString(); + String[] keys = text.split(":"); + Object first = eval(keys[0].trim(), map); + Object second = eval(keys[1].trim(), map); + return isTrue(testText.split(" "), map) ? first : second; + } }