JAVA-POI之Excel導出

    最近公司要求使用JAVA操作office ,研究了一天有關Excel的POI知識 ,也上網找了很多POI操作Excel的博客 ,無奈發現使用後多數代碼都是過期內容,還有一部分代碼使用起來操作時間過久,有的導出20000行數據慢到幾乎可以睡一覺起來再看了 ,於是乎急眼自己着手搞了一個導出的Util,我是小菜鳥理解並不是太透徹,不過還是站在了巨人的肩膀上,多有借鑑各位巨人的經驗,在此也多謝各位巨人們。

    那麼正文開始:

    首先 導入Apache的POIjar包,沒有Jar包的童鞋,可以去 ApachePOI的Jar包飛機票 下載

         

    上圖爲下載位置

    至於怎麼導入我就不多說了(如果你不會導jar包的話,那你真該回爐了 -__-)。

    這裏我只是在本地搞了一個Util類,隨便弄了一個簡單的bean進行測試。時間不足,僅供參考!(有了實現,不怕別的)。

    這裏主要操作的是XSSFWorkBook ,03版本與07版本在代碼區分改動,主要就是HSSF與XSSF的區別,命名上也就是xsl與xslx的區分,這裏也就不多說了,簡單研究一下,兩者大同小異。

    順便多嘮叨一嘴 POI 的創建流程,方便理解。

    1、創建工作簿     (workbook)

    2、創建sheet頁   (可以多個創建)

    3、創建樣式        (可有可無)

    4、創建 行          

    5、創建 單元格   

    

    以下就是導出Excel的梳理代碼 **

