官方文檔(完整功能展示):地址
依賴
<!-- easyexcel導(dǎo)入導(dǎo)出 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
導(dǎo)出
1.隨便一個實體類(默認不管加不加@ExcelProperty的注解的所有字段都會參與讀寫,若某字段不想?yún)⑴c,可在字段上添加@ExcelIgnore。若只想加@ExcelProperty才參與,則類上加@ExcelIgnoreUnannotated)更多注解使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@ExcelProperty("用戶id")
private Long uid;
@ExcelProperty("用戶名")
private String uname;
@ExcelProperty("用戶性別")
private int usex;
@ExcelProperty("注冊時間")
private Date udate;
}
2.編一個方法用于返回要導(dǎo)出的數(shù)據(jù)
//編數(shù)據(jù)用作導(dǎo)出
private List<User> data() {
List<User> list = ListUtils.newArrayList();
Random random = new Random();
for (long i = 0; i < 10; i++) {
User data = new User(i,"用戶"+i,random.nextInt(2),new Date());
list.add(data);
}
return list;
}
3.1 用戶訪問接口時進行下載
@GetMapping(value = "ceshi")
public void ceshi(HttpServletResponse response, @Param("fileName") String fileName) throws IOException {
ServletOutputStream out = response.getOutputStream();
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
EasyExcel.write(out, User.class).sheet("模板").doWrite( data() );//User.class是要到出數(shù)據(jù)的實體類,data()是要導(dǎo)出的數(shù)據(jù)
out.flush();//使用戶下載文件
}
3.2 直接規(guī)定一個地址進行保存
@GetMapping(value = "ceshi")
public void ceshi(){
String fileName = "E:\\ceshi\\" + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
EasyExcel.write(fileName, User.class).sheet("模板").doWrite(data());
}
請求接口方法:鏈接
我這里是直接瀏覽器輸入url訪問的
測試3.1,效果
測試3.2,效果
導(dǎo)入
1.隨便一個實體類
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@ExcelProperty("用戶id")
private Long uid;
@ExcelProperty("用戶名")
private String uname;
@ExcelProperty("用戶性別")
private int usex;
@ExcelProperty("注冊時間")
private Date udate;
}
2.一個dao用于存儲至數(shù)據(jù)庫,此處隨便寫的用于演示
public class DemoDAO {
public void save(List<User> list){
System.out.println("調(diào)用-------------------------");
list.forEach(x->{
System.out.println(x);
});
}
}
3.官網(wǎng)復(fù)制的監(jiān)聽類
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
// 有個很重要的點 UserListener 不能被spring管理,要每次讀取excel都要new,然后里面用到spring可以構(gòu)造方法傳進去
@Slf4j
public class UserListener implements ReadListener<User> {
/**
* 每隔5條存儲數(shù)據(jù)庫,實際使用中可以100條,然后清理list ,方便內(nèi)存回收
*/
private static final int BATCH_COUNT = 5;
/**
* 緩存的數(shù)據(jù)
*/
private List<User> userDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 假設(shè)這個是一個DAO,當然有業(yè)務(wù)邏輯這個也可以是一個service。當然如果不用存儲這個對象沒用。
*/
private DemoDAO demoDAO;
public UserListener() {
// 這里是demo,所以隨便new一個。實際使用如果到了spring,請使用下面的有參構(gòu)造函數(shù)
demoDAO = new DemoDAO();
}
/**
* 如果使用了spring,請使用這個構(gòu)造方法。每次創(chuàng)建Listener的時候需要把spring管理的類傳進來
*
* @param demoDAO
*/
public UserListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
/**
* 這個每一條數(shù)據(jù)解析都會來調(diào)用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(User data, AnalysisContext context) {
log.info("解析到一條數(shù)據(jù):{}");
userDataList.add(data);
// 達到BATCH_COUNT了,需要去存儲一次數(shù)據(jù)庫,防止數(shù)據(jù)幾萬條數(shù)據(jù)在內(nèi)存,容易OOM
if (userDataList.size() >= BATCH_COUNT) {
saveData();
// 存儲完成清理 list
userDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有數(shù)據(jù)解析完成了 都會來調(diào)用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 這里也要保存數(shù)據(jù),確保最后遺留的數(shù)據(jù)也存儲到數(shù)據(jù)庫
saveData();
log.info("所有數(shù)據(jù)解析完成!");
}
/**
* 加上存儲數(shù)據(jù)庫
*/
private void saveData() {
log.info("{}條數(shù)據(jù),開始存儲數(shù)據(jù)庫!", userDataList.size());
demoDAO.save(userDataList);
log.info("存儲數(shù)據(jù)庫成功!");
}
}
4.測試接口
@GetMapping(value = "ceshi1")
public void ceshi1() {
String fileName="E:\\ceshi\\1678090270171.xlsx";
EasyExcel.read(fileName, User.class, new UserListener()).sheet().doRead();
}
第一個參數(shù)也可是輸入流,如multipartFile.getInputStream()
效果
對于需要字典的字段(基本數(shù)據(jù)類型封裝類寫法)
1.修改實體類
@ExcelProperty(value = "用戶性別",converter = UsexConverter.class)
private Integer usex;
2.類型裝換器
public class UsexConverter implements Converter<Integer> {
@Override
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.NUMBER;
}
@Override
public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
// 導(dǎo)入時字符串轉(zhuǎn)換數(shù)字
switch (cellData.getStringValue()){
case "男" : return 1;
case "女" : return 0;
default: return -1;
}
}
/**
* 將從數(shù)據(jù)庫中查到的數(shù)據(jù)轉(zhuǎn)換為 Excel 展示的數(shù)據(jù)
* @param value 枚舉對象
*/
@Override
public WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String sexName;
switch (value){
case 0 : sexName= "女";break;
case 1 : sexName= "男";break;
default: sexName="其他";
}
return new WriteCellData<>(sexName);
}
}
導(dǎo)出效果
導(dǎo)入效果
對于需要字典的字段(枚舉寫法)
1.添加枚舉類
public enum UsexEnum {
MAN("男",1),WOMEN("女",0),UNKNOWN("未知",-1);
String name;
int value;
UsexEnum(String name,int value){
this.name = name;
this.value = value;
}
/*
根據(jù)name值返回枚舉類
*/
public static UsexEnum getUsexEnumofName(String name){
for (UsexEnum us : UsexEnum.values())
if (name.equals(us.getName()))
return us;
return UNKNOWN;
}
String getName(){
return name;
}
int getValue(){
return value;
}
@Override
public String toString(){
return name;
}
}
2.修改實體類
@ExcelProperty(value = "用戶性別",converter = UsexConverter.class)//UsexConverter為類型裝換器
private UsexEnum usex;
3.類型裝換器
package Ceshi.daorudaochu;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
/**
* Excel 性別類型裝換器
*
* @author wang suo
* @version 1.0
* @date 2021/9/14 15:06
*/
@Slf4j
public class UsexConverter implements Converter<UsexEnum> {
@Override
public Class<?> supportJavaTypeKey() {
return UsexEnum.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return null;
}
/**
*導(dǎo)入觸發(fā)
* @param value 枚舉對象
*/
@Override
public UsexEnum convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
// 導(dǎo)入時根據(jù)表格name值轉(zhuǎn)化為枚舉對象
return UsexEnum.getUsexEnumofName(cellData.getStringValue());
}
/**
* 導(dǎo)出觸發(fā),將從數(shù)據(jù)庫中查到的數(shù)據(jù)轉(zhuǎn)換為 Excel 展示的數(shù)據(jù)
* @param value 枚舉對象
*/
@Override
public WriteCellData<?> convertToExcelData(UsexEnum value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
// 將枚舉類型按照 key 傳值
return new WriteCellData<UsexEnum>(String.valueOf(value));
}
}
導(dǎo)出效果
導(dǎo)入效果(里邊是空時沒觸發(fā)類型轉(zhuǎn)換)
導(dǎo)出時添加下拉選項
1.添加自定義攔截器
public class CustomSheetWriteHandler implements SheetWriteHandler {
@Override
public void afterSheetCreate(SheetWriteHandlerContext context) {
// 區(qū)間設(shè)置 第一列第一行和第二行的數(shù)據(jù)。由于第一行是頭,所以第一、二行的數(shù)據(jù)實際上是第二三行
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 0, 2, 2);//四個參數(shù)分別為起始行號,終止行號,起始列號,終止列號。均從0開始
DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"男", "女"});//下拉框值
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
}
}
2.導(dǎo)出時添加(此處為鏈式操作,可添加多個攔截器)文章來源:http://www.zghlxwxcb.cn/news/detail-544381.html
.registerWriteHandler(new CustomSheetWriteHandler())
效果
導(dǎo)出多個工作表文章來源地址http://www.zghlxwxcb.cn/news/detail-544381.html
ExcelWriter excelWriter = EasyExcel.write("E:\\ceshi\\1678090270171.xlsx").build();
//具體工作表
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").head(xxx.class).build();//head根據(jù)實體類確定表頭,不加就直接填充數(shù)據(jù)
excelWriter.write(result,writeSheet);//向表填充數(shù)據(jù)
writeSheet = EasyExcel.writerSheet("表2").build();//writerSheet隨便起,不是指定要填哪個表而是第二個表叫表2
excelWriter.write(result2,writeSheet);
writeSheet = EasyExcel.writerSheet("Sheet3").build();//有幾個writeSheet最后的xlsx就有幾個工作表,sheel順序按照代碼順序
excelWriter.write(result3,writeSheet);
excelWriter.finish();//關(guān)閉流(必須)
到了這里,關(guān)于java 實現(xiàn)數(shù)據(jù)導(dǎo)入導(dǎo)出的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!