Java POI 資料視覺化(原創)
一:Java POI 基本簡介
ApachePOI(PoorObfuscationImplementation)是用Java編寫的免費開源的跨平臺的JavaAPI,ApachePOI提供API給Java程式對Microsoft Office格式檔案讀和寫的功能,其中使用最多的就是使用POI操作Excel檔案
它是建立和維護操作各種符合OfficeOpenXML(OOXML)標準和微軟的OLE2複合文件格式(OLE2)的JavaAPI。用它可以使用Java讀取和建立,修改MSExcel檔案.而且,還可以使用Java讀取和建立MSWord和MSPowerPoint檔案。ApachePOI提供Java操作Excel解決方案(適用於Excel97-2008)
POI發行版可以對許多文件檔案格式的支援。這種支援是在幾個JAR檔案中提供的。並不是每種格式都需要所有的JAR。下面我介紹一下POI元件、Maven儲存庫標記和專案的Jar檔案之間的關係 【詳細POI API 】
元件 操作格式 依賴 說明 XSSF Excel XLSX poi-ooxml XSLF PowerPoint PPTX poi-ooxml XWPF Word DOCX poi-ooxml XDGF Visio VSDX poi-ooxml POIFS OLE2 Filesystem poi 需要處理基於OLE2/POIFS的檔案 HPSF OLE2 Property Sets poi HSSF Excel XLS poi 僅支援HSSF(只可以操作XLS) DDF Escher common drawings poi HSLFPowerPoint PPT poi-scratchpad HWPF Word DOC poi-scratchpad HDGF Visio VSD poi-scratchpad HPBF Publisher PUB poi-scratchpad HSMF Outlook MSG poi-scratchpad HWMF WMF drawings poi-scratchpad 特殊: Common SL: PPT和PPTX poi-scratchpad 和 poi-ooxml SL程式碼在核心POIjar中,但是實現的是poi-scratchpad和poi-ooxml Common SS: XLS和XLSX poi-ooxml WorkbookFactory和其它實現都需要poi-ooxml,而不僅僅是核心po OpenXML4J: OOXML poi-ooxml和poi-ooxml-lite或poi-ooxml-full
maven關於POI操作的整套依賴:
<!--設定maven使用什麼版本的jdk解析編譯 注意4.1.2版本的jdk編譯要是1.8及以上 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.9</maven.compiler.source> <maven.compiler.target>1.9</maven.compiler.target> </properties> <dependencies> <!--前3個座標按照上表搭配--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>4.1.2</version> </dependency> <!--poi其它依賴包,正常使用可以不用新增--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-examples</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-excelant</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> </dependencies>POI資料視覺化maven依賴
二:POI操作之XSSF(基本)
XSSF是我們最常用的api了,它可以操作我們最常用的Excel XLSX表格,而Excel XLS老闆格式的表格慢慢淡出了我們的視線,因為老版格式的表格只能存在65535行,而XLSX就不會出現這個問題,我針對XSSF詳細介紹
1:簡單建立xlsx之流程瞭解
操作XLSX檔案我們得使用XSSFWorkbook類來構建我們的工作簿,其實查詢繼承關係,這一類的工作簿都繼承自Workbook介面,它實現了HSSFWorkbook,SXSSFWorkbook,XSSFWorkbook等
public static void main(String[] args) throws IOException { //①:建立工作簿 Workbook workbook = new XSSFWorkbook(); //②:建立工作表 開啟Xlsx檔案最下邊的sheet1、sheet2工作表 Sheet sheet = workbook.createSheet("螞蟻小哥日常統計"); //③:通過下面2行程式碼建立一個座標為0,0 並寫上內容 對應Excel 1,1 位置 //建立行 當前建立的為0行 對應Excel第一行 Row row = sheet.createRow(0); //建立列 當前建立列為0列 對應Excel第一列 Cell cell = row.createCell(0); //寫入內容 今天買菜花300 cell.setCellValue("今天買菜花300"); //或者鏈式呼叫寫法:sheet.createRow(0).createCell(0).setCellValue("今天買菜花300"); //④:把構建的記憶體資料寫入到磁碟 確保有這個磁碟 OutputStream out = new FileOutputStream("h://test.xlsx"); workbook.write(out); //⑤:關閉資源 out.close(); workbook.close(); }建立xlsx基本流程
2:xlsx檔案建立日期型別及不同型別的單元格
對於寫出的資料中包含日期型別的話,我們就得進行樣式轉換其中操作樣式的 CellStyle 介面方法,它內部定義了各種樣式操作,如邊框顏色、對齊方式、字型、顏色等等,但是我要介紹的是樣式裡的 setDataFormat 方法,可是它接收的是short引數,這就使得我要介紹 CreationHelper介面,它裡面的createDataFormat方法可以建立DataFormat例項並返回short引數
public static void main(String[] args) throws IOException { //建立工作簿 Workbook workbook = new XSSFWorkbook(); //建立工作表 不指定名則預設Sheet(0~N) Sheet sheet = workbook.createSheet(); //建立第一行 Row row = sheet.createRow(0); //建立第一列 Cell cellA = row.createCell(0); //在0,0的位置寫入日期資料 cellA.setCellValue(new Date()); //返回一個物件,該物件處理XSSF各種例項的具體類的例項化 CreationHelper creationHelper = workbook.getCreationHelper(); //建立新的DataFormat例項。獲取與給定格式字串匹配的格式索引,在需要時建立一個新的格式條目。 short format = creationHelper.createDataFormat().getFormat("yyyy-MM-dd"); //通過Workbook來獲取一個樣式操作類來對已有的表設定樣式 CellStyle cellStyle = workbook.createCellStyle(); //把日期格式設定噹噹前樣式cellStyle中 cellStyle.setDataFormat(format); //在1,1位置寫入日期資料 並對1,1位置寫入樣式 Cell cellB = row.createCell(1); cellB.setCellValue(new Date()); cellB.setCellStyle(cellStyle); //把構建的記憶體資料寫入到磁碟 OutputStream out = new FileOutputStream("h://test1.xlsx"); workbook.write(out); //關閉資源 out.close(); workbook.close(); }插入日期型別及轉換
public static void main(String[] args) throws IOException { //建立工作簿 Workbook workbook = new XSSFWorkbook(); //建立工作表 不指定名則預設Sheet(0~N) Sheet sheet = workbook.createSheet(); Row row = sheet.createRow(0); row.createCell(0).setCellValue("我是字串"); row.createCell(1).setCellValue(25.5555); row.createCell(2).setCellValue(true); //對0,3 0,4 時間類和日曆類 row.createCell(3).setCellValue(new Date()); row.createCell(4).setCellValue(Calendar.getInstance()); //把構建的記憶體資料寫入到磁碟 OutputStream out = new FileOutputStream("h://test1.xlsx"); workbook.write(out); //關閉資源 out.close(); workbook.close(); }建立不同型別單元格
3:總結上面1~2節知識來個總結
學完基礎的我們就可以自己動手寫個簡單的建立xlsx格式的檔案了,再接下來的幾節我將建立更好看的樣式表格及讀xlsx檔案
public static void main(String[] args) throws IOException { //建立資料來源 Object[] title = {"ID", "姓名", "零花錢", "生日", "是否被刪除"}; Object[] stu1 = {"tx001", "許齡月", 66.66, new Date(), true}; Object[] stu2 = {"tx002", "周星馳", 66.66, new Date(213465654L), false}; List<Object[]> list = new ArrayList<>(); list.add(title); list.add(stu1); list.add(stu2); //建立工作簿 Workbook workbook = new XSSFWorkbook(); //建立工作表 Sheet sheet = workbook.createSheet("總結"); //迴圈建立 for (int r = 0; r < list.size(); r++) { //建立行 Row row = sheet.createRow(r); for (int c = 0; c < list.get(r).length; c++) { if (r == 0) { //標題寫入 //建立列 Cell cell = row.createCell(c); cell.setCellValue(list.get(r)[c].toString()); } else { Object o = list.get(r)[c]; //獲取每個單元格資料然後匹配型別 //建立列 Cell cell = row.createCell(c); //此時資料是要改變樣式 if (o instanceof Date) { CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("yyyy-mm-dd")); cell.setCellValue((Date) list.get(r)[c]); cell.setCellStyle(cellStyle); } else { //寫入正文 cell.setCellValue(list.get(r)[c].toString()); } } } } //寫出及關閉 OutputStream out = new FileOutputStream("h:\\test02.xlsx"); workbook.write(out); out.close(); workbook.close(); }小練習
4:從xlsx檔案中遍歷資料
遍歷資料可謂是重點了,我們得建立一個工作簿並傳入xlsx檔案,其中獲取起始行和結尾行則使用 getFirstRowNum 和 getLastRowNum 方法,但是獲取的每個單元格表格資料型別不同則需要使用型別匹配
public static void main(String[] args) throws IOException { //建立工作簿並傳入一個真實存在的檔案 Workbook workbook = new XSSFWorkbook("h:\\abc.xlsx"); //獲取檔案的第一個工作表 Sheet sheetAt = workbook.getSheetAt(0); //獲取工作表中的起始行 int rowStart = Math.max(0, sheetAt.getFirstRowNum()); //獲取工作表中的結束行,如果大於21行則按照21行讀 0開始-20 int rowEnd = Math.min(20, sheetAt.getLastRowNum()); //迴圈行rowStart ~ rowEnd for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) { //建立行例項 Row row = sheetAt.getRow(rowNum); //為空則全部結束 if (row == null) { continue; } //不為空則建立每行的列 lastColumn 如果讀到的行數大於11行則按照11行讀取 int lastColumn = Math.min(10, row.getLastCellNum()); //迴圈每行的列0 ~ lastColumn for (int colNum = 0; colNum < lastColumn; colNum++) { //建立列的例項 Cell cell = row.getCell(colNum); //列為空的話就跳出迴圈去遍歷下一列 if (cell == null) { continue; } else { //switch來匹配型別 ,因為表格的每個型別不一樣 switch (cell.getCellType()) { case NUMERIC: //數字型別 (這個相對複雜,還要判斷是數字還是日期) //通過查詢StylesSource獲取格式字串的內容 String formatString = cell.getCellStyle().getDataFormatString(); //判斷當前的字串形式的內容是否以m/d/yy的日期格式 if (formatString.equals("m/d/yy")) { System.out.print(cell.getDateCellValue() + " | "); } else { System.out.print(cell.getNumericCellValue() + " | "); } break; case STRING: //字串型別 System.out.print(cell.getStringCellValue() + " | "); break; case BOOLEAN: //真假值 System.out.print(cell.getBooleanCellValue() + " | "); break; case ERROR: //錯誤型別 System.out.print(cell.getErrorCellValue() + " | "); break; case BLANK: //空資料 System.out.print("空資料" + " | "); break; case FORMULA: //計算型別 System.out.print(cell.getCellFormula() + " | "); case _NONE: //未知型別 System.out.print("未知型別" + " | "); } } } System.out.println(); } workbook.close(); }遍歷查詢全部單元格及資料
三:POI操作之XSSF(樣式)
1:設定單元格的對齊方式
說到對齊方式我們就得談談2個列舉類了HorizontalAlignment(水平對齊)VerticalAlignment(垂直對齊),但是我們設定對齊方式還得藉助CellStyle樣式介面內部的實現類完成,通過 setAlignment 和 setVerticalAlignment 方法來對單元格設定對齊方式
public static void main(String[] args) throws IOException { //建立工作簿和建立工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); //設定行 Row row = sheet.createRow(0); //設定行高度 row.setHeightInPoints(60); //建立0,1單元格 Cell cell = row.createCell(1); cell.setCellValue("啦啦"); //建立樣式 CellStyle cellStyle = workbook.createCellStyle(); //設定單元格的水平對齊型別。 此時水平居中 cellStyle.setAlignment(HorizontalAlignment.CENTER); //設定單元格的垂直對齊型別。 此時垂直靠底邊 cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM); //把樣式設定到單元格上 cell.setCellStyle(cellStyle); //寫出及關閉 OutputStream out = new FileOutputStream("h:\\test03.xlsx"); workbook.write(out); out.close(); workbook.close(); }單元格的對齊方式程式碼演示
2:設定單元格的邊框樣式及邊框的顏色
感覺這個用處並不大,要設定漂亮樣式可以使用一番 主要是通過CellStyle來設定邊框和邊框顏色,具體的就得參照BorderStyle、IndexedColors這2個列舉類來獲取具體的樣式
public static void main(String[] args) throws IOException { //建立工作簿和建立工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); //設定行 Row row = sheet.createRow(1); //為了可以看到樣式 特地設定大高度 row.setHeightInPoints(60); //建立0,1單元格 Cell cell = row.createCell(1); cell.setCellValue("啦"); //建立樣式 CellStyle cellStyle = workbook.createCellStyle(); //通過set設定邊框樣式及邊框顏色 反之通過get可以獲取設定的樣式 cellStyle.setBorderBottom(BorderStyle.DOTTED); cellStyle.setBottomBorderColor(IndexedColors.GREEN.getIndex()); cellStyle.setBorderTop(BorderStyle.THIN); cellStyle.setTopBorderColor(IndexedColors.CORAL.getIndex()); cellStyle.setBorderLeft(BorderStyle.THIN); cellStyle.setLeftBorderColor(IndexedColors.RED.getIndex()); cellStyle.setBorderRight(BorderStyle.DASH_DOT_DOT); cellStyle.setRightBorderColor(IndexedColors.AQUA.getIndex()); //別忘了把剛才這些設定的樣式設定到單元格上 cell.setCellStyle(cellStyle); //寫出及關閉 OutputStream out = new FileOutputStream("h:\\test03.xlsx"); workbook.write(out); out.close(); workbook.close(); }設定單元格邊框樣式及顏色
3:設定單元格填色
有時候我們會對單元格前景/背景進行色彩設定,以及對單元格的填充圖案,這時候我們就會用到樣式類裡面的填充方法,具體看程式碼
public static void main(String[] args) throws IOException { //建立工作簿和建立Sheet0工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); //設定第一列的寬度是20個字元寬度 sheet.setColumnWidth(1, 20*256); //建立第一行 Row row = sheet.createRow(1); row.setHeightInPoints(60); //建立樣式物件 CellStyle style = workbook.createCellStyle(); //設定背景色 style.setFillBackgroundColor(IndexedColors.AQUA.getIndex()); //設定填充圖案(紋理)填充圖案預設為黑色 style.setFillPattern(FillPatternType.BIG_SPOTS); //此時我設定填充圖案(前景色為紅色) style.setFillForegroundColor(IndexedColors.RED.getIndex()); //建立行(1,1)並設定文字加樣式 Cell cell = row.createCell(1); cell.setCellValue("螞蟻小哥"); cell.setCellStyle(style); //建立流並寫出檔案關閉流 OutputStream out = new FileOutputStream("h:\\test3.xlsx"); workbook.write(out); out.close(); workbook.close(); }紋理/背景/紋理顏色設定
<!--Enum FillPatternType:--> <!--Enum:IndexedColors:--> 常量名 漢譯 常量名 漢譯 常量名 漢譯 常量名 漢譯 ALT_BARS: 寬點 BLACK: 黑色 GREEN: 綠色 DARK_RED:深紅色 BIG_SPOTS: 大斑點 BLACK1: 黑色1 VIOLET: 紫羅蘭 DARK_BLUE: 深藍色 BRICKS: 磚狀佈局 WHITE: 白色 TEAL: 藍綠色 DARK_YELLOW:深黃色 DIAMONDS: 鑽石 WHITE1: 白色1 MAROON: 栗色 DARK_GREEN: 深綠色 FINE_DOTS: 小細點 RED: 紅色 ROSE: 粉紅色 DARK_TEAL: 深青色 LEAST_DOTS: 最小點 RED1: 紅色1 AQUA: 水綠色 LIGHT_GREEN: 淺綠色 LESS_DOTS: 少點 BRIGHT_GREEN:亮綠色 LIME: 石灰色 LIGHT_YELLOW: 淺黃色 NO_FILL: 無背景 BRIGHT_GREEN1:亮綠色1 GOLD: 金 LIGHT_ORANGE:淡橙色 SOLID_FOREGROUND: 實填 BLUE: 藍色 LAVENDER:淡紫色 LIGHT_BLUE: 淺藍色 SPARSE_DOTS: 稀疏點 BLUE1: 藍色1 BROWN: 棕色 LIGHT_CORNFLOWER_BLUE:淺矢車菊藍 SQUARES: 正方形 YELLOW: 黃色 PLUM: 紫紅色 PALE_BLUE: 淡藍色 THICK_BACKWARD_DIAG:厚厚的後向對角線 YELLOW1: 黃色1 INDIGO: 靛藍色 SEA_GREEN: 海綠色 THICK_FORWARD_DIAG: 厚正面對角線 PINK: 粉紅 TAN: 棕黃色 BLUE_GREY: 藍灰 THICK_HORZ_BANDS: 厚水平帶 PINK1: 粉色1 ORCHID: 蘭花色 SKY_BLUE: 天空藍色 THICK_VERT_BANDS: 厚垂直帶 TURQUOISE: 青綠色 CORAL: 珊瑚色 GREY_25_PERCENT:灰25% THIN_BACKWARD_DIAG: 薄後向對角線 TURQUOISE1: 青綠色1 ROYAL_BLUE:皇家藍 GREY_40_PERCENT:灰40% THIN_FORWARD_DIAG: 細正對角線 LEMON_CHIFFON: 檸檬雪紡 ORNFLOWER_BLUE:矢車菊藍 GREY_50_PERCENT:灰50% THIN_HORZ_BANDS: 薄水平帶 LIGHT_TURQUOISE:淺青綠色 ORANGE: 桔黃色的 GREY_80_PERCENT:灰80% THIN_VERT_BANDS: 薄垂直帶 LIGHT_TURQUOISE1:淺青綠色1 OLIVE_GREEN: 橄欖綠 AUTOMATIC:自然色關於FillPatternType和IndexedColors列舉類的中文漢譯
4:合併單元格
有時候我們要設定單元格的合併,這個時候我們就可以使用addMergedRegion方法完成
public static void main(String[] args) throws IOException { //建立工作簿和建立Sheet0工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); //設定單元格合併 //第一個引數和第二個引數設定左位置(1,1) 0開始 //第三個引數和第四個引數設定右位置(1,5) 0開始 //連線2點的範圍的形狀就是單元格合併的範圍 注意只是合併單元格 不能跨行!!想單元格高點就設定高度 sheet.addMergedRegion(new CellRangeAddress(1,1,1,5)); //建立行 Row row = sheet.createRow(1); //建立列此時為1,1 併為單元格設定資訊 Cell cell = row.createCell(1); cell.setCellValue("螞蟻小哥"); //建立流並寫出檔案關閉流 OutputStream out = new FileOutputStream("h:\\test3.xlsx"); workbook.write(out); out.close(); workbook.close(); }合併單元格練習
5:字型樣式設定
對字型的設定我們得通過工作簿先建立字型樣式類,然後再進行字型的設定
public static void main(String[] args) throws IOException { //建立工作簿和建立Sheet0工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); //建立行 Row row = sheet.createRow(1); //建立字型類 Font font = workbook.createFont(); //設定字型顏色 font.setColor(IndexedColors.RED1.getIndex()); //設定字型 true粗體(預設) false細 font.setBold(false); //設定字型大小 font.setFontHeightInPoints((short) 60); //設定字型名 如楷體,微軟雅黑....中文和英文表示都行 font.setFontName("楷體"); //傾斜設定 font.setItalic(true); //設定刪除線 font.setStrikeout(true); //建立樣式類 CellStyle cellStyle = workbook.createCellStyle(); //樣式設定font樣式 cellStyle.setFont(font); //建立列此時為1,1 併為單元格設定資訊 Cell cell = row.createCell(1); cell.setCellValue("螞蟻小哥"); cell.setCellStyle(cellStyle); //建立流並寫出檔案關閉流 OutputStream out = new FileOutputStream("h:\\test3.xlsx"); workbook.write(out); out.close(); workbook.close(); }字型樣式設定
6:使用函式方便構建樣式及單元格合併
通過上面的樣式建立和單元格的建立我們發現,每次設定樣式都要建立物件,麻煩,還浪費記憶體,其實ReginUtil(區域工具)CellUtil(樣式工具)可以很快構建我們的樣式,可以簡寫很多程式碼
public static void main(String[] args) throws IOException { //建立工作簿和建立Sheet0工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("new sheet"); //建立2行 對應表中的第1行和第2行 0開始 Row row = sheet.createRow(1); Row row2 = sheet.createRow(2); //建立1,1的單元格 Cell cell = row.createCell(1); cell.setCellValue("螞蟻小哥"); //此類可以建立單元格的範圍 B2(1,1):E5(4,4) CellRangeAddress region = CellRangeAddress.valueOf("B2:E5"); //傳遞給合併單元格方法裡 sheet.addMergedRegion(region); //設定四邊樣式及顏色 但是得傳遞Sheet和CellRangeAddress RegionUtil.setBorderBottom(BorderStyle.MEDIUM_DASHED, region, sheet); RegionUtil.setBorderTop(BorderStyle.MEDIUM_DASHED, region, sheet); RegionUtil.setBorderLeft(BorderStyle.MEDIUM_DASH_DOT, region, sheet); RegionUtil.setBorderRight(BorderStyle.MEDIUM_DASHED, region, sheet); RegionUtil.setBottomBorderColor(IndexedColors.BLUE.getIndex(), region, sheet); RegionUtil.setTopBorderColor(IndexedColors.AQUA.getIndex(), region, sheet); RegionUtil.setLeftBorderColor(IndexedColors.RED.getIndex(), region, sheet); RegionUtil.setRightBorderColor(IndexedColors.AQUA.getIndex(), region, sheet); //建立樣式類 CellStyle style = workbook.createCellStyle(); //設定空格數以縮排單元格中的文字 style.setIndention((short) 4); CellUtil.createCell(row, 8, "my name is ant", style); Cell cell2 = CellUtil.createCell(row2, 8, "阿三大蘇打"); //設定居中 CellUtil.setAlignment(cell2, HorizontalAlignment.CENTER); //建立流並寫出檔案關閉流 OutputStream out = new FileOutputStream("h:\\test3.xlsx"); workbook.write(out); out.close(); workbook.close(); }使用函式方法來構建樣式及區域合併
.