Java對Excel表格的導出一直是對我有種可怕噩夢的東西,每次對要建立行與列,並一個一個放值,我是從心底拒絕的。
處於項目需求,需要導出表格,於是找到網上一版很好的開發, 《不想用POI?幾行代碼完成Excel導出導入》原文鏈接: https://juejin.im/post/5c3b683ee51d4551d14175ee
但是、我們項目不支持如此進行開發,
================================分割線=================================
因為需要引入xml文件進行開發,於是,只能自己動手封裝一個滿足需求的類:
一、需求:
查詢統計的數據 List,進行數據導出,並且表頭有合並單元格的需求。
直接上圖:以下是部分結果(由於全部截取失真)
二、設計思路:
表頭::把表頭與數據插入表格對象進行分開。表頭部分,每一行做為一個list, 使用String[]進行存儲。每次分析表頭,進行解析,生成表頭。
表體::需要插入的數據使用list中存入 map對象,其中的對象字段名稱與表頭部分相同,就可以進行數據的插入。
代碼如下:
/**
* Created by 閑一 on 2019/2/20.
*/
package
com.test;
import
org.apache.poi.ss.usermodel.Cell;
import
org.apache.poi.ss.usermodel.Row;
import
org.apache.poi.ss.usermodel.Sheet;
import
org.apache.poi.ss.util.CellRangeAddress;
import
org.apache.poi.xssf.usermodel.XSSFWorkbook;
import
org.junit.Test;
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.OutputStream;
import
java.text.SimpleDateFormat;
import
java.util.*;
public
class
POItest2 {
@Test
public
void
test1()
throws
IOException {
List<String[]> list =
new
ArrayList<>();
String[] arr = {
"部門"
,
"雲速"
};
String[] arr1 = {
"總計"
,
"10000000"
};
String[] arr2 = {
"單位"
,
"元"
};
list.add(arr);
list.add(arr1);
list.add(arr2);
XSSFWorkbook workbook =
new
XSSFWorkbook();
workbook = workbookList(workbook,
"come"
,
""
, list);
String[] arra0 = {
"name"
,
"名稱"
,
"1"
,
"1"
};
String[] arra1 = {
"Person"
,
"人類"
,
"1"
,
"2"
};
String[] arrb1 = {
"Amions"
,
"動物"
,
"1"
,
"1"
};
List<String[]> lista =
new
ArrayList<>();
List<List<String[]>> titles =
new
ArrayList<>();
lista.add(arra0);
lista.add(arra1);
lista.add(arrb1);
titles.add(lista);
String[] arr11 = {
""
,
""
,
"2"
,
"1"
};
List<String[]> list1 =
new
ArrayList<>();
list1.add(arr11);
String[] arr21 = {
"sex"
,
"性別"
,
"1"
,
"1"
};
list1.add(arr21);
String[] arr31 = {
"kaka"
,
"咳咳"
,
"1"
,
"1"
};
list1.add(arr31);
String[] arr41 = {
"kaka"
,
"小米"
,
"1"
,
"1"
};
list1.add(arr41);
titles.add(list1);
workbook = workbookinList(workbook,
"come"
,
""
, titles,
new
ArrayList<>());
workbook = workbookinList(workbook,
"come"
,
""
, titles,
new
ArrayList<>());
String path =
"d:/data/2019-02-19-04.csv"
;
wirteOutWorkbook(workbook, path);
}
/**
* 將數據寫入指定Excel對象中
*
* @param workbook Excel對象
* @param sheetName sheet名
* @param style Excel類型
* @param titles 標題串 {{['person','人類',1,2]},
* {['name','名稱',1,1], ['sex','性別',1,1]}} 【 字段名稱,標題,所占行數,所占列數】
* @param values 內容集
* @return True\False
*/
public
XSSFWorkbook workbookinList(XSSFWorkbook workbook, String sheetName, String style, List<List<String[]>> titles, List<Map<String, Object>> values) {
// 生成一個表格
Sheet sheet;
sheet = workbook.getSheet(sheetName);
if
(sheet ==
null
) {
if
(
null
== sheetName ||
""
.equals(sheetName)) {
sheet = workbook.createSheet();
// sheetName 為空則使用默認值
}
else
{
sheet = workbook.createSheet(sheetName);
}
}
// 設置表格默認列寬度為15個字節
sheet.setDefaultColumnWidth((
short
)
15
);
// 第一行生成賬單標題
Row row =
null
;
int
rowNumCount =
0
== sheet.getLastRowNum() ?
0
: sheet.getLastRowNum() +
2
;
//獲得總行數
// 存儲標題在Excel文件中的序號
Map<String, Integer> titleOrder =
new
HashMap<>();
for
(
int
j =
0
; j < titles.size(); j++) {
List<String[]> list = titles.get(j);
row = sheet.createRow(rowNumCount + j);
int
curCol =
0
;
//當前列數名稱
for
(
int
i =
0
; i < list.size(); i++) {
org.apache.poi.ss.usermodel.Cell cell = row.createCell(curCol);
String[] title = list.get(i);
cell.setCellValue(title[
1
]);
// 標題值
// 需要記錄每次的列位置
int
rowNum = Integer.valueOf(title[
2
]) -
1
;
// 需要占用的行數
int
colNum = Integer.valueOf(title[
3
]) -
1
;
// 需要占用的列數
if
(
0
!= rowNum ||
0
!= colNum) {
int
curRow = rowNumCount + j;
CellRangeAddress region =
new
CellRangeAddress(curRow - rowNum, curRow, curCol, curCol + colNum);
sheet.addMergedRegion(region);
curCol += Integer.valueOf(title[
3
]);
}
else
{
curCol++;
}
// 最后一行包含所有列
if
(j == titles.size() -
1
) {
titleOrder.put(title[
0
], i);
}
}
}
/*
* 寫入正文
*/
Iterator<Map<String, Object>> iterator = values.iterator();
int
index = rowNumCount +
1
;
// 行號
while
(iterator.hasNext()) {
index++;
// 出去標題行,從第一行開始寫
row = sheet.createRow(index);
Map<String, Object> value = iterator.next();
for
(Map.Entry<String, Object> map : value.entrySet()) {
// 獲取列名
String title = map.getKey();
// 根據列名獲取序號
Integer i = titleOrder.get(title);
if
(i ==
null
) {
continue
;
}
// 在指定序號處創建cell
Cell cell = row.createCell(i);
// 獲取列的值
Object object = map.getValue();
// 判斷object的類型
SimpleDateFormat simpleDateFormat =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
);
if
(object
instanceof
Double) {
cell.setCellValue((Double) object);
}
else
if
(object
instanceof
Date) {
String time = simpleDateFormat.format((Date) object);
cell.setCellValue(time);
}
else
if
(object
instanceof
Calendar) {
Calendar calendar = (Calendar) object;
String time = simpleDateFormat.format(calendar.getTime());
cell.setCellValue(time);
}
else
if
(object
instanceof
Boolean) {
cell.setCellValue((Boolean) object);
}
else
{
if
(object ==
null
) {
cell.setCellValue(
""
);
}
else
{
cell.setCellValue(object.toString());
}
}
}
}
return
workbook;
}
/**
* 將數據寫入Excel文件中
*
* @param workbook Excel對象
* @param sheetName sheet名
* @param style Excel類型
* @param dataList 標題串+內容集 {{'部門','201930'},{'總計','10000萬'}}
* @return True\False
*/
public
XSSFWorkbook workbookList(XSSFWorkbook workbook, String sheetName, String style, List<String[]> dataList) {
// 生成一個表格
Sheet sheet;
sheet = workbook.getSheet(sheetName);
if
(sheet ==
null
) {
if
(
null
== sheetName ||
""
.equals(sheetName)) {
sheet = workbook.createSheet();
// sheetName 為空則使用默認值
}
else
{
sheet = workbook.createSheet(sheetName);
}
}
// 設置表格默認列寬度為15個字節
sheet.setDefaultColumnWidth((
short
)
15
);
// 第一行生成賬單標題
Row row =
null
;
int
rowNumCount =
0
== sheet.getLastRowNum() ?
0
: sheet.getLastRowNum() +
2
;
//獲得總行數
// 存儲標題在Excel文件中的序號
for
(
int
i =
0
; i < dataList.size(); i++) {
row = sheet.createRow(rowNumCount + i);
row.createCell(
0
).setCellValue(dataList.get(i)[
0
]);
row.createCell(
1
).setCellValue(dataList.get(i)[
1
]);
}
return
workbook;
}
/**
* 文件寫出
*
* @param workbook
* @param path
* @throws IOException
*/
public
void
wirteOutWorkbook(XSSFWorkbook workbook, String path)
throws
IOException {
String dirPath = path.substring(
0
, path.lastIndexOf(
'.'
));
File dirFile =
new
File(dirPath);
if
(!dirFile.exists() && !dirFile.isDirectory()) {
dirFile.mkdirs();
}
File file =
new
File(path);
if
(file.exists()) {
file.delete();
}
OutputStream outputStream =
new
FileOutputStream(file);
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
}
如有疑問,歡迎留言討論!