最近公司要求使用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 );
}
}