<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    利用注解+反射優(yōu)雅的實現(xiàn)通用Excel導入導出

    共 20853字,需瀏覽 42分鐘

     ·

    2021-07-30 22:50

    點擊上方藍色字體,選擇“標星公眾號”

    優(yōu)質(zhì)文章,第一時間送達

    日常在做后臺系統(tǒng)的時候會很頻繁的遇到Excel導入導出的問題,正好這次在做一個后臺系統(tǒng),就想著寫一個公用工具來進行Excel的導入導出。
    一般我們在導出的時候都是導出的前端表格,而前端表格同時也會對應的在后臺有一個映射類。
    所以在寫這個工具的時候我們先理一下我們需要實現(xiàn)的效果:

    1. 導出方法接收一個list集合,和一個Class類型,和HttpServletResponse 對象

    2. 導出是可能會有下拉列表,所以需要一個map存儲下拉列表數(shù)據(jù)源,傳入?yún)?shù)后只需一行代碼即可導出

    3. 導入方法需要傳入file文件,以及一個Class類型,導入之后將會返回一個list集合,里面的對象就是傳入類型的對象,傳入?yún)?shù)后只需一行代碼即可導入

    實現(xiàn)過程:
    首先需要創(chuàng)建三個注解
    一個是EnableExport ,必須有這個注解才能導出

    /**
     * 設置允許導出
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EnableExport {
         String fileName();

    }


    然后就是EnableExportField,有這個注解的字段才會導出到Excel里面,并且可以設置列寬

    /**
     * 設置該字段允許導出
     * 并且可以設置寬度
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EnableExportField {
         int colWidth() default  100;
         String colName();
    }


    再就是ImportIndex,導入的時候設置Excel中的列對應的序號

    /**
     * 導入時索引
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ImportIndex {
         int index() ;


    }

    注解使用示例

    三個注解創(chuàng)建好之后就需要開始操作Excel了
    首先,導入方法。在后臺接收到前端上傳的Excel文件之后,使用poi來讀取Excel文件
    我們根據(jù)傳入的類型上面的字段注解的順序來分別為不同的字段賦值,然后存入集合中,再返回
    代碼如下:


    /**
         * 將Excel轉(zhuǎn)換為對象集合
         * @param excel Excel 文件
         * @param clazz pojo類型
         * @return
         */
        public static List<Object> parseExcelToList(File excel,Class clazz){
            List<Object> res = new ArrayList<>();
            // 創(chuàng)建輸入流,讀取Excel
            InputStream is = null;
            Sheet sheet = null;
            try {
                is = new FileInputStream(excel.getAbsolutePath());
                if (is != null) {
                    Workbook workbook = WorkbookFactory.create(is);
                    //默認只獲取第一個工作表
                    sheet = workbook.getSheetAt(0);
                    if (sheet != null) {
                     //前兩行是標題
                        int i = 2;
                        String values[] ;
                        Row row = sheet.getRow(i);
                        while (row != null) {
                            //獲取單元格數(shù)目
                            int cellNum = row.getPhysicalNumberOfCells();
                            values = new String[cellNum];
                            for (int j = 0; j <= cellNum; j++) {
                                Cell cell =   row.getCell(j);
                                if (cell != null) {
                                    //設置單元格內(nèi)容類型
                                    cell.setCellType(Cell.CELL_TYPE_STRING );
                                    //獲取單元格值
                                    String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();
                                    values[j]=value;
                                }
                            }
                            Field[] fields = clazz.getDeclaredFields();
                            Object obj = clazz.newInstance();
                            for(Field f : fields){
                                if(f.isAnnotationPresent(ImportIndex.class)){
                                    ImportIndex annotation = f.getDeclaredAnnotation(ImportIndex.class);
                                    int index = annotation.index();
                                    f.setAccessible(true);
                                    //此處使用了阿里巴巴的fastjson包里面的一個類型轉(zhuǎn)換工具類
                                    Object val =TypeUtils.cast(values[index],f.getType(),null);
                                    f.set(obj,val);
                                }
                            }
                            res.add(obj);
                            i++;
                            row=sheet.getRow(i);
                        }

                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return res;
        }


    接下來就是導出方法
    導出分為幾個步驟:

    1. 建立一個工作簿,也就是類型新建一個Excel文件

    2. 建立一張sheet表

    3. 設置標的行高和列寬

    4. 繪制標題和表頭

      這兩個方法是自定義方法,代碼會貼在后面

    5. 寫入數(shù)據(jù)到Excel

    6. 創(chuàng)建下拉列表

    7. 寫入文件到response

      到這里導出工作就完成了
      下面是一些自定義方法的代碼

      /**
         * 獲取一個基本的帶邊框的單元格
         * @param workbook
         * @return
         */
        private static HSSFCellStyle getBasicCellStyle(HSSFWorkbook workbook){
            HSSFCellStyle hssfcellstyle = workbook.createCellStyle();
            hssfcellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            hssfcellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            hssfcellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
            hssfcellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
            hssfcellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            hssfcellstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            hssfcellstyle.setWrapText(true);
            return hssfcellstyle;
        }

        /**
         * 獲取帶有背景色的標題單元格
         * @param workbook
         * @return
         */
        private static HSSFCellStyle getTitleCellStyle(HSSFWorkbook workbook){
            HSSFCellStyle hssfcellstyle =  getBasicCellStyle(workbook);
            hssfcellstyle.setFillForegroundColor((short) HSSFColor.CORNFLOWER_BLUE.index); // 設置背景色
            hssfcellstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
            return hssfcellstyle;
        }

        /**
         * 創(chuàng)建一個跨列的標題行
         * @param workbook
         * @param hssfRow
         * @param hssfcell
         * @param hssfsheet
         * @param allColNum
         * @param title
         */
        private static void createTitle(HSSFWorkbook workbook, HSSFRow hssfRow , HSSFCell hssfcell, HSSFSheet hssfsheet,int allColNum,String title){
            //在sheet里增加合并單元格
            CellRangeAddress cra = new CellRangeAddress(0, 0, 0, allColNum);
            hssfsheet.addMergedRegion(cra);
            // 使用RegionUtil類為合并后的單元格添加邊框
            RegionUtil.setBorderBottom(1, cra, hssfsheet, workbook); // 下邊框
            RegionUtil.setBorderLeft(1, cra, hssfsheet, workbook); // 左邊框
            RegionUtil.setBorderRight(1, cra, hssfsheet, workbook); // 有邊框
            RegionUtil.setBorderTop(1, cra, hssfsheet, workbook); // 上邊框

            //設置表頭
            hssfRow = hssfsheet.getRow(0);
            hssfcell = hssfRow.getCell(0);
            hssfcell.setCellStyle( getTitleCellStyle(workbook));
            hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
            hssfcell.setCellValue(title);
        }

        /**
         * 設置表頭標題欄以及表格高度
         * @param workbook
         * @param hssfRow
         * @param hssfcell
         * @param hssfsheet
         * @param colNames
         */
        private static void createHeadRow(HSSFWorkbook workbook,HSSFRow hssfRow , HSSFCell hssfcell,HSSFSheet hssfsheet,List<String> colNames){
            //插入標題行
            hssfRow = hssfsheet.createRow(1);
            for (int i = 0; i < colNames.size(); i++) {
                hssfcell = hssfRow.createCell(i);
                hssfcell.setCellStyle(getTitleCellStyle(workbook));
                hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
                hssfcell.setCellValue(colNames.get(i));
            }
        }
        /**
         * excel添加下拉數(shù)據(jù)校驗
         * @param sheet 哪個 sheet 頁添加校驗
         * @return
         */
        public static void createDataValidation(Sheet sheet,Map<Integer,String[]> selectListMap) {
            if(selectListMap!=null) {
                selectListMap.forEach(
                        // 第幾列校驗(0開始)key 數(shù)據(jù)源數(shù)組value
                        (key, value) -> {
                            if(value.length>0) {
                                CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(2, 65535, key, key);
                                DataValidationHelper helper = sheet.getDataValidationHelper();
                                DataValidationConstraint constraint = helper.createExplicitListConstraint(value);
                                DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
                                //處理Excel兼容性問題
                                if (dataValidation instanceof XSSFDataValidation) {
                                    dataValidation.setSuppressDropDownArrow(true);
                                    dataValidation.setShowErrorBox(true);
                                } else {
                                    dataValidation.setSuppressDropDownArrow(false);
                                }
                                dataValidation.setEmptyCellAllowed(true);
                                dataValidation.setShowPromptBox(true);
                                dataValidation.createPromptBox("提示""只能選擇下拉框里面的數(shù)據(jù)");
                                sheet.addValidationData(dataValidation);
                            }
                        }
                );
            }
        }


    使用實例
    導出數(shù)據(jù)

    導入數(shù)據(jù)(返回對象List)

      作者 |  _JenKin

    來源 |  csdn.net/youzi1394046585/article/details/86670203


    加鋒哥微信: java3459  
    圍觀鋒哥朋友圈,天天推送Java干貨!

    瀏覽 78
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    国产av一区二区三本 | 麻豆激情四射在线播放 | 草久久免费视频 | 美利坚一区二区三区 | 亚洲精品高清无码 |