日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POI导出详解

發布時間:2024/1/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POI导出详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最為常見的POI導出方式有3種:HSSF,XSSF,SXSSF

XSSFworkbook:操作Excel2007版本,擴展名為xlsx,玩這個不如玩SXSSF

pom文件,下面那個fastjson是我做數據格式化的,可以不用

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.68</version></dependency>

實體類

package com.xx.entity;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.Date;/*** @author aqi* DateTime: 2020/5/20 11:03 上午* Description: No Description*/ @Data @AllArgsConstructor @NoArgsConstructor public class User {private Integer id;private String name;private String password;private Integer gender;private Boolean live;private String remarks;private Date createTime;private String other;private String msg1;private String msg2;private String msg3;}

?下面是工具類

使用HSSF導出的工具類,不推薦使用,是2003版本之前的Excel,導出文件擴展名為xls,這種方式在數據量不大的情況下也可以使用,速度也不會差很多,當數據量大的時候,每個sheet限制在6w條,會產生很多的sheet,并且導出的文件大小很大,效率相較于SXSSF稍微差點,如果是遺留項目,需要更改時HSSF轉SXSSF也非常的容易,代碼變化不大,可以放心技術迭代
1w條數據基本上在0.5s以內,文件大小在2.5MB左右

5w條數據基本上在3s左右,文件大小在11MB左右

