Excel匯入匯出工具
阿新 • • 發佈:2019-01-07
# Easy-POI 工具連結 https://github.com/programmeres/easy-poi https://gitee.com/nw1992/easy-poi Easy-POI是一款Excel匯入匯出解決方案組成的輕量級開源元件。 (如果喜歡或願意使用, 請star並且Watch本專案, 如果是企業使用, 請通過修改本檔案的企業列表告訴我企業名稱, 藉此給我們鼓勵及動力持續維護本專案。) 發現解決bug並已自測,pullRequest後,可以通過郵件告知我們([email protected]), 第一時間合併並且釋出最新版本 ## 使用企業列表: ## 功能簡介 1. 瀏覽器匯出Excel檔案(支援單/多sheet) 2. 瀏覽器匯出Excel模板檔案 3. 指定路徑生成Excel檔案(支援單/多sheet) 4. 返回Excel檔案(支援單/多sheet)的OutputStream, 一般用於將Excel檔案上傳到遠端, 例如FTP 5. 匯入Excel檔案(支援單/多sheet) ## 解決的問題 1.解決匯出大量資料造成的記憶體溢位問題(支援分頁查詢資料庫、採用poi官方推薦api(SXSSFWorkbook), 實現指定行數重新整理到磁碟) 2.解決匯入大量資料造成的記憶體溢位問題(分頁插入資料庫、採用poi官方推薦api(XSSF and SAX),採用SAX模式一行行讀取到記憶體當中去) 3.解決含有佔位符的空假行造成的讀空值問題 4.解決Long型別或者BigDecimal的精度不准問題 ## 元件特色 1.匯入可以自定義解析成功或失敗的處理邏輯 2.匯出支援分頁查詢、全量查詢, 自定義每條資料的處理邏輯 3.內建快取,3萬條11列資料,第一次匯出2.2s左右、第二次匯出在1.4s左右;第一次匯入3.5s左右、第二次匯入2.5s左右 4.註解操作, 輕量且便捷 5.內建常用正則表示式類RegexConst(身份證號、手機號、金額、郵件) 6.適配單元格寬度(單元格內容最長不得超過20個漢字) 7.假如出現異常,Sheet、行、列位置也都一併列印 8.註解中的使用者自定義字串資訊以及Excel資訊已全部trim,不用擔心存在前後空格的風險 9.Excel樣式簡潔、大方、美觀 ## 元件需知 匯入和匯出只支援尾綴為xlsx的Excel檔案、標註註解的屬性順序即Excel列的排列順序、時間轉化格式(dateFormat)預設為“yyyy-MM-dd HH:mm:ss“. ### 匯入 1.當匯入Excel, 讀取到空行, 則停止讀取當前Sheet的後面資料行 2.匯入Excel檔案, 單元格格式使用文字或者常規, 防止出現不可預測異常 3.匯入欄位型別支援:Date、Short(short)、Integer(int)、Double(double)、Long(long)、Float(float)、BigDecimal、String型別 4.匯入BigDecimal欄位精度預設為2, roundingMode預設為BigDecimal.ROUND_HALF_EVEN 5.第一行有效單元格內必須包含內容並且以第一行為依據, 匯入Excel檔案列數必須等於標註註解的屬性數量 6.Date型別欄位,Excel與時間轉化格式(dateFormat)相比,格式要保持一致(反例:2018/12/31和“yyyy-MM-dd“)並且長度要一致或更長(反例:"2018-12-31"和yyyy-MM-dd HH:mm:ss"),否則SimpleDateFormat將解析失敗,報 “Unparseable date:” ### 匯出 1.匯出BigDecimal欄位預設不進行精度格式化 2.分頁查詢預設從第一頁開始, 每頁3000條 3.Excel每超過2000條資料, 將記憶體中的資料重新整理到磁碟當中去 4.使用分Sheet匯出方法, 每8萬行資料分Sheet 5.當使用(exportResponse、exportStream、generateExcelStream)方法時, 當單個Sheet超過100萬條則會分Sheet 6.標註屬性型別要與資料庫型別保持一致 ## 擴充套件 繼承EasyPoi類, 可以使用子類構造器覆蓋以下預設引數 ```java //Excel自動重新整理到磁碟的數量 public static final int DEFAULT_ROW_ACCESS_WINDOW_SIZE = 2000; //分頁條數 public static final int DEFAULT_PAGE_SIZE = 3000; //分Sheet條數 public static final int DEFAULT_RECORD_COUNT_PEER_SHEET = 80000; ``` ## 版本 當前為1.0.0版本, 2.0.0版正在開發當中 ## 使用手冊 1.引入Maven依賴 2.將需要匯出或者匯入的實體屬性上標註@ExportField或@ImportField註解 3.直接呼叫匯出或匯入API即可 ### POM.xml ```xml <dependency> <groupId>io.github.magic-core</groupId> <artifactId>easy-poi</artifactId> <version>1.0</version> </dependency> ``` ### @ExportField ```java /** * 匯出註解功能介紹 */ public @interface ExportField { /** * excel列名稱 */ String columnName(); /** * 預設單元格值 */ String defaultCellValue() default ""; /** * 日期格式 預設 yyyy-MM-dd HH:mm:ss */ String dateFormat() default "yyyy-MM-dd HH:mm:ss"; /** * BigDecimal精度 預設:-1(預設不開啟BigDecimal格式化) */ int scale() default -1; /** * BigDecimal 舍入規則 預設:BigDecimal.ROUND_HALF_EVEN */ int roundingMode() default BigDecimal.ROUND_HALF_EVEN; } ``` ```java /** * 匯出註解Demo */ public class ExportFielddemo { @ExportField(columnName = "ID", defaultCellValue = "1") private Integer id; @ExportField(columnName = "姓名", defaultCellValue = "張三") private String name; @ExportField(columnName = "收入金額", defaultCellValue = "100", scale = 2, roundingMode=BigDecimal.ROUND_HALF_EVEN) private BigDecimal money; @ExportField(columnName = "建立時間", dateFormat="yyyy-MM-dd", defaultCellValue = "2019-01-01") private Date createTime; } ``` ### @ImportField ```java /** * 匯入註解功能介紹 */ public @interface ImportField { /** * @return 是否必填 */ boolean required() default false; /** * 日期格式 預設 yyyy-MM-dd HH:mm:ss */ String dateFormat() default "yyyy-MM-dd HH:mm:ss"; /** * 正則表示式校驗 */ String regex() default ""; /** * 正則表示式校驗失敗返回的錯誤資訊, regex配置後生效 */ String regexMessage() default "正則表示式驗證失敗"; /** * BigDecimal精度 預設:2 */ int scale() default 2; /** * BigDecimal 舍入規則 預設:BigDecimal.ROUND_HALF_EVEN */ int roundingMode() default BigDecimal.ROUND_HALF_EVEN; } ``` ```java /** * 匯入註解Demo */ public class ImportField { @ImportField(required = true) private Integer id; @ImportField(regex = IDCARD_REGEX, regexMessage="身份證校驗失敗") private String idCard; @ImportField(scale = 2, roundingMode=BigDecimal.ROUND_HALF_EVEN) private BigDecimal money; @ImportField(dateFormat="yyyy-MM-dd") private Date createTime; } ``` ### 匯出Demo ```java /** * 匯出Demo */ public class ExportDemo { /** * 瀏覽器匯出Excel * * @param httpServletResponse */ public void exportResponse(HttpServletResponse httpServletResponse) { ParamEntity queryQaram = new ParamEntity(); EasyPoi.ExportBuilder(httpServletResponse, "Excel檔名", AnnotationEntity.class).exportResponse(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 瀏覽器多sheet匯出Excel * * @param httpServletResponse */ public void exportMultiSheetResponse(HttpServletResponse httpServletResponse) { ParamEntity queryQaram = new ParamEntity(); EasyPoi.ExportBuilder(httpServletResponse, "Excel檔名", AnnotationEntity.class).exportMultiSheetStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<ResultEntity>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 匯出Excel到指定路徑 */ public void exportStream() throws FileNotFoundException { ParamEntity queryQaram = new ParamEntity(); EasyPoi.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel檔案.xlsx")), "Sheet名", AnnotationEntity.class) .exportStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 匯出多sheet Excel到指定路徑 */ @RequestMapping(value = "exportResponse") public void exportMultiSheetStream() throws FileNotFoundException { ParamEntity queryQaram = new ParamEntity(); EasyPoi.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel檔案.xlsx")), "Sheet名", AnnotationEntity.class) .exportMultiSheetStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 生成Excel OutputStream物件 */ public void generateExcelStream() throws FileNotFoundException { ParamEntity queryQaram = new ParamEntity(); OutputStream outputStream = EasyPoi.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel檔案.xlsx")), "Sheet名", AnnotationEntity.class) .generateExcelStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 生成多Sheet Excel OutputStream物件 */ public void generateMultiSheetExcelStream() throws FileNotFoundException { ParamEntity queryQaram = new ParamEntity(); OutputStream outputStream = EasyPoi.ExportBuilder(new FileOutputStream(new File("C:\\Users\\Excel檔案.xlsx")), "Sheet名", AnnotationEntity.class) .generateMultiSheetExcelStream(queryQaram, new ExportFunction<ParamEntity, ResultEntity>() { /** * @param queryQaram 查詢條件物件 * @param pageNum 當前頁數,從1開始 * @param pageSize 每頁條數,預設3000 * @return */ @Override public List<ResultEntity> pageQuery(ParamEntity queryQaram, int pageNum, int pageSize) { //分頁查詢操作 return new ArrayList<>(); } /** * 將查詢出來的每條資料進行轉換 * * @param o */ @Override public void convert(ResultEntity o) { //轉換操作 } }); } /** * 匯出Excel模板 */ public void exportTemplate(HttpServletResponse httpServletResponse) { EasyPoi.ExportBuilder(httpServletResponse, "Excel模板名稱", AnnotationEntity.class).exportTemplate(); } } ``` ### 匯入Demo ```java /** * 匯入Demo */ public class ImportDemo { public void importExcel() throws IOException { EasyPoi.ImportBuilder(new FileInputStream(new File("C:\\Users\\匯入Excel檔案.xlsx")), AnnotationEntity.class) .importExcel(new ExcelImportFunction<ResultEntity>() { /** * @param sheetIndex 當前執行的Sheet的索引, 從1開始 * @param rowIndex 當前執行的行數, 從1開始 * @param resultEntity Excel行資料的實體 */ @Override public void onProcess(int sheetIndex, int rowIndex, ResultEntity resultEntity) { //對每條資料自定義校驗以及操作 //分頁插入:當讀取行數到達使用者自定義條數執行插入資料庫操作 } /** * @param errorEntity 錯誤資訊實體 */ @Override public void onError(ErrorEntity errorEntity) { //操作每條資料非空和正則校驗後的錯誤資訊 } }); } } ```