Excel注解支持导出对象的子列表方法
This commit is contained in:
		| @@ -7,12 +7,14 @@ import java.io.InputStream; | ||||
| import java.io.OutputStream; | ||||
| import java.lang.reflect.Field; | ||||
| import java.lang.reflect.Method; | ||||
| import java.lang.reflect.ParameterizedType; | ||||
| import java.math.BigDecimal; | ||||
| import java.text.DecimalFormat; | ||||
| import java.time.LocalDate; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collection; | ||||
| import java.util.Comparator; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| @@ -24,6 +26,7 @@ import java.util.stream.Collectors; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import org.apache.commons.lang3.ArrayUtils; | ||||
| import org.apache.commons.lang3.RegExUtils; | ||||
| import org.apache.commons.lang3.reflect.FieldUtils; | ||||
| import org.apache.poi.hssf.usermodel.HSSFClientAnchor; | ||||
| import org.apache.poi.hssf.usermodel.HSSFPicture; | ||||
| import org.apache.poi.hssf.usermodel.HSSFPictureData; | ||||
| @@ -149,6 +152,26 @@ public class ExcelUtil<T> | ||||
|      */ | ||||
|     private short maxHeight; | ||||
|  | ||||
|     /** | ||||
|      * 合并后最后行数 | ||||
|      */ | ||||
|     private int subMergedLastRowNum = 0; | ||||
|  | ||||
|     /** | ||||
|      * 合并后开始行数 | ||||
|      */ | ||||
|     private int subMergedFirstRowNum = 1; | ||||
|  | ||||
|     /** | ||||
|      * 对象的子列表方法 | ||||
|      */ | ||||
|     private Method subMethod; | ||||
|  | ||||
|     /** | ||||
|      * 对象的子列表属性 | ||||
|      */ | ||||
|     private List<Field> subFields; | ||||
|  | ||||
|     /** | ||||
|      * 统计列表 | ||||
|      */ | ||||
| @@ -198,6 +221,7 @@ public class ExcelUtil<T> | ||||
|         createExcelField(); | ||||
|         createWorkbook(); | ||||
|         createTitle(); | ||||
|         createSubHead(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -207,13 +231,48 @@ public class ExcelUtil<T> | ||||
|     { | ||||
|         if (StringUtils.isNotEmpty(title)) | ||||
|         { | ||||
|             subMergedFirstRowNum++; | ||||
|             subMergedLastRowNum++; | ||||
|             int titleLastCol = this.fields.size() - 1; | ||||
|             if (isSubList()) | ||||
|             { | ||||
|                 titleLastCol = titleLastCol + subFields.size() - 1; | ||||
|             } | ||||
|             Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); | ||||
|             titleRow.setHeightInPoints(30); | ||||
|             Cell titleCell = titleRow.createCell(0); | ||||
|             titleCell.setCellStyle(styles.get("title")); | ||||
|             titleCell.setCellValue(title); | ||||
|             sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), | ||||
|                     this.fields.size() - 1)); | ||||
|             sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 创建对象的子列表名称 | ||||
|      */ | ||||
|     public void createSubHead() | ||||
|     { | ||||
|         if (isSubList()) | ||||
|         { | ||||
|             subMergedFirstRowNum++; | ||||
|             subMergedLastRowNum++; | ||||
|             Row subRow = sheet.createRow(rownum); | ||||
|             int excelNum = 0; | ||||
|             for (Object[] objects : fields) | ||||
|             { | ||||
|                 Excel attr = (Excel) objects[1]; | ||||
|                 Cell headCell1 = subRow.createCell(excelNum); | ||||
|                 headCell1.setCellValue(attr.name()); | ||||
|                 headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); | ||||
|                 excelNum++; | ||||
|             } | ||||
|             int headFirstRow = excelNum - 1; | ||||
|             int headLastRow = headFirstRow + subFields.size() - 1; | ||||
|             if (headLastRow > headFirstRow) | ||||
|             { | ||||
|                 sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); | ||||
|             } | ||||
|             rownum++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -593,8 +652,20 @@ public class ExcelUtil<T> | ||||
|             // 写入各个字段的列头名称 | ||||
|             for (Object[] os : fields) | ||||
|             { | ||||
|                 Field field = (Field) os[0]; | ||||
|                 Excel excel = (Excel) os[1]; | ||||
|                 this.createCell(excel, row, column++); | ||||
|                 if (Collection.class.isAssignableFrom(field.getType())) | ||||
|                 { | ||||
|                     for (Field subField : subFields) | ||||
|                     { | ||||
|                         Excel subExcel = subField.getAnnotation(Excel.class); | ||||
|                         this.createHeadCell(subExcel, row, column++); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     this.createHeadCell(excel, row, column++); | ||||
|                 } | ||||
|             } | ||||
|             if (Type.EXPORT.equals(type)) | ||||
|             { | ||||
| @@ -610,21 +681,60 @@ public class ExcelUtil<T> | ||||
|      * @param index 序号 | ||||
|      * @param row 单元格行 | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public void fillExcelData(int index, Row row) | ||||
|     { | ||||
|         int startNo = index * sheetSize; | ||||
|         int endNo = Math.min(startNo + sheetSize, list.size()); | ||||
|         int rowNo = (1 + rownum) - startNo; | ||||
|         for (int i = startNo; i < endNo; i++) | ||||
|         { | ||||
|             row = sheet.createRow(i + 1 + rownum - startNo); | ||||
|             rowNo = i > 1 ? rowNo + 1 : rowNo + i; | ||||
|             row = sheet.createRow(rowNo); | ||||
|             // 得到导出对象. | ||||
|             T vo = (T) list.get(i); | ||||
|             Collection<?> subList = null; | ||||
|             if (isSubListValue(vo)) | ||||
|             { | ||||
|                 subList = getListCellValue(vo); | ||||
|                 subMergedLastRowNum = subMergedLastRowNum + subList.size(); | ||||
|             } | ||||
|  | ||||
|             int column = 0; | ||||
|             for (Object[] os : fields) | ||||
|             { | ||||
|                 Field field = (Field) os[0]; | ||||
|                 Excel excel = (Excel) os[1]; | ||||
|                 this.addCell(excel, row, vo, field, column++); | ||||
|                 if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) | ||||
|                 { | ||||
|                     boolean subFirst = false; | ||||
|                     for (Object obj : subList) | ||||
|                     { | ||||
|                         if (subFirst) | ||||
|                         { | ||||
|                             rowNo++; | ||||
|                             row = sheet.createRow(rowNo); | ||||
|                         } | ||||
|                         List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); | ||||
|                         int subIndex = 0; | ||||
|                         for (Field subField : subFields) | ||||
|                         { | ||||
|                             if (subField.isAnnotationPresent(Excel.class)) | ||||
|                             { | ||||
|                                 subField.setAccessible(true); | ||||
|                                 Excel attr = subField.getAnnotation(Excel.class); | ||||
|                                 this.addCell(attr, row, (T) obj, subField, column + subIndex); | ||||
|                             } | ||||
|                             subIndex++; | ||||
|                         } | ||||
|                         subFirst = true; | ||||
|                     } | ||||
|                     this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     this.addCell(excel, row, vo, field, column++); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -759,7 +869,7 @@ public class ExcelUtil<T> | ||||
|     /** | ||||
|      * 创建单元格 | ||||
|      */ | ||||
|     public Cell createCell(Excel attr, Row row, int column) | ||||
|     public Cell createHeadCell(Excel attr, Row row, int column) | ||||
|     { | ||||
|         // 创建列 | ||||
|         Cell cell = row.createCell(column); | ||||
| @@ -767,6 +877,15 @@ public class ExcelUtil<T> | ||||
|         cell.setCellValue(attr.name()); | ||||
|         setDataValidation(attr, row, column); | ||||
|         cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); | ||||
|         if (isSubList()) | ||||
|         { | ||||
|             // 填充默认样式,防止合并单元格样式失效 | ||||
|             sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); | ||||
|             if (attr.needMerge()) | ||||
|             { | ||||
|                 sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); | ||||
|             } | ||||
|         } | ||||
|         return cell; | ||||
|     } | ||||
|  | ||||
| @@ -874,6 +993,11 @@ public class ExcelUtil<T> | ||||
|             { | ||||
|                 // 创建cell | ||||
|                 cell = row.createCell(column); | ||||
|                 if (isSubListValue(vo) && attr.needMerge()) | ||||
|                 { | ||||
|                     CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); | ||||
|                     sheet.addMergedRegion(cellAddress); | ||||
|                 } | ||||
|                 cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); | ||||
|  | ||||
|                 // 用于读取对象中的属性 | ||||
| @@ -969,7 +1093,7 @@ public class ExcelUtil<T> | ||||
|         for (String item : convertSource) | ||||
|         { | ||||
|             String[] itemArray = item.split("="); | ||||
|             if (StringUtils.containsAny(separator, propertyValue)) | ||||
|             if (StringUtils.containsAny(propertyValue, separator)) | ||||
|             { | ||||
|                 for (String value : propertyValue.split(separator)) | ||||
|                 { | ||||
| @@ -1006,7 +1130,7 @@ public class ExcelUtil<T> | ||||
|         for (String item : convertSource) | ||||
|         { | ||||
|             String[] itemArray = item.split("="); | ||||
|             if (StringUtils.containsAny(separator, propertyValue)) | ||||
|             if (StringUtils.containsAny(propertyValue, separator)) | ||||
|             { | ||||
|                 for (String value : propertyValue.split(separator)) | ||||
|                 { | ||||
| @@ -1230,6 +1354,13 @@ public class ExcelUtil<T> | ||||
|                         field.setAccessible(true); | ||||
|                         fields.add(new Object[] { field, attr }); | ||||
|                     } | ||||
|                     if (Collection.class.isAssignableFrom(field.getType())) | ||||
|                     { | ||||
|                         subMethod = getSubMethod(field.getName(), clazz); | ||||
|                         ParameterizedType pt = (ParameterizedType) field.getGenericType(); | ||||
|                         Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0]; | ||||
|                         this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // 多注解 | ||||
| @@ -1473,4 +1604,61 @@ public class ExcelUtil<T> | ||||
|         } | ||||
|         return str; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否有对象的子列表 | ||||
|      */ | ||||
|     public boolean isSubList() | ||||
|     { | ||||
|         return StringUtils.isNotNull(subFields) && subFields.size() > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否有对象的子列表,集合不为空 | ||||
|      */ | ||||
|     public boolean isSubListValue(T vo) | ||||
|     { | ||||
|         return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取集合的值 | ||||
|      */ | ||||
|     public Collection<?> getListCellValue(Object obj) | ||||
|     { | ||||
|         Object value; | ||||
|         try | ||||
|         { | ||||
|             value = subMethod.invoke(obj, new Object[] {}); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return new ArrayList<Object>(); | ||||
|         } | ||||
|         return (Collection<?>) value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取对象的子列表方法 | ||||
|      *  | ||||
|      * @param name 名称 | ||||
|      * @param pojoClass 类对象 | ||||
|      * @return 子列表方法 | ||||
|      */ | ||||
|     public Method getSubMethod(String name, Class<?> pojoClass) | ||||
|     { | ||||
|         StringBuffer getMethodName = new StringBuffer("get"); | ||||
|         getMethodName.append(name.substring(0, 1).toUpperCase()); | ||||
|         getMethodName.append(name.substring(1)); | ||||
|         Method method = null; | ||||
|         try | ||||
|         { | ||||
|             method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("获取对象异常{}", e.getMessage()); | ||||
|         } | ||||
|         return method; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user