package com.xx.utils;import com.alibaba.fastjson.JSON; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.HorizontalAlignment;import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.util.List; import java.util.Map;/*** @author aqi* DateTime: 2020/5/28 9:17 上午* Description:* 使用HSSF進行Excel導出(不推薦使用)* 1.HSSF操作的是2003版本之前的Excel,擴展名是xls* 2.不希望方法調用的時候傳遞那么多參數,想要修改的參數直接修改方法內的靜態參數就好了* 3.過多的樣式我就不diy了,實在是太多了,默認定義了一個我覺得還行的樣式,可以直接使用* HSSF的缺陷:* 當導出數據超過65536條就會報錯,拋出這個異常,網上有很多解決方案,我比較推薦不使用這種方式導出 java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)* HSSF的效率* 10次一組跑了10次:* 1w條數據基本上在0.5秒以內,文件大小在2.5MB左右,偶爾存在波動情況* 5w條數據基本上在3秒左右,文件大小在11MB左右***/ public class ExcelUtils {/*** 表頭字體大小*/private static String headerFontSize = "13";/*** 表頭字體樣式*/private static String headerFontName = FontStyle.MicrosoftYahei.name;/*** 數據字體大小*/private static String otherFontSize = "10";/*** 數據字體樣式*/private static String otherFontName = FontStyle.MicrosoftYahei.name;/*** 單元格寬度*/private static Integer width = 30;/*** sheet的名字*/private static String sheetName = "sheetName";/*** 是否開啟表頭樣式,默認為true,開啟*/private static Boolean isOpeanHeaderStyle = true;/*** ##############是否開始其他數據樣式,默認為false,關閉(不建議開啟,數據量大時影響性能)################*/private static Boolean isOpeanOtherStyle = false;/*** @param keys 對象屬性對應中文名* @param columnNames 對象的屬性名* @param fileName 文件名* @param list 需要導出的json數據* @description 使用HSSFWorkBook導出數據, HSSF導出數據存在一些問題*/public static void exportExcel(HttpServletResponse response, String[] keys, String[] columnNames, String fileName, List<Map<String, Object>> list) throws IOException {// 創建一個工作簿HSSFWorkbook wb = new HSSFWorkbook();// 創建一個sheetHSSFSheet sh = wb.createSheet(sheetName);// 創建Excel工作表第一行,設置表頭信息HSSFRow row0 = sh.createRow(0);for (int i = 0; i < keys.length; i++) {// 設置單元格寬度sh.setColumnWidth(i, 256 * width + 184);HSSFCell cell = row0.createCell(i);cell.setCellValue(keys[i]);// 是否開啟表頭樣式if (isOpeanHeaderStyle) {// 創建表頭樣式HSSFCellStyle headerStyle = setCellStyle(wb, headerFontSize, headerFontName, "header");cell.setCellStyle(headerStyle);}}for (int i = 0; i < list.size(); i++) {// 循環創建行HSSFRow row = sh.createRow(i + 1);// 給這行的每列寫入數據for (int j = 0; j < columnNames.length; j++) {HSSFCell cell = row.createCell(j);// 以這樣的方式取值,過濾掉不需要的字段String value = String.valueOf(list.get(i).get(columnNames[j]));cell.setCellValue(value);// 是否開始其他數據樣式if (isOpeanOtherStyle) {// 設置數據樣式HSSFCellStyle otherStyle = setCellStyle(wb, otherFontSize, otherFontName, "other");cell.setCellStyle(otherStyle);}}}response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));// 這個操作也非常的耗時,暫時不知道和什么有關,應該該和文件的大小有關wb.write(response.getOutputStream());}/*** @param wb 工作簿* @param fontSize 字體大小* @param fontName 字體名稱* @return 工作簿樣式* @description 設置Excel樣式*/private static HSSFCellStyle setCellStyle(HSSFWorkbook wb, String fontSize, String fontName, String boo) {// 創建自定義樣式類HSSFCellStyle style = wb.createCellStyle();// 創建自定義字體類HSSFFont font = wb.createFont();// 設置字體樣式font.setFontName(fontName);// 設置字體大小font.setFontHeightInPoints(Short.parseShort(fontSize));// 我這個版本的POI沒找到網上的HSSFCellStyle// 設置對齊方式style.setAlignment(HorizontalAlignment.CENTER);// 數據內容設置邊框實在太丑,容易看瞎眼睛,我幫你們去掉了if ("header".equals(boo)) {// 設置邊框style.setBorderBottom(BorderStyle.MEDIUM);style.setBorderLeft(BorderStyle.MEDIUM);style.setBorderRight(BorderStyle.MEDIUM);style.setBorderTop(BorderStyle.MEDIUM);// 表頭字體加粗font.setBold(true);}style.setFont(font);return style;}/*** 格式化數據(我發現這個操作非常的消耗時間,盡量不要使用到這個數據轉化,如果是List<Map>就直接傳,如果是Json稍微改一下上面的工具類,List<Bean>好像沒什么比較好的處理手段)** @param s json數據* @return 裝換成List集合的數據*/public static List<Map<String, Object>> toList(String s) {List<Map<String, Object>> list = (List) JSON.parse(s);return list;}/*** 找了半天也沒找到可以diy的類,我自己寫個吧*/enum FontStyle {// 微軟雅黑MicrosoftYahei("微軟雅黑"),// 宋體TimesNewRoman("宋體"),// 楷體Italics("楷體"),// 幼圓YoungRound("幼圓");private String name;FontStyle(String name) {this.name = name;}} }

使用SXSSF導出的工具類,推薦使用,SXSSF可用于大數據量的導出,更加推薦使用這種方式,效率更高,每個sheet可以容納的數據更多,還可以避免內存溢出的問題,每個sheet可以存儲100w以上的數據

1w條數據基本上在0.5s以內,文件大小在700KB左右

5w條數據基本上在1.7s以內,文件大小在3.5MB左右

100w條數據基本上在35s左右,文件大小在70MB左右

200w條數據基本上在85s左右,文件大小在140MB左右(做了多sheet處理,如果項目經理要一次性導出還要在5s內的話,你就把他鯊了吧)

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?這個是在導出200w數據時的電腦性能監控

package com.xx.utils;import com.alibaba.fastjson.JSON; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.xssf.streaming.SXSSFCell; import org.apache.poi.xssf.streaming.SXSSFRow; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook;import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.util.List; import java.util.Map;/*** @author aqi* DateTime: 2020/5/28 11:50 上午* Description:* 使用SXSSF進行Excel導出(推薦使用)* 1.SXSSF用于大數據量導出,擴展名是xlsx* 2.不希望方法調用的時候傳遞那么多參數,想要修改的參數直接修改方法內的靜態參數就好了* 3.過多的樣式我就不diy了,實在是太多了,默認定義了一個我覺得還行的樣式,可以直接使用* SXSSF的缺陷:* 當導出數據超過1048576條就會報錯,拋出這個異常,因為每個Sheet最多只能存1048576條數據,這時候需要將數據寫到新的Sheet中,工具類已優化 java.lang.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)* SXSSF的效率* 10次一組跑了10次:* 1w條數據基本上在0.5秒以內,文件大小在700KB左右* 5w條數據基本上在1.7秒左右,文件大小在3.5MB左右* 100w條數據基本上在35秒左右,文件大小在70MB左右(雖然內存沒有溢出,但是cpu資源吃的厲害)* 200W條數據基本上在85秒左右,文件大小在140MB左右(做了多sheet處理,如果項目經理要一次性導出還要在5s內的話,你就把他鯊了吧)***/ public class ExcelUtils {/*** 表頭字體大小*/private static String headerFontSize = "13";/*** 表頭字體樣式*/private static String headerFontName = FontStyle.MicrosoftYahei.name;/*** 數據字體大小*/private static String otherFontSize = "10";/*** 數據字體樣式*/private static String otherFontName = FontStyle.MicrosoftYahei.name;/*** 單元格寬度*/private static Integer width = 30;/*** sheet的名字*/private static String sheetName = "sheetName";/*** 每個sheet存放的數據量*/private static Integer sheetLength = 1000000;/*** 是否開啟表頭樣式,默認為true,開啟*/private static Boolean isOpeanHeaderStyle = true;/*** ##############是否開始其他數據樣式,默認為false,關閉(不建議開啟,數據量大時影響性能)################*/private static Boolean isOpeanOtherStyle = false;/*** @param keys 對象屬性對應中文名* @param columnNames 對象的屬性名* @param fileName 文件名* @param list 需要導出的json數據* @description 使用SXSSFWorkBook導出數據*/public static void exportExcel(HttpServletResponse response, String[] keys, String[] columnNames, String fileName, List<Map<String, Object>> list) throws IOException {// 創建一個工作簿,每寫100條數據就刷新數據出緩存,避免內存溢出SXSSFWorkbook wb = new SXSSFWorkbook(100);// 傳入數據的大小int listSize = list.size();// 創建一個sheetSXSSFSheet sh = wb.createSheet(sheetName);// 設置這個sheet表頭信息和樣式setHeaderStyle(sh, keys, wb);// 用于計數,每100w時重新開始創建行int temp = 0;// 用于創建不同的sheetNameint sheetNameEnd = 0;// 這個二重循環不知道有沒有優化的空間了for (int i = 0; i < listSize; i++, temp++) {// 每100w重新創建一個新的sheetif (i % sheetLength == 0 && i != 0) {sheetNameEnd++;// 創建新的sheetsh = wb.createSheet(sheetName + sheetNameEnd);// 新的sheet設置新的單元格寬度setHeaderStyle(sh, keys, wb);temp = 0;}// 循環創建行SXSSFRow row = sh.createRow(temp + 1);// 給這行的每列寫入數據for (int j = 0; j < columnNames.length; j++) {SXSSFCell cell = row.createCell(j);// 以這樣的方式取值,過濾掉不需要的字段String value = String.valueOf(list.get(i).get(columnNames[j]));cell.setCellValue(value);// 是否開始其他數據樣式if (isOpeanOtherStyle) {// 設置數據樣式CellStyle otherStyle = setCellStyle(wb, otherFontSize, otherFontName, "other");cell.setCellStyle(otherStyle);}}}response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));// 這個操作也非常的耗時,應該該和文件的大小有關,后續看看能不能優化wb.write(response.getOutputStream());}/*** 設置表頭樣式,在大數據情況下每個sheet都要執行一次,所以抽出出來了* @param sh sheet* @param keys 對象屬性對應中文名* @param wb 工作簿*/private static void setHeaderStyle (SXSSFSheet sh, String[] keys, SXSSFWorkbook wb) {// 創建Excel工作表第一行,設置表頭信息SXSSFRow row0 = sh.createRow(0);for (int i = 0; i < keys.length; i++) {// 設置單元格寬度sh.setColumnWidth(i, 256 * width + 184);SXSSFCell cell = row0.createCell(i);cell.setCellValue(keys[i]);// 是否開啟表頭樣式if (isOpeanHeaderStyle) {// 創建表頭樣式CellStyle headerStyle = setCellStyle(wb, headerFontSize, headerFontName, "header");cell.setCellStyle(headerStyle);}}}/*** @param wb 工作簿* @param fontSize 字體大小* @param fontName 字體名稱* @return 工作簿樣式* @description 設置Excel樣式*/private static CellStyle setCellStyle(SXSSFWorkbook wb, String fontSize, String fontName, String boo) {// 創建自定義樣式類CellStyle style = wb.createCellStyle();// 創建自定義字體類Font font = wb.createFont();// 設置字體樣式font.setFontName(fontName);// 設置字體大小font.setFontHeightInPoints(Short.parseShort(fontSize));// 我這個版本的POI沒找到網上的HSSFCellStyle// 設置對齊方式style.setAlignment(HorizontalAlignment.CENTER);// 數據內容設置邊框實在太丑,容易看瞎眼睛,我幫你們去掉了if ("header".equals(boo)) {// 設置邊框style.setBorderBottom(BorderStyle.MEDIUM);style.setBorderLeft(BorderStyle.MEDIUM);style.setBorderRight(BorderStyle.MEDIUM);style.setBorderTop(BorderStyle.MEDIUM);// 表頭字體加粗font.setBold(true);}style.setFont(font);return style;}/*** 格式化數據(我發現這個操作非常的消耗時間,盡量不要使用到這個數據轉化,如果是List<Map>就直接傳,如果是Json稍微改一下上面的工具類,List<Bean>好像沒什么比較好的處理手段)* 數據量達到200w的時候堆內存直接就爆了,我錯了我錯了,數量達千萬別用 java.lang.OutOfMemoryError: Java heap space** @param s json數據* @return 轉換成List集合的數據*/public static List<Map<String, Object>> toList(String s) {List<Map<String, Object>> list = (List) JSON.parse(s);return list;}/*** 找了半天也沒找到可以diy的類,我自己寫個吧*/enum FontStyle {// 微軟雅黑MicrosoftYahei("微軟雅黑"),// 宋體TimesNewRoman("宋體"),// 楷體Italics("楷體"),// 幼圓YoungRound("幼圓");private String name;FontStyle(String name) {this.name = name;}} }

測試接口

package com.xx.controller;import com.alibaba.fastjson.JSON; import com.xx.entity.User; import com.xx.utils.ExcelUtils; import com.xx.utils.ExcelUtils1; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*;/*** @author aqi* DateTime: 2020/5/27 2:02 下午* Description: poi導出* HSSFWorkBook,* XSSFworkbook,* SXSSFworkbook*/ @RestController public class POI {/*** 控制數據的大小*/private static Integer count = 2000000;private static List<User> userList = new ArrayList<>();private static ArrayList<Map<String, Object>> mapsList = new ArrayList<>();/*** 初始化數據*/static {for (int i = 0; i < count; i++) {userList.add(new User(i, "張三" + i, UUID.randomUUID().toString().replaceAll("-", ""), i % 2, i % 2 == 0, "這個數據是用戶的備注信息,我想把這個數據弄長一點,現在這個長度感覺還不太行,應該要再長一點,現在這個長度我感覺差不多了,就這樣吧,但是有時候導出的時候會導出很長的字段,不知道對導出的效率影響大不大,現在這個長度應該是夠了", new Date(), "這里存放了一些其他字段", "", "其他2個就不存值了", ""));HashMap<String, Object> map = new HashMap<>(11);map.put("id", i);map.put("name", "張三" + i);map.put("password", UUID.randomUUID().toString().replaceAll("-", ""));map.put("gender", i % 2);map.put("live", i % 2 == 0);map.put("remarks", "這個數據是用戶的備注信息,我想把這個數據弄長一點,現在這個長度感覺還不太行,應該要再長一點,現在這個長度我感覺差不多了,就這樣吧,但是有時候導出的時候會導出很長的字段,不知道對導出的效率影響大不大,現在這個長度應該是夠了");map.put("createTime", new Date());map.put("other", "這里存放了一些其他字段");map.put("msg1", "");map.put("msg2", "其他2個就不存值了");map.put("msg3", "");mapsList.add(map);}}@GetMapping("/getExcel")public void getExcel(HttpServletResponse response) throws IOException {String[] keys = {"序號", "姓名", "密碼", "性別", "是否激活", "備注信息", "創建時間", "其他", "備注字段1", "備用字段2", "備用字段3"};String[] columnNames = {"id", "name", "password", "gender", "live", "remarks", "createTime", "other", "msg1", "msg2", "msg3"};String fileName = "demo.xlsx";// 這個數據格式化在數據量很大的情況下,會導致堆內存溢出 // String s = JSON.toJSONString(userList); // List<Map<String, Object>> maps = ExcelUtils.toList(s);// ExcelUtils.exportExcel(response, keys, columnNames, fileName, mapsList);}}

?

總結

以上是生活随笔為你收集整理的POI导出详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。