自界说注解实现Excel 导出

渣渣兔  金牌会员 | 2024-6-14 20:09:10 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 942|帖子 942|积分 2826

概述

一个用自界说注解实现导出字段界说的工具实现。
1. 注解界说,界说导出Excel的字段

  1. @Target(ElementType.FIELD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface PoiExportField {
  4.     // Label of the column
  5.     String label();
  6.     // Order of the column,default 0,means the first column
  7.     int order() default 0;
  8.     // If true, this field will be used to create subgroup rows
  9.     boolean subGroup() default false;
  10.     // Width of the column
  11.     int width() default 20;
  12.     // Alignment of the column
  13.     HorizontalAlignment align() default HorizontalAlignment.LEFT;
  14. }
复制代码
2. 实体类,使用注解界说导出字段,不导出的字段不用加注解

  1. @Data
  2. public class OrderVO {
  3.     @PoiExportUtil.PoiExportField(label = "订单编号", order = 1, align = HorizontalAlignment.CENTER)
  4.     private String orderNo;
  5.     @PoiExportUtil.PoiExportField(label = "订单用户", order = 2, align = HorizontalAlignment.CENTER)
  6.     private String orderUser;
  7.     @PoiExportUtil.PoiExportField(label = "订单时间", order = 3, align = HorizontalAlignment.CENTER)
  8.     private String orderTime;
  9.     @PoiExportUtil.PoiExportField(label = "订单金额", order = 4, width = 15, align = HorizontalAlignment.RIGHT)
  10.     private String orderAmount;
  11.     private String orderDesc;
  12.     private String orderRemark;
  13.     private String orderPhone;
  14.     private String orderZipCode;
  15.     @PoiExportUtil.PoiExportField(label = "订单国家", subGroup = true)
  16.     private String orderCountry;
  17.     @PoiExportUtil.PoiExportField(label = "订单省份", subGroup = true)
  18.     private String orderProvince;
  19.     @PoiExportUtil.PoiExportField(label = "订单城市", order = 6)
  20.     private String orderCity;
  21.     @PoiExportUtil.PoiExportField(label = "详细地址", order = 7)
  22.     private String orderAddressDetail;
  23. }
复制代码
3. Excel导出工具类,注解界说放到工具类中,方便使用

  1. public class PoiExportUtil {
  2.     /**
  3.      * Custom annotation for exporting Excel file
  4.      */
  5.     @Target(ElementType.FIELD)
  6.     @Retention(RetentionPolicy.RUNTIME)
  7.     public @interface PoiExportField {
  8.         // Label of the column
  9.         String label();
  10.         // Order of the column,default 0,means the first column
  11.         int order() default 0;
  12.         // If true, this field will be used to create subgroup rows
  13.         boolean subGroup() default false;
  14.         // Width of the column
  15.         int width() default 20;
  16.         // Alignment of the column
  17.         HorizontalAlignment align() default HorizontalAlignment.LEFT;
  18.     }
  19.     /**
  20.      * Export data to excel file
  21.      *
  22.      * @param list     List of data
  23.      * @param fileName File name
  24.      * @param <T>      Type of data
  25.      */
  26.     public <T> void exportToExcel(List<T> list, String fileName) {
  27.         Workbook workbook = new XSSFWorkbook();
  28.         Sheet sheet = workbook.createSheet("Data");
  29.         writeSheet(sheet, list, null, null, null);
  30.         // Write to file
  31.         try (FileOutputStream fileOut = new FileOutputStream(fileName)) {
  32.             workbook.write(fileOut);
  33.             fileOut.flush();
  34.         } catch (Exception e) {
  35.             e.printStackTrace();
  36.         }
  37.     }
  38.     /**
  39.      * Write data to a sheet
  40.      *
  41.      * @param sheet         Sheet
  42.      * @param dataList      List of data
  43.      * @param headerStyle   Header style
  44.      * @param subGroupStyle Subgroup style
  45.      * @param dataCellStyle Data cell style
  46.      * @param <T>           Type of data
  47.      */
  48.     public <T> void writeSheet(Sheet sheet, List<T> dataList, CellStyle headerStyle, CellStyle subGroupStyle, CellStyle dataCellStyle) {
  49.         // If data list is empty, return
  50.         if (dataList == null || dataList.isEmpty()) {
  51.             return;
  52.         }
  53.         // If styles are not provided, use default styles
  54.         if (headerStyle == null) {
  55.             headerStyle = createDefaultHeaderStyle(sheet.getWorkbook());
  56.         }
  57.         if (subGroupStyle == null) {
  58.             subGroupStyle = createDefaultSubGroupStyle(sheet.getWorkbook());
  59.         }
  60.         if (dataCellStyle == null) {
  61.             dataCellStyle = createDefaultDataCellStyle(sheet.getWorkbook());
  62.         }
  63.         Field[] fields = dataList.get(0).getClass().getDeclaredFields();
  64.         // Filter fields with PoiExportField annotation
  65.         List<Field> annotatedFields = new ArrayList<>();
  66.         // Filter fields with PoiExportField annotation and subGroup is true, for creating subgroup rows
  67.         List<Field> subGroupFields = new ArrayList<>();
  68.         // Filter fields with PoiExportField annotation and sort them by order attribute
  69.         for (Field field : fields) {
  70.             PoiExportField annotation = field.getAnnotation(PoiExportField.class);
  71.             if (annotation != null) {
  72.                 if (annotation.subGroup()) {
  73.                     subGroupFields.add(field);
  74.                 } else {
  75.                     annotatedFields.add(field);
  76.                 }
  77.             }
  78.         }
  79.         // Sort fields by order attribute
  80.         annotatedFields.sort(Comparator.comparingInt(field -> {
  81.             PoiExportField annotation = field.getAnnotation(PoiExportField.class);
  82.             return annotation.order();
  83.         }));
  84.         //annotated fields is empty, return
  85.         if (annotatedFields.isEmpty()) {
  86.             return;
  87.         }
  88.         // Create header row
  89.         createHeaderRow(sheet, annotatedFields, headerStyle);
  90.         // Create data rows
  91.         createSheetWithData(sheet, dataList, annotatedFields, subGroupFields, subGroupStyle, dataCellStyle);
  92.     }
  93.     /**
  94.      * Create header row
  95.      *
  96.      * @param sheet           Sheet
  97.      * @param annotatedFields List of annotated fields
  98.      * @param headerStyle     Header style
  99.      */
  100.     private void createHeaderRow(Sheet sheet, List<Field> annotatedFields, CellStyle headerStyle) {
  101.         int lastRowNum = sheet.getLastRowNum();
  102.         Row headerRow = sheet.createRow(lastRowNum + 1);
  103.         for (int i = 0; i < annotatedFields.size(); i++) {
  104.             Field field = annotatedFields.get(i);
  105.             PoiExportField annotation = field.getAnnotation(PoiExportField.class);
  106.             Cell headerCell = headerRow.createCell(i);
  107.             headerCell.setCellValue(annotation.label());
  108.             headerCell.setCellStyle(headerStyle);
  109.             // Set column width
  110.             sheet.setColumnWidth(i, annotation.width() * 256);
  111.         }
  112.     }
  113.     /**
  114.      * Create data rows
  115.      *
  116.      * @param sheet           Sheet
  117.      * @param dataList        List of data
  118.      * @param annotatedFields List of annotated fields
  119.      * @param subGroupFields  List of subgroup fields
  120.      * @param subGroupStyle   Subgroup style
  121.      * @param dataCellStyle   Data cell style
  122.      * @param <T>             Type of data
  123.      */
  124.     private <T> void createSheetWithData(Sheet sheet, List<T> dataList, List<Field> annotatedFields, List<Field> subGroupFields, CellStyle subGroupStyle, CellStyle dataCellStyle) {
  125.         String lastSubGroupValue = null;
  126.         int rowIndex = sheet.getLastRowNum() + 1;
  127.         for (T data : dataList) {
  128.             // Create subgroup row
  129.             if (subGroupFields != null && !subGroupFields.isEmpty()) {
  130.                 String currentSubGroupValue = getSubGroupValue(data, subGroupFields);
  131.                 if (!currentSubGroupValue.equals(lastSubGroupValue)) {
  132.                     Row subGroupRow = sheet.createRow(rowIndex++);
  133.                     Cell subGroupCell = subGroupRow.createCell(0);
  134.                     subGroupCell.setCellValue(currentSubGroupValue);
  135.                     CellRangeAddress mergeRegion = new CellRangeAddress(rowIndex - 1, rowIndex - 1, 0, annotatedFields.size() - 1);
  136.                     sheet.addMergedRegion(mergeRegion);
  137.                     //CellRangeAddress  mergeRegion = sheet.getMergedRegion(sheet.getNumMergedRegions() - 1);
  138.                     RegionUtil.setBorderBottom(BorderStyle.THIN, mergeRegion, sheet);
  139.                     RegionUtil.setBorderTop(BorderStyle.THIN, mergeRegion, sheet);
  140.                     RegionUtil.setBorderLeft(BorderStyle.THIN, mergeRegion, sheet);
  141.                     RegionUtil.setBorderRight(BorderStyle.THIN, mergeRegion, sheet);
  142.                     subGroupCell.setCellStyle(subGroupStyle);
  143.                     lastSubGroupValue = currentSubGroupValue;
  144.                 }
  145.             }
  146.             // Create data row
  147.             Row row = sheet.createRow(rowIndex++);
  148.             for (int j = 0; j < annotatedFields.size(); j++) {
  149.                 Field field = annotatedFields.get(j);
  150.                 PoiExportField annotation = field.getAnnotation(PoiExportField.class);
  151.                 Cell cell = row.createCell(j);
  152.                 try {
  153.                     // Get field value from getter method
  154.                     field.setAccessible(true);
  155.                     String getterName = "get" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
  156.                     Method getterMethod = data.getClass().getMethod(getterName);
  157.                     Object value = getterMethod.invoke(data);
  158.                     if (value != null) {
  159.                         cell.setCellValue(value.toString());
  160.                     }
  161.                     // Set cell style alignment
  162.                     CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
  163.                     cellStyle.cloneStyleFrom(dataCellStyle);
  164.                     cellStyle.setAlignment(annotation.align());
  165.                     cell.setCellStyle(cellStyle);
  166.                 } catch (Exception e) {
  167.                     e.printStackTrace();
  168.                 }
  169.             }
  170.         }
  171.     }
  172.     /**
  173.      * Get subgroup value
  174.      *
  175.      * @param data           Data
  176.      * @param subGroupFields List of subgroup fields
  177.      * @param <T>            Type of data
  178.      * @return Subgroup value
  179.      */
  180.     private <T> String getSubGroupValue(T data, List<Field> subGroupFields) {
  181.         StringBuilder subGroupValue = new StringBuilder();
  182.         for (Field field : subGroupFields) {
  183.             try {
  184.                 field.setAccessible(true);
  185.                 Object value = field.get(data);
  186.                 if (value != null) {
  187.                     subGroupValue.append(value.toString()).append(" ");
  188.                 }
  189.             } catch (IllegalAccessException e) {
  190.                 e.printStackTrace();
  191.             }
  192.         }
  193.         return subGroupValue.toString().trim();
  194.     }
  195.     /**
  196.      * Create and return default header style
  197.      *
  198.      * @param workbook Workbook
  199.      * @return CellStyle
  200.      */
  201.     private CellStyle createDefaultHeaderStyle(Workbook workbook) {
  202.         Font fontBold = workbook.createFont();
  203.         fontBold.setBold(true);
  204.         fontBold.setFontHeightInPoints((short) 12);
  205.         CellStyle headerStyle = workbook.createCellStyle();
  206.         headerStyle.setBorderTop(BorderStyle.THIN);
  207.         headerStyle.setBorderBottom(BorderStyle.THIN);
  208.         headerStyle.setBorderLeft(BorderStyle.THIN);
  209.         headerStyle.setBorderRight(BorderStyle.THIN);
  210.         headerStyle.setAlignment(HorizontalAlignment.CENTER);
  211.         headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  212.         headerStyle.setWrapText(true);
  213.         headerStyle.setFont(fontBold);
  214.         return headerStyle;
  215.     }
  216.     /**
  217.      * Create and return default subgroup style
  218.      *
  219.      * @param workbook Workbook
  220.      * @return CellStyle
  221.      */
  222.     private CellStyle createDefaultSubGroupStyle(Workbook workbook) {
  223.         // Create and return default subgroup style
  224.         Font fontBold = workbook.createFont();
  225.         fontBold.setBold(true);
  226.         fontBold.setFontHeightInPoints((short) 11);
  227.         CellStyle subGroupStyle = workbook.createCellStyle();
  228.         subGroupStyle.setBorderTop(BorderStyle.THIN);
  229.         subGroupStyle.setBorderBottom(BorderStyle.THIN);
  230.         subGroupStyle.setBorderLeft(BorderStyle.THIN);
  231.         subGroupStyle.setBorderRight(BorderStyle.THIN);
  232.         subGroupStyle.setAlignment(HorizontalAlignment.CENTER);
  233.         subGroupStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  234.         subGroupStyle.setFont(fontBold);
  235.         return subGroupStyle;
  236.     }
  237.     /**
  238.      * Create and return default data cell style
  239.      *
  240.      * @param workbook Workbook
  241.      * @return CellStyle
  242.      */
  243.     private CellStyle createDefaultDataCellStyle(Workbook workbook) {
  244.         // Create and return default data cell style
  245.         CellStyle dataCellStyle = workbook.createCellStyle();
  246.         Font fontBold = workbook.createFont();
  247.         fontBold.setBold(true);
  248.         fontBold.setFontHeightInPoints((short) 11);
  249.         dataCellStyle.setBorderTop(BorderStyle.THIN);
  250.         dataCellStyle.setBorderBottom(BorderStyle.THIN);
  251.         dataCellStyle.setBorderLeft(BorderStyle.THIN);
  252.         dataCellStyle.setBorderRight(BorderStyle.THIN);
  253.         dataCellStyle.setFont(fontBold);
  254.         return dataCellStyle;
  255.     }
  256. }
复制代码
4. 测试

  1. public class PoiExportUtilTest {
  2.     @Test
  3.     public void exportToExcel() {
  4.         PoiExportUtil poiExportUtil = new PoiExportUtil();
  5.         List<OrderVO> orderVOList = generateOrders();
  6.         poiExportUtil.exportToExcel(orderVOList, "order.xlsx");
  7.     }
  8.     public List<OrderVO> generateOrders() {
  9.         String[] COUNTRIES = {"China", "Japan", "Canada"};
  10.         Random RANDOM = new Random();
  11.         List<OrderVO> orders = new ArrayList<>();
  12.         for (int i = 0; i < 30; i++) {
  13.             String orderNo = "OrderNo" + (i + 1);
  14.             String orderUser = "User" + (i + 1);
  15.             String orderTime = "Time" + (i + 1);
  16.             String orderAmount = RANDOM.nextInt(10000) + ".00";
  17.             String orderDesc = "Desc" + (i + 1);
  18.             String orderRemark = "Remark" + (i + 1);
  19.             String orderPhone = "Phone" + (i + 1);
  20.             String orderZipCode = "ZipCode" + (i + 1);
  21.             String orderCountry = COUNTRIES[RANDOM.nextInt(COUNTRIES.length)];
  22.             String orderProvince = "Province" + (i + 1) % 3;
  23.             String orderCity = "City" + (i + 1);
  24.             String orderAddressDetail = "AddressDetail" + (i + 1);
  25.             OrderVO order = createOrder(orderNo, orderUser, orderTime, orderAmount, orderDesc, orderRemark, orderPhone,
  26.                     orderZipCode, orderCountry, orderProvince, orderCity, orderAddressDetail);
  27.             orders.add(order);
  28.         }
  29.         // Sort by orderCountry and orderTime
  30.         return orders.stream()
  31.                 .sorted(Comparator.comparing(OrderVO::getOrderCountry)
  32.                         .thenComparing(OrderVO::getOrderProvince)
  33.                         .thenComparing(OrderVO::getOrderTime))
  34.                 .collect(Collectors.toList());
  35.     }
  36.     private OrderVO createOrder(String orderNo, String orderUser, String orderTime, String orderAmount,
  37.                                 String orderDesc, String orderRemark, String orderPhone, String orderZipCode,
  38.                                 String orderCountry, String orderProvince, String orderCity, String orderAddressDetail) {
  39.         OrderVO order = new OrderVO();
  40.         order.setOrderNo(orderNo);
  41.         order.setOrderUser(orderUser);
  42.         order.setOrderTime(orderTime);
  43.         order.setOrderAmount(orderAmount);
  44.         order.setOrderDesc(orderDesc);
  45.         order.setOrderRemark(orderRemark);
  46.         order.setOrderPhone(orderPhone);
  47.         order.setOrderZipCode(orderZipCode);
  48.         order.setOrderCountry(orderCountry);
  49.         order.setOrderProvince(orderProvince);
  50.         order.setOrderCity(orderCity);
  51.         order.setOrderAddressDetail(orderAddressDetail);
  52.         return order;
  53.     }
  54. }
复制代码
参考源代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表