EasyPoi 的多 sheet 導出,導入和基本校驗


這里使用的是 springboot 項目

導入 easypoi 的 starter

<dependency>
  <groupId>cn.afterturn</groupId>
  <artifactId>easypoi-spring-boot-starter</artifactId>
  <version>4.0.0</version>
</dependency>

// 用於校驗 excel 字段
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

ExcelPoiUtil 工具類

/**
 * @author sunhw
 * @date 2021/5/29
 */
@Slf4j
public class EasyPoiUtil {


    /**
     * 構建 sheet
     *
     * @param sheetName sheet 名字
     * @param clazz     clazz
     * @param list      列表
     * @return {@link Map<String, Object>}
     */
    public static Map<String, Object> buildSheet(String sheetName, Class<?> clazz, List<?> list) {

        ExportParams exportParams = new ExportParams();
        exportParams.setType(ExcelType.XSSF);
        exportParams.setSheetName(sheetName);
        // 導出樣式
        exportParams.setStyle(EasyPoiExcelStyleUtil.class);

        Map<String, Object> map = new HashMap<>(4);
        // title的參數為ExportParams類型
        map.put("title", exportParams);
        // 模版導出對應得實體類型
        map.put("entity", clazz);
        // sheet中要填充得數據
        map.put("data", list);

        return map;

    }

    /**
     * 下載 excel
     *
     * 前端如果用xlsx格式接收表格 后台用XSSFWorkbook workbook = new XSSFWorkbook();創建工作薄
     * response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
     * response.addHeader("Content-Disposition", "attachment;filename=fileName" + ".xlsx");
     * 
     * 前端如果用用xls格式接收表格 后台 用HSSFWorkbook workbook = new HSSFWorkbook();創建工作薄
     * response.setContentType("application/vnd.ms-excel");
     * response.addHeader("Content-Disposition", "attachment;filename=fileName"+".xls");
     *
     * @param fileName 文件名稱
     * @param response 響應
     * @param workbook 工作簿
     */
    public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers",
                    "Content-Disposition");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.info("文件下載失敗", e);
            throw new RuntimeException(e);
        }
    }


    /**
     * 功能描述:根據接收的Excel文件來導入Excel,並封裝成實體類
     *
     * @param file       文件
     * @param sheetNum   第幾個 sheet
     * @param titleRows  title 行數
     * @param headerRows 標題 行數
     * @param pojoClass  pojo類
     * @return {@link List<T>}
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer sheetNum, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
        if (Objects.isNull(file)) {
            return Collections.emptyList();
        }
        ImportParams params = new ImportParams();
        params.setStartSheetIndex(sheetNum);
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass,
                    params);
        } catch (NoSuchElementException e) {
            throw new RuntimeException("excel文件不能為空");
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return list;
    }

    /**
     * 功能描述:根據接收的 Excel 文件來導入 Excel,並封裝成 Map
     *
     * @param file       文件
     * @param sheetNum   第幾個 sheet
     * @param titleRows  title 行數
     * @param headerRows 標題 行數
     * @return {@link List<T>}
     */
    public static <T> List<T> parseExcelMap(MultipartFile file, Integer sheetNum, Integer titleRows, Integer headerRows) {
        if (Objects.isNull(file)) {
            return Collections.emptyList();
        }
        ImportParams params = new ImportParams();
        params.setStartSheetIndex(sheetNum);
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setNeedCheckOrder(true);

        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), Map.class,
                    params);
        } catch (NoSuchElementException e) {
            throw new RuntimeException("excel文件不能為空");
        } catch (Exception e) {
            log.info("excel 文件讀取失敗", e);
            throw new RuntimeException("文件讀取失敗");
        }
        return list;
    }

    /**
     * 得到 Workbook 對象
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static Workbook getWorkBook(MultipartFile file) throws IOException {
        //這樣寫  excel 能兼容03和07
        InputStream is = file.getInputStream();
        Workbook hssfWorkbook = null;
        try {
            hssfWorkbook = new HSSFWorkbook(is);
        } catch (Exception ex) {
            is = file.getInputStream();
            hssfWorkbook = new XSSFWorkbook(is);
        }
        return hssfWorkbook;
    }


    /**
     * 檢查excel
     *
     * @param file       文件
     * @param sheetNum   第幾個 sheet
     * @param titleRows  title 所占行數
     * @param headerRows head 所占行數
     * @param clazz      clazz
     * @return {@link ExcelImportResult<T>}
     */
    public static <T> ExcelImportResult<T> checkExcel(MultipartFile file, Integer sheetNum, Integer titleRows, Integer headerRows, Class<T> clazz) {
        if (Objects.isNull(file)) {
            return new ExcelImportResult<>();
        }

        ImportParams params = new ImportParams();
        params.setStartSheetIndex(sheetNum);
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        // 開啟校驗
        params.setNeedVerify(true);

        ExcelImportResult<T> result = null;
        try {
            result = ExcelImportUtil.importExcelMore(
                    file.getInputStream(), clazz, params);
        } catch (NoSuchElementException e) {
            throw new RuntimeException("excel文件不能為空");
        } catch (Exception e) {
            log.info("excel 文件讀取失敗", e);
            throw new RuntimeException("文件讀取失敗");
        }
        return result;
    }

}

