最近在作使用POI進行大數據量導出,如今把其整理成工具類供你們參考。Apache POI 3.8版本增長了前綴爲SXSSF相關的類,主要用於大數據量的寫入與讀取。關於ApachePOI導出Excel基本的使用我這裏就不詳解了,具體參考:html
Apache POI官方網站java
關於封裝的工具類須要注意:apache
如下代碼少ReportInternalException你們能夠忽略(咱們封裝的一個異常類)xss
導出的Excel同時考慮到數據的自己類型,如整數、小數、日期等工具
寫入數據方式需依次調用方法[writeExcelTitle、writeExcelData、dispose],先完成寫入Excel標題與列名,再完成數據寫入(或者說基於模板方式寫入數據),最終關閉流與資源的釋放測試
咱們使用[styleMap]方法避免重複建立Excel單元格樣式(不然受Excel建立樣式數量限制)字體
SXSSFWorkbook基於模板寫入數據的時候仍須要藉助XSSFWorkbook大數據
SXSSFWorkbook寫入數據模式大體爲:根據初始化設置的flushRows(內存存儲條數)數隨着數據寫入逐步把數據刷新至硬盤,具體參考官方文檔與API介紹網站
XSSFWorkbook tplWorkBook = new XSSFWorkbook(new FileInputStream(file)); Workbook writeDataWorkBook = new SXSSFWorkbook(tplWorkBook, flushRows);
Maven依賴配置
使用的Apache POI版本
<poi.version>3.9</poi.version>
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>${poi.version}</version> </dependency>
import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * Excel 相關操做類(大數據量寫入但受Excel數據行數限制) * 先寫入Excel標題(writeExcelTitle),再寫入數據(writeExcelData),最後釋放資源(dispose) */ public class ExportExcel2007 { //默認列寬度 private final int DEFAULT_COLUMN_SIZE = 30; //刷新寫入硬盤數據閥值 private final int flushRows = 1000; //聲明一個模板工做薄(寫入流式數據) private Workbook writeDataWorkBook; //樣式列表 private Map<String, CellStyle> cellStyleMap; //Excel當前數據行數(將要寫入數據的索引數) private int currentRowNum = 0; //數據輸出流 private OutputStream outputStream; /** * 斷言Excel文件寫入以前的條件 * * @param directory 目錄 * @param fileName 文件名 * @return file * @throws IOException */ private File assertFile(String directory, String fileName) throws IOException { File tmpFile = new File(directory + File.separator + fileName + ".xlsx"); if (tmpFile.exists()) { if (tmpFile.isDirectory()) { throw new IOException("File '" + tmpFile + "' exists but is a directory"); } if (!tmpFile.canWrite()) { throw new IOException("File '" + tmpFile + "' cannot be written to"); } } else { File parent = tmpFile.getParentFile(); if (parent != null) { if (!parent.mkdirs() && !parent.isDirectory()) { throw new IOException("Directory '" + parent + "' could not be created"); } } } return tmpFile; } /** * 日期轉化爲字符串,格式爲yyyy-MM-dd HH:mm:ss */ private String getCnDate(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } /** * Excel 導出,POI實現,先寫入Excel標題,與writeExcelData配合使用 * 先使用writeExcelTitle再使用writeExcelData * * @param directory 目錄 * @param fileName 文件名 * @param sheetName sheetName * @param columnNames 列名集合 * @param sheetTitle 表格標題 */ public void writeExcelTitle(String directory, String fileName, String sheetName, List<String> columnNames, String sheetTitle) throws ReportInternalException, IOException { File tmpFile = assertFile(directory, fileName); exportExcelTitle(tmpFile, sheetName, columnNames, sheetTitle); loadTplWorkbook(tmpFile); } /** * Excel 導出,POI實現,寫入Excel數據行列,與writeExcelTitle配合使用 * 先使用writeExcelTitle再使用writeExcelData * * @param directory 目錄 * @param fileName 文件名 * @param sheetName sheetName * @param objects 數據信息 */ public void writeExcelData(String directory, String fileName, String sheetName, List<List<Object>> objects) throws ReportInternalException, IOException { File tmpFile = assertFile(directory, fileName); outputStream = new FileOutputStream(tmpFile); exportExcelData(sheetName, objects); } /** * 釋放資源 */ public void dispose() throws ReportInternalException { try { if (writeDataWorkBook != null) { writeDataWorkBook.write(outputStream); } if (outputStream != null) { outputStream.flush(); outputStream.close(); } if (cellStyleMap != null) { cellStyleMap.clear(); } cellStyleMap = null; outputStream = null; writeDataWorkBook = null; } catch (IOException e) { throw new ReportInternalException(e); } } /** * 導出字符串數據 * * @param file 文件名 * @param columnNames 表頭 * @param sheetTitle sheet頁Title */ private void exportExcelTitle(File file, String sheetName, List<String> columnNames, String sheetTitle) throws ReportInternalException { Workbook tplWorkBook = new XSSFWorkbook(); Map<String, CellStyle> cellStyleMap = styleMap(tplWorkBook); // 表頭樣式 CellStyle headStyle = cellStyleMap.get("head"); // 生成一個表格 Sheet sheet = tplWorkBook.getSheet(sheetName); if (sheet == null) { sheet = tplWorkBook.createSheet(sheetName); } //最新Excel列索引,從0開始 //int lastRowIndex = sheet.getLastRowNum(); // 設置表格默認列寬度 sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE); // 合併單元格 sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum, 0, columnNames.size() - 1)); // 產生表格標題行 Row rowMerged = sheet.createRow(currentRowNum); Cell mergedCell = rowMerged.createCell(0); mergedCell.setCellStyle(headStyle); mergedCell.setCellValue(new XSSFRichTextString(sheetTitle)); //寫入成功一行數據遞增行數 currentRowNum = currentRowNum + 1; // 產生表格表頭列標題行 Row row = sheet.createRow(currentRowNum); for (int i = 0; i < columnNames.size(); i++) { Cell cell = row.createCell(i); cell.setCellStyle(headStyle); RichTextString text = new XSSFRichTextString(columnNames.get(i)); cell.setCellValue(text); } //寫入成功一行數據遞增行數 currentRowNum = currentRowNum + 1; try { OutputStream ops = new FileOutputStream(file); tplWorkBook.write(ops); ops.flush(); ops.close(); } catch (IOException e) { throw new ReportInternalException(e); } } /** * 加載模板文件 */ private void loadTplWorkbook(File file) throws ReportInternalException { try { XSSFWorkbook tplWorkBook = new XSSFWorkbook(new FileInputStream(file)); writeDataWorkBook = new SXSSFWorkbook(tplWorkBook, flushRows); cellStyleMap = styleMap(writeDataWorkBook); } catch (IOException e) { throw new ReportInternalException("Excel模板文件不存在"); } } /** * 導出字符串數據 * * @param objects 目標數據 */ private void exportExcelData(String sheetName, List<List<Object>> objects) throws ReportInternalException, IOException { // 正文樣式 CellStyle contentStyle = cellStyleMap.get("content"); //正文整數樣式 CellStyle contentIntegerStyle = cellStyleMap.get("integer"); //正文帶小數整數樣式 CellStyle contentDoubleStyle = cellStyleMap.get("double"); // 生成一個表格 Sheet sheet = writeDataWorkBook.getSheet(sheetName); if (sheet == null) { throw new ReportInternalException("讀取Excel模板錯誤"); } // 設置表格默認列寬度 sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE); // 遍歷集合數據,產生數據行,前兩行爲標題行與表頭行 for (List<Object> dataRow : objects) { Row row = sheet.createRow(currentRowNum); for (int j = 0; j < dataRow.size(); j++) { Cell contentCell = row.createCell(j); Object dataObject = dataRow.get(j); if (dataObject != null) { if (dataObject instanceof Integer) { contentCell.setCellStyle(contentIntegerStyle); contentCell.setCellValue(Integer.parseInt(dataObject.toString())); } else if (dataObject instanceof Double) { contentCell.setCellStyle(contentDoubleStyle); contentCell.setCellValue(Double.parseDouble(dataObject.toString())); } else if (dataObject instanceof Long && dataObject.toString().length() == 13) { contentCell.setCellStyle(contentStyle); contentCell.setCellValue(getCnDate(new Date(Long.parseLong(dataObject.toString())))); } else if (dataObject instanceof Date) { contentCell.setCellStyle(contentStyle); contentCell.setCellValue(getCnDate((Date) dataObject)); } else { contentCell.setCellStyle(contentStyle); contentCell.setCellValue(dataObject.toString()); } } else { contentCell.setCellStyle(contentStyle); // 設置單元格內容爲字符型 contentCell.setCellValue(""); } } //寫入成功一行數據遞增行數 currentRowNum = currentRowNum + 1; } try { ((SXSSFSheet) sheet).flushRows(flushRows); } catch (IOException e) { throw new ReportInternalException(e); } } /** * 建立單元格表頭樣式 * * @param workbook 工做薄 */ private CellStyle createCellHeadStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); // 設置邊框樣式 style.setBorderBottom(XSSFCellStyle.BORDER_THIN); style.setBorderLeft(XSSFCellStyle.BORDER_THIN); style.setBorderRight(XSSFCellStyle.BORDER_THIN); style.setBorderTop(XSSFCellStyle.BORDER_THIN); //設置對齊樣式 style.setAlignment(XSSFCellStyle.ALIGN_CENTER); // 生成字體 Font font = workbook.createFont(); // 表頭樣式 style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND); style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); font.setFontHeightInPoints((short) 12); font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD); // 把字體應用到當前的樣式 style.setFont(font); return style; } /** * 建立單元格正文樣式 * * @param workbook 工做薄 */ private CellStyle createCellContentStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); // 設置邊框樣式 style.setBorderBottom(XSSFCellStyle.BORDER_THIN); style.setBorderLeft(XSSFCellStyle.BORDER_THIN); style.setBorderRight(XSSFCellStyle.BORDER_THIN); style.setBorderTop(XSSFCellStyle.BORDER_THIN); //設置對齊樣式 style.setAlignment(XSSFCellStyle.ALIGN_CENTER); // 生成字體 Font font = workbook.createFont(); // 正文樣式 style.setFillPattern(XSSFCellStyle.NO_FILL); style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); font.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL); // 把字體應用到當前的樣式 style.setFont(font); return style; } /** * 單元格樣式(Integer)列表 */ private CellStyle createCellContent4IntegerStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); // 設置邊框樣式 style.setBorderBottom(XSSFCellStyle.BORDER_THIN); style.setBorderLeft(XSSFCellStyle.BORDER_THIN); style.setBorderRight(XSSFCellStyle.BORDER_THIN); style.setBorderTop(XSSFCellStyle.BORDER_THIN); //設置對齊樣式 style.setAlignment(XSSFCellStyle.ALIGN_CENTER); // 生成字體 Font font = workbook.createFont(); // 正文樣式 style.setFillPattern(XSSFCellStyle.NO_FILL); style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); font.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL); // 把字體應用到當前的樣式 style.setFont(font); style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0"));//數據格式只顯示整數 return style; } /** * 單元格樣式(Double)列表 */ private CellStyle createCellContent4DoubleStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); // 設置邊框樣式 style.setBorderBottom(XSSFCellStyle.BORDER_THIN); style.setBorderLeft(XSSFCellStyle.BORDER_THIN); style.setBorderRight(XSSFCellStyle.BORDER_THIN); style.setBorderTop(XSSFCellStyle.BORDER_THIN); //設置對齊樣式 style.setAlignment(XSSFCellStyle.ALIGN_CENTER); // 生成字體 Font font = workbook.createFont(); // 正文樣式 style.setFillPattern(XSSFCellStyle.NO_FILL); style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); font.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL); // 把字體應用到當前的樣式 style.setFont(font); style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));//保留兩位小數點 return style; } /** * 單元格樣式列表 */ private Map<String, CellStyle> styleMap(Workbook workbook) { Map<String, CellStyle> styleMap = new LinkedHashMap<>(); styleMap.put("head", createCellHeadStyle(workbook)); styleMap.put("content", createCellContentStyle(workbook)); styleMap.put("integer", createCellContent4IntegerStyle(workbook)); styleMap.put("double", createCellContent4DoubleStyle(workbook)); return styleMap; } }
import java.io.IOException; import java.sql.Date; import java.util.LinkedList; import java.util.List; public class ExcelExport { public static void main(String[] args) throws IOException { String sheetName = "測試Excel格式"; String sheetTitle = "測試Excel格式"; List<String> columnNames = new LinkedList<>(); columnNames.add("日期-String"); columnNames.add("日期-Date"); columnNames.add("時間戳-Long"); columnNames.add("客戶編碼"); columnNames.add("整數"); columnNames.add("帶小數的正數"); ExportExcel2007 exportExcel2007 = new ExportExcel2007(); exportExcel2007.writeExcelTitle("E:\\temp", "a", sheetName, columnNames, sheetTitle); for (int j = 0; j < 2; j++) { List<List<Object>> objects = new LinkedList<>(); for (int i = 0; i < 1000; i++) { List<Object> dataA = new LinkedList<>(); dataA.add("2016-09-05 17:27:25"); dataA.add(new Date(1451036631012L)); dataA.add(1451036631012L); dataA.add("000628"); dataA.add(i); dataA.add(1.323 + i); objects.add(dataA); } try { exportExcel2007.writeExcelData("E:\\temp", "a", sheetName, objects); } catch (Exception e) { e.printStackTrace(); } objects.clear(); } exportExcel2007.dispose(); } }