使用POI做的一個生成Excel的工具類。包含了導出Excel和解析Excel方法
阿新 • • 發佈:2019-01-04
time 類型 解析excel rom 統計表 pty reat iou 包括
PoiExcelUtils.java
/** * */ package com.common.office; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import net.sf.json.JSONArray; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.util.CellRangeAddress; import com.common.reflect.ReflectUtils; /** * Excel工具類 * @author luolin */ public class PoiExcelUtils { private static NumberFormat format = NumberFormat.getInstance(); /** 日誌 */ private static final Logger LOGGER = Logger.getLogger(PoiExcelUtils.class); /** 列默認寬度 */ private static final int DEFAUL_COLUMN_WIDTH = 4000; /** * 1.創建 workbook * * @return {@link HSSFWorkbook} */ private HSSFWorkbook getHSSFWorkbook() { LOGGER.info("【創建 workbook】"); return new HSSFWorkbook(); } /** * 2.創建 sheet * * @param hssfWorkbook {@link HSSFWorkbook} * @param sheetName sheet 名稱 * @return {@link HSSFSheet} */ private HSSFSheet getHSSFSheet(HSSFWorkbook hssfWorkbook, String sheetName) { LOGGER.info("【創建 sheet】sheetName : " + sheetName); return hssfWorkbook.createSheet(sheetName); } /** * 3.寫入表頭信息 * * @param hssfWorkbook {@link HSSFWorkbook} * @param hssfSheet {@link HSSFSheet} * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param title 標題 */ private void writeHeader(HSSFWorkbook hssfWorkbook, HSSFSheet hssfSheet, String[] headers, String title) { LOGGER.info("【寫入表頭信息】"); // 頭信息處理 String[] newHeaders = headersHandler(headers); // 初始化標題和表頭單元格樣式 HSSFCellStyle titleCellStyle = createTitleCellStyle(hssfWorkbook); // 標題欄 HSSFRow titleRow = hssfSheet.createRow(0); titleRow.setHeight((short) 500); HSSFCell titleCell = titleRow.createCell(0); // 設置標題文本 titleCell.setCellValue(new HSSFRichTextString(title)); // 設置單元格樣式 titleCell.setCellStyle(titleCellStyle); // 處理單元格合並,四個參數分別是:起始行,終止行,起始行,終止列 hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, (short) 0, (short) (newHeaders.length - 1))); // 設置合並後的單元格的樣式 titleRow.createCell(newHeaders.length - 1).setCellStyle(titleCellStyle); // 表頭 HSSFRow headRow = hssfSheet.createRow(1); headRow.setHeight((short) 500); HSSFCell headCell = null; String[] headInfo = null; // 處理excel表頭 for (int i = 0, len = newHeaders.length; i < len; i++) { headInfo = newHeaders[i].split("@"); headCell = headRow.createCell(i); headCell.setCellValue(headInfo[0]); headCell.setCellStyle(titleCellStyle); // 設置列寬度 setColumnWidth(i, headInfo, hssfSheet); } } /** * 頭信息校驗和處理 * @param headers */ private String[] headersHandler(String[] headers) { List<String> newHeaders = new ArrayList<String>(); for (String string : headers) { if (StringUtils.isNotBlank(string)) { newHeaders.add(string); } } int size = newHeaders.size(); return newHeaders.toArray(new String[size]); } /** * 4.寫入內容部分 * * @param hssfWorkbook {@link HSSFWorkbook} * @param hssfSheet {@link HSSFSheet} * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出的數據集合 * @throws Exception */ private void writeContent(HSSFWorkbook hssfWorkbook, HSSFSheet hssfSheet, String[] headers, List<?> dataList) throws Exception { LOGGER.info("【寫入Excel內容部分】"); // 2015-8-13 增加,當沒有數據的時候,把原來拋異常的方式修改成返回一個只有頭信息,沒有數據的空Excel if (CollectionUtils.isEmpty(dataList)) { LOGGER.warn("【沒有內容數據】"); return; } HSSFRow row = null; HSSFCell cell = null; // 單元格的值 Object cellValue = null; // 數據寫入行索引 int rownum = 2; // 單元格樣式 HSSFCellStyle cellStyle = createContentCellStyle(hssfWorkbook); // 遍歷集合,處理數據 for (int j = 0, size = dataList.size(); j < size; j++) { row = hssfSheet.createRow(rownum); for (int i = 0, len = headers.length; i < len; i++) { cell = row.createCell(i); cellValue = ReflectUtils.getCellValue(dataList.get(j), headers[i].split("@")[1]); cellValueHandler(cell, cellValue); cell.setCellStyle(cellStyle); } rownum++; } } /** * 設置列寬度 * @param i 列的索引號 * @param headInfo 表頭信息,其中包含了用戶需要設置的列寬 */ private void setColumnWidth(int i, String[] headInfo, HSSFSheet hssfSheet) { if (headInfo.length < 3) { // 用戶沒有設置列寬,使用默認寬度 hssfSheet.setColumnWidth(i, DEFAUL_COLUMN_WIDTH); return; } if (StringUtils.isBlank(headInfo[2])) { // 使用默認寬度 hssfSheet.setColumnWidth(i, DEFAUL_COLUMN_WIDTH); return; } // 使用用戶設置的列寬進行設置 hssfSheet.setColumnWidth(i, Integer.parseInt(headInfo[2])); } /** * 單元格寫值處理器 * @param {{@link HSSFCell} * @param cellValue 單元格值 */ private void cellValueHandler(HSSFCell cell, Object cellValue) { // 2015-8-13 修改,判斷cellValue是否為空,否則在cellValue.toString()會出現空指針異常 if (cellValue == null) { cell.setCellValue(""); return; } if (cellValue instanceof String) { cell.setCellValue((String) cellValue); } else if (cellValue instanceof Boolean) { cell.setCellValue((Boolean) cellValue); } else if (cellValue instanceof Calendar) { cell.setCellValue((Calendar) cellValue); } else if (cellValue instanceof Double) { cell.setCellValue((Double) cellValue); } else if (cellValue instanceof Integer || cellValue instanceof Long || cellValue instanceof Short || cellValue instanceof Float) { cell.setCellValue((Double.parseDouble(cellValue.toString()))); } else if (cellValue instanceof HSSFRichTextString) { cell.setCellValue((HSSFRichTextString) cellValue); } cell.setCellValue(cellValue.toString()); } /** * 創建標題和表頭單元格樣式 * @param hssfWorkbook {@link HSSFWorkbook} * @return {@link HSSFCellStyle} */ private HSSFCellStyle createTitleCellStyle(HSSFWorkbook hssfWorkbook) { LOGGER.info("【創建標題和表頭單元格樣式】"); // 單元格的樣式 HSSFCellStyle cellStyle = hssfWorkbook.createCellStyle(); // 設置字體樣式,改為不變粗 HSSFFont font = hssfWorkbook.createFont(); font.setFontHeightInPoints((short) 13); font.setBoldweight(Font.BOLDWEIGHT_BOLD); cellStyle.setFont(font); // 單元格垂直居中 cellStyle.setVerticalAlignment(HSSFCellStyle.ALIGN_CENTER_SELECTION); // 設置通用的單元格屬性 setCommonCellStyle(cellStyle); return cellStyle; } /** * 創建內容單元格樣式 * @param hssfWorkbook {@link HSSFWorkbook} * @return {@link HSSFCellStyle} */ private HSSFCellStyle createContentCellStyle(HSSFWorkbook hssfWorkbook) { LOGGER.info("【創建內容單元格樣式】"); // 單元格的樣式 HSSFCellStyle cellStyle = hssfWorkbook.createCellStyle(); // 設置字體樣式,改為不變粗 HSSFFont font = hssfWorkbook.createFont(); font.setFontHeightInPoints((short) 11); cellStyle.setFont(font); // 設置單元格自動換行 cellStyle.setWrapText(true); // 單元格垂直居中 cellStyle.setVerticalAlignment(HSSFCellStyle.ALIGN_CENTER_SELECTION); //水平居中 // cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 設置通用的單元格屬性 setCommonCellStyle(cellStyle); return cellStyle; } /** * 設置通用的單元格屬性 * @param cellStyle 要設置屬性的單元格 */ private void setCommonCellStyle(HSSFCellStyle cellStyle) { // 居中 cellStyle.setAlignment(CellStyle.ALIGN_CENTER); // 設置邊框 cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); } /** * 將生成的Excel輸出到指定目錄 * @param hssfWorkbook {@link HSSFWorkbook} * @param filePath 文件輸出目錄,包括文件名(.xls) */ private void write2FilePath(HSSFWorkbook hssfWorkbook, String filePath) { LOGGER.info("【將生成的Excel輸出到指定目錄】filePath :" + filePath); FileOutputStream fileOut = null; try { fileOut = new FileOutputStream(filePath); hssfWorkbook.write(fileOut); } catch (Exception e) { LOGGER.error("【將生成的Excel輸出到指定目錄失敗】", e); throw new RuntimeException("將生成的Excel輸出到指定目錄失敗"); } finally { IOUtils.closeQuietly(fileOut); } } /** * 生成Excel,存放到指定目錄 * @param sheetName sheet名稱 * @param title 標題 * @param filePath 要導出的Excel存放的文件路徑 * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出數據的集合 * @throws Exception */ public static void createExcel2FilePath(String sheetName, String title, String filePath, String[] headers, List<?> dataList) throws Exception { LOGGER.info("【生成Excel,並存放到指定文件夾目錄下】sheetName : " + sheetName + " , title : " + title + " , filePath : " + filePath + " , headers : " + JSONArray.fromObject(headers)); if (ArrayUtils.isEmpty(headers)) { LOGGER.warn("【表頭為空】"); throw new RuntimeException("表頭不能為空"); } PoiExcelUtils poiExcelUtil = new PoiExcelUtils(); // 1.創建 Workbook HSSFWorkbook hssfWorkbook = poiExcelUtil.getHSSFWorkbook(); // 2.創建 Sheet HSSFSheet hssfSheet = poiExcelUtil.getHSSFSheet(hssfWorkbook, sheetName); // 3.寫入 head poiExcelUtil.writeHeader(hssfWorkbook, hssfSheet, headers, title); // 4.寫入內容 poiExcelUtil.writeContent(hssfWorkbook, hssfSheet, headers, dataList); // 5.保存文件到filePath中 poiExcelUtil.write2FilePath(hssfWorkbook, filePath); } /** * 生成Excel的WorkBook,用於導出Excel * @param sheetName sheet名稱 * @param title 標題 * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出數據的集合 * @throws Exception */ public static HSSFWorkbook createExcel2Export(String sheetName, String title, String[] headers, List<?> dataList) throws Exception { LOGGER.info("【生成Excel的WorkBook,用於導出Excel】sheetName : " + sheetName + " , title : " + title + " , headers : " + JSONArray.fromObject(headers)); if (ArrayUtils.isEmpty(headers)) { LOGGER.warn("【表頭為空】"); throw new RuntimeException("表頭不能為空"); } PoiExcelUtils poiExcelUtil = new PoiExcelUtils(); // 1.創建 Workbook HSSFWorkbook hssfWorkbook = poiExcelUtil.getHSSFWorkbook(); // 2.創建 Sheet HSSFSheet hssfSheet = poiExcelUtil.getHSSFSheet(hssfWorkbook, sheetName); // 3.寫入 head poiExcelUtil.writeHeader(hssfWorkbook, hssfSheet, headers, title); // 4.寫入內容 poiExcelUtil.writeContent(hssfWorkbook, hssfSheet, headers, dataList); return hssfWorkbook; } /** * 創建知識庫TOP3系統渠道統計的Excel數據 * @param sheetName sheet名稱 * @param title 標題 * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出數據的集合 */ public static HSSFWorkbook createknowledgeTop3Excel(String sheetName, String title, String[] headers, List<List<?>> dataList) { LOGGER.info("【生成Excel的WorkBook,用於導出Excel】sheetName : " + sheetName + " , title : " + title + " , headers : " + JSONArray.fromObject(headers)); if (ArrayUtils.isEmpty(headers)) { LOGGER.warn("【表頭為空】"); throw new RuntimeException("表頭不能為空"); } PoiExcelUtils poiExcelUtil = new PoiExcelUtils(); // 1.創建 Workbook HSSFWorkbook hssfWorkbook = poiExcelUtil.getHSSFWorkbook(); // 2.創建 Sheet HSSFSheet hssfSheet = poiExcelUtil.getHSSFSheet(hssfWorkbook, sheetName); // 3.寫入 head poiExcelUtil.writeHeader(hssfWorkbook, hssfSheet, headers, title); // 4.寫入內容 try { poiExcelUtil.writeComplexContent(hssfWorkbook, hssfSheet, headers, dataList); } catch (Exception e) { LOGGER.error("【寫入內容部分失敗】", e); throw new RuntimeException("寫入內容部分失敗"); } return hssfWorkbook; } /** * 生成內容部分(復雜內容,每列來自不同的數據集合) * @param hssfWorkbook {@link HSSFWorkbook} * @param hssfSheet {@link HSSFSheet} * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出數據的集合 * @throws Exception */ private void writeComplexContent(HSSFWorkbook hssfWorkbook, HSSFSheet hssfSheet, String[] headers, List<List<?>> dataList) throws Exception { LOGGER.info("【寫入Excel內容部分】"); // 2015-8-13 增加,當沒有數據的時候,把原來拋異常的方式修改成返回一個只有頭信息,沒有數據的空Excel if (CollectionUtils.isEmpty(dataList)) { LOGGER.warn("【沒有內容數據】"); return; } HSSFRow row = null; HSSFCell cell = null; // 單元格的值 Object cellValue = null; // 數據寫入行索引 int rownum = 2; // 單元格樣式 HSSFCellStyle cellStyle = createContentCellStyle(hssfWorkbook); // 遍歷集合,處理數據 // 要寫的內容的行數 int rows = dataList.get(0).size(); // 除去固定列“日期”外,還需要寫的列數 int columns = dataList.size(); /** * 思路說明 * 如果是top3,那麽dataList的長度應該是3(即除去固定列“日期”剩下的列數) * 其次索引依次是top1的數據、top2的數據、top3的數據 * top1/top2/top3的數據長度表示行數 * 第一層循環,肯定以行數為基準來進行 * 然後第一層循環的第一步是完成固定列的數據填充 * 第二步是填充對應行每個列的數據,而每個列的數據應該分別從top1、top2、top3中取 */ for (int j = 0; j < rows; j++) { row = hssfSheet.createRow(rownum); // 寫固定列“日期” cell = row.createCell(0); cellValue = ReflectUtils.getCellValue(dataList.get(0).get(j), headers[0].split("@")[1]); cellValueHandler(cell, cellValue); cell.setCellStyle(cellStyle); for (int i = 1; i <= columns; i++) { cell = row.createCell(i); cellValue = ReflectUtils.getCellValue(dataList.get(i - 1).get(j), headers[i].split("@")[1]); cellValueHandler(cell, cellValue); cell.setCellStyle(cellStyle); } rownum++; } } /** * 根據文件路徑讀取excel文件 * @param excelPath excel的路徑 * @param skipRows 需要跳過的行數 * @return List<String[]> 集合中每一個元素是一個數組,按單元格索引存儲每個單元格的值,一個元素可以封裝成一個需要的java bean * @throws Exception */ public static List<String[]> readExcel(String excelPath, int skipRows, int columCount) throws Exception { LOGGER.info("【讀取Excel】excelPath : " + excelPath + " , skipRows : " + skipRows); FileInputStream is = new FileInputStream(new File(excelPath)); POIFSFileSystem fs = new POIFSFileSystem(is); HSSFWorkbook wb = new HSSFWorkbook(fs); List<String[]> list = new ArrayList<String[]>(); HSSFSheet sheet = wb.getSheetAt(0); // 得到總共的行數 int rowNum = sheet.getPhysicalNumberOfRows(); try { for (int i = skipRows; i < rowNum; i++) { String[] vals = new String[columCount]; HSSFRow row = sheet.getRow(i); if (null == row) { continue; } for (int j = 0; j < columCount; j++) { HSSFCell cell = row.getCell(j); String val = getStringCellValue(cell); vals[j] = val; } list.add(vals); } } catch (Exception e) { LOGGER.error("【Excel解析失敗】", e); throw new RuntimeException("Excel解析失敗"); } finally { wb.close(); } return list; } /** * 獲取單元格數據內容為字符串類型的數據 * * @param cell Excel單元格 * @return String 單元格數據內容 */ private static String getStringCellValue(HSSFCell cell) { if (cell == null) return ""; String strCell = ""; switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_STRING: strCell = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_NUMERIC: strCell = String.valueOf(format.format(cell.getNumericCellValue())).replace(",", ""); break; case HSSFCell.CELL_TYPE_BOOLEAN: strCell = String.valueOf(cell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_BLANK: strCell = ""; break; default: strCell = ""; break; } if (strCell.equals("") || strCell == null) { return ""; } return strCell; } /** * 生成車票銷售總量統計表格 * @param sheetName sheet名稱 * @param title 標題 * @param headers 列標題,數組形式, * 如{"列標題1@beanFieldName1@columnWidth","列標題2@beanFieldName2@columnWidth","列標題3@beanFieldName3@columnWidth"} * 其中參數@columnWidth可選,columnWidth為整型數值 * @param dataList 要導出數據的集合 * @return {@link HSSFWorkbook} * @Author : luolin. create at 2015年12月22日 下午5:17:04 */ public static HSSFWorkbook createTicketReportExcel(String sheetName, String title, String[] headers, List<List<?>> dataList) { LOGGER.info("【生成車票銷售總量統計表格】sheetName : " + sheetName + " , title : " + title + " , headers : " + JSONArray.fromObject(headers)); if (ArrayUtils.isEmpty(headers)) { LOGGER.warn("【表頭為空】"); throw new RuntimeException("表頭不能為空"); } PoiExcelUtils poiExcelUtil = new PoiExcelUtils(); // 1.創建 Workbook HSSFWorkbook hssfWorkbook = poiExcelUtil.getHSSFWorkbook(); // 2.創建 Sheet HSSFSheet hssfSheet = poiExcelUtil.getHSSFSheet(hssfWorkbook, sheetName); // 3.寫入 head poiExcelUtil.writeHeader(hssfWorkbook, hssfSheet, headers, title); // 4.寫入內容 try { poiExcelUtil.writeComplexContent(hssfWorkbook, hssfSheet, headers, dataList); } catch (Exception e) { LOGGER.error("【寫入內容部分失敗】", e); throw new RuntimeException("寫入內容部分失敗"); } return hssfWorkbook; } }
使用POI做的一個生成Excel的工具類。包含了導出Excel和解析Excel方法