日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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

 鷹兔牛熊眼 2021-07-27

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

日常在做后臺(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)的效果:

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

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

  3. 導(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文件
    圖片

  2. 建立一張sheet表
    圖片

  3. 設(shè)置標(biāo)的行高和列寬
    圖片

  4. 繪制標(biāo)題和表頭
    圖片
    這兩個(gè)方法是自定義方法,代碼會(huì)貼在后面

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

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

  7. 寫入文件到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(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); // 上邊框

        //設(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(2, 65535, 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)
圖片

  作者 |  _JenKin

來(lái)源 |  csdn.net/youzi1394046585/article/details/86670203

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多