測試 VO 實體類

@Data
public class CreditDebt implements Serializable, IExcelDataModel, IExcelModel {
    private static final long serialVersionUID = 1L;

    @Excel(name = "債券代碼")
    @NotBlank(message = "債券代碼不可為空")
    private String bondCode;

    /**
     * 行號
     */
    private int rowNum;
  
    /**
     * 錯誤消息
     */
    private String errorMsg;

}
@Data
public class IndustryInfo implements Serializable, IExcelDataModel, IExcelModel {
   private static final long serialVersionUID = 1L;

   @Excel(name = "行業")
   @NotBlank(message = "行業名稱不可為空")
   private String industry;

   @Excel(name = "行業整體評級")
   @NotBlank(message = "行業整體評級不可為空")
   @Pattern(regexp = "^優秀|良好$")
   private String industryGood;

   /**
    * 行號
    */
   private int rowNum;

   /**
    * 錯誤消息
    */
   private String errorMsg;

}

ExcelController Demo

/**
 * @author sunhw
 * @date 2021/5/28 使用 ExcelPoi 進行 Excel 的導出
 */
@RestController
@RequestMapping("/excel")
public class ExcelController {

    /**
     * 多 sheet 導出
     */
    @GetMapping("/download")
    public void download(HttpServletResponse response) {

        Map<String, Object> creditSheet = EasyPoiUtil.buildSheet("信用債",
                CreditDebt.class, Collections.EMPTY_LIST);

        Map<String, Object> industrySheet = EasyPoiUtil.buildSheet("行業",
                IndustryInfo.class, Collections.EMPTY_LIST);

        List<Map<String, Object>> sheetsList = new ArrayList<>();
        sheetsList.add(creditSheet);
        sheetsList.add(industrySheet);

        Workbook workBook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.XSSF);

        EasyPoiUtil.downLoadExcel("資產類型", response, workBook);

    }


    /**
     * 解析 excel 實體類
     *
     * @param file 文件
     */
    @GetMapping("/parse")
    public String parse(@RequestParam("file") MultipartFile file) throws IOException {

        String fileType = FileTypeUtil.getFileType(file);

        if (!FileTypeUtil.isAllowedTypes(fileType)) {
            return "文件格式不支持";
        }

        List<CreditDebt> creditDebtList = EasyPoiUtil.importExcel(file,
                0, 0, 1, CreditDebt.class);
        List<IndustryInfo> industryInfoList = EasyPoiUtil.importExcel(file,
                1, 0, 1, IndustryInfo.class);

        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(creditDebtList);
    }

    /**
     * 解析 excel Map結構
     *
     * @param file 文件
     */
    @GetMapping("/parseMap")
    public String parseMap(@RequestParam("file") MultipartFile file) throws IOException {

        String fileType = FileTypeUtil.getFileType(file);

        if (!FileTypeUtil.isAllowedTypes(fileType)) {
            return "文件格式不支持";
        }

        List<List<Object>> excelInfoList = new ArrayList<>();

        Workbook workbook = EasyPoiUtil.getWorkBook(file);

        int sheetNum = workbook.getNumberOfSheets();

        for (int i = 0; i < sheetNum; i++) {
            excelInfoList.add(EasyPoiUtil.parseExcelMap(file, i, 0, 1));
        }

        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(excelInfoList);
    }

    /**
     * 校驗 excel
     *
     * @param file 文件
     * @return {@link String}
     */
    @GetMapping("/check")
    public String check(@RequestParam("file") MultipartFile file) throws Exception {
        String fileType = FileTypeUtil.getFileType(file);

        if (!FileTypeUtil.isAllowedTypes(fileType)) {
            return "文件格式不支持";
        }

        ExcelImportResult<CreditDebt> result = EasyPoiUtil.checkExcel(file, 0, 0, 1, CreditDebt.class);

        ExcelImportResult<IndustryInfo> result2= EasyPoiUtil.checkExcel(file, 1, 0, 1, IndustryInfo.class);

        ObjectMapper objectMapper = new ObjectMapper();

        System.out.println("是否校驗失敗: " + result.isVerfiyFail());
        System.out.println("校驗失敗的集合:" + objectMapper.writeValueAsString(result.getFailList()));
        System.out.println("校驗通過的集合:" + objectMapper.writeValueAsString(result.getList()));

        System.out.println("是否校驗失敗: " + result2.isVerfiyFail());
        System.out.println("校驗失敗的集合:" + objectMapper.writeValueAsString(result2.getFailList()));
        System.out.println("校驗通過的集合:" + objectMapper.writeValueAsString(result2.getList()));

        for (CreditDebt entity : result.getFailList()) {
            String msg = "第" + entity.getRowNum() + "行的錯誤是:" + entity.getErrorMsg();
            System.out.println(msg);
        }

        for (IndustryInfo entity : result2.getFailList()) {
            String msg = "第" + entity.getRowNum() + "行的錯誤是:" + entity.getErrorMsg();
            System.out.println(msg);
        }

        return "false";
    }
}

