摘要:最近在做使用進(jìn)行大數(shù)據(jù)量導(dǎo)出,現(xiàn)在把其整理成工具類供大家參考。版本增加了前綴為相關(guān)的類,主要用于大數(shù)據(jù)量的寫入與讀取。
最近在做使用POI進(jìn)行大數(shù)據(jù)量導(dǎo)出,現(xiàn)在把其整理成工具類供大家參考。Apache POI 3.8版本增加了前綴為SXSSF相關(guān)的類,主要用于大數(shù)據(jù)量的寫入與讀取。關(guān)于ApachePOI導(dǎo)出Excel基本的使用我這里就不詳解了,具體參考:
Apache POI官方網(wǎng)站
Apache POI使用詳解
關(guān)于封裝的工具類需要注意:
以下代碼少ReportInternalException大家可以忽略(我們封裝的一個(gè)異常類)
導(dǎo)出的Excel同時(shí)考慮到數(shù)據(jù)的本身類型,如整數(shù)、小數(shù)、日期等
寫入數(shù)據(jù)方式需依次調(diào)用方法[writeExcelTitle、writeExcelData、dispose],先完成寫入Excel標(biāo)題與列名,再完成數(shù)據(jù)寫入(或者說基于模板方式寫入數(shù)據(jù)),最終關(guān)閉流與資源的釋放
我們使用[styleMap]方法避免重復(fù)創(chuàng)建Excel單元格樣式(否則受Excel創(chuàng)建樣式數(shù)量限制)
SXSSFWorkbook基于模板寫入數(shù)據(jù)的時(shí)候仍需要借助XSSFWorkbook
SXSSFWorkbook寫入數(shù)據(jù)模式大致為:根據(jù)初始化設(shè)置的flushRows(內(nèi)存存儲(chǔ)條數(shù))數(shù)隨著數(shù)據(jù)寫入逐步把數(shù)據(jù)刷新至硬盤,具體參考官方文檔與API介紹
XSSFWorkbook tplWorkBook = new XSSFWorkbook(new FileInputStream(file)); Workbook writeDataWorkBook = new SXSSFWorkbook(tplWorkBook, flushRows);
Maven依賴配置
使用的Apache POI版本
3.9
org.apache.poi poi ${poi.version} org.apache.poi poi-ooxml ${poi.version} org.apache.poi poi-ooxml-schemas ${poi.version}
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 相關(guān)操作類(大數(shù)據(jù)量寫入但受Excel數(shù)據(jù)行數(shù)限制) * 先寫入Excel標(biāo)題(writeExcelTitle),再寫入數(shù)據(jù)(writeExcelData),最后釋放資源(dispose) */ public class ExportExcel2007 { //默認(rèn)列寬度 private final int DEFAULT_COLUMN_SIZE = 30; //刷新寫入硬盤數(shù)據(jù)閥值 private final int flushRows = 1000; //聲明一個(gè)模板工作薄(寫入流式數(shù)據(jù)) private Workbook writeDataWorkBook; //樣式列表 private MapcellStyleMap; //Excel當(dāng)前數(shù)據(jù)行數(shù)(將要寫入數(shù)據(jù)的索引數(shù)) private int currentRowNum = 0; //數(shù)據(jù)輸出流 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; } /** * 日期轉(zhuǎn)化為字符串,格式為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 導(dǎo)出,POI實(shí)現(xiàn),先寫入Excel標(biāo)題,與writeExcelData配合使用 * 先使用writeExcelTitle再使用writeExcelData * * @param directory 目錄 * @param fileName 文件名 * @param sheetName sheetName * @param columnNames 列名集合 * @param sheetTitle 表格標(biāo)題 */ public void writeExcelTitle(String directory, String fileName, String sheetName, List columnNames, String sheetTitle) throws ReportInternalException, IOException { File tmpFile = assertFile(directory, fileName); exportExcelTitle(tmpFile, sheetName, columnNames, sheetTitle); loadTplWorkbook(tmpFile); } /** * Excel 導(dǎo)出,POI實(shí)現(xiàn),寫入Excel數(shù)據(jù)行列,與writeExcelTitle配合使用 * 先使用writeExcelTitle再使用writeExcelData * * @param directory 目錄 * @param fileName 文件名 * @param sheetName sheetName * @param objects 數(shù)據(jù)信息 */ public void writeExcelData(String directory, String fileName, String sheetName, List > 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); } } /** * 導(dǎo)出字符串?dāng)?shù)據(jù) * * @param file 文件名 * @param columnNames 表頭 * @param sheetTitle sheet頁Title */ private void exportExcelTitle(File file, String sheetName, List
columnNames, String sheetTitle) throws ReportInternalException { Workbook tplWorkBook = new XSSFWorkbook(); Map cellStyleMap = styleMap(tplWorkBook); // 表頭樣式 CellStyle headStyle = cellStyleMap.get("head"); // 生成一個(gè)表格 Sheet sheet = tplWorkBook.getSheet(sheetName); if (sheet == null) { sheet = tplWorkBook.createSheet(sheetName); } //最新Excel列索引,從0開始 //int lastRowIndex = sheet.getLastRowNum(); // 設(shè)置表格默認(rèn)列寬度 sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE); // 合并單元格 sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum, 0, columnNames.size() - 1)); // 產(chǎn)生表格標(biāo)題行 Row rowMerged = sheet.createRow(currentRowNum); Cell mergedCell = rowMerged.createCell(0); mergedCell.setCellStyle(headStyle); mergedCell.setCellValue(new XSSFRichTextString(sheetTitle)); //寫入成功一行數(shù)據(jù)遞增行數(shù) currentRowNum = currentRowNum + 1; // 產(chǎn)生表格表頭列標(biāo)題行 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); } //寫入成功一行數(shù)據(jù)遞增行數(shù) 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模板文件不存在"); } } /** * 導(dǎo)出字符串?dāng)?shù)據(jù) * * @param objects 目標(biāo)數(shù)據(jù) */ private void exportExcelData(String sheetName, List > objects) throws ReportInternalException, IOException { // 正文樣式 CellStyle contentStyle = cellStyleMap.get("content"); //正文整數(shù)樣式 CellStyle contentIntegerStyle = cellStyleMap.get("integer"); //正文帶小數(shù)整數(shù)樣式 CellStyle contentDoubleStyle = cellStyleMap.get("double"); // 生成一個(gè)表格 Sheet sheet = writeDataWorkBook.getSheet(sheetName); if (sheet == null) { throw new ReportInternalException("讀取Excel模板錯(cuò)誤"); } // 設(shè)置表格默認(rèn)列寬度 sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE); // 遍歷集合數(shù)據(jù),產(chǎn)生數(shù)據(jù)行,前兩行為標(biāo)題行與表頭行 for (List
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 = "測(cè)試Excel格式"; String sheetTitle = "測(cè)試Excel格式"; ListcolumnNames = new LinkedList<>(); columnNames.add("日期-String"); columnNames.add("日期-Date"); columnNames.add("時(shí)間戳-Long"); columnNames.add("客戶編碼"); columnNames.add("整數(shù)"); columnNames.add("帶小數(shù)的正數(shù)"); ExportExcel2007 exportExcel2007 = new ExportExcel2007(); exportExcel2007.writeExcelTitle("E: emp", "a", sheetName, columnNames, sheetTitle); for (int j = 0; j < 2; j++) { List > objects = new LinkedList<>(); for (int i = 0; i < 1000; i++) { List
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/65285.html
摘要:并且在對(duì)的抽象中,每一行,每一個(gè)單元格都是一個(gè)對(duì)象。對(duì)支持使用官方例子需要繼承,覆蓋方法,每讀取到一個(gè)單元格的數(shù)據(jù)則會(huì)回調(diào)次方法。概要Java對(duì)Excel的操作一般都是用POI,但是數(shù)據(jù)量大的話可能會(huì)導(dǎo)致頻繁的FGC或OOM,這篇文章跟大家說下如果避免踩POI的坑,以及分別對(duì)于xls和xlsx文件怎么優(yōu)化大批量數(shù)據(jù)的導(dǎo)入和導(dǎo)出。一次線上問題這是一次線上的問題,因?yàn)橐粋€(gè)大數(shù)據(jù)量的Excel導(dǎo)出...
摘要:事件將通過添加關(guān)注來激活。自動(dòng)注冊(cè)事件監(jiān)聽器通過使用,你可以自動(dòng)注冊(cè)事件監(jiān)聽器,而不需要使用。你可以自由使用這個(gè)宏,或者創(chuàng)造你自己的語法以上例子可作對(duì)于方法可查看文檔測(cè)試測(cè)試下載測(cè)試存儲(chǔ)導(dǎo)出測(cè)試隊(duì)列導(dǎo)出 Basics 最簡單的導(dǎo)出方法是創(chuàng)建一個(gè)自定義的導(dǎo)出類, 這里我們使用發(fā)票導(dǎo)出作為示例. 在 App/Exports 下創(chuàng)建一個(gè) InvoicesExport 類 namespace...
摘要:實(shí)現(xiàn)并發(fā)請(qǐng)求實(shí)現(xiàn)并發(fā)請(qǐng)求生成并下載字符串文件首先我們需要了解一個(gè)特殊的數(shù)據(jù)格式。如果類型未知,則該值為空字符串。表示狀態(tài)的數(shù)字。一旦完成,屬性中將包含一個(gè)字符串以表示所讀取的文件內(nèi)容。 在web開發(fā)中,如果你想讓用戶下載或者導(dǎo)出一個(gè)文件,應(yīng)該怎么做呢?傳統(tǒng)的做法是在后端存儲(chǔ)或者即時(shí)生成一個(gè)文件來提供下載功能,這樣的優(yōu)勢(shì)是可以做權(quán)限控制、數(shù)據(jù)二次處理,但缺點(diǎn)是需要額外發(fā)起請(qǐng)求、增大服務(wù)端...
摘要:實(shí)現(xiàn)并發(fā)請(qǐng)求實(shí)現(xiàn)并發(fā)請(qǐng)求生成并下載字符串文件首先我們需要了解一個(gè)特殊的數(shù)據(jù)格式。如果類型未知,則該值為空字符串。表示狀態(tài)的數(shù)字。一旦完成,屬性中將包含一個(gè)字符串以表示所讀取的文件內(nèi)容。 在web開發(fā)中,如果你想讓用戶下載或者導(dǎo)出一個(gè)文件,應(yīng)該怎么做呢?傳統(tǒng)的做法是在后端存儲(chǔ)或者即時(shí)生成一個(gè)文件來提供下載功能,這樣的優(yōu)勢(shì)是可以做權(quán)限控制、數(shù)據(jù)二次處理,但缺點(diǎn)是需要額外發(fā)起請(qǐng)求、增大服務(wù)端...
閱讀 923·2023-04-26 01:34
閱讀 3356·2023-04-25 20:58
閱讀 3260·2021-11-08 13:22
閱讀 2108·2019-08-30 14:17
閱讀 2522·2019-08-29 15:27
閱讀 2673·2019-08-29 12:45
閱讀 2996·2019-08-29 12:26
閱讀 2811·2019-08-28 17:51