package com.excel.org;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.SimpleDateFormat;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExportExcelUtil {

	/**
	 * 
	 * @param sheetName		sheet頁的名稱
	 * @param titleName		表格標題的名稱
	 * @param headers		表格列頭的名稱數組
	 * @param data			數據源
	 * @param resultUrl		本地的地址
	 * @param pattern		時間的格式
	 */
	private static void doExportExcel07(String sheetName,String titleName,String[] headers,Collection<?> data,String resultUrl,String pattern) {

		// 聲明一個工作薄
		XSSFWorkbook workbook = new XSSFWorkbook();
		OutputStream out=null;

		// 生成一個工作表
		XSSFSheet sheet = workbook.createSheet(sheetName);
		// 設置工作表默認列寬度爲20個字節
		sheet.setDefaultColumnWidth((short) 20);
		//設置工作表的默認高度爲14個字節
//		sheet.setDefaultRowHeight((short) 14);
		//在工作表中合併首行並居中
		sheet.addMergedRegion(new CellRangeAddress(0,0,0,headers.length-1));

		/** start 關於標題 start **/
		
		// 創建[標題]樣式
		XSSFCellStyle titleStyle = workbook.createCellStyle();
		// 設置[標題]樣式
		titleStyle.setFillForegroundColor(IndexedColors.DARK_YELLOW.getIndex()); 	//屎黃色
		titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);			    //填充模式
		titleStyle.setBorderBottom(BorderStyle.THIN);					            //下邊框樣式
		titleStyle.setBorderLeft(BorderStyle.THIN);					                //左邊框樣式
		titleStyle.setBorderRight(BorderStyle.THIN);					            //右邊框樣式
		titleStyle.setBorderTop(BorderStyle.THIN);					                //上邊框樣式
		titleStyle.setAlignment(HorizontalAlignment.CENTER);				        //居中
		//創建[標題]字體
		XSSFFont titleFont = workbook.createFont();
		//設置[標題]字體
		titleFont.setColor(IndexedColors.BLUE.getIndex());				            //藍色
		titleFont.setFontHeightInPoints((short) 24);					           //字體大小
		titleFont.setFontName("Courier New");						                //字體樣式
		titleFont.setBold(true);                                                   //是否粗體
		// 應用
		titleStyle.setFont(titleFont);
		//設置標題的座標 並 賦值
		XSSFRow titleRow = sheet.createRow(0);
		XSSFCell titleCell = titleRow.createCell(0);
		titleCell.setCellStyle(titleStyle);
		titleCell.setCellValue(titleName);

		/** end 關於標題 end **/
		
		
		/** start 關於列頭 start **/
		
		// 創建[列頭]樣式
		XSSFCellStyle headersStyle = workbook.createCellStyle();
		// 設置[列頭]樣式
		headersStyle.setFillForegroundColor(IndexedColors.BLUE.index);	    //顏色
		headersStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);		//填充模式
		headersStyle.setBorderBottom(BorderStyle.THIN);						//下邊框樣式
		headersStyle.setBorderLeft(BorderStyle.THIN);						//左邊框樣式
		headersStyle.setBorderRight(BorderStyle.THIN);						//右邊框樣式
		headersStyle.setBorderTop(BorderStyle.THIN);						//上邊框樣式
		headersStyle.setAlignment(HorizontalAlignment.CENTER);				//居中
		//創建[列頭]字體
		XSSFFont headersFont = workbook.createFont();
		//設置[列頭]字體
		headersFont.setColor(HSSFColorPredefined.VIOLET.getIndex());
		headersFont.setFontHeightInPoints((short) 12);
		// 應用
		headersStyle.setFont(headersFont);
		// 設置列頭的座標 並 循環賦值
		XSSFRow row = sheet.createRow(1);
		for (short i = 0; i < headers.length; i++) {
			XSSFCell cell = row.createCell(i);
			cell.setCellStyle(headersStyle);
			XSSFRichTextString text = new XSSFRichTextString(headers[i]);
			cell.setCellValue(text);
		}

		/** end 關於列頭 end **/

		
		/** start 關於表中數據 start **/
		// 創建[表中數據]樣式
		XSSFCellStyle dataSetStyle = workbook.createCellStyle();
		// 設置[表中數據]樣式
		dataSetStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_ORANGE.getIndex());
		dataSetStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		dataSetStyle.setBorderBottom(BorderStyle.THIN);
		dataSetStyle.setBorderLeft(BorderStyle.THIN);
		dataSetStyle.setBorderRight(BorderStyle.THIN);
		dataSetStyle.setBorderTop(BorderStyle.THIN);
		dataSetStyle.setAlignment(HorizontalAlignment.CENTER);
		dataSetStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		// 創建[表中數據]字體
		XSSFFont dataSetFont = workbook.createFont();
		// 設置[表中數據]字體
		dataSetFont.setColor(IndexedColors.BLUE.getIndex());
		// 應用
		dataSetStyle.setFont(dataSetFont);
		
		
		/**此處多謝某位前輩省去了我一部分時間,我把前輩的代碼稍作修改以達到更效率的方式,望見諒**/
		// 創建表中數據行-增加樣式-賦值
		Iterator<?> it = data.iterator();
		int index = 1;
		while (it.hasNext()) {
			index++;
			row = sheet.createRow(index);   
			Object t = it.next();
			// 利用反射,根據javabean屬性的先後順序,動態調用getXxx()方法得到屬性值
			Field[] fields = t.getClass().getDeclaredFields();
			for (short i = 0; i < fields.length; i++) {
				XSSFCell cell = row.createCell(i);
				cell.setCellStyle(dataSetStyle);
				Field field = fields[i];
				String fieldName = field.getName();
				String getMethodName = "get"+ fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);
				try {
					@SuppressWarnings("rawtypes")
					Class tCls = t.getClass();
					@SuppressWarnings("unchecked")
					Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
					Object value = getMethod.invoke(t, new Object[] {});

					// 如果是時間類型,按照格式轉換
					String textValue = null;
					if (value instanceof Date) {
						Date date = (Date) value;
						SimpleDateFormat sdf = new SimpleDateFormat(pattern);
						textValue = sdf.format(date);
					} else {
						// 其它數據類型都當作字符串簡單處理
						if (value != null) {
							textValue = value.toString();
						}else {
							textValue = "";
						}
					}
					// 利用正則表達式判斷textValue是否全部由數字組成
					if (textValue != null) {
						Pattern p = Pattern.compile("^\\d+(\\.\\d+)?$");
						Matcher matcher = p.matcher(textValue);
						if (matcher.matches()) {
							// 是數字當作double處理
							cell.setCellValue(Double.parseDouble(textValue));
						} else {
							// 不是數字做普通處理
							cell.setCellValue(textValue);
						}
					}
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		try {
			out = new FileOutputStream(resultUrl);
			workbook.write(out);
			out.flush();
			out.close();
			workbook.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

        
        
	public static void main(String[] args) throws Exception{

		String sheetName="我是sheet頁名字";
		String titleName="我是標題";
		String[] headers = { "我是列頭1號", "我是列頭2號", "我是列頭3號", "我是列頭4號" };
		
		List<TestBean> data = new ArrayList<>();
		for (int i = 0; i < 50000; i++) { 
			TestBean b = new TestBean();			//這裏寫一個javaBean  裏面有幾個參數 不多做介紹 循環添加了5萬次
			b.setid(String.valueOf(i));
			b.setMoney("19.21");
			b.setName("新年快樂" + i);
			b.setDate(java.sql.Date.valueOf("2018-02-24"));
			data.add(b);
		}
		
		//測試一下使用時間
		long end,start;
		start = System.currentTimeMillis();
		
		String resultUrl="F:\\新建文件夾\\顯靈吧!.xlsx";
		String pattern="yyyy-MM-dd";
		ExportExcelUtil.doExportExcel07(sheetName, titleName, headers, data, resultUrl, pattern);
		end = System.currentTimeMillis();
		
		System.out.println((end - start) /1000 );
	}
}


運行了一下,5萬行的簡單數據,我的電腦大概是 7~10秒左右。 還算中肯。 接下來還有新任務,歡迎各位大佬指點、批評!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章