POI全稱PoorObfuscation Implementation ,是Apache組件的一個開源項目,可以對微軟的Office一系列辦公軟件進行讀寫操作。
實現方式有三種(建議SXSSF):
1,HSSF是POI工程對Excel 97(-2007)文件操作的純Java實現
2,XSSF是POI工程對Excel 2007 OOXML (.xlsx)文件操作的純Java實現
3,從POI 3.8版本開始,提供了一種基於XSSF的低內存占用的API----SXSSF
SXSSF通過一個滑動窗口來限制訪問Row的數量從而達到低內存占用的目錄,XSSF可以訪問所有行。舊的行數據不再出現在滑動窗口中並變得無法訪問,與此同時寫到磁盤上。
在自動刷新的模式下,可以指定窗口中訪問Row的數量,從而在內存中保持一定數量的Row。當達到這一數量時,在窗口中產生新的Row數據,並將低索引的數據從窗口中移動到磁盤中。
或者,滑動窗口的行數可以設定成自動增長的。它可以根據需要周期的根據一次明確的flushRow(int keepRows)調用來進行修改。
1,使用的POM包
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.0.1</version> </dependency>
2,導出案例

/** * 票據匯總 * * @param in: * @param response: * @return: com.jfa.common.utils.R * @author: */ @PostMapping("/billSummary") public R billSummary(@RequestBody ExportExcelIn in, HttpServletResponse response) { exportExcelService.billSummary(in, response); return R.ok(); } /** * 票據匯總 excel報表 * * @param in: * @param response: * @return: void * @author: */ public void billSummary(ExportExcelIn in, HttpServletResponse response) { //如果參數為空,設置實際為當前年份 if (in == null || StringUtils.isBlank(in.getYear())) { in.setYear(DUtils.fmtDateY(new Date())); } ExcelUtils excelUtils = new ExcelUtils(); excelUtils.setResponse(response); //設置文件名稱 excelUtils.setFileName(StringUtils.isNotBlank(in.getFileName()) ? in.getFileName() : "綜合分析".concat(Constant.HG).concat(String.valueOf(System.currentTimeMillis()))); //文檔內超鏈接跳轉 excelUtils.setLinkType(CommonsUtils.DOCUMENT); /** 根據時間段,查詢票據數據 */ List<BillPollEntity> billPollList = billPollService.queryByBillByParams(in); Optional.ofNullable(billPollList).filter(s -> s.size() > 0).orElseThrow(() -> new RRException("當前時間數據為空,請重新選擇再導出")); if (billPollList != null && billPollList.size() > 0) { //根據出票日期、到期日、出票人、收款人 分組 TreeMap<String, List<BillPollEntity>> billPollData = billPollList.stream().collect(Collectors.groupingBy(s -> DUtils.dateFmtYYMMDD(s.getDrawTime()).concat(Constant.HG).concat(DUtils.dateFmtYYMMDD(s.getDueTime())).concat(Constant.HG).concat(s.getDrawName().concat(s.getPayeeName())), TreeMap::new, Collectors.toList())); //組裝各Sheet數據 List<List<Object[]>> retDataList = new ArrayList<>(); //設置sheet名稱; 名稱規則:出票日+到期日+總票額(萬元)+總條數 List<Object> sheetNameList = new ArrayList<>(); sheetNameList.add("匯總"); //存放sheet數據對象 List<Object[]> sheetList = new ArrayList<>(); /** ============== 匯總 數據組裝開始 ============== */ //票據回款信息集合 Map<String, BillBackInfoEntity> billBackDataMap = billBackInfoService.getAllBillBackList(ShiroUtils.getUserMark()); /** 匯總 設置列頭 */ sheetList.add(ExcelHeadUtil.getBillSummaryHead()); /** 匯總 設置總計 */ List<Object> sumValueList = new ArrayList<>(); ExcelTools.setEmpty(sumValueList, 5); sumValueList.add(ExcelTools.setFormula(5, 3, (billPollData.size() + 2))); sumValueList.add(ExcelTools.setFormula(6, 3, (billPollData.size() + 2))); sumValueList.add(ExcelTools.setFormula(7, 3, (billPollData.size() + 2))); sheetList.add(ExcelTools.list2ObjArr(sumValueList)); for (Map.Entry<String, List<BillPollEntity>> m : billPollData.entrySet()) { String key = m.getKey(); // 鍵 List<BillPollEntity> dataList = m.getValue(); // 值 String sheetName = key.substring(0, key.lastIndexOf(Constant.HG)); //總票面額 BigDecimal totalBillAmount = dataList.stream().map(BillPollEntity::getBillAmount).reduce(BigDecimal.ZERO, BigDecimal::add); sheetName = sheetName.concat(Constant.L_KH + Constant.fmtAMT(totalBillAmount) + "萬" + Constant.R_KH).concat(dataList.size() + "條"); //添加sheet名稱 sheetNameList.add(sheetName); //總貼現金額 BigDecimal totalBackAmount = dataList.stream().map(t -> billBackDataMap.get(t.getBillNo()) != null ? billBackDataMap.get(t.getBillNo()).getBackAmount() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add); //總利息 BigDecimal totalInterest = dataList.stream().map(t -> billBackDataMap.get(t.getBillNo()) != null ? billBackDataMap.get(t.getBillNo()).getInterest() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add); /** 匯總 設置內容 */ List<Object> valueList = new ArrayList<>(); valueList.add(sheetName); valueList.add(DUtils.dateFmtYMD(dataList.get(0).getDrawTime())); valueList.add(DUtils.dateFmtYMD(dataList.get(0).getDueTime())); valueList.add(dataList.get(0).getDrawName()); valueList.add(dataList.get(0).getPayeeName()); valueList.add(totalBillAmount); valueList.add(totalBackAmount); valueList.add(totalInterest); sheetList.add(ExcelTools.list2ObjArr(valueList)); } retDataList.add(sheetList); /** ============== 匯總 數據組裝結束 ============== */ //設置各Sheet名稱 excelUtils.setSheetName(ExcelTools.list2StrArr(sheetNameList)); if (Constant.WHETHERE_DETAIL.YES.equals(in.getWhethereDetail())) { /** 設置匯總分類的詳細數據 */ setBillSummaryData(billPollData, retDataList, billBackDataMap); } //設置Sheet數據 excelUtils.setDataLists(retDataList); } List<List<Object[]>> dataList = excelUtils.getDataLists(); Optional.ofNullable(dataList).filter(s -> s.size() > 0).ifPresent(s -> { //固定列頭、表頭 HashMap paneMap = new HashMap(); ArrayList<Integer[]> paneList = new ArrayList<>(); paneList.add(new Integer[]{3, 2});//凍結的列數、凍結的行數 paneMap.put(1, paneList); //設置篩選 HashMap filterMap = new HashMap(); filterMap.put(1, setDataFilter(ExcelHeadUtil.getBillSummaryHead().length)); for (int i = 1; i < s.size(); i++) { ArrayList<Integer[]> pList = new ArrayList<>(); pList.add(new Integer[]{1, 2}); paneMap.put(i + 1, pList); filterMap.put(i + 1, setDataFilter(ExcelHeadUtil.getBillSummaryChildHead().length)); } excelUtils.setPaneMap(paneMap); excelUtils.setFilterMap(filterMap); }); //設置數字精度 excelUtils.setPrecision(2); //開始導出 excelUtils.exportForExcelsOptimize(); } /** * 設置 票據匯總 excel報表數據 * * @param billPollMap: 數據源 * @param retDataList: Sheet數據 * @return: java.util.List<java.util.List < java.lang.String [ ]>> * @author: */ private List<List<Object[]>> setBillSummaryData(TreeMap<String, List<BillPollEntity>> billPollMap, List<List<Object[]>> retDataList, Map<String, BillBackInfoEntity> billBackDataMap) { for (Map.Entry<String, List<BillPollEntity>> m : billPollMap.entrySet()) { //值 List<BillPollEntity> dataList = m.getValue(); //存放sheet數據對象 List<Object[]> sheetList = new ArrayList<>(); //設置列頭 sheetList.add(ExcelHeadUtil.getBillSummaryChildHead()); //票據種類 Map<String, String> kindMap = billKindConfigService.getCtNMap(); //設置頭部統計 List<Object> totalList = new ArrayList<>(); ExcelTools.setEmpty(totalList, 6); totalList.add(ExcelTools.setFormula(6, 3, (dataList.size() + 2))); ExcelTools.setEmpty(totalList, 3); totalList.add(ExcelTools.setFormula(10, 3, (dataList.size() + 2))); totalList.add(ExcelTools.setFormula(11, 3, (dataList.size() + 2))); ExcelTools.setEmpty(totalList, 1); sheetList.add(ExcelTools.list2ObjArr(totalList)); dataList.forEach(d -> { //設置內容 List<Object> valueList = new ArrayList<>(); valueList.add(d.getBillNo()); valueList.add(kindMap.get(d.getBillKind())); valueList.add(d.getDrawName()); valueList.add(d.getPayeeName()); valueList.add(DUtils.dateFmtYMD(d.getDrawTime())); valueList.add(DUtils.dateFmtYMD(d.getDueTime())); valueList.add(d.getBillAmount()); valueList.add(BillStatusEnum.getName(d.getBillStatus())); BillBackInfoEntity billBackInfoEntity = billBackDataMap.get(d.getBillNo()); if (billBackInfoEntity != null) { valueList.add(DUtils.dateFmtYMD(billBackInfoEntity.getBackTime())); valueList.add(String.valueOf(billBackInfoEntity.getInterestDays())); valueList.add(billBackInfoEntity.getInterest()); valueList.add(billBackInfoEntity.getBackAmount()); valueList.add(String.valueOf(billBackInfoEntity.getInterestRate().multiply(new BigDecimal(100)).setScale(2)).concat("%")); } else { ExcelTools.setEmpty(valueList, 5); } sheetList.add(ExcelTools.list2ObjArr(valueList)); }); retDataList.add(sheetList); } return retDataList; }
3,導出工具類
ExcelUtils:

package com.xxx.common.excel; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFRow; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.net.URLEncoder; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import static com.jfa.common.excel.CommonsUtils.*; /** * @ProjectName: git-dev * @Package: com.jfa.modules.peak.controller * @ClassName: ExcelUtils * @Author * @Description: Excel 導入導出操作相關工具類 */ @Slf4j public class ExcelUtils { private static Logger log = LoggerFactory.getLogger(ExcelUtils.class); private static final ThreadLocal<SimpleDateFormat> fmt = new ThreadLocal<>(); private static final ThreadLocal<DecimalFormat> df = new ThreadLocal<>(); private static final ThreadLocal<ExcelUtils> UTILS_THREAD_LOCAL = new ThreadLocal<>(); private static final Integer DATE_LENGTH = 10; // private static final String MESSAGE_FORMAT_df = "#.######"; // private static final String MESSAGE_FORMAT = "yyyy-MM-dd"; private SimpleDateFormat getDateFormat() { SimpleDateFormat format = fmt.get(); if (format == null) { //默認格式日期: "yyyy-MM-dd" format = new SimpleDateFormat(expectDateFormatStr, Locale.getDefault()); fmt.set(format); } return format; } public DecimalFormat getDecimalFormat() { DecimalFormat format = df.get(); if (format == null) { //默認數字格式: "#.######" 六位小數點 format = new DecimalFormat(numeralFormat); df.set(format); } return format; } public static final ExcelUtils initialization() { ExcelUtils excelUtils = UTILS_THREAD_LOCAL.get(); if (excelUtils == null) { excelUtils = new ExcelUtils(); UTILS_THREAD_LOCAL.set(excelUtils); } return excelUtils; } public ExcelUtils() { filePath = this.getFilePath(); dataLists = this.getDataLists(); response = this.getResponse(); regionMap = this.getRegionMap(); mapColumnWidth = this.getMapColumnWidth(); styles = this.getStyles(); paneMap = this.getPaneMap(); fileName = this.getFileName(); sheetName = this.getSheetName(); labelName = this.getLabelName(); rowStyles = this.getRowStyles(); columnStyles = this.getColumnStyles(); dropDownMap = this.getDropDownMap(); numeralFormat = this.getNumeralFormat(); dateFormatStr = this.getDateFormatStr(); expectDateFormatStr = this.getExpectDateFormatStr(); defaultColumnWidth = this.getDefaultColumnWidth(); fontSize = this.getFontSize(); precision = this.getPrecision(); linkType = this.getLinkType(); filterMap = this.getFilterMap(); } /** * web 響應(response) * Excel導出:有樣式(行、列、單元格樣式)、自適應列寬 * 功能描述: excel 數據導出、導出模板 * 更新日志: * 1.response.reset();注釋掉reset,否在會出現跨域錯誤。[2018-05-18] * 2.新增導出多個單元。[2018-08-08] * 3.poi官方建議大數據量解決方案:SXSSFWorkbook。[2018-08-08] * 4.自定義下拉列表:對每個單元格自定義下拉列表。[2018-08-08] * 5.數據遍歷方式換成數組(效率較高)。[2018-08-08] * 6.可提供模板下載。[2018-08-08] * 7.每個表格的大標題[2018-09-14] * 8.自定義列寬:對每個單元格自定義列寬[2018-09-18] * 9.自定義樣式:對每個單元格自定義樣式[2018-10-22] * 10.自定義單元格合並:對每個單元格合並[2018-10-22] * 11.固定表頭[2018-10-23] * 12.自定義樣式:單元格自定義某一列或者某一行樣式[2018-11-12] * 13.忽略邊框(默認是有邊框)[2018-11-15] * 14.函數式編程換成面向對象編程[2018-12-06-5] * 15.單表百萬數據量導出時樣式設置過多,導致速度慢(行、列、單元格樣式暫時控制10萬行、超過無樣式)[2019-01-30] * 版 本: * 1.apache poi 3.17 * 2.apache poi-ooxml 3.17 * * @return */ public Boolean exportForExcelsOptimize() { long startTime = System.currentTimeMillis(); log.info("=== === === :Excel tool class export start run!"); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000); OutputStream outputStream = null; SXSSFRow sxssfRow = null; try { // 設置數據 setDataList(sxssfWorkbook, sxssfRow, dataLists, regionMap, mapColumnWidth, styles, paneMap, sheetName, labelName, rowStyles, columnStyles, dropDownMap, defaultColumnWidth, fontSize,linkType,slashMap,precision,filterMap,rowStyleMap,rowList); // io 響應 setIo(sxssfWorkbook, outputStream, fileName, sheetName, response); } catch (Exception e) { e.printStackTrace(); } log.info("=== === === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!"); return true; } /** * Excel導出:無樣式(行、列、單元格樣式)、自適應列寬 * web 響應(response) * * @return */ public Boolean exportForExcelsNoStyle() { long startTime = System.currentTimeMillis(); log.info("=== === === :Excel tool class export start run!"); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000); OutputStream outputStream = null; SXSSFRow sxssfRow = null; try { setDataListNoStyle(sxssfWorkbook, sxssfRow, dataLists, regionMap, mapColumnWidth, paneMap, sheetName, labelName, dropDownMap, defaultColumnWidth, fontSize,linkType,precision); setIo(sxssfWorkbook, outputStream, fileName, sheetName, response); } catch (Exception e) { e.printStackTrace(); } log.info("=== === === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!"); return true; } /** * 功能描述: * 1.excel 模板數據導入。 * <p> * 更新日志: * 1.共用獲取Excel表格數據。 * 2.多單元數據獲取。 * 3.多單元從第幾行開始獲取數據[2018-09-20] * 4.多單元根據那些列為空來忽略行數據[2018-10-22] * <p> * 版 本: * 1.apache poi 3.17 * 2.apache poi-ooxml 3.17 * * @param book Workbook對象(不可為空) * @param sheetName 多單元數據獲取(不可為空) * @param indexMap 多單元從第幾行開始獲取數據,默認從第二行開始獲取(可為空,如 hashMapIndex.put(1,3); 第一個表格從第三行開始獲取) * @param continueRowMap 多單元根據那些列為空來忽略行數據(可為空,如 mapContinueRow.put(1,new Integer[]{1, 3}); 第一個表格從1、3列為空就忽略) * @return */ @SuppressWarnings({"deprecation", "rawtypes"}) public static List<List<LinkedHashMap<String, String>>> importForExcelData(Workbook book, String[] sheetName, HashMap indexMap, HashMap continueRowMap) { long startTime = System.currentTimeMillis(); log.info("=== === === :Excel tool class export start run!"); try { List<List<LinkedHashMap<String, String>>> returnDataList = new ArrayList<>(); for (int k = 0; k <= sheetName.length - 1; k++) { // 得到第K個工作表對象、得到第K個工作表中的總行數。 Sheet sheet = book.getSheetAt(k); int rowCount = sheet.getLastRowNum() + 1; Row valueRow = null; List<LinkedHashMap<String, String>> rowListValue = new ArrayList<>(); LinkedHashMap<String, String> cellHashMap = null; int irow = 1; // 第n個工作表:從開始獲取數據、默認第一行開始獲取。 if (indexMap != null && indexMap.get(k + 1) != null) { irow = Integer.valueOf(indexMap.get(k + 1).toString()) - 1; } // 第n個工作表:數據獲取。 for (int i = irow; i < rowCount; i++) { valueRow = sheet.getRow(i); if (valueRow == null) { continue; } // 第n個工作表:從開始列忽略數據、為空就跳過。 if (continueRowMap != null && continueRowMap.get(k + 1) != null) { int continueRowCount = 0; Integer[] continueRow = (Integer[]) continueRowMap.get(k + 1); for (int w = 0; w <= continueRow.length - 1; w++) { Cell valueRowCell = valueRow.getCell(continueRow[w] - 1); if (valueRowCell == null || isBlank(valueRowCell.toString())) { continueRowCount = continueRowCount + 1; } } if (continueRowCount == continueRow.length) { continue; } } cellHashMap = new LinkedHashMap<>(); // 第n個工作表:獲取列數據。 for (int j = 0; j < valueRow.getLastCellNum(); j++) { cellHashMap.put(Integer.toString(j), getCellVal(valueRow.getCell(j))); } if (cellHashMap.size() > 0) { rowListValue.add(cellHashMap); } } returnDataList.add(rowListValue); } log.info("=== === === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!"); return returnDataList; } catch (Exception e) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:Excel tool class export exception !"); e.printStackTrace(); return null; } } /** * response 響應 * * @param sxssfWorkbook * @param outputStream * @param fileName * @param sheetName * @param response * @throws Exception */ private static void setIo(SXSSFWorkbook sxssfWorkbook, OutputStream outputStream, String fileName, String[] sheetName, HttpServletResponse response) throws Exception { try { if (response != null) { response.setCharacterEncoding("utf-8"); response.setHeader("Charset", "UTF-8"); response.setHeader("Content-Type", "application/force-download"); response.setHeader("Content-Type", "application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName == null ? sheetName[0] : fileName, "utf8") + ".xlsx"); response.flushBuffer(); outputStream = response.getOutputStream(); } writeAndColse(sxssfWorkbook, outputStream); } catch (Exception e) { e.getSuppressed(); } } /** * 功能描述: 獲取Excel單元格中的值並且轉換java類型格式 * * @param cell * @return */ private static String getCellVal(Cell cell) { String val = null; if (cell != null) { CellType cellType = cell.getCellType(); switch (cellType) { case NUMERIC: if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) { val = ExcelUtils.initialization().getDateFormat().format(cell.getDateCellValue()); } else { val = ExcelUtils.initialization().getDecimalFormat().format(cell.getNumericCellValue()); } break; case STRING: if (cell.getStringCellValue().trim().length() >= DATE_LENGTH && verificationDate(cell.getStringCellValue(), ExcelUtils.initialization().dateFormatStr)) { val = strToDateFormat(cell.getStringCellValue(), ExcelUtils.initialization().dateFormatStr, ExcelUtils.initialization().expectDateFormatStr); } else { val = cell.getStringCellValue(); } break; case BOOLEAN: val = String.valueOf(cell.getBooleanCellValue()); break; case BLANK: val = cell.getStringCellValue(); break; case ERROR: val = "錯誤"; break; case FORMULA: try { val = String.valueOf(cell.getStringCellValue()); } catch (IllegalStateException e) { val = String.valueOf(cell.getNumericCellValue()); } break; default: val = cell.getRichStringCellValue() == null ? null : cell.getRichStringCellValue().toString(); } } else { val = ""; } return val; } /** * 導出數據必填 */ private List<List<Object[]>> dataLists; /** * sheet名稱必填 */ private String[] sheetName; /** * 每個表格的大標題 */ private String[] labelName; /** * 頁面響應 */ private HttpServletResponse response; /** * 自定義:單元格合並 */ private HashMap regionMap; /** * 自定義:對每個單元格自定義列寬 */ private HashMap mapColumnWidth; /** * 自定義:每一個單元格樣式 */ private HashMap styles; /** * 自定義:固定表頭 */ private HashMap paneMap; /** * 自定義:設置斜線 */ private HashMap slashMap; /** * 自定義:某一行樣式 */ private HashMap rowStyles; /** * 自定義:某一列樣式 */ private HashMap columnStyles; /** * 自定義:對每個單元格自定義下拉列表 */ private HashMap dropDownMap; /** * 文件名稱 */ private String fileName; /** * 導出本地路徑 */ private String filePath; /** * 導出數字格式化:默認是保留六位小數點 */ private String numeralFormat; /** * 導出日期格式化:默認是"yyyy-MM-dd"格式 */ private String dateFormatStr; /** * 期望轉換后的日期格式:默認是 dateFormatStr */ private String expectDateFormatStr; /** * 默認列寬大小:默認16 */ private Integer defaultColumnWidth; /** * 默認字體大小:默認12號字體 */ private Integer fontSize; /** * 超鏈接類型;DOCUMENT = 文檔 */ private String linkType; /** * 自定義數字精度 */ private Integer precision = 0; /** * 自定義過濾列 */ private HashMap filterMap; /** * 自定義行 樣式 */ private HashMap rowStyleMap; /** * 自定義行 樣式 */ private List<Integer> rowList; public Integer getFontSize() { if (fontSize == null) { fontSize = 12; } return fontSize; } public void setFontSize(Integer fontSize) { this.fontSize = fontSize; } public Integer getDefaultColumnWidth() { if (defaultColumnWidth == null) { defaultColumnWidth = 30; } return defaultColumnWidth; } public void setDefaultColumnWidth(Integer defaultColumnWidth) { this.defaultColumnWidth = defaultColumnWidth; } public void setDateFormatStr(String dateFormatStr) { if (dateFormatStr == null) { dateFormatStr = "yyyy-MM-dd"; } this.dateFormatStr = dateFormatStr; } public String getDateFormatStr() { if (dateFormatStr == null) { dateFormatStr = "yyyy-MM-dd"; } return dateFormatStr; } public String getExpectDateFormatStr() { if (expectDateFormatStr == null) { expectDateFormatStr = dateFormatStr; } return expectDateFormatStr; } public void setExpectDateFormatStr(String expectDateFormatStr) { if (expectDateFormatStr == null) { expectDateFormatStr = dateFormatStr; } this.expectDateFormatStr = expectDateFormatStr; } public void setNumeralFormat(String numeralFormat) { if (numeralFormat == null) { numeralFormat = "#.######"; } this.numeralFormat = numeralFormat; } public String getNumeralFormat() { if (numeralFormat == null) { numeralFormat = "#.######"; } return numeralFormat; } public List<List<Object[]>> getDataLists() { return dataLists; } public void setDataLists(List<List<Object[]>> dataLists) { this.dataLists = dataLists; } public String[] getSheetName() { return sheetName; } public void setSheetName(String[] sheetName) { this.sheetName = sheetName; } public String[] getLabelName() { return labelName; } public void setLabelName(String[] labelName) { this.labelName = labelName; } public HttpServletResponse getResponse() { return response; } public void setResponse(HttpServletResponse response) { this.response = response; } public HashMap getRegionMap() { return regionMap; } public void setRegionMap(HashMap regionMap) { this.regionMap = regionMap; } public HashMap getMapColumnWidth() { return mapColumnWidth; } public void setMapColumnWidth(HashMap mapColumnWidth) { this.mapColumnWidth = mapColumnWidth; } public HashMap getStyles() { return styles; } public void setStyles(HashMap styles) { this.styles = styles; } public HashMap getPaneMap() { return paneMap; } public void setPaneMap(HashMap paneMap) { this.paneMap = paneMap; } public HashMap getRowStyles() { return rowStyles; } public void setRowStyles(HashMap rowStyles) { this.rowStyles = rowStyles; } public HashMap getColumnStyles() { return columnStyles; } public void setColumnStyles(HashMap columnStyles) { this.columnStyles = columnStyles; } public HashMap getDropDownMap() { return dropDownMap; } public void setDropDownMap(HashMap dropDownMap) { this.dropDownMap = dropDownMap; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public String getLinkType() { return linkType; } public void setLinkType(String linkType) { this.linkType = linkType; } public HashMap getSlashMap() { return slashMap; } public void setSlashMap(HashMap slashMap) { this.slashMap = slashMap; } public Integer getPrecision() { return precision; } public void setPrecision(Integer precision) { this.precision = precision; } public HashMap getFilterMap() { return filterMap; } public void setFilterMap(HashMap filterMap) { this.filterMap = filterMap; } public HashMap getRowStyleMap() { return rowStyleMap; } public void setRowStyleMap(HashMap rowStyleMap) { this.rowStyleMap = rowStyleMap; } public List<Integer> getRowList() { return rowList; } public void setRowList(List<Integer> rowList) { this.rowList = rowList; } }
CommonsUtils:

package com.xxx.common.excel; import org.apache.commons.lang.StringUtils; import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.streaming.SXSSFDrawing; import org.apache.poi.xssf.streaming.SXSSFRow; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.text.AttributeSet; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.apache.poi.ss.usermodel.ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE; import static org.apache.poi.ss.util.CellUtil.createCell; /** * @ProjectName: git-dev * @Package: com.jfa.common.excel * @ClassName: CommonsUtils * @Author: * @Description: */ public class CommonsUtils { private static Logger log = LoggerFactory.getLogger(CommonsUtils.class); private static final String DataValidationError1 = "Excel表格提醒:"; private static final String DataValidationError2 = "數據不規范,請選擇表格下拉列表中的數據!"; public static final Integer MAX_ROWSUM = 1048570; public static final Integer MAX_ROWSYTLE = 100000; public static final String BIGDECIMAL_CLASS = "class java.math.BigDecimal"; /** * 超鏈接類型;DOCUMENT = 文檔 */ public static final String DOCUMENT = "DOCUMENT"; /** * 超鏈接類型;DOCUMENT = 文檔 */ public static final String GS = "公式:"; /** * 設置數據:有樣式(行、列、單元格樣式) * * @param wb * @param sxssfRow * @param dataLists * @param regionMap * @param columnMap * @param styles * @param paneMap * @param sheetName * @param labelName * @param rowStyles * @param columnStyles * @param dropDownMap * @throws Exception */ public static void setDataList(SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> dataLists, HashMap regionMap, HashMap columnMap, HashMap styles, HashMap paneMap, String[] sheetName, String[] labelName, HashMap rowStyles, HashMap columnStyles, HashMap dropDownMap, Integer defaultColumnWidth, Integer fontSize, String linkType, HashMap slashMap, Integer precision, HashMap filterMap, HashMap rowStyleMap, List<Integer> rowList) throws Exception { if (dataLists == null) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:Export data(type:List<List<String[]>>) cannot be empty!"); } if (sheetName == null) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:Export sheet(type:String[]) name cannot be empty!"); } int k = 0; for (List<Object[]> listRow : dataLists) { SXSSFSheet sxssfSheet = wb.createSheet(); sxssfSheet.setForceFormulaRecalculation(true); // sxssfSheet.setDefaultColumnWidth(defaultColumnWidth); wb.setSheetName(k, sheetName[k]); CellStyle cellStyle = wb.createCellStyle(); XSSFFont font = (XSSFFont) wb.createFont(); SXSSFDrawing sxssfDrawing = sxssfSheet.createDrawingPatriarch(); int jRow = 0; // 自定義:大標題(看該方法說明)。 jRow = setLabelName(jRow, k, wb, labelName, sxssfRow, sxssfSheet, listRow); // 自定義:每個表格固定表頭(看該方法說明)。 if (paneMap != null && paneMap.get(k + 1) != null) { createFreezePane(sxssfSheet, (ArrayList<Integer[]>) paneMap.get(k + 1)); } // 自定義:設置斜線 if (slashMap != null && slashMap.get(k + 1) != null) { createSlash(wb, sxssfSheet, (ArrayList<Integer[]>) slashMap.get(k + 1)); } // 自定義:過濾數據 if (filterMap != null && filterMap.get(k + 1) != null) { createFilter(sxssfSheet, filterMap, k + 1); } // 自定義:每個單元格自定義合並單元格:對每個單元格自定義合並單元格(看該方法說明)。 if (regionMap != null) { setMergedRegion(sxssfSheet, (ArrayList<Integer[]>) regionMap.get(k + 1)); } // 自定義:每個單元格自定義下拉列表:對每個單元格自定義下拉列表(看該方法說明)。 if (dropDownMap != null) { setDataValidation(sxssfSheet, (List<String[]>) dropDownMap.get(k + 1), listRow.size()); } // 自定義:每個表格自定義列寬:對每個單元格自定義列寬(看該方法說明)。 if (columnMap != null) { setColumnWidth(sxssfSheet, (HashMap) columnMap.get(k + 1)); } // 默認樣式。 setStyle(cellStyle, font, fontSize); CellStyle cell_style = null; CellStyle row_style = null; CellStyle column_style = null; // 寫入小標題與數據。 Integer SIZE = listRow.size() < MAX_ROWSUM ? listRow.size() : MAX_ROWSUM; Integer MAXSYTLE = listRow.size() < MAX_ROWSYTLE ? listRow.size() : MAX_ROWSYTLE; Map<Integer, Integer> sizeMap = new HashMap<>(); sxssfSheet.setForceFormulaRecalculation(true); for (int i = 0; i < SIZE; i++) { sxssfRow = sxssfSheet.createRow(jRow); for (int j = 0; j < listRow.get(i).length; j++) { // 樣式過多會導致GC內存溢出! try { Cell cell = null; if (patternIsImg(String.valueOf(listRow.get(i)[j]))) { cell = createCell(sxssfRow, j, " "); drawPicture(wb, sxssfDrawing, String.valueOf(listRow.get(i)[j]), j, jRow); } else { cell = createCell(sxssfRow, j, String.valueOf(listRow.get(i)[j])); } /** ========== 單元格類型;設置對應格式 ========start== */ //BigDecimal 類型 if (BIGDECIMAL_CLASS.equals(listRow.get(i)[j].getClass().toString())) { cell.setCellValue(Double.valueOf(String.valueOf(listRow.get(i)[j]))); XSSFDataFormat format = wb.getXSSFWorkbook().createDataFormat(); String defualtFmt = "_ * #,##0 ;_ * -#,##0 ;_ * \"-\"??_ ;_ @_ "; switch (precision) { case 1: defualtFmt = "_ * #,##0.0 ;_ * -#,##0.0 ;_ * \"-\"??_ ;_ @_ "; break; case 2: defualtFmt = "_ * #,##0.00 ;_ * -#,##0.00 ;_ * \"-\"??_ ;_ @_ "; break; case 3: defualtFmt = "_ * #,##0.000 ;_ * -#,##0.000 ;_ * \"-\"??_ ;_ @_ "; break; case 4: defualtFmt = "_ * #,##0.0000 ;_ * -#,##0.0000 ;_ * \"-\"??_ ;_ @_ "; break; } cellStyle.setDataFormat(format.getFormat(defualtFmt)); } /** ========== 單元格類型;設置對應格式 ========end== */ //設置單元格樣式 cell.setCellStyle(cellStyle); /** ========== 設置公式 ========start== */ if (String.valueOf(listRow.get(i)[j]).indexOf(GS) != -1) { String rowCell = String.valueOf(listRow.get(i)[j]).replace(GS, ""); cell.setCellFormula(rowCell); } /** ========== 設置公式 ========end== */ /** ========== 超鏈接設置 ========start== */ if (DOCUMENT.equals(linkType)) { //設置超鏈接 if (Arrays.asList(sheetName).contains(listRow.get(i)[j])) { for (int n = 1; n < sheetName.length; n++) { if (sheetName[n].equals(listRow.get(i)[j])) { CreationHelper createHelper = wb.getCreationHelper(); XSSFHyperlink link = (XSSFHyperlink) createHelper.createHyperlink(HyperlinkType.DOCUMENT); link.setAddress("#'" + sheetName[n] + "'!A1"); //設置超鏈接樣式 XSSFCellStyle linkStyle = wb.getXSSFWorkbook().createCellStyle(); XSSFFont cellFont = wb.getXSSFWorkbook().createFont(); cellFont.setUnderline((byte) 1); cellFont.setColor(IndexedColors.fromInt(4).index); cellFont.setFontName("Arial"); cellFont.setFontHeight(12); linkStyle.setAlignment(HorizontalAlignment.CENTER); linkStyle.setVerticalAlignment(VerticalAlignment.CENTER); linkStyle.setFont(cellFont); cell.setCellStyle(linkStyle); //超鏈接 setBorder(linkStyle, true); cell.setHyperlink(link); break; } } } } /** ========== 超鏈接設置 ========start== */ // 自定義:每個表格每一列的樣式(看該方法說明)。 // if (columnStyles != null && jRow >= pane && i <= MAXSYTLE) { if (columnStyles != null && i <= MAXSYTLE) { setExcelRowStyles(cell, wb, sxssfRow, (List) columnStyles.get(k + 1), j); } // 自定義:每個表格每一行的樣式(看該方法說明)。 if (rowStyles != null && i <= MAXSYTLE) { setExcelRowStyles(cell, wb, sxssfRow, (List) rowStyles.get(k + 1), jRow); } if (Arrays.asList(listRow.get(i)).contains("小計") || Arrays.asList(listRow.get(i)).contains("總計")) { setTotalStyles(wb, cell); } // 自定義標題樣式 if (rowList != null && rowList.size() > 0) { for (int rowListIndex = 0; rowListIndex < rowList.size(); rowListIndex++) { if (rowList.get(rowListIndex) == i) { setSubTitleStyles(wb, cell, sxssfRow, slashMap); } } } else { if (i == 0) { setSubTitleStyles(wb, cell, sxssfRow, slashMap); } } // 自定義:每一個單元格樣式(看該方法說明)。 if (styles != null && i <= MAXSYTLE) { setExcelStyles(cell, wb, sxssfRow, (List<List<Object[]>>) styles.get(k + 1), j, i); } //篩選單元格最大長度 if (sizeMap.get(j) != null && !CellType.FORMULA.equals(cell.getCellType())) { // BigDecimal b = ((new BigDecimal(sizeMap.get(j)).add(new BigDecimal(listRow.get(i)[j].getBytes().length))).divide(new BigDecimal(2)).setScale(0, RoundingMode.HALF_UP)); // sizeMap.put(j, Integer.valueOf(String.valueOf(b))); sizeMap.put(j, Math.max(sizeMap.get(j), String.valueOf(listRow.get(i)[j]).getBytes().length)); } else { sizeMap.put(j, String.valueOf(listRow.get(i)[j]).getBytes().length); } } catch (Exception e) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:The maximum number of cell styles was exceeded. You can define up to 4000 styles!"); } } jRow++; sxssfSheet.setForceFormulaRecalculation(true); } //設置單元格長度, 這里要乘上256 for (Integer i : sizeMap.keySet()) { sxssfSheet.setColumnWidth(i, (sizeMap.get(i) + 9) * 256); } k++; sxssfSheet.setForceFormulaRecalculation(true); } } private static boolean hasDouble(String s) { boolean bol = true; try { Double.valueOf(s); } catch (Exception e) { bol = false; } return bol; } /** * @param cell Cell對象。 * @param wb SXSSFWorkbook對象。 * @param fontSize 字體大小。 * @param bold 是否加粗。 * @param center 是否左右上下居中。 * @param isBorder 是否忽略邊框 * @param leftBoolean 左對齊 * @param rightBoolean 右對齊 * @param height 行高 */ public static void setExcelStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, Integer fontSize, Boolean bold, Boolean center, Boolean isBorder, Boolean leftBoolean, Boolean rightBoolean, Integer fontColor, Integer height) { CellStyle cellStyle = cell.getRow().getSheet().getWorkbook().createCellStyle(); //保證了既可以新建一個CellStyle,又可以不丟失原來的CellStyle 的樣式 cellStyle.cloneStyleFrom(cell.getCellStyle()); //左右居中、上下居中 if (center != null && center) { cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); } //右對齊 if (rightBoolean != null && rightBoolean) { cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setAlignment(HorizontalAlignment.RIGHT); } //左對齊 if (leftBoolean != null && leftBoolean) { cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setAlignment(HorizontalAlignment.LEFT); } //是否忽略邊框 if (isBorder != null && isBorder) { setBorderColor(cellStyle, isBorder); } //設置單元格字體樣式 XSSFFont font = (XSSFFont) wb.createFont(); if (bold != null && bold) { font.setBold(bold); } //行高 if (height != null) { sxssfRow.setHeight((short) (height * 2)); } font.setFontName("Arial"); font.setFontHeight(fontSize == null ? 12 : fontSize); cellStyle.setFont(font); // 點擊可查看顏色對應的值: BLACK(8), WHITE(9), RED(10), font.setColor(IndexedColors.fromInt(fontColor == null ? 8 : fontColor).index); //金額右對齊 if (BIGDECIMAL_CLASS.equals(sxssfRow.getClass().toString())) { cellStyle.setAlignment(HorizontalAlignment.RIGHT); } cell.setCellStyle(cellStyle); } public static void setExcelTitleStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<Object[]> rowstyleList, int rowIndex) { if (rowstyleList != null && rowstyleList.size() > 0) { Integer[] rowstyle = (Integer[]) rowstyleList.get(1); for (int i = 0; i < rowstyle.length; i++) { if (rowIndex == rowstyle[i]) { Boolean[] bool = (Boolean[]) rowstyleList.get(0); Integer fontColor = null; Integer fontSize = null; Integer height = null; //當有設置顏色值 、字體大小、行高才獲取值 if (rowstyleList.size() >= 3) { int leng = rowstyleList.get(2).length; if (leng >= 1) { fontColor = (Integer) rowstyleList.get(2)[0]; } if (leng >= 2) { fontSize = (Integer) rowstyleList.get(2)[1]; } if (leng >= 3) { height = (Integer) rowstyleList.get(2)[2]; } } setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height); } } } } public static void setExcelRowStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<Object[]> rowstyleList, int rowIndex) { if (rowstyleList != null && rowstyleList.size() > 0) { Integer[] rowstyle = (Integer[]) rowstyleList.get(1); for (int i = 0; i < rowstyle.length; i++) { if (rowIndex == rowstyle[i]) { Boolean[] bool = (Boolean[]) rowstyleList.get(0); Integer fontColor = null; Integer fontSize = null; Integer height = null; //當有設置顏色值 、字體大小、行高才獲取值 if (rowstyleList.size() >= 3) { int leng = rowstyleList.get(2).length; if (leng >= 1) { fontColor = (Integer) rowstyleList.get(2)[0]; } if (leng >= 2) { fontSize = (Integer) rowstyleList.get(2)[1]; } if (leng >= 3) { height = (Integer) rowstyleList.get(2)[2]; } } setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height); } } } } /** * 畫圖片 * @param wb * @param sxssfSheet * @param pictureUrl * @param rowIndex */ /** * 畫圖片 * * @param wb * @param sxssfDrawing * @param pictureUrl * @param rowIndex */ private static void drawPicture(SXSSFWorkbook wb, SXSSFDrawing sxssfDrawing, String pictureUrl, int colIndex, int rowIndex) { //rowIndex代表當前行 try { if (pictureUrl != null) { URL url = new URL(pictureUrl); //打開鏈接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5 * 1000); InputStream inStream = conn.getInputStream(); byte[] data = readInputStream(inStream); //設置圖片大小, XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 50, 50, colIndex, rowIndex, colIndex + 1, rowIndex + 1); anchor.setAnchorType(DONT_MOVE_AND_RESIZE); sxssfDrawing.createPicture(anchor, wb.addPicture(data, XSSFWorkbook.PICTURE_TYPE_JPEG)); } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 是否是圖片 * * @param str * @return */ public static Boolean patternIsImg(String str) { String reg = ".+(.JPEG|.jpeg|.JPG|.jpg|.png|.gif)$"; Pattern pattern = Pattern.compile(reg); Matcher matcher = pattern.matcher(str); Boolean temp = matcher.find(); return temp; } /** * @param inStream * @return * @throws Exception */ private static byte[] readInputStream(InputStream inStream) throws Exception { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //創建一個Buffer字符串 byte[] buffer = new byte[1024]; //每次讀取的字符串長度,如果為-1,代表全部讀取完畢 int len = 0; //使用一個輸入流從buffer里把數據讀取出來 while ((len = inStream.read(buffer)) != -1) { //用輸出流往buffer里寫入數據,中間參數代表從哪個位置開始讀,len代表讀取的長度 outStream.write(buffer, 0, len); } //關閉輸入流 inStream.close(); //把outStream里的數據寫入內存 return outStream.toByteArray(); } /** * 自定義:大標題 * * @param jRow * @param k * @param wb * @param labelName * @param sxssfRow * @param sxssfSheet * @param listRow * @return */ private static int setLabelName(Integer jRow, Integer k, SXSSFWorkbook wb, String[] labelName, SXSSFRow sxssfRow, SXSSFSheet sxssfSheet, List<Object[]> listRow) { if (labelName != null) { // 自定義:大標題和樣式。參數說明:new String[]{"表格數據一", "表格數據二", "表格數據三"} sxssfRow = sxssfSheet.createRow(0); Cell cell = createCell(sxssfRow, 0, labelName[k]); setMergedRegion(sxssfSheet, 0, 0, 0, listRow.get(0).length - 1); setLabelStyles(wb, cell, sxssfRow); jRow = 1; } return jRow; } /** * 設置數據:無樣式(行、列、單元格樣式) * * @param wb * @param sxssfRow * @param dataLists * @param regionMap * @param columnMap * @param paneMap * @param sheetName * @param labelName * @param dropDownMap * @throws Exception */ public static void setDataListNoStyle(SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> dataLists, HashMap regionMap, HashMap columnMap, HashMap paneMap, String[] sheetName, String[] labelName, HashMap dropDownMap, Integer defaultColumnWidth, Integer fontSize, String linkType, Integer precision) throws Exception { if (dataLists == null) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:Export data(type:List<List<String[]>>) cannot be empty!"); } if (sheetName == null) { log.debug("=== === === :Andyczy ExcelUtils Exception Message:Export sheet(type:String[]) name cannot be empty!"); } int k = 0; for (List<Object[]> listRow : dataLists) { SXSSFSheet sxssfSheet = wb.createSheet(); sxssfSheet.setDefaultColumnWidth(defaultColumnWidth); wb.setSheetName(k, sheetName[k]); CellStyle cellStyle = wb.createCellStyle(); XSSFFont font = (XSSFFont) wb.createFont(); int jRow = 0; // 自定義:大標題(看該方法說明)。 jRow = setLabelName(jRow, k, wb, labelName, sxssfRow, sxssfSheet, listRow); // 自定義:每個表格固定表頭(看該方法說明)。 if (paneMap != null && paneMap.get(k + 1) != null) { createFreezePane(sxssfSheet, (ArrayList<Integer[]>) paneMap.get(k + 1)); } // 自定義:每個單元格自定義合並單元格:對每個單元格自定義合並單元格(看該方法說明)。 if (regionMap != null) { setMergedRegion(sxssfSheet, (ArrayList<Integer[]>) regionMap.get(k + 1)); } // 自定義:每個單元格自定義下拉列表:對每個單元格自定義下拉列表(看該方法說明)。 if (dropDownMap != null) { setDataValidation(sxssfSheet, (List<String[]>) dropDownMap.get(k + 1), listRow.size()); } // 自定義:每個表格自定義列寬:對每個單元格自定義列寬(看該方法說明)。 if (columnMap != null) { setColumnWidth(sxssfSheet, (HashMap) columnMap.get(k + 1)); } // 默認樣式。 setStyle(cellStyle, font, fontSize); // 寫入小標題與數據。 Integer SIZE = listRow.size() < MAX_ROWSUM ? listRow.size() : MAX_ROWSUM; for (int i = 0; i < SIZE; i++) { sxssfRow = sxssfSheet.createRow(jRow); for (int j = 0; j < listRow.get(i).length; j++) { Cell cell = createCell(sxssfRow, j, String.valueOf(listRow.get(i)[j])); cell.setCellStyle(cellStyle); } jRow++; } k++; } } public static void writeAndColse(SXSSFWorkbook sxssfWorkbook, OutputStream outputStream) throws Exception { try { if (outputStream != null) { sxssfWorkbook.setForceFormulaRecalculation(true);// 執行公式 sxssfWorkbook.write(outputStream); sxssfWorkbook.dispose(); outputStream.flush(); outputStream.close(); } } catch (Exception e) { System.out.println(" Andyczy ExcelUtils Exception Message:Output stream is not empty !"); e.getSuppressed(); } } /** * 功能描述:所有自定義單元格樣式 * * @param cell * @param wb * @param styles */ public static void setExcelStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> styles, int cellIndex, int rowIndex) { if (styles != null) { for (int z = 0; z < styles.size(); z++) { List<Object[]> stylesList = styles.get(z); if (stylesList != null) { //樣式 Boolean[] bool = (Boolean[]) stylesList.get(0); //顏色和字體 Integer fontColor = null; Integer fontSize = null; Integer height = null; //當有設置顏色值 、字體大小、行高才獲取值 if (stylesList.size() >= 2) { int leng = stylesList.get(1).length; if (leng >= 1) { fontColor = (Integer) stylesList.get(1)[0]; } if (leng >= 2) { fontSize = (Integer) stylesList.get(1)[1]; } if (leng >= 3) { height = (Integer) stylesList.get(1)[2]; } } //第幾行第幾列 for (int m = 2; m < stylesList.size(); m++) { Integer[] str = (Integer[]) stylesList.get(m); if (cellIndex + 1 == (str[1]) && rowIndex + 1 == (str[0])) { setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height); } } } } } } /** * 大標題樣式 * * @param wb * @param cell * @param sxssfRow */ public static void setLabelStyles(SXSSFWorkbook wb, Cell cell, SXSSFRow sxssfRow) { CellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); sxssfRow.setHeight((short) (399 * 2)); XSSFFont font = (XSSFFont) wb.createFont(); font.setFontName("Arial"); font.setFontHeight(14); font.setBold(true); cellStyle.setFont(font); cell.setCellStyle(cellStyle); } /** * 合計/小計 樣式 * * @param wb * @param cell */ public static void setTotalStyles(SXSSFWorkbook wb, Cell cell) { XSSFCellStyle cellStyle = wb.getXSSFWorkbook().createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); XSSFFont font = (XSSFFont) wb.createFont(); font.setFontName("Arial"); font.setFontHeight(12); // font.setColor(new XSSFColor(new java.awt.Color(221,235,247))); font.setBold(true); cellStyle.setFont(font); cellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(189, 235, 247))); cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); setBorder(cellStyle, true); cell.setCellStyle(cellStyle); } /** * 小標題樣式 * * @param wb * @param cell */ public static void setSubTitleStyles(SXSSFWorkbook wb, Cell cell, SXSSFRow sxssfRow, HashMap slashMap) { XSSFCellStyle cellStyle = wb.getXSSFWorkbook().createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); if (slashMap != null) { sxssfRow.setHeight((short) (399 * 1.8)); } XSSFFont font = (XSSFFont) wb.createFont(); font.setFontName("Arial"); font.setFontHeight(12); font.setColor(IndexedColors.WHITE.index); font.setBold(true); cellStyle.setFont(font); cellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(47, 117, 181))); cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); setBorder(cellStyle, true); cell.setCellStyle(cellStyle); } /** * 默認樣式 * * @param cellStyle * @param font * @return * @Parm */ public static void setStyle(CellStyle cellStyle, XSSFFont font, Integer fontSize) { cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); font.setFontName("Arial"); cellStyle.setFont(font); font.setFontHeight(fontSize); setBorder(cellStyle, true); } /** * 判斷字符串是否為空 * * @param str * @return */ public static boolean isBlank(String str) { int strLen; if (str != null && (strLen = str.length()) != 0) { for (int i = 0; i < strLen; ++i) { if (!Character.isWhitespace(str.charAt(i))) { return false; } } return true; } else { return true; } } /** * 功能描述: 鎖定行(固定表頭) * * @param sxssfSheet * @param row */ public static void createFreezePane(SXSSFSheet sxssfSheet, Integer row) { if (row != null && row > 0) { sxssfSheet.createFreezePane(0, row, 0, 1); } } /** * 功能描述: 鎖定行/列(固定表頭/列頭) * * @param sxssfSheet * @param rowColList */ public static void createFreezePane(SXSSFSheet sxssfSheet, ArrayList<Integer[]> rowColList) { Optional.ofNullable(rowColList).filter(s -> s.size() > 0).ifPresent(s -> { for (int i = 0; i < rowColList.size(); i++) { Integer[] str = rowColList.get(i); if (str.length > 0 && str.length == 2) { int colSplit = str[0]; //凍結的列數 int rowSplit = str[1]; //凍結的行數 // int leftmostColumn = str[2]; //首列可見序號 // int topRow = str[3]; //首行可見序號 // colSplit=凍結的列數、rowSplit=凍結的行數、leftmostColumn=首列序號、leftmostColumn=首行序號 // sxssfSheet.createFreezePane(colSplit, rowSplit, leftmostColumn, leftmostColumn); sxssfSheet.createFreezePane(colSplit, rowSplit); } } }); } /** * 功能描述: 設置斜線 * * @param sxssfSheet * @param rowColList */ public static void createSlash(SXSSFWorkbook wb, SXSSFSheet sxssfSheet, ArrayList<Integer[]> rowColList) { Optional.ofNullable(rowColList).filter(s -> s.size() > 0).ifPresent(s -> { for (int i = 0; i < rowColList.size(); i++) { Integer[] str = rowColList.get(i); if (str.length > 0 && str.length == 4) { CreationHelper helper = wb.getCreationHelper(); XSSFDrawing drawing = sxssfSheet.getDrawingPatriarch(); ClientAnchor anchor = helper.createClientAnchor(); // 設置斜線的開始位置 anchor.setCol1(str[0]); anchor.setRow1(str[1]); // 設置斜線的結束位置 anchor.setCol2(str[2]); anchor.setRow2(str[3]); XSSFSimpleShape shape = drawing.createSimpleShape((XSSFClientAnchor) anchor); // 設置形狀類型為線型 shape.setShapeType(ShapeTypes.LINE); // 設置線寬 shape.setLineWidth(0.3); // 設置線的風格 shape.setLineStyle(0); // 設置線的顏色 shape.setLineStyleColor(00, 00, 00); } } }); } public static void createFilter(SXSSFSheet sxssfSheet, HashMap dataFilter, Integer k) { Optional.ofNullable(dataFilter).filter(s -> s.size() > 0).ifPresent(s -> { String value = String.valueOf(s.get(k)); if (StringUtils.isNotBlank(value)) { CellRangeAddress c = CellRangeAddress.valueOf(value); sxssfSheet.setAutoFilter(c); } }); } /** * 功能描述: 自定義列寬 * * @param sxssfSheet * @param map */ public static void setColumnWidth(SXSSFSheet sxssfSheet, HashMap map) { if (map != null) { Iterator iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); Object key = entry.getKey(); Object val = entry.getValue(); sxssfSheet.setColumnWidth((int) key, (int) val * 512); } } } /** * 功能描述: excel 合並單元格 * * @param sheet * @param rowColList */ public static void setMergedRegion(SXSSFSheet sheet, ArrayList<Integer[]> rowColList) { if (rowColList != null && rowColList.size() > 0) { for (int i = 0; i < rowColList.size(); i++) { Integer[] str = rowColList.get(i); if (str.length > 0 && str.length == 4) { Integer firstRow = str[0]; Integer lastRow = str[1]; Integer firstCol = str[2]; Integer lastCol = str[3]; setMergedRegion(sheet, firstRow, lastRow, firstCol, lastCol); } } } } /** * 功能描述: 合並單元格 * * @param sheet * @param firstRow * @param lastRow * @param firstCol * @param lastCol */ public static void setMergedRegion(SXSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) { sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol)); } /** * 功能描述:下拉列表 * * @param sheet * @param dropDownListData * @param dataListSize */ public static void setDataValidation(SXSSFSheet sheet, List<String[]> dropDownListData, int dataListSize) { if (dropDownListData.size() > 0) { for (int col = 0; col < dropDownListData.get(0).length; col++) { Integer colv = Integer.parseInt(dropDownListData.get(0)[col]); setDataValidation(sheet, dropDownListData.get(col + 1), 1, dataListSize < 100 ? 500 : dataListSize, colv, colv); } } } /** * 功能描述:下拉列表 * * @param xssfWsheet * @param list * @param firstRow * @param lastRow * @param firstCol * @param lastCol */ public static void setDataValidation(SXSSFSheet xssfWsheet, String[] list, Integer firstRow, Integer lastRow, Integer firstCol, Integer lastCol) { DataValidationHelper helper = xssfWsheet.getDataValidationHelper(); CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol); DataValidationConstraint constraint = helper.createExplicitListConstraint(list); DataValidation dataValidation = helper.createValidation(constraint, addressList); dataValidation.createErrorBox(DataValidationError1, DataValidationError2); // 處理Excel兼容性問題 if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); } else { dataValidation.setSuppressDropDownArrow(false); } xssfWsheet.addValidationData(dataValidation); } /** * 功能描述:設置邊框 * * @param cellStyle * @param isBorder */ public static void setBorder(CellStyle cellStyle, Boolean isBorder) { if (isBorder) { cellStyle.setBorderBottom(BorderStyle.THIN); cellStyle.setBorderLeft(BorderStyle.THIN); cellStyle.setBorderTop(BorderStyle.THIN); cellStyle.setBorderRight(BorderStyle.THIN); } else { //添加白色背景,統一設置邊框后但不能選擇性去掉,只能通過背景覆蓋達到效果。 cellStyle.setBottomBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setTopBorderColor(IndexedColors.WHITE.getIndex()); } } public static void setBorderColor(CellStyle cellStyle, Boolean isBorder) { if (isBorder) { //添加白色背景,統一設置邊框后但不能選擇性去掉,只能通過背景覆蓋達到效果。 cellStyle.setBottomBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex()); cellStyle.setTopBorderColor(IndexedColors.WHITE.getIndex()); } } /** * 驗證是否是日期 * * @param strDate * @return */ public static boolean verificationDate(String strDate, String style) { Date date = null; if (style == null) { style = "yyyy-MM-dd"; } SimpleDateFormat formatter = new SimpleDateFormat(style); try { formatter.parse(strDate); } catch (Exception e) { return false; } return true; } public static String strToDateFormat(String strDate, String style, String expectDateFormatStr) { Date date = null; if (style == null) { style = "yyyy-MM-dd"; } // 日期字符串轉成date類型 SimpleDateFormat formatter = new SimpleDateFormat(style); try { date = formatter.parse(strDate); } catch (Exception e) { return null; } // 轉成指定的日期格式 SimpleDateFormat sdf = new SimpleDateFormat(expectDateFormatStr == null ? style : expectDateFormatStr); String str = sdf.format(date); return str; } }
ExcelTools:

package com.xxx.common.excel; import org.apache.poi.ss.util.CellReference; import java.math.BigDecimal; import java.util.List; /** * @ProjectName: git-dev * @Package: com.jfa.common.utils * @ClassName: ExcelTools * @Author: * @Description: excel 工具類 */ public class ExcelTools { /** * 設置公式 * * @param col: 需轉化成對應字母的列號 * @param startIndex: 開始計算行號/列號 * @param endIndex: 結束計算行號/列號 * @return: java.lang.String * @author: */ public static String setFormula(Integer col, Integer startIndex, Integer endIndex) { String colString = CellReference.convertNumToColString(col); String formula = CommonsUtils.GS.concat("=SUM(" + colString + startIndex + ":" + colString + endIndex + ")"); return formula; } /** * 設置公式 * * @param startCol: 需轉化成對應字母的列號 * @param endCol: 需轉化成對應字母的列號 * @param startIndex: 開始計算行號/列號 * @param endIndex: 結束計算行號/列號 * @return: java.lang.String * @author: */ public static String setFormula(Integer startCol, Integer endCol, Integer startIndex, Integer endIndex) { String startColString = CellReference.convertNumToColString(startCol); String endColString = CellReference.convertNumToColString(endCol); String formula = CommonsUtils.GS.concat("=SUM(" + startColString + startIndex + ":" + endColString + endIndex + ")"); return formula; } /** * 設置公式 * * @param col: 需轉化成對應字母的列號 * @param indexList: 續統計的行號 * @return: java.lang.String * @author: */ public static String setFormula(Integer col, List<Integer> indexList) { String colString = CellReference.convertNumToColString(col); StringBuffer sb = new StringBuffer(); if (indexList != null && indexList.size() > 0) { for (int n = 0; n < indexList.size(); n++) { sb.append(colString.concat(indexList.get(n).toString())); if (n < indexList.size() - 1) { sb.append("+"); } } } String formula = CommonsUtils.GS.concat("=SUM(" + sb.toString() + ")"); return formula; } /** * 設置空字符串 * * @param n: * @return: java.lang.String[] * @author: */ public static void setEmpty(List<Object> list, int n) { for (int i = 0; i < n; i++) { list.add(""); } } /** * 設置橫崗 * * @param n: * @return: java.lang.String[] * @author: */ public static void setBigDecimal(List<Object> list, int n) { for (int i = 0; i < n; i++) { list.add(BigDecimal.ZERO); } } /** * List轉String[] * * @param list: * @return: java.lang.String[] * @author: */ public static Object[] list2ObjArr(List<Object> list) { Object[] strArr = new Object[list.size()]; for (int i = 0; i < list.size(); i++) { strArr[i] = list.get(i); } return strArr; } /** * List轉String[] * * @param list: * @return: java.lang.String[] * @author: */ public static String[] list2StrArr(List<Object> list) { String[] strArr = new String[list.size()]; for (int i = 0; i < list.size(); i++) { strArr[i] = String.valueOf(list.get(i)); } return strArr; } /** * List轉String[] * * @param list: * @return: java.lang.String[] * @author: */ public static String[] list2StrArr2(List<String> list) { String[] strArr = new String[list.size()]; for (int i = 0; i < list.size(); i++) { strArr[i] = String.valueOf(list.get(i)); } return strArr; } }
會持續更新,先發個粗糙版的