1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        優(yōu)雅的實(shí)現(xiàn) Excel 導(dǎo)入導(dǎo)出

        共 17098字,需瀏覽 35分鐘

         ·

        2021-08-18 20:55

        日常在做后臺(tái)系統(tǒng)的時(shí)候會(huì)很頻繁的遇到Excel導(dǎo)入導(dǎo)出的問(wèn)題,正好這次在做一個(gè)后臺(tái)系統(tǒng),就想著寫一個(gè)公用工具來(lái)進(jìn)行Excel的導(dǎo)入導(dǎo)出。

        一般我們?cè)趯?dǎo)出的時(shí)候都是導(dǎo)出的前端表格,而前端表格同時(shí)也會(huì)對(duì)應(yīng)的在后臺(tái)有一個(gè)映射類。

        所以在寫這個(gè)工具的時(shí)候我們先理一下我們需要實(shí)現(xiàn)的效果:

        • 導(dǎo)出方法接收一個(gè)list集合,和一個(gè)Class類型,和HttpServletResponse 對(duì)象

        • 導(dǎo)出是可能會(huì)有下拉列表,所以需要一個(gè)map存儲(chǔ)下拉列表數(shù)據(jù)源,傳入?yún)?shù)后只需一行代碼即可導(dǎo)出

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

        實(shí)現(xiàn)過(guò)程:

        首先需要?jiǎng)?chuàng)建三個(gè)注解

        一個(gè)是EnableExport ,必須有這個(gè)注解才能導(dǎo)出

        /**
         * 設(shè)置允許導(dǎo)出
         */

        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface EnableExport {
             String fileName();

        }

        然后就是EnableExportField,有這個(gè)注解的字段才會(huì)導(dǎo)出到Excel里面,并且可以設(shè)置列寬

        /**
         * 設(shè)置該字段允許導(dǎo)出
         * 并且可以設(shè)置寬度
         */

        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface EnableExportField {
             int colWidth() default  100;
             String colName();
        }

        再就是ImportIndex,導(dǎo)入的時(shí)候設(shè)置Excel中的列對(duì)應(yīng)的序號(hào)

        /**
         * 導(dǎo)入時(shí)索引
         */

        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface ImportIndex {
             int index() ;

        }

        注解使用示例

        三個(gè)注解創(chuàng)建好之后就需要開始操作Excel了

        首先,導(dǎo)入方法。在后臺(tái)接收到前端上傳的Excel文件之后,使用poi來(lái)讀取Excel文件

        我們根據(jù)傳入的類型上面的字段注解的順序來(lái)分別為不同的字段賦值,然后存入集合中,再返回

        代碼如下:


        /**
         * 將Excel轉(zhuǎn)換為對(duì)象集合
         * @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);
                    //默認(rèn)只獲取第一個(gè)工作表
                    sheet = workbook.getSheetAt(0);
                    if (sheet != null) {
                     //前兩行是標(biāo)題
                        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) {
                                    //設(shè)置單元格內(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包里面的一個(gè)類型轉(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;
        }

        接下來(lái)就是導(dǎo)出方法。

        導(dǎo)出分為幾個(gè)步驟:

        1. 建立一個(gè)工作簿,也就是類型新建一個(gè)Excel文件
        1. 建立一張sheet表
        1. 設(shè)置標(biāo)的行高和列寬
        1. 繪制標(biāo)題和表頭

        這兩個(gè)方法是自定義方法,代碼會(huì)貼在后面

        1. 寫入數(shù)據(jù)到Excel
        1. 創(chuàng)建下拉列表
        1. 寫入文件到response

        到這里導(dǎo)出工作就完成了

        下面是一些自定義方法的代碼

        /**
         * 獲取一個(gè)基本的帶邊框的單元格
         * @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;
        }

        /**
         * 獲取帶有背景色的標(biāo)題單元格
         * @param workbook
         * @return
         */

        private static HSSFCellStyle getTitleCellStyle(HSSFWorkbook workbook){
            HSSFCellStyle hssfcellstyle =  getBasicCellStyle(workbook);
            hssfcellstyle.setFillForegroundColor((short) HSSFColor.CORNFLOWER_BLUE.index); // 設(shè)置背景色
            hssfcellstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
            return hssfcellstyle;
        }

        /**
         * 創(chuàng)建一個(gè)跨列的標(biāo)題行
         * @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(000, 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); // 上邊框

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

        /**
         * 設(shè)置表頭標(biāo)題欄以及表格高度
         * @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){
            //插入標(biāo)題行
            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ù)校驗(yàn)
         * @param sheet 哪個(gè) sheet 頁(yè)添加校驗(yàn)
         * @return
         */

        public static void createDataValidation(Sheet sheet,Map<Integer,String[]> selectListMap) {
            if(selectListMap!=null) {
                selectListMap.forEach(
                        // 第幾列校驗(yàn)(0開始)key 數(shù)據(jù)源數(shù)組value
                        (key, value) -> {
                            if(value.length>0) {
                                CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(265535, key, key);
                                DataValidationHelper helper = sheet.getDataValidationHelper();
                                DataValidationConstraint constraint = helper.createExplicitListConstraint(value);
                                DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
                                //處理Excel兼容性問(wèn)題
                                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í)例

        導(dǎo)出數(shù)據(jù)

        導(dǎo)入數(shù)據(jù)(返回對(duì)象List)

        源碼地址:

        https://github.com/xyz0101/excelutils
        來(lái)源:blog.csdn.net/youzi1394046585/article/details/86670203

        推薦閱讀:

        世界的真實(shí)格局分析,地球人類社會(huì)底層運(yùn)行原理

        不是你需要中臺(tái),而是一名合格的架構(gòu)師(附各大廠中臺(tái)建設(shè)PPT)

        企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案

        論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

        華為干部與人才發(fā)展手冊(cè)(附PPT)

        企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

        【中臺(tái)實(shí)踐】華為大數(shù)據(jù)中臺(tái)架構(gòu)分享.pdf

        華為的數(shù)字化轉(zhuǎn)型方法論

        華為如何實(shí)施數(shù)字化轉(zhuǎn)型(附PPT)

        超詳細(xì)280頁(yè)Docker實(shí)戰(zhàn)文檔!開放下載

        華為大數(shù)據(jù)解決方案(PPT)


        瀏覽 25
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久涩网| 欧美日韩免费高清一区色橹橹 | 狠狠干狠狠操视频 | 国产亲子乱视频看 | 性做爰三级无删减 | 人人插人人干在线观看 | 久热中文在线 | 无码日本精品人妻一区二区妖精 | 88大鸡巴操操 | 亚洲免费在线播放 |