1. 程式人生 > >Java進階學習第二十九天(POI操作Excel)

Java進階學習第二十九天(POI操作Excel)

一、POI操作Excel

1、Excel簡介
一個excel檔案就是一個工作簿workbook,一個工作簿中可以建立多張工作表sheet,而一個工作表中包含多個單元格Cell,這些單元格都是由列(Column)行(Row)組成,列用大寫英文字母表示,從A開始到Z共26列,然後再從AA到AZ又26列,再從BA到BZ再26列以此類推。行則使用數字表示,例如;A3 表示第三行第一列,E5表示第五行第五列。

2、POI工具包
JAVA中操作Excel的有兩種比較主流的工具包: JXL 和 POI 。
① JXL只能操作Excel 95, 97, 2000也即以.xls為字尾的excel
② POI可以操作Excel 95及以後的版本,即可操作字尾為 .xls 和 .xlsx兩種格式的excel

3、POI全稱 Poor Obfuscation Implementation,利用POI介面可以通過JAVA操作Microsoft office 套件工具的讀寫功能。
① 官網:http://poi.apache.org
② POI支援office的所有版本,並且在接下來的演示中需要從前端頁面匯入使用者上傳的版本不確定的excel檔案,所以選擇POI來講解。

4、在官網下載完後,開啟“poi-bin-3.10.1-20140818”獲取操作excel需要的jar包,並將這些jar包複製到專案中。
對於只操作2003 及以前版本的excel,只需要poi-3.10.1-20140818.jar ,如果需要同時對2007及以後版本進行操作則需要複製poi-ooxml-3.10.1-20140818.jar

poi-ooxml-schemas-3.10.1-20140818.jar,以及複製在ooxml-lib目錄下的xmlbeans-2.6.0.jardom4j-1.6.1.jar

5、POI 簡單操作
在POI包中有如下幾個主要物件和Excel的幾個物件對應

POI Excel
HSSFWorkbook、XSSFWorkbook Excel 工作簿workbook
HSSFSheet、XSSFSheet Excel 工作表 sheet
HSSFRow、XSSFRow Excel 行
HSSFCell、XSSFCell Excel 單元格
public class TestPOI2Excel {
	@Test
	// 寫入資料到Excel03
	public void testWrite03Excel() throws Exception {
		//1、建立工作簿
		HSSFWorkbook workbook = new HSSFWorkbook();
		//2、建立工作表
		HSSFSheet sheet = workbook.createSheet("hello world");//指定工作表名
		//3、建立行;建立第3行
		HSSFRow row = sheet.createRow(2);
		//4、建立單元格;建立第3行第3列
		HSSFCell cell = row.createCell(2);
		cell.setCellValue("Hello World");
		//輸出到硬碟
		FileOutputStream outputStream = new FileOutputStream("D:\\itcast\\測試.xls");
		//把excel輸出到具體的地址
		workbook.write(outputStream);
		workbook.close();
		outputStream.close();
	}
	
	@Test
	// 寫入資料到Excel07
	public void testWrite07Excel() throws Exception {
		//1、建立工作簿
		XSSFWorkbook workbook = new XSSFWorkbook();
		//2、建立工作表
		XSSFSheet sheet = workbook.createSheet("hello world");//指定工作表名
		//3、建立行;建立第3行
		XSSFRow row = sheet.createRow(2);
		//4、建立單元格;建立第3行第3列
		XSSFCell cell = row.createCell(2);
		cell.setCellValue("Hello World");
		//輸出到硬碟
		FileOutputStream outputStream = new FileOutputStream("D:\\itcast\\測試.xlsx");
		//把excel輸出到具體的地址
		workbook.write(outputStream);
		workbook.close();
		outputStream.close();
	}

	@Test
	// 從Excel03讀取資料
	public void testRead03Excel() throws Exception {
		FileInputStream inputStream = new FileInputStream("D:\\itcast\\測試.xls");
		//1、讀取工作簿
		HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
		//2、讀取第一個工作表
		HSSFSheet sheet = workbook.getSheetAt(0);
		//3、讀取行;讀取第3行
		HSSFRow row = sheet.getRow(2);
		//4、讀取單元格;讀取第3行第3列
		HSSFCell cell = row.getCell(2);
		System.out.println("第3行第3列單元格的內容為:" + cell.getStringCellValue());	
		workbook.close();
		inputStream.close();
	}
	
	@Test
	// 從Excel07讀取資料
	public void testRead07Excel() throws Exception {
		FileInputStream inputStream = new FileInputStream("D:\\itcast\\測試.xlsx");
		//1、讀取工作簿
		XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
		//2、讀取第一個工作表
		XSSFSheet sheet = workbook.getSheetAt(0);
		//3、讀取行;讀取第3行
		XSSFRow row = sheet.getRow(2);
		//4、讀取單元格;讀取第3行第3列
		XSSFCell cell = row.getCell(2);
		System.out.println("第3行第3列單元格的內容為:" + cell.getStringCellValue());
		workbook.close();
		inputStream.close();
	}
	
	@Test
	// 從Excel03或07讀取資料
	public void testRead03And07Excel() throws Exception {
		String fileName = "D:\\itcast\\測試.xlsx";
		if(fileName.matches("^.+\\.(?i)((xls)|(xlsx))$")){//判斷是否excel文件
			boolean is03Excel = fileName.matches("^.+\\.(?i)(xls)$");
			FileInputStream inputStream = new FileInputStream(fileName);
			//1、讀取工作簿
			Workbook workbook = is03Excel ?new HSSFWorkbook(inputStream):new XSSFWorkbook(inputStream);
			//2、讀取第一個工作表
			Sheet sheet = workbook.getSheetAt(0);
			//3、讀取行;讀取第3行
			Row row = sheet.getRow(2);
			//4、讀取單元格;讀取第3行第3列
			Cell cell = row.getCell(2);
			System.out.println("第3行第3列單元格的內容為:" + cell.getStringCellValue());
			workbook.close();
			inputStream.close();
		}
	}	
}

從POI-API文件中我們瞭解到:
① HSSFWorkbook 和 XSSFWorkbook 都實現了Workbook介面;
② HSSFSheet 和 XSSFSheet 實現了Sheet介面;
③ HSSFRow 和 XSSFRow 實現了Row介面;
④ HSSFCell 和 XSSFCell 實現了Cell介面。
因為這兩類處理物件共同實現了對應的同一介面,屆時將大大方便和簡化了同時處理不同格式的excel檔案的編碼工作。如:在處理03和07版本的excel檔案時利用統一的介面就可以做到分析兩個版本的excel資料。

6、格式化Excel
在POI中可以利用格式化物件來格式化excel文件,也即設定excel內容的樣式。POI中主要的格式化物件常用的有合併單元格、設定單元格字型、邊框,背景顏色等。
① 合併單元格
在POI中有一個CellRangeAddress物件,中文直譯是【單元格範圍地址】,主要用於在單元格的合併上,這個物件的構造方法CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) 有4個引數,分別表示(起始行號,終止行號, 起始列號,終止列號), 設定這個物件中要合併的單元格範圍後,工作表物件sheet呼叫方法addMergedRegion(CellRangeAddress region) ,將上述設定的CellRangeAddress物件作為引數傳入即可合併單元格。
【注意】合併單元格後,單元格的名稱是第一個單元格,即上面中合併了第二行的第二列到第五列,合併後的單元格叫B2,而其它被合併的單元格已經無效了,不能對無效單元格設定值,如果進行了設定將不顯示
② 設定單元格樣式
首先要設定單元格樣式則要先初始化POI中的單元格樣式物件HSSFCellStyle,然後在樣式物件中設定不同的樣式(內容位置、字型、背景、顏色、邊框等)。單元格樣式是由工作簿workbook建立的,一個工作簿可以建立多個樣式。
◇ 設定單元格內容位置;設定水平位置 setAlignment(short align) ,設定垂直位置setVerticalAlignment(short align)
◇ 設定單元格字型;POI中的字型物件為HSSFFont,字型是由工作簿建立,可以用於多個單元格上。
◇ 設定單元格背景色。

@Test
	public void testExcelStyle() throws Exception {
		//1、建立工作簿
		HSSFWorkbook workbook = new HSSFWorkbook();
		//1.1、建立合併單元格物件;合併第3行的第3列到第5列
		CellRangeAddress cellRangeAddress = new CellRangeAddress(2, 2, 2, 4);//起始行號,結束行號,起始列號,結束列號
		//1.2、建立單元格樣式
		HSSFCellStyle style = workbook.createCellStyle();
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中
		//1.3、建立字型
		HSSFFont font = workbook.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//加粗字型
		font.setFontHeightInPoints((short) 16);//設定字型大小
		//載入字型
		style.setFont(font);
		//單元格背景
		//設定背景填充模式
		style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		//設定填充背景色
		style.setFillBackgroundColor(HSSFColor.YELLOW.index);
		//設定填充前景色
		style.setFillForegroundColor(HSSFColor.RED.index);
		
		//2、建立工作表
		HSSFSheet sheet = workbook.createSheet("Hello World");//指定工作表名
		//2.1、載入合併單元格物件
		sheet.addMergedRegion(cellRangeAddress);
		//3、建立行;建立第3行
		HSSFRow row = sheet.createRow(2);
		//4、建立單元格;建立第3行第3列
		HSSFCell cell = row.createCell(2);
		//載入樣式
		cell.setCellStyle(style);
		cell.setCellValue("Hello World!");
		//輸出到硬碟
		FileOutputStream outputStream = new FileOutputStream("D:\\itcast\\測試.xls");
		//把excel輸出到具體的地址
		workbook.write(outputStream);
		workbook.close();
		outputStream.close();
	}	

7、POI應用案例
【需求1】在專案資料庫中,有一張使用者表user,裡面有系統的使用者資料;現在需要將這個使用者表的資料匯出到excel中提供使用者下載。要求excel要有個一個主標題,各個列名稱。
【分析】① 從資料庫中讀取使用者資料;② 建立excel並寫入資料; ③ 將excel輸出到瀏覽器提供使用者下載。
【編碼】利用POI中的HSSFWorkbook建立一個excel,再利用 HSSFSheet 建立一個sheet,HSSFRow/HSSFCell建立行/列。建立的excel第一行標題(CellRangeAddress合併單元格),第二行列名,第三行開始是具體使用者資料。
【注意】在輸出excel時,要設定要好respone的頭部ContentType為application/octet-stream或者application/x-excel,Header的Content-Disposition要正確設定下載檔名稱編碼,以便可以在各大瀏覽器中都能夠正確輸出中文的下載檔名稱。

【需求2】將一張有使用者資料的Excel匯入到資料庫中並展示在頁面。
【分析】① 獲取excel資料;② 解析excel 資料;③ 插入資料到資料庫。
【編碼】使用正則表示式^.+\\.(?i)((xls)|(xlsx))$判斷使用者上傳的excel是什麼版本,使用HSSFWorkbook來讀取2003以前版本,使用XSSFWorkbook來讀取2007及以後版本。逐個遍歷sheet,row,cell獲取每個單元格對應資料並將資料轉換為使用者物件插入資料庫中,當匯入完畢後返回列表頁面。