java導(dǎo)出Excel文件的步驟全紀(jì)錄
一、背景
當(dāng)前B/S模式已成為應(yīng)用開(kāi)發(fā)的主流,而在企業(yè)辦公系統(tǒng)中,常常有客戶(hù)這樣子要求:你要把我們的報(bào)表直接用Excel打開(kāi)(電信系統(tǒng)、銀行系統(tǒng))?;蛘呤牵何覀円呀?jīng)習(xí)慣用Excel打印。這樣在我們實(shí)際的開(kāi)發(fā)中,很多時(shí)候需要實(shí)現(xiàn)導(dǎo)入、導(dǎo)出Excel的應(yīng)用。
最近在java上做了一個(gè)EXCEL的導(dǎo)出功能,寫(xiě)了一個(gè)通用類(lèi),在這里分享分享,該類(lèi)支持多sheet,且無(wú)需手動(dòng)進(jìn)行復(fù)雜的類(lèi)型轉(zhuǎn)換,只需提供三個(gè)參數(shù)即可:
1、fileName
excel文件名
2、HasMap<String,List<?>> data
具體的數(shù)據(jù),每個(gè)List代表一張表的數(shù)據(jù),?表示可為任意的自定義對(duì)象
3、LinkedHashMap<String,String[][]> headers
Stirng代表sheet名。每個(gè)String[][]代表一個(gè)sheet的定義,舉個(gè)例子如下:
String[][] header = {
{"field1","參數(shù)1"}
,{"field2","參數(shù)2"}
,{"field3","參數(shù)3"}
}
其中的field1,field2,field3為對(duì)象中的屬性名,參數(shù)1,參數(shù)2,參數(shù)3為列名,實(shí)際上這個(gè)指定了列的名稱(chēng)和這個(gè)列用到數(shù)據(jù)對(duì)象的哪個(gè)屬性。
二、怎么用
以一個(gè)例子來(lái)說(shuō)明怎么用,假設(shè)有兩個(gè)類(lèi)A和B定義如下:
public class A{
private String name;
private String address;
}
public class B{
private int id;
private double sum;
private String cat;
}
現(xiàn)在我們通過(guò)查詢(xún)數(shù)據(jù)庫(kù)獲得了A和B的兩個(gè)列表:
List<A> dataA = .....;
List<B> dataB = .....;
我們將這兩個(gè)導(dǎo)出到excel中,首先需要定義sheet:
String[][] sheetA = {
{"name","姓名"}
,{"address","住址"}
}
String[][] sheetB = {
{"id","ID"}
,{"sum","余額"}
,{"cat","貓的名字"}
}
然后將數(shù)據(jù)匯總構(gòu)造一個(gè)ExcelUtil:
String fileName = "測(cè)試Excel";
HashMap<String,List<?>> data = new HashMap<>();
//ASheet為表名,后面headers里的key要跟這里一致
data.put("ASheet",dataA);
data.put("BSheet",dataB);
LinkedHashMap<String,String[][]> headers = new LinkedHashMap<>();
headers.put("ASheet",sheetA);
headers.put("BSheet",sheetB);
ExcelUtil excelUtil = new ExcelUtil(fileName,data,headers);
//獲取表格對(duì)象
HSSFWorkbook workbook = excelUtil.createExcel();
//這里內(nèi)置了一個(gè)寫(xiě)到response的方法(判斷瀏覽器類(lèi)型設(shè)置合適的參數(shù)),如果想寫(xiě)到文件也是類(lèi)似的
workbook.writeToResponse(workbook,request,response);
當(dāng)然通常數(shù)據(jù)是通過(guò)數(shù)據(jù)庫(kù)查詢(xún)的,這里為了演示方便沒(méi)有從數(shù)據(jù)庫(kù)查找。
三、實(shí)現(xiàn)原理
這里簡(jiǎn)單說(shuō)明下實(shí)現(xiàn)過(guò)程,從調(diào)用createExcel()這里開(kāi)始
1、遍歷headers創(chuàng)建sheet
public HSSFWorkbook createExcel() throws Exception {
try {
HSSFWorkbook workbook = new HSSFWorkbook();
//遍歷headers創(chuàng)建表格
for (String key : headers.keySet()) {
this.createSheet(workbook, key, headers.get(key), this.data.get(key));
}
return workbook;
} catch (Exception e) {
log.error("創(chuàng)建表格失敗:{}", e.getMessage());
throw e;
}
}
將workbook,sheet名,表頭數(shù)據(jù),行數(shù)據(jù)傳入crateSheet方法中創(chuàng)建sheet。
2、創(chuàng)建表頭
表頭也就是一個(gè)表格的第一行,通常用來(lái)對(duì)列進(jìn)行說(shuō)明
HSSFSheet sheet = workbook.createSheet(sheetName);
// 列數(shù)
int cellNum = header.length;
// 單元行,單元格
HSSFRow row;
HSSFCell cell;
// 表頭單元格樣式
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
// 設(shè)置表頭
row = sheet.createRow(0);
for (int i = 0; i < cellNum; i++) {
cell = row.createCell(i);
cell.setCellStyle(columnTopStyle);
String str = header[i][1];
cell.setCellValue(str);
// 設(shè)置列寬為表頭的文字寬度+6個(gè)半角符號(hào)寬度
sheet.setColumnWidth(i, (str.getBytes("utf-8").length + 6) * 256);
}
3、插入行數(shù)據(jù)
這里是最重要的部分,首先通過(guò)數(shù)據(jù)的類(lèi)對(duì)象獲取它的反射屬性Field類(lèi),然后將屬性名和Field做一個(gè)hash映射,避免循環(huán)查找,提高插入速度,接著通過(guò)一個(gè)switch語(yǔ)句,根據(jù)屬性類(lèi)別設(shè)值,主要代碼如下:
/**
* 設(shè)置單元格,根據(jù)fieldName獲取對(duì)應(yīng)的Field類(lèi),使用反射得到值
*
* @param cell 單元格實(shí)例
* @param obj 存有屬性的對(duì)象實(shí)例
* @param fieldMap 屬性名與Field的映射
* @param fieldName 屬性名
*/
private void setCell(HSSFCell cell, Object obj, Map<String, Field> fieldMap, String fieldName) throws Exception {
//獲取該屬性的Field對(duì)象
Field field = fieldMap.get(fieldName);
//通過(guò)反射獲取屬性的值,由于不能確定該值的類(lèi)型,用下面的判斷語(yǔ)句進(jìn)行合適的轉(zhuǎn)型
Object value = field.get(obj);
if (value == null) {
cell.setCellValue("");
} else {
switch (field.getGenericType().getTypeName()) {
case "java.lang.String":
cell.setCellValue((String) value);
break;
case "java.lang.Integer":
case "int":
cell.setCellValue((int) value);
break;
case "java.lang.Double":
case "double":
cell.setCellValue((double) value);
break;
case "java.util.Date":
cell.setCellValue(this.dateFormat.format((Date) value));
break;
default:
cell.setCellValue(obj.toString());
}
}
}
完整代碼可以到github上查看下載,這里就不列出來(lái)了。
github地址:點(diǎn)擊跳轉(zhuǎn)
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- java實(shí)現(xiàn)合并單元格的同時(shí)并導(dǎo)出excel示例
- Java數(shù)據(jù)導(dǎo)出功能之導(dǎo)出Excel文件實(shí)例
- Java實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出操作詳解
- java實(shí)現(xiàn)導(dǎo)出Excel的功能
- java實(shí)現(xiàn)Excel的導(dǎo)入、導(dǎo)出
- Java實(shí)現(xiàn)導(dǎo)出Excel功能
- java導(dǎo)出數(shù)據(jù)庫(kù)的全部表到excel
- java導(dǎo)出到excel常用的幾種方式總結(jié)
相關(guān)文章
SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java及Android中常用鏈?zhǔn)秸{(diào)用寫(xiě)法簡(jiǎn)單示例
這篇文章主要介紹了Java及Android中常用鏈?zhǔn)秸{(diào)用寫(xiě)法,結(jié)合實(shí)例形式分析了java編程中的鏈?zhǔn)秸{(diào)用概念、簡(jiǎn)單使用方法及相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
Java實(shí)現(xiàn)雙向鏈表(兩個(gè)版本)
這篇文章主要介紹了Java實(shí)現(xiàn)雙向鏈表(兩個(gè)版本)的相關(guān)資料,需要的朋友可以參考下2016-02-02
IntelliJ IDEA 安裝 Grep Console插件 自定義控制臺(tái)輸出多顏色格式功能
由于Intellij idea不支持顯示ascii顏色,grep-console插件能很好的解決這個(gè)問(wèn)題,下面就以開(kāi)發(fā)JavaEE項(xiàng)目中,結(jié)合Log4j配置多顏色日志輸出功能,感興趣的朋友一起看看吧2020-05-05
Java并發(fā)編程this逃逸問(wèn)題總結(jié)
本篇文章給大家詳細(xì)分析了Java并發(fā)編程this逃逸的問(wèn)題分享,對(duì)此有需要的朋友參考下。2018-02-02
淺談Java中浮點(diǎn)型數(shù)據(jù)保留兩位小數(shù)的四種方法
今天在進(jìn)行開(kāi)發(fā)的過(guò)程中遇到了一個(gè)小問(wèn)題,是關(guān)于如何將double類(lèi)型的數(shù)據(jù)保留兩位小數(shù)。具有一定的參考價(jià)值,本文就詳細(xì)的介紹一下2021-09-09
Spring Boot 實(shí)現(xiàn)配置文件加解密原理
這篇文章主要介紹了Spring Boot 實(shí)現(xiàn)配置文件加解密原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