調整 Excel 樣式的工具類

/**
 * excel風格
 *
 * @author sunhw
 * @date 2021/05/29
 */
public class EasyPoiExcelStyleUtil implements IExcelExportStyler {
    private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
    private static final short FONT_SIZE_TEN = 9;
    private static final short FONT_SIZE_ELEVEN = 10;
    private static final short FONT_SIZE_TWELVE = 11;
    /**
     * 大標題樣式
     */
    private CellStyle headerStyle;
    /**
     * 每列標題樣式
     */
    private CellStyle titleStyle;
    /**
     * 數據行樣式
     */
    private CellStyle styles;

    public EasyPoiExcelStyleUtil(Workbook workbook) {
        this.init(workbook);
    }

    /**
     * 初始化樣式
     *
     * @param workbook
     */
    private void init(Workbook workbook) {
        this.headerStyle = initHeaderStyle(workbook);
        this.titleStyle = initTitleStyle(workbook);
        this.styles = initStyles(workbook);
    }

    /**
     * 大標題樣式
     *
     * @param color
     * @return
     */
    @Override
    public CellStyle getHeaderStyle(short color) {
        return headerStyle;
    }

    /**
     * 每列標題樣式
     *
     * @param color
     * @return
     */
    @Override
    public CellStyle getTitleStyle(short color) {
        return titleStyle;
    }

    /**
     * 數據行樣式
     *
     * @param parity 可以用來表示奇偶行
     * @param entity 數據內容
     * @return 樣式
     */
    @Override
    public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
        return styles;
    }

    /**
     * 獲取樣式方法
     *
     * @param dataRow 數據行
     * @param obj     對象
     * @param data    數據
     */
    @Override
    public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
        return getStyles(true, entity);
    }

    /**
     * 模板使用的樣式設置
     */
    @Override
    public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
        return null;
    }

    /**
     * 初始化--大標題樣式
     *
     * @param workbook
     * @return
     */
    private CellStyle initHeaderStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
        return style;
    }

    /**
     * 初始化--每列標題樣式
     *
     * @param workbook
     * @return
     */
    private CellStyle initTitleStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
        //背景色
        style.setFillForegroundColor(IndexedColors.WHITE1.getIndex());
        style.setFillPattern(FillPatternType.NO_FILL);
        return style;
    }

    /**
     * 初始化--數據行樣式
     *
     * @param workbook
     * @return
     */
    private CellStyle initStyles(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
        style.setDataFormat(STRING_FORMAT);
        return style;
    }

    /**
     * 基礎樣式
     *
     * @return
     */
    private CellStyle getBaseCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        //下邊框
        style.setBorderBottom(BorderStyle.THIN);
        //左邊框
        style.setBorderLeft(BorderStyle.THIN);
        //上邊框
        style.setBorderTop(BorderStyle.THIN);
        //右邊框
        style.setBorderRight(BorderStyle.THIN);
        //水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //設置自動換行
        style.setWrapText(false);
        return style;
    }

    /**
     * 字體樣式
     *
     * @param size   字體大小
     * @param isBold 是否加粗
     * @return
     */
    private Font getFont(Workbook workbook, short size, boolean isBold) {
        Font font = workbook.createFont();
        //字體樣式
        font.setFontName("宋體");
        //是否加粗
        font.setBold(isBold);
        //字體大小
        font.setFontHeightInPoints(size);
        return font;
    }
}

參考鏈接:

源碼地址傳送

easypoi 官方文檔

http://nullpointer.pw/easypoi導入Excel最佳實踐.html

https://github.com/CuiZhongyuan/IWeb4j


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM