diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/annotation/Excel.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/annotation/Excel.java index 67cf28cc..2888d4e9 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/annotation/Excel.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/annotation/Excel.java @@ -1,5 +1,7 @@ package com.xhpc.common.core.annotation; +import com.xhpc.common.core.utils.poi.ExcelHandlerAdapter; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -103,7 +105,17 @@ public @interface Excel /** * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右) */ - Align align() default Align.AUTO; + public Align align() default Align.AUTO; + + /** + * 自定义数据处理器 + */ + public Class handler() default ExcelHandlerAdapter.class; + + /** + * 自定义数据处理器参数 + */ + public String[] args() default {}; public enum Align { diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelHandlerAdapter.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelHandlerAdapter.java new file mode 100644 index 00000000..fa281262 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelHandlerAdapter.java @@ -0,0 +1,18 @@ +package com.xhpc.common.core.utils.poi; + +/** + * Excel数据格式处理适配器 + * + * @author ruoyi + */ +public interface ExcelHandlerAdapter { + /** + * 格式化 + * + * @param value 单元格数据值 + * @param args excel注解args参数组 + * + * @return 处理后的值 + */ + Object format(Object value, String[] args); +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelUtil.java index 183f300d..1e98e61d 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/xhpc/common/core/utils/poi/ExcelUtil.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.text.DecimalFormat; import java.util.ArrayList; @@ -149,33 +150,37 @@ public class ExcelUtil */ public List importExcel(InputStream is) throws Exception { - return importExcel(StringUtils.EMPTY, is); + return importExcel(StringUtils.EMPTY, is, 0); + } + + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @param titleNum 标题占用行数 + * @return 转换后集合 + */ + public List importExcel(InputStream is, int titleNum) throws Exception + { + return importExcel(StringUtils.EMPTY, is, titleNum); } /** * 对excel表单指定表格索引名转换成list * * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 * @param is 输入流 * @return 转换后集合 */ - public List importExcel(String sheetName, InputStream is) throws Exception + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception { this.type = Type.IMPORT; this.wb = WorkbookFactory.create(is); List list = new ArrayList(); - Sheet sheet = null; - if (StringUtils.isNotEmpty(sheetName)) - { - // 如果指定sheet名,则取指定sheet中的内容. - sheet = wb.getSheet(sheetName); - } - else - { - // 如果传入的sheet名不存在则默认指向第1个sheet. - sheet = wb.getSheetAt(0); - } - + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); if (sheet == null) { throw new IOException("文件sheet不存在"); @@ -189,14 +194,21 @@ public class ExcelUtil // 定义一个map用于存放excel列的序号和field. Map cellMap = new HashMap(); // 获取表头 - Row heard = sheet.getRow(0); + Row heard = sheet.getRow(titleNum); for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) { Cell cell = heard.getCell(i); if (StringUtils.isNotNull(cell)) { String value = this.getCellValue(heard, i).toString(); - cellMap.put(value, i); + /** + * 当存在两列标题是一样的时候,以最先存在的一列为准 + * 主要针对快电的对账单 + */ + if (!cellMap.containsKey(value)){ + cellMap.put(value, i); + } + } else { @@ -204,25 +216,18 @@ public class ExcelUtil } } // 有数据时才处理 得到类的所有field. - Field[] allFields = clazz.getDeclaredFields(); - // 定义一个map用于存放列的序号和field. - Map fieldsMap = new HashMap(); - for (int col = 0; col < allFields.length; col++) + List fields = this.getFields(); + Map fieldsMap = new HashMap(); + for (Object[] objects : fields) { - Field field = allFields[col]; - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + Excel attr = (Excel) objects[1]; + Integer column = cellMap.get(attr.name()); + if (column != null) { - // 设置类的私有字段属性可访问. - field.setAccessible(true); - Integer column = cellMap.get(attr.name()); - if (column != null) - { - fieldsMap.put(column, field); - } + fieldsMap.put(column, objects); } } - for (int i = 1; i <= rows; i++) + for (int i = titleNum + 1; i <= rows; i++) { // 从第2行开始取数据,默认第一行是表头. Row row = sheet.getRow(i); @@ -232,14 +237,15 @@ public class ExcelUtil continue; } T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) + for (Map.Entry entry : fieldsMap.entrySet()) { Object val = this.getCellValue(row, entry.getKey()); // 如果不存在实例则新建. entity = (entity == null ? clazz.newInstance() : entity); // 从map中得到对应列的field. - Field field = fieldsMap.get(entry.getKey()); + Field field = (Field) entry.getValue()[0]; + Excel attr = (Excel) entry.getValue()[1]; // 取得类型,并根据对象类型设置值. Class fieldType = field.getType(); if (String.class == fieldType) @@ -299,7 +305,6 @@ public class ExcelUtil } if (StringUtils.isNotNull(fieldType)) { - Excel attr = field.getAnnotation(Excel.class); String propertyName = field.getName(); if (StringUtils.isNotEmpty(attr.targetAttr())) { @@ -309,6 +314,10 @@ public class ExcelUtil { val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + val = dataFormatHandlerAdapter(val, attr); + } ReflectUtils.invokeSetter(entity, propertyName, val); } } @@ -318,6 +327,48 @@ public class ExcelUtil return list; } + + /** + * 获取字段注解信息 + */ + public List getFields() + { + List fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + } + } + } + return fields; + } + + /** * 对list数据源将其里面的数据导入到excel表单 * @@ -427,6 +478,28 @@ public class ExcelUtil } } + /** + * 数据处理器 + * + * @param value 数据值 + * @param excel 数据注解 + * @return + */ + public String dataFormatHandlerAdapter(Object value, Excel excel) + { + try + { + Object instance = excel.handler().newInstance(); + Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); + value = formatMethod.invoke(instance, value, excel.args()); + } + catch (Exception e) + { + log.error("不能格式化数据 " + excel.handler(), e.getMessage()); + } + return Convert.toStr(value); + } + /** * 创建表格样式 *