原文鏈接:https://blog.csdn.net/YiQ2018/article/details/81458149
用JavaPOI導出Excel時,我們需要考慮到Excel版本及數據量的問題。針對不同的Excel版本,要采用不同的工具類,如果使用錯了,會出現錯誤信息。JavaPOI導出Excel有三種形式,他們分別是1.HSSFWorkbook 2.XSSFWorkbook 3.SXSSFWorkbook。
HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,擴展名是.xls;
XSSFWorkbook:是操作Excel2007后的版本,擴展名是.xlsx;
SXSSFWorkbook:是操作Excel2007后的版本,擴展名是.xlsx;
第一種:HSSFWorkbook
poi導出excel最常用的方式;但是此種方式的局限就是導出的行數至多為65535行,超出65536條后系統就會報錯。此方式因為行數不足七萬行所以一般不會發生內存不足的情況(OOM)。
第二種:XSSFWorkbook
這種形式的出現是為了突破HSSFWorkbook的65535行局限。其對應的是excel2007(1048576行,16384列)擴展名為“.xlsx”,最多可以導出104萬行,不過這樣就伴隨着一個問題---OOM內存溢出,原因是你所創建的book sheet row cell等此時是存在內存的並沒有持久化。
第三種:SXSSFWorkbook
從POI 3.8版本開始,提供了一種基於XSSF的低內存占用的SXSSF方式。對於大型excel文件的創建,一個關鍵問題就是,要確保不會內存溢出。其實,就算生成很小的excel(比如幾Mb),它用掉的內存是遠大於excel文件實際的size的。如果單元格還有各種格式(比如,加粗,背景標紅之類的),那它占用的內存就更多了。對於大型excel的創建且不會內存溢出的,就只有SXSSFWorkbook了。它的原理很簡單,用硬盤空間換內存(就像hash map用空間換時間一樣)。
SXSSFWorkbook是streaming版本的XSSFWorkbook,它只會保存最新的excel rows在內存里供查看,在此之前的excel rows都會被寫入到硬盤里(Windows電腦的話,是寫入到C盤根目錄下的temp文件夾)。被寫入到硬盤里的rows是不可見的/不可訪問的。只有還保存在內存里的才可以被訪問到。
SXSSF與XSSF的對比:
a. 在一個時間點上,只可以訪問一定數量的數據
b. 不再支持Sheet.clone()
c. 不再支持公式的求值
d. 在使用Excel模板下載數據時將不能動態改變表頭,因為這種方式已經提前把excel寫到硬盤的了就不能再改了
當數據量超出65536條后,在使用HSSFWorkbook或XSSFWorkbook,程序會報OutOfMemoryError:Javaheap space;內存溢出錯誤。這時應該用SXSSFworkbook。
/** * 導出excel * * @param request * @param response */ @RequestMapping(params = "exportXls") public void exportXls(HttpServletRequest request, HttpServletResponse response) throws Exception { String ids = request.getParameter("ids"); String hql="from UserEntity where id in ('"+ids.replace(",","','")+"')"; List<UserEntity > list = userService.findHql(hql); System.out.println(ids); //sheet名 String sheetName = "報表"; // 第一步,創建一個HSSFWorkbook,對應一個Excel文件 HSSFWorkbook wb = new HSSFWorkbook(); // 第二步,在workbook中添加一個sheet,對應Excel文件中的sheet HSSFSheet sheet = wb.createSheet(sheetName); //設置單元格風格,居中對齊. HSSFCellStyle cs = wb.createCellStyle(); cs.setAlignment(HSSFCellStyle.ALIGN_CENTER); cs.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下邊框 cs.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左邊框 cs.setBorderTop(HSSFCellStyle.BORDER_THIN);//上邊框 cs.setBorderRight(HSSFCellStyle.BORDER_THIN);//右邊框 //設置字體: HSSFFont font = wb.createFont(); font.setFontName("黑體"); font.setFontHeightInPoints((short) 12);//設置字體大小 font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗體顯示 cs.setFont(font);//要用到的字體格式 // 第三步,在sheet中添加表頭第0行 HSSFRow row = sheet.createRow((short) 0); HSSFCell cell ; for (int i = 0; i < 4; i++) {//設置表頭-標題 cell = row.createCell(i); if(i==0){ cell.setCellValue("姓名"); } if(i==1){ cell.setCellValue("年齡"); } if(i==2){ cell.setCellValue("性別"); } cell.setCellStyle(cs); sheet.autoSizeColumn(i);//自動設寬 } //設置合並的標題頭(注意:橫向合並的時候,標題頭單元格必須長度和內容單元格一致否則合並時會把其他標題頭單元格內容擠掉) sheet.addMergedRegion(new CellRangeAddress(0,0,2,3));//橫向 sheet.addMergedRegion(new CellRangeAddress(0,1,0,0));//縱向 sheet.addMergedRegion(new CellRangeAddress(0,1,1,1)); //設置對應的合並單元格標題 row = sheet.createRow(1); for (int i = 2; i < 4; i++) { cell = row.createCell((short)i); cell.setCellStyle(cs); if(i==2){ cell.setCellValue("男"); } if(i==3){ cell.setCellValue("女"); } cell.setCellStyle(cs); sheet.autoSizeColumn(i);//自動設寬 } //設置列值-內容 for (int i = 0; i < list.size(); i++) { row = sheet.createRow(i + 2); UserEntity entity = list.get(i); row.createCell(0).setCellValue(entity.getName()); row.createCell(1).setCellValue(entity.getAge()); row.createCell(2).setCellValue(entity.getSex1()); row.createCell(3).setCellValue(entity.getSex2()); } try { String fileName = "報表" + System.currentTimeMillis() + ".xls"; //生成到當前系統桌面路徑 // File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory(); // String desktopPath = desktopDir.getAbsolutePath(); // FileOutputStream fileOut = new FileOutputStream(desktopPath+"/"+fileName); // wb.write(fileOut); // fileOut.close(); // System.out.println("輸出完成"); //頁面下載或保存 response.setContentType("application/x-download"); response.setHeader("Content-disposition","attachment;filename="+ new String(fileName.getBytes("utf-8"), "iso-8859-1")); response.setCharacterEncoding("utf-8"); OutputStream os=response.getOutputStream(); wb.write(os); os.close(); } catch (Exception e) { System.out.println("文件輸出失敗!"); e.printStackTrace(); } }
XSSFWorkbook對應的改改就行
