From a67fa5bcbdced2a5b89e33a75dff8309f3022830 Mon Sep 17 00:00:00 2001 From: jueyue Date: Sun, 16 Aug 2015 02:26:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=A4=84=E7=90=86=E5=A4=9A?= =?UTF-8?q?=E8=A1=8C=E6=A8=A1=E6=9D=BF=E7=9A=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/params/ExcelForEachParams.java | 101 +++++++ .../entity/params/ExcelTemplateParams.java | 65 ----- .../template/ExcelExportOfTemplateUtil.java | 246 ++++++++++++------ .../excel/enums/ExcelExportEnum.java | 2 +- .../jeecgframework/poi/util/PoiElUtil.java | 9 +- 5 files changed, 282 insertions(+), 141 deletions(-) create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java delete mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java new file mode 100644 index 0000000..684a8e5 --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java @@ -0,0 +1,101 @@ +package org.jeecgframework.poi.excel.entity.params; + +import java.io.Serializable; + +import org.apache.poi.ss.usermodel.CellStyle; + +/** + * 模板for each是的参数 + * @author JueYue + * @date 2015年4月29日 下午9:22:48 + */ +public class ExcelForEachParams implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + /** + * key + */ + private String name; + /** + * 模板的cellStyle + */ + private CellStyle cellStyle; + /** + * 行高 + */ + private short height; + /** + * 常量值 + */ + private String constValue; + /** + * 列合并 + */ + private int colspan = 1; + /** + * 行合并 + */ + private int rowspan = 1; + + public ExcelForEachParams() { + + } + + public ExcelForEachParams(String name, CellStyle cellStyle, short height) { + this.name = name; + this.cellStyle = cellStyle; + this.height = height; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public CellStyle getCellStyle() { + return cellStyle; + } + + public void setCellStyle(CellStyle cellStyle) { + this.cellStyle = cellStyle; + } + + public short getHeight() { + return height; + } + + public void setHeight(short height) { + this.height = height; + } + + public String getConstValue() { + return constValue; + } + + public void setConstValue(String constValue) { + this.constValue = constValue; + } + + public int getColspan() { + return colspan; + } + + public void setColspan(int colspan) { + this.colspan = colspan; + } + + public int getRowspan() { + return rowspan; + } + + public void setRowspan(int rowspan) { + this.rowspan = rowspan; + } + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java deleted file mode 100644 index 994e82d..0000000 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.jeecgframework.poi.excel.entity.params; - -import java.io.Serializable; - -import org.apache.poi.ss.usermodel.CellStyle; - -/** - * 模板便利是的参数 - * @author JueYue - * @date 2015年4月29日 下午9:22:48 - */ -public class ExcelTemplateParams implements Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - /** - * key - */ - private String name; - /** - * 模板的cellStyle - */ - private CellStyle cellStyle; - /** - * 行高 - */ - private short height; - - public ExcelTemplateParams() { - - } - - public ExcelTemplateParams(String name, CellStyle cellStyle, short height) { - this.name = name; - this.cellStyle = cellStyle; - this.height = height; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public CellStyle getCellStyle() { - return cellStyle; - } - - public void setCellStyle(CellStyle cellStyle) { - this.cellStyle = cellStyle; - } - - public short getHeight() { - return height; - } - - public void setHeight(short height) { - this.height = height; - } - -} 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 fdcf63e..a931f35 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 @@ -32,15 +32,17 @@ import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.jeecgframework.poi.cache.ExcelCache; import org.jeecgframework.poi.excel.annotation.ExcelTarget; import org.jeecgframework.poi.excel.entity.TemplateExportParams; import org.jeecgframework.poi.excel.entity.enmus.ExcelType; import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity; -import org.jeecgframework.poi.excel.entity.params.ExcelTemplateParams; +import org.jeecgframework.poi.excel.entity.params.ExcelForEachParams; import org.jeecgframework.poi.excel.export.base.ExcelExportBase; import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler; +import org.jeecgframework.poi.excel.html.helper.MergedRegionHelper; import org.jeecgframework.poi.exception.excel.ExcelExportException; import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum; @@ -356,62 +358,117 @@ 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); - List columns = getAllDataColumns(cell, name.replace(keys[0], EMPTY)); + MergedRegionHelper mergedRegionHelper = new MergedRegionHelper(cell.getSheet()); + Object[] columnsInfo = getAllDataColumns(cell, name.replace(keys[0], EMPTY), + mergedRegionHelper); if (datas == null) { return; } Iterator its = datas.iterator(); - Row row; + int rowspan = (Integer) columnsInfo[0], colspan = (Integer) columnsInfo[1]; + @SuppressWarnings("unchecked") + List columns = (List) columnsInfo[2]; + Row row = null; int rowIndex = cell.getRow().getRowNum() + 1; //处理当前行 if (its.hasNext()) { Object t = its.next(); - cell.getRow().setHeight(columns.get(0).getHeight()); - setForEeachCellValue(isCreate, cell.getRow(), cell.getColumnIndex(), t, columns, map); + setForEeachRowCellValue(isCreate, cell.getRow(), cell.getColumnIndex(), t, columns, map, + rowspan, colspan, mergedRegionHelper); + rowIndex += rowspan - 1; } if (isShift) { cell.getRow().getSheet().shiftRows(cell.getRowIndex() + 1, - cell.getRow().getSheet().getLastRowNum(), datas.size() - 1, true, true); + cell.getRow().getSheet().getLastRowNum(), (datas.size() - 1) * rowspan, true, true); } while (its.hasNext()) { Object t = its.next(); + row = createRow(rowIndex, cell.getSheet(), isCreate, rowspan); + setForEeachRowCellValue(isCreate, row, cell.getColumnIndex(), t, columns, map, rowspan, + colspan, mergedRegionHelper); + rowIndex += rowspan; + } + } + + /** + * 创建并返回第一个Row + * @param sheet + * @param rowIndex + * @param isCreate + * @param rows + * @return + */ + private Row createRow(int rowIndex, Sheet sheet, boolean isCreate, int rows) { + for (int i = 0; i < rows; i++) { if (isCreate) { - row = cell.getRow().getSheet().createRow(rowIndex++); - } else { - row = cell.getRow().getSheet().getRow(rowIndex++); - if (row == null) { - row = cell.getRow().getSheet().createRow(rowIndex - 1); - } + sheet.createRow(rowIndex++); + } else if (sheet.getRow(rowIndex++) == null) { + sheet.createRow(rowIndex - 1); } - row.setHeight(columns.get(0).getHeight()); - setForEeachCellValue(isCreate, row, cell.getColumnIndex(), t, columns, map); } + return sheet.getRow(rowIndex - rows); } - private void setForEeachCellValue(boolean isCreate, Row row, int columnIndex, Object t, - List columns, - Map map) throws Exception { - for (int i = 0, max = columnIndex + columns.size(); i < max; i++) { - if (row.getCell(i) == null) - row.createCell(i); - } - for (int i = 0, max = columns.size(); i < max; i++) { - boolean isNumber = false; - String tempStr = new String(columns.get(i).getName()); - if (isNumber(tempStr)) { - isNumber = true; - tempStr = tempStr.replace(NUMBER_SYMBOL, ""); + private void setForEeachRowCellValue(boolean isCreate, Row row, int columnIndex, Object t, + List columns, Map map, + int rowspan, int colspan, + MergedRegionHelper mergedRegionHelper) throws Exception { + //所有的cell创建一遍 + for (int i = 0; i < rowspan; i++) { + for (int j = 0, max = columnIndex + colspan; j < max; j++) { + if (row.getCell(j) == null) + row.createCell(j); } - map.put(teplateParams.getTempParams(), t); - String val = eval(tempStr, map).toString(); - if (isNumber && StringUtils.isNotEmpty(val)) { - row.getCell(i + columnIndex).setCellValue(Double.parseDouble(val)); - row.getCell(i + columnIndex).setCellType(Cell.CELL_TYPE_NUMERIC); - } else { - row.getCell(i + columnIndex).setCellValue(val); + if (i < rowspan - 1) { + row = row.getSheet().getRow(row.getRowNum() + 1); + } + } + //填写数据 + ExcelForEachParams params; + row = row.getSheet().getRow(row.getRowNum() - rowspan + 1); + for (int k = 0; k < rowspan; k++) { + for (int i = 0; i < colspan; i++) { + boolean isNumber = false; + params = columns.get(colspan * k + i); + tempCreateCellSet.add(row.getRowNum() + "_" + (i + columnIndex)); + if (params == null) { + continue; + } + if (StringUtils.isEmpty(params.getName()) + && StringUtils.isEmpty(params.getConstValue())) { + row.getCell(i + columnIndex).setCellStyle(columns.get(i).getCellStyle()); + continue; + } + String val = null; + //是不是常量 + if (StringUtils.isEmpty(params.getName())) { + val = params.getConstValue(); + } else { + String tempStr = new String(params.getName()); + if (isNumber(tempStr)) { + isNumber = true; + tempStr = tempStr.replace(NUMBER_SYMBOL, ""); + } + map.put(teplateParams.getTempParams(), t); + val = eval(tempStr, map).toString(); + } + if (isNumber && StringUtils.isNotEmpty(val)) { + row.getCell(i + columnIndex).setCellValue(Double.parseDouble(val)); + row.getCell(i + columnIndex).setCellType(Cell.CELL_TYPE_NUMERIC); + } else { + row.getCell(i + columnIndex).setCellValue(val); + } + row.getCell(i + columnIndex).setCellStyle(columns.get(i).getCellStyle()); + //合并对应单元格 + if ((params.getRowspan() != 1 || params.getColspan() != 1) + && !mergedRegionHelper.isMergedRegion(row.getRowNum() + 1, i + columnIndex)) { + row.getSheet() + .addMergedRegion(new CellRangeAddress(row.getRowNum(), + row.getRowNum() + params.getRowspan() - 1, i + columnIndex, + i + columnIndex + params.getColspan() - 1)); + } } - row.getCell(i + columnIndex).setCellStyle(columns.get(i).getCellStyle()); - tempCreateCellSet.add(row.getRowNum() + "_" + (i + columnIndex)); + row = row.getSheet().getRow(row.getRowNum() + 1); } } @@ -420,52 +477,95 @@ public final class ExcelExportOfTemplateUtil extends ExcelExportBase { * 获取迭代的数据的值 * @param cell * @param name + * @param mergedRegionHelper * @return */ - private List getAllDataColumns(Cell cell, String name) { - List columns = new ArrayList(); + private Object[] getAllDataColumns(Cell cell, String name, + MergedRegionHelper mergedRegionHelper) { + List columns = new ArrayList(); cell.setCellValue(""); - if (name.contains(END_STR)) { - columns.add(new ExcelTemplateParams(name.replace(END_STR, EMPTY).trim(), - cell.getCellStyle(), cell.getRow().getHeight())); - return columns; - } - columns.add( - new ExcelTemplateParams(name.trim(), cell.getCellStyle(), cell.getRow().getHeight())); - int index = cell.getColumnIndex(); - Cell tempCell; - while (true) { - tempCell = cell.getRow().getCell(++index); - if (tempCell == null) { - break; - } - String cellStringString; - try {//允许为空,单表示已经完结了,因为可能被删除了 - cellStringString = tempCell.getStringCellValue(); - if (StringUtils.isBlank(cellStringString)) { - break; + columns.add(getExcelTemplateParams(name.replace(END_STR, EMPTY), cell, mergedRegionHelper)); + int rowspan = 1, colspan = 1; + if (!name.contains(END_STR)) { + int index = cell.getColumnIndex(); + //保存col 的开始列 + int startIndex = index; + Row row = cell.getRow(); + while (true) { + cell = row.getCell(++index); + //可能是合并的单元格 + if (cell == null) { + //读取是判断,跳过 + columns.add(null); + continue; } - } catch (Exception e) { - throw new ExcelExportException("for each 当中存在空字符串,请检查模板"); - } - //把读取过的cell 置为空 - tempCell.setCellValue(""); - if (cellStringString.contains(END_STR)) { - columns.add(new ExcelTemplateParams(cellStringString.trim().replace(END_STR, ""), - tempCell.getCellStyle(), tempCell.getRow().getHeight())); - break; - } else { - if (cellStringString.trim().contains(teplateParams.getTempParams())) { - columns.add(new ExcelTemplateParams(cellStringString.trim(), - tempCell.getCellStyle(), tempCell.getRow().getHeight())); - } else { - //最后一行被删除了 + String cellStringString; + try {//不允许为空 便利单元格必须有结尾和值 + cellStringString = cell.getStringCellValue(); + if (StringUtils.isBlank(cellStringString) && colspan + startIndex <= index) { + throw new ExcelExportException("for each 当中存在空字符串,请检查模板"); + } else + if (StringUtils.isBlank(cellStringString) && colspan + startIndex > index) { + //读取是判断,跳过,数据为空,但是不是第一次读这一列,所以可以跳过 + columns.add(new ExcelForEachParams(null, cell.getCellStyle(), (short) 0)); + continue; + } + } catch (Exception e) { + throw new ExcelExportException(ExcelExportEnum.TEMPLATE_ERROR, e); + } + //把读取过的cell 置为空 + cell.setCellValue(""); + if (cellStringString.contains(END_STR)) { + columns.add(getExcelTemplateParams(cellStringString.replace(END_STR, EMPTY), + cell, mergedRegionHelper)); break; + } else if (cellStringString.contains(WRAP)) { + columns.add(getExcelTemplateParams(cellStringString.replace(WRAP, EMPTY), cell, + mergedRegionHelper)); + //发现换行符,执行换行操作 + colspan = index - startIndex + 1; + index = startIndex - 1; + row = row.getSheet().getRow(row.getRowNum() + 1); + rowspan++; + } else { + columns.add(getExcelTemplateParams(cellStringString.replace(WRAP, EMPTY), cell, + mergedRegionHelper)); } } + } + return new Object[] { rowspan, colspan, columns }; + } + /** + * 获取模板参数 + * @param string + * @param cell + * @param mergedRegionHelper + * @return + */ + private ExcelForEachParams getExcelTemplateParams(String name, Cell cell, + MergedRegionHelper mergedRegionHelper) { + name = name.trim(); + ExcelForEachParams params = new ExcelForEachParams(name, cell.getCellStyle(), + cell.getRow().getHeight()); + //判断是不是常量 + if (name.startsWith(CONST) && name.endsWith(CONST)) { + params.setName(null); + params.setConstValue(name.substring(1, name.length() - 1)); + } + //判断是不是空 + if (NULL.equals(name)) { + params.setName(null); + params.setConstValue(EMPTY); + } + //获取合并单元格的数据 + if (mergedRegionHelper.isMergedRegion(cell.getRowIndex() + 1, cell.getColumnIndex())) { + Integer[] colAndrow = mergedRegionHelper.getRowAndColSpan(cell.getRowIndex() + 1, + cell.getColumnIndex()); + params.setRowspan(colAndrow[0]); + params.setColspan(colAndrow[1]); } - return columns; + return params; } /** diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/exception/excel/enums/ExcelExportEnum.java b/easypoi-base/src/main/java/org/jeecgframework/poi/exception/excel/enums/ExcelExportEnum.java index ef6d7c8..97831d5 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/exception/excel/enums/ExcelExportEnum.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/exception/excel/enums/ExcelExportEnum.java @@ -22,7 +22,7 @@ package org.jeecgframework.poi.exception.excel.enums; */ public enum ExcelExportEnum { - PARAMETER_ERROR("Excel 导出 参数错误"), EXPORT_ERROR("Excel导出错误"); + PARAMETER_ERROR("Excel 导出 参数错误"), EXPORT_ERROR("Excel导出错误"),TEMPLATE_ERROR("Excel 模板错误"); private String msg; 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 76287e8..3ae480a 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 @@ -32,11 +32,14 @@ public final class PoiElUtil { 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 = ")"; @@ -167,7 +170,8 @@ public final class PoiElUtil { text = text.replace(FORMAT_DATE, EMPTY); return innerEval( replacinnerEvalue(text, - PoiFunctionUtil.formatDate(PoiPublicUtil.getParamsValue(key[0], map), key[1])), map); + PoiFunctionUtil.formatDate(PoiPublicUtil.getParamsValue(key[0], map), key[1])), + map); } /** @@ -199,7 +203,8 @@ public final class PoiElUtil { 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++) { + for (int i = text.indexOf(prefix + LEFT_BRACKET) + prefix.length() + 1; i < text + .length(); i++) { if (text.charAt(i) == LEFT_BRACKET.charAt(0)) { leftBracket++; }