摘要:是阿里巴巴對(duì)封裝的一個(gè)庫(kù),號(hào)稱(chēng)解決了的問(wèn)題,并且在使用上也更方便一些然而我在使用的時(shí)候發(fā)現(xiàn)還是有很多坑,其中一個(gè)比較頭疼的是對(duì)單個(gè)單元格樣式的設(shè)置。
EasyExcel是阿里巴巴對(duì)POI封裝的一個(gè)庫(kù),號(hào)稱(chēng)解決了POI的OOM問(wèn)題,并且在使用上也更方便一些Github:[](https://github.com/alibaba/ea...
然而我在使用的時(shí)候發(fā)現(xiàn)還是有很多坑,其中一個(gè)比較頭疼的是對(duì)單個(gè)單元格樣式的設(shè)置。EasyExcel提供了一個(gè)BaseRowModel作為每行數(shù)據(jù)的一個(gè)模型,并且其中有一個(gè)屬性cellStyleMap代表每列樣式的集合,本來(lái)我以為這個(gè)只要在自己定義模型的時(shí)候,也把CellStyle定義進(jìn)去就行了,然而,還是我想多了……定義了CellStyle并沒(méi)有什么卵用,這是第一個(gè)蛋疼的地方
/** * Excel基礎(chǔ)模型 * @author jipengfei */ public class BaseRowModel { /** * 每列樣式 */ private MapcellStyleMap = new HashMap (); public void addStyle(Integer row, CellStyle cellStyle){ cellStyleMap.put(row,cellStyle); } public CellStyle getStyle(Integer row){ return cellStyleMap.get(row); } public Map getCellStyleMap() { return cellStyleMap; } public void setCellStyleMap(Map cellStyleMap) { this.cellStyleMap = cellStyleMap; } }
后來(lái)測(cè)試半天,才發(fā)現(xiàn)創(chuàng)建CellStyle時(shí)必須通過(guò)一個(gè)Workbook對(duì)象來(lái)創(chuàng)建,而這個(gè)Workbook不能隨便新建一個(gè)對(duì)象完事兒,得用你當(dāng)前寫(xiě)入的Workbook來(lái)創(chuàng)建對(duì)應(yīng)的CellStyle樣式才能起作用。然而……事情并沒(méi)有那么簡(jiǎn)單,經(jīng)過(guò)我對(duì)源碼的反復(fù)查看,EasyExcel生成excel表的步驟是用一個(gè)ExcelWriter來(lái)寫(xiě)入數(shù)據(jù),并沒(méi)有提供獲取Workbook的方法,不知道什么原因讓阿里巴巴不提供這樣一個(gè)接口……這是第二個(gè)蛋疼的地方
既然沒(méi)有提供接口,那就只能用反射來(lái)硬剛了,下面就直接上代碼了
我這里是在開(kāi)始寫(xiě)數(shù)據(jù)之前就將每張表的CellStyle與每張表關(guān)聯(lián)起來(lái),再在后面的handler中獲取到這個(gè)CellStyle進(jìn)行設(shè)置
package edu.uddp.util; import com.alibaba.excel.EasyExcelFactory; import com.alibaba.excel.ExcelReader; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.ExcelBuilderImpl; import com.sun.corba.se.spi.orbutil.threadpool.Work; import edu.uddp.enums.CellStyleEnum; import edu.uddp.model.SignExcelRow; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFSheet; import java.io.*; import java.lang.reflect.Field; import java.util.*; /** * 生成Excel表 * * @author Juzi * @date 2018/12/23 12:37 * Blog https://juzibiji.top */ public class ExcelUtil { private static Map> cellStyles = new HashMap<>(); /** * 使用java對(duì)象模型創(chuàng)建excel,并使用handler * 生成Excel格式為xlsx * * @param path Excel生成路徑 * @param headLineMun 表頭占幾行 * @param data 傳入的鍵值對(duì)數(shù)據(jù)(key為sheet名,value為sheet數(shù)據(jù)) * @param handler 自定義的EasyExcel Handler,不使用傳入null即可 * @param columnWidthMap 每列寬度 * @throws IOException */ public static void createExcelWithModelAndHandler( String path, int headLineMun, Map > data, WriteHandler handler, Map columnWidthMap, List cellStyleEnums) throws IOException { File file = new File(path); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } OutputStream out = new FileOutputStream(path); // ExcelWriter用于導(dǎo)出Excel ExcelWriter writer = EasyExcelFactory.getWriterWithTempAndHandler(null, out, ExcelTypeEnum.XLSX, true, handler); // 構(gòu)造單元格樣式 Workbook workbook = getWorkbook(writer); cellStyles.put(workbook, createCellStyle(workbook, cellStyleEnums)); // sheet的序號(hào),從1開(kāi)始 int i = 1; // 遍歷傳入的sheet名和sheet數(shù)據(jù)來(lái)創(chuàng)建sheet for (Map.Entry > entry : data.entrySet()) { Sheet sheet = new Sheet(i, headLineMun, entry.getValue().get(0).getClass(), entry.getKey(), null); sheet.setColumnWidthMap(columnWidthMap); writer.write(entry.getValue(), sheet); i++; } // 必須要調(diào)用finish(),否則數(shù)據(jù)不會(huì)寫(xiě)入文件 writer.finish(); out.close(); } /** * **獲取workbook** * 因?yàn)镋asyExcel這個(gè)庫(kù)設(shè)計(jì)的原因 * 只能使用反射獲取workbook * * @param writer * @return */ private static Workbook getWorkbook(ExcelWriter writer) { Workbook workbook = null; try { Class> clazz1 = Class.forName("com.alibaba.excel.ExcelWriter"); Field[] fs = clazz1.getDeclaredFields(); for (Field field : fs) { // 要設(shè)置屬性可達(dá),不然會(huì)拋出IllegalAccessException異常 field.setAccessible(true); if ("excelBuilder".equals(field.getName())) { ExcelBuilderImpl excelBuilder = (ExcelBuilderImpl) field.get(writer); Class> clazz2 = Class.forName("com.alibaba.excel.write.ExcelBuilderImpl"); Field[] fs2 = clazz2.getDeclaredFields(); for (Field field2 : fs2) { field2.setAccessible(true); if ("context".equals(field2.getName())) { WriteContext context = (WriteContext) field2.get(excelBuilder); workbook = context.getWorkbook(); } } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return workbook; } public static Map createCellStyle(Workbook workbook, List cellStyleEnums) { Map map = new HashMap<>(); for (CellStyleEnum cellStyleEnum : cellStyleEnums) { if (cellStyleEnum.getNo() == 1) { CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setBorderBottom(BorderStyle.THIN); //下邊框 cellStyle.setBorderLeft(BorderStyle.THIN);//左邊框 cellStyle.setBorderTop(BorderStyle.THIN);//上邊框 cellStyle.setBorderRight(BorderStyle.THIN);//右邊框 cellStyle.setAlignment(HorizontalAlignment.CENTER); map.put(cellStyleEnum.getName(), cellStyle); } else if (cellStyleEnum.getNo() == 2) { CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setBorderBottom(BorderStyle.THIN); //下邊框 cellStyle.setBorderLeft(BorderStyle.THIN);//左邊框 cellStyle.setBorderTop(BorderStyle.THIN);//上邊框 cellStyle.setBorderRight(BorderStyle.THIN);//右邊框 cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); map.put(cellStyleEnum.getName(), cellStyle); } } return map; } public static Map > getCellStyles() { return cellStyles; } }
EasyExcel提供了一個(gè)WriteHandler,我們實(shí)現(xiàn)這個(gè)接口,就可以在每個(gè)單元格寫(xiě)入之后或者每行寫(xiě)入之前來(lái)進(jìn)行攔截(這個(gè)handler設(shè)計(jì)的也很蛋疼),并注入我們自己的業(yè)務(wù)邏輯(設(shè)置單元格樣式)。
package edu.uddp.handler; import com.alibaba.excel.event.WriteHandler; import edu.uddp.util.ExcelUtil; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFSheet; import java.util.Map; /** * 第三方庫(kù)EasyExcel的Handler * 教師端生成簽到歷史表Excel時(shí) * 將未簽到學(xué)生進(jìn)行特殊標(biāo)識(shí) * * @author Juzi * @since 2018/12/22 22:07 * Blog https://juzibiji.top */ public class SignRecordExcelHandler implements WriteHandler { @Override public void sheet(int i, Sheet sheet) { } @Override public void row(int i, Row row) { } @Override public void cell(int i, Cell cell) { // 獲取當(dāng)前workbook對(duì)應(yīng)的CellStyle集合 MapcellStyleMap = ExcelUtil.getCellStyles().get(cell.getSheet().getWorkbook()); // 從第二行開(kāi)始設(shè)置格式,第一行是表頭 if (cell.getRowIndex() > 0) { if (i == 7 && "未簽到".equals(cell.getStringCellValue())) { // 該生未簽到 for (int j = 0; j < 8; j++) { cell.getRow().getCell(j).setCellStyle(cellStyleMap.get("未簽到")); } } else if (i == 8 && "已簽到".equals(cell.getRow().getCell(7).getStringCellValue())) { // 該生已簽到 for (int j = 0; j < 9; j++) { cell.getRow().getCell(j).setCellStyle(cellStyleMap.get("已簽到")); } }else if(i == 8 && "未簽到".equals(cell.getRow().getCell(7).getStringCellValue())){ cell.setCellStyle(cellStyleMap.get("已簽到")); } } } }
上面有一些簡(jiǎn)單的邏輯處理,就不一一介紹了。
若文章有任何問(wèn)題,歡迎留言指出——作者博客:桔子筆記
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72841.html
摘要:背景小白今天閑著沒(méi)事,在公司摸魚(yú),以為今天有事無(wú)聊的一天,突然上頭說(shuō)小子,今天實(shí)現(xiàn)一下批量導(dǎo)入數(shù)據(jù)吧,當(dāng)時(shí)我的內(nèi)心是拒絕的,然后默默打開(kāi)。介紹框架本身并不支持讀取,所有讀取需要借助一些框架。 1 背景 小白今天閑著沒(méi)事,在公司摸魚(yú),以為今天有事無(wú)聊的一天,突然上頭說(shuō)小子,今天實(shí)現(xiàn)一下批量導(dǎo)入Excel數(shù)據(jù)吧,當(dāng)時(shí)我的內(nèi)心是拒絕的,然后默默打開(kāi)idea。 2 介紹 2.1 框架 java...
摘要:最快的方式測(cè)量屏幕上所有東西的尺寸,切圖必備收費(fèi),不貴,代碼沙箱,前端代碼在線編輯器,在線編程時(shí)代的到來(lái)。歡迎訂閱原周報(bào)改名為周刊更合適這個(gè)專(zhuān)欄每周末發(fā)布,同步更新在前端學(xué)堂微信公眾號(hào)。 周刊是個(gè)人本周內(nèi)看到的有意思的東西,或是技術(shù)學(xué)習(xí)的好文章或好資源,收集分享給大家。 開(kāi)源庫(kù)&框架動(dòng)向 Java 11 (LTS) 版本正式發(fā)布 TypeScript 發(fā)布 3.1.1 版本 Crea...
摘要:消費(fèi)之后,多線程處理文件導(dǎo)出,生成文件后上傳到等文件服務(wù)器。前端直接查詢(xún)并且展現(xiàn)對(duì)應(yīng)的任務(wù)執(zhí)行列表,去等文件服務(wù)器下載文件即可。這客戶體驗(yàn)不友好,而且網(wǎng)絡(luò)傳輸,系統(tǒng)占用多種問(wèn)題。拓展閱讀導(dǎo)出最佳實(shí)踐框架 產(chǎn)品需求 產(chǎn)品經(jīng)理需要導(dǎo)出一個(gè)頁(yè)面的所有的信息到 EXCEL 文件。 需求分析 對(duì)于 excel 導(dǎo)出,是一個(gè)很常見(jiàn)的需求。 最常見(jiàn)的解決方案就是使用 poi 直接同步導(dǎo)出一個(gè) exc...
摘要:命名規(guī)則樣式類(lèi)名全部用小寫(xiě),首字符必須是字母,禁止數(shù)字或其他特殊字符。其他禁止使用在樣式表命名中,一律使用命名。什么是命名空間通過(guò)統(tǒng)一的命名規(guī)范定義命名的范圍,成為命名空間。1 前端開(kāi)發(fā)命名規(guī)范 1.1 為什么要制定CSS命名規(guī)范 統(tǒng)一的命名規(guī)范,便于多人開(kāi)發(fā)維護(hù)時(shí)代碼統(tǒng)一,減少項(xiàng)目溝通和交接的成本,增加代碼的語(yǔ)義化。 1.2 CSS命名規(guī)則 樣式類(lèi)名全部用小寫(xiě),首字符必須是字母,禁止數(shù)...
摘要:因?yàn)槎撕鸵苿?dòng)端布局差異較大,所以我將兩端布局分開(kāi)講,本文章將針對(duì)端的布局進(jìn)行講解,以下代碼只寫(xiě)關(guān)鍵代碼。為了提高網(wǎng)頁(yè)性能,考慮到,表格元素盡量少用,有其他選擇的情況盡量用其他布局。 前言 此文章是 解剖CSS布局原理 的續(xù)集,之前那篇文章講的都是理論,本文章講具體的實(shí)例,根據(jù)自己對(duì)布局的理解與開(kāi)發(fā)經(jīng)驗(yàn)分為以下幾類(lèi)。 因?yàn)镻C端和移動(dòng)端布局差異較大,所以我將兩端布局分開(kāi)講,本文章將針對(duì)P...
閱讀 2761·2021-11-16 11:45
閱讀 1669·2021-09-26 10:19
閱讀 2062·2021-09-13 10:28
閱讀 2822·2021-09-08 10:46
閱讀 1547·2021-09-07 10:13
閱讀 1544·2019-08-30 13:50
閱讀 1383·2019-08-30 11:17
閱讀 1463·2019-08-29 13:18