目錄
easyExcel是阿里巴巴開源的一個excel處理框架,以使用簡單、節省內存著稱。
64M內存1分鍾內讀取75M(46W行25列)的Excel(當然還有急速模式能更快,但是內存占用會在100M多一點)
可有效避免OOM。
致敬阿里:
---參照官方文檔進行編輯,主要記錄了工作中用到的,用的少的就沒有記錄
---官方文檔 : https://www.yuque.com/easyexcel
---官方github : https://github.com/alibaba/easyexcel
寫入數據實體類
@Data
public class DemoData {
@ExcelProperty("字符串標題")
private String stringData;
@ExcelProperty("整型標題")
private Integer integerData;
@ExcelProperty("日期標題")
private Date dateData;
@NumberFormat("#.##%")
private Double dounleData;
}
- @ExcelProperty("***") 標題行名稱
構造數據的方法
private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setStringData("字符串" + i);
data.setIntegerData(i);
data.setDateData(new Date());
data.setDounleData(0.56);
list.add(data);
}
return list;
}
創建對象的寫
簡單寫入
//寫法一
String fileName = "c://Users//****";
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后文件流會自動關閉
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
//寫法二
String fileName = "c://Users//****";
// 這里 需要指定寫用哪個class去寫
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
// 千萬別忘記finish 會幫忙關閉流
excelWriter.finish();
根據參數只導出指定列
String fileName = "c://Users//****";
//排除掉不想輸出的列 假設我們要忽略 stringData
Set<String> excludeColumnFiledNames = new HashSet<String>();
excludeColumnFiledNames.add("stringData");
EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(data());
//只輸出實體類我們想要的字段 假設我們只要導出 stringData
Set<String> includeColumnFiledNames = new HashSet<String>();
includeColumnFiledNames.add("stringData");
EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板").doWrite(data());
指定寫入的列
修改實體類注解即可
@ExcelProperty(value = "數字標題", index =5)
private Integer integerData;
復雜頭寫入
修改實體類注解即可
@ExcelProperty({"主標題", "字符串標題"})
@ExcelProperty({"主標題", "日期標題"})
@ExcelProperty({"主標題", "數字標題"})
重復多次寫入(寫到單個或者多個Sheet)
同一個sheet多次寫
String fileName = "c://Users//****";
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
//同一個sheet只要創建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 調用寫入,實際使用時根據數據庫分頁的總的頁數來
for (int i = 0; i < 5; i++) {
// 分頁去數據庫查詢數據 這里可以去數據庫查詢每一頁的數據
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
/// 千萬別忘記finish 會幫忙關閉流
excelWriter.finish();
寫到不同的sheet 同一個對象
String fileName = "c://Users//****";
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 去調用寫入,實際使用時根據數據庫分頁的總的頁數來。最終會寫到5個sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要創建writeSheet 這里注意必須指定sheetNo 而且sheetName必須不一樣
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
// 分頁去數據庫查詢數據 這里可以去數據庫查詢每一頁的數據
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
/// 千萬別忘記finish 會幫忙關閉流
excelWriter.finish();
寫到不同的sheet 不同的對象
String fileName = "c://Users//****";
//指定文件
ExcelWriter excelWriter = EasyExcel.write(fileName).build();
// 去調用寫入,實際使用時根據數據庫分頁的總的頁數來。這里最終會寫到5個sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要創建writeSheet 這里注意必須指定sheetNo 而且sheetName必須不一樣。這里注意DemoData.class 可以每次都變,我這里為了方便 所以用的同一個class 實際上可以一直變
writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
// 分頁去數據庫查詢數據 這里可以去數據庫查詢每一頁的數據
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
/// 千萬別忘記finish 會幫忙關閉流
excelWriter.finish();
日期、數字或者自定義格式轉換
修改實體類注解即可
日期、數字
@DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
@ExcelProperty("日期標題")
private Date dateData;
@NumberFormat("#.##%")
@ExcelProperty("浮點型標題")
private Double dounleData;
自定義格式轉換
@ExcelProperty(converter = CustomStringStringConverter.class)
private String stringData;
public class CustomStringStringConverter implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 這里讀的時候會調用
*/
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return "自定義:" + cellData.getStringValue();
}
/**
* 這里是寫的時候會調用
*/
@Override
public CellData convertToExcelData(String value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return new CellData(value);
}
}
指定列寬、行高
@Data
@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
public class DemoData {
@ColumnWidth(50)
@ExcelProperty("字符串標題")
//@ExcelProperty(converter = CustomStringStringConverter.class)
private String stringData;
@ExcelProperty(value = "數字標題")
private Integer integerData;
@DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
@ExcelProperty("日期標題")
private Date dateData;
@NumberFormat("#.##%")
@ExcelProperty("浮點型標題")
private Double dounleData;
}
注解形式自定義樣式
@Data
// 頭背景設置成紅色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10)
// 頭字體設置成20
@HeadFontStyle(fontHeightInPoints = 20)
// 內容的背景設置成綠色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17)
// 內容字體設置成20
@ContentFontStyle(fontHeightInPoints = 20)
public class DemoData {
@ColumnWidth(50)
@ExcelProperty("字符串標題")
// 字符串的頭背景設置成粉紅 IndexedColors.PINK.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)
private String stringData;
// 字符串的頭字體設置成20
@HeadFontStyle(fontHeightInPoints = 30)
@ExcelProperty(value = "數字標題")
private Integer integerData;
// 字符串的內容的背景設置成天藍 IndexedColors.SKY_BLUE.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40)
@DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
@ExcelProperty("日期標題")
private Date dateData;
// 字符串的內容字體設置成20
@ContentFontStyle(fontHeightInPoints = 30)
@NumberFormat("#.##%")
@ExcelProperty("浮點型標題")
private Double dounleData;
}
自定義樣式
String fileName = "c://Users//****";
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后文件流會自動關閉
// 頭的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景設置為紅色
headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)20);
headWriteCellStyle.setWriteFont(headWriteFont);
// 內容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 這里需要指定 FillPatternType 為FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色.頭默認了 FillPatternType所以可以不指定
contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 背景綠色
contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
WriteFont contentWriteFont = new WriteFont();
// 字體大小
contentWriteFont.setFontHeightInPoints((short)20);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 這個策略是 頭是頭的樣式 內容是內容的樣式 其他的策略可以自己實現
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后文件流會自動關閉
EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
.doWrite(data());
合並單元格
@Data
// 將第6-7行的2-3列合並成一個單元格
//@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
public class DemoData {
// 這一列 每隔2行 合並單元格
@ContentLoopMerge(eachRow = 2)
@ExcelProperty("字符串標題")
private String stringData;
@ExcelProperty(value = "數字標題")
private Integer integerData;
@DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
@ExcelProperty("日期標題")
private Date dateData;
@NumberFormat("#.##%")
@ExcelProperty("浮點型標題")
private Double dounleData;
}
自動列寬(不太精確)
EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板")
.doWrite(data());
不創建對象的寫
String fileName = "c://Users//****";
EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());
-------------------------------------------------------------------------
private List<List<String>> head() {
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
head0.add("字符串" + System.currentTimeMillis());
List<String> head1 = new ArrayList<String>();
head1.add("數字" + System.currentTimeMillis());
List<String> head2 = new ArrayList<String>();
head2.add("日期" + System.currentTimeMillis());
list.add(head0);
list.add(head1);
list.add(head2);
return list;
}
private List<List<Object>> dataList() {
List<List<Object>> list = new ArrayList<List<Object>>();
for (int i = 0; i < 10; i++) {
List<Object> data = new ArrayList<Object>();
data.add("字符串" + i);
data.add(new Date());
data.add(0.56);
list.add(data);
}
return list;
}
web的寫(文件下載)
/**
* 文件下載(失敗了會返回一個有部分數據的Excel)
*/
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 這里URLEncoder.encode可以防止中文亂碼 easyexcel沒有關系
String fileName = URLEncoder.encode("測試", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}
web中的寫並且失敗的時候返回json
@GetMapping("downloadFailedUsingJson")
public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
try {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 這里URLEncoder.encode可以防止中文亂碼 和easyexcel沒有關系
String fileName = URLEncoder.encode("測試", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
// 這里需要設置不關閉流
EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
.doWrite(data());
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap<String, String>();
map.put("status", "failure");
map.put("message", "下載文件失敗" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
private List<DownloadData> data() {
List<DownloadData> list = new ArrayList<DownloadData>();
for (int i = 0; i < 10; i++) {
DownloadData data = new DownloadData();
data.setStringData("字符串" + i);
data.setIntegerData(i);
data.setDateData(new Date());
data.setDounleData(0.56);
list.add(data);
}
return list;
}