当前位置:网站首页>Easyexcel read write simple to use
Easyexcel read write simple to use
2022-07-07 10:18:00 【wnfee】
List of articles
Official documents https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read
One . Read
1.1 Defining entity classes
@Data
public class EmailImportParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = " Data adding method 1 The system automatically finds the registered company name through the email domain name 2 Manual input ")
@NotNull
@ExcelProperty(index = 0)
private Integer dataType;
@ApiModelProperty(value = " Alternate company name ")
@ExcelProperty(index = 1)
private String inputCompanyName;
@ApiModelProperty(value = " Email address ")
@NotBlank
@ExcelProperty(index = 2)
private String email;
}
- If you don't use headings
@ExcelProperty(index = 0)
, Title From0
Turn on- If you use the title
@ExcelProperty(" Data adding method ")
1.2 Do not check data batch import
Interface implementation
@Override
@SneakyThrows
public Boolean importExcel(MultipartFile file) {
EasyExcel.read(file.getInputStream(), EmailImportParam.class, new EmailDataListener(this)).sheet().doRead();
return true;
}
add to EmailDataListener
package com.tophant.pentestinfoinv.listener;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.tophant.pentestinfoinv.common.domain.query.EmailAddParam;
import com.tophant.pentestinfoinv.common.domain.query.EmailImportParam;
import com.tophant.pentestinfoinv.service.IEmailService;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @Description email excel Import listening class
* @Author WanFei
* @Date 2022/7/4 16:43
**/
@Slf4j
public class EmailDataListener implements ReadListener<EmailImportParam> {
/**
* every other 5 Storage database , It can be used in practice 100 strip , Then clean up list , Convenient for memory recycling
*/
private static final int BATCH_COUNT = 100;
private List<EmailImportParam> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* Suppose this is a DAO, Of course, there is business logic, which can also be a service. Of course, it's useless if you don't have to store this object .
*/
private IEmailService emailService;
/**
* If used spring, Please use this construction method . Each creation Listener You need to put spring The management class came in
*
* @param emailService
*/
public EmailDataListener(IEmailService emailService) {
this.emailService = emailService;
}
/**
* Every data parsing will call
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(EmailImportParam data, AnalysisContext context) {
log.info(" Parse to a piece of data :{}", JSONUtil.toJsonStr(data));
cachedDataList.add(data);
// achieve BATCH_COUNT 了 , Need to store the database once , Prevent tens of thousands of data in memory , Easy to OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// Storage complete cleaning list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* All data analysis is done Will call
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// We also need to save data here , Make sure that the last legacy data is also stored in the database
saveData();
log.info(" All data analysis completed !");
}
/**
* Plus the storage database
*/
private void saveData() {
log.info("{} Data , Start storing the database !", cachedDataList.size());
List<EmailAddParam> emailAddParams = cachedDataList.stream().map(emailImportParam -> new EmailAddParam()
.setEmails(Set.of(emailImportParam.getEmail()))
.setDataType(emailImportParam.getDataType())
.setInputCompanyName(emailImportParam.getInputCompanyName()))
.collect(Collectors.toList());
emailAddParams.forEach(emailService::create);
log.info(" Storage database success !");
}
}
1.3 Check the one-time import of data
@Override
@SneakyThrows
public Boolean importExcel(MultipartFile file) {
File newFile = MultipartFileUtil.multipartFileToFile(file);
Assert.isFalse(ObjectUtil.isNull(file) || ObjectUtil.isNull(newFile), " The file cannot be empty !");
// Get file type
String fileType = FileUtil.getType(newFile);
log.info(" Upload file extension : {}", fileType);
Assert.notNull(fileType, " The extension name of the uploaded file is empty !");
Assert.isTrue(StrUtil.containsAnyIgnoreCase(fileType, "xls", "xlsx"), StrUtil.format(" Upload of file type is not allowed : {}", fileType));
List<EmailImportParam> emailList = new ArrayList<>();
EasyExcel.read(file.getInputStream()).head(EmailImportParam.class)
.sheet()
.registerReadListener(new AnalysisEventListener<EmailImportParam>() {
@Override
public void invoke(EmailImportParam data, AnalysisContext context) {
emailList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info(" Data read complete ");
}
}).doRead();
Set<String> emails = emailList.stream().map(EmailImportParam::getEmail).collect(Collectors.toSet());
InfoInvUtil.checkDomain(emails);
// Query the existing mailbox
Set<String> repeatEmails = this.lambdaQuery()
.eq(Email::getDelFlag, false)
.in(Email::getEmail, emails)
.select(Email::getEmail)
.list()
.stream()
.map(Email::getEmail)
.collect(Collectors.toSet());
Assert.isFalse(CollUtil.isNotEmpty(repeatEmails), StrUtil.format(" mailbox : {} Already exists , Please check excel file ", CollUtil.join(repeatEmails, ", ")));
// Add to database
List<EmailAddParam> emailAddParams = emailList.stream().map(emailImportParam -> new EmailAddParam()
.setEmails(Set.of(emailImportParam.getEmail()))
.setDataType(emailImportParam.getDataType())
.setInputCompanyName(emailImportParam.getInputCompanyName()))
.collect(Collectors.toList());
emailAddParams.forEach(this::create);
return true;
}
MultipartFileUtil
Tool class
package com.tophant.pentestinfoinv.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
/**
* File Transformation tool
*
* @author [email protected]
* @date 06-21-0021-2021
*/
@Slf4j
public class MultipartFileUtil {
/**
* MultipartFile Convert to File
*
* @param file multipartFile
* @return File
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) {
try {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
} catch (Exception e) {
log.warn("MultipartFile Turn into File Failure !");
return null;
}
}
/**
* Get stream file
* @param ins
* @param file
*/
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Two . write in
2.1 write in
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
EasyExcel.write(byteArrayOutputStream, EmailExcelVO.class)
// Register a custom interceptor
.registerWriteHandler(new CustomCellWriteConfig())
.registerWriteHandler(new CustomColumnWidthConfig())
.registerWriteHandler(new CustomRowHeightConfig())
.sheet(" mailbox ")
.doWrite(excelVOList);
2.2 Custom interceptors
2.2.1 Set the style
package com.tophant.component.starter.excel.common.config;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.*;
import java.util.List;
/**
* @Description Set the style
* @Author WanFei
* @Date 2022/5/13 12:13
*/
public class CustomCellWriteConfig implements CellWriteHandler {
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
CellStyle cellStyle = workbook.createCellStyle();
// In the middle
cellStyle.setAlignment(HorizontalAlignment.LEFT);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
// Set borders
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setBorderTop(BorderStyle.THIN);
// Word wrap
cellStyle.setWrapText(true);
// Configuration takes effect
cell.setCellStyle(cellStyle);
}
}
2.2.2 Adaptive width
package com.tophant.component.starter.excel.common.config;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description Adaptive width
* @Author WanFei
* @Date 2022/5/13 13:59
*/
public class CustomColumnWidthConfig extends AbstractColumnWidthStyleStrategy {
private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>();
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {
boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (needSetWidth) {
Map<Integer, Integer> maxColumnWidthMap = CACHE.computeIfAbsent(writeSheetHolder.getSheetNo(), k -> new HashMap<>());
Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
if (columnWidth >= 0) {
if (columnWidth > 254) {
columnWidth = 254;
}
Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
Sheet sheet = writeSheetHolder.getSheet();
sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
}
}
}
}
/**
* Calculate the length
* @param cellDataList
* @param cell
* @param isHead
* @return
*/
private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
if (isHead) {
return cell.getStringCellValue().getBytes().length;
} else {
CellData<?> cellData = cellDataList.get(0);
CellDataTypeEnum type = cellData.getType();
if (type == null) {
return -1;
} else {
switch (type) {
case STRING:
// A newline ( The data needs to be parsed in advance )
int index = cellData.getStringValue().indexOf("\n");
return index != -1 ?
cellData.getStringValue().substring(0, index).getBytes().length + 1 : cellData.getStringValue().getBytes().length + 1;
case BOOLEAN:
return cellData.getBooleanValue().toString().getBytes().length;
case NUMBER:
return cellData.getNumberValue().toString().getBytes().length;
default:
return -1;
}
}
}
}
}
2.2.3 Adaptive line height
package com.tophant.component.starter.excel.common.config;
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import java.util.Iterator;
/**
* @Description Adaptive line height
* @Author WanFei
* @Date 2022/5/13 14:03
*/
public class CustomRowHeightConfig extends AbstractRowHeightStyleStrategy {
/**
* Default height
*/
private static final Integer DEFAULT_HEIGHT = 300;
@Override
protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
}
@Override
protected void setContentColumnHeight(Row row, int relativeRowIndex) {
Iterator<Cell> cellIterator = row.cellIterator();
if (!cellIterator.hasNext()) {
return;
}
// The default is 1 Line height
Integer maxHeight = 1;
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case STRING:
if (cell.getStringCellValue().contains("\n")) {
int length = cell.getStringCellValue().split("\n").length;
maxHeight = Math.max(maxHeight, length);
}
break;
default:
break;
}
}
row.setHeight((short) (maxHeight * DEFAULT_HEIGHT));
}
}
边栏推荐
- 能源路由器入门必读:面向能源互联网的架构和功能
- 网上可以开炒股账户吗安全吗
- Horizontal split of database
- 一文讲解单片机、ARM、MUC、DSP、FPGA、嵌入式错综复杂的关系
- phpcms实现PC网站接入微信Native支付
- ORM--数据库增删改查操作逻辑
- ISP、IAP、ICP、JTAG、SWD的编程特点
- Parameter sniffing (2/2)
- ORM -- query type, association query
- Official media attention! The list of top 100 domestic digital collection platforms was released, and the industry accelerated the healthy development of compliance
猜你喜欢
Fiddler break point
Appx code signing Guide
ORM模型--数据记录的创建操作,查询操作
电表远程抄表拉合闸操作命令指令
Pdf document signature Guide
【学习笔记-李宏毅】GAN(生成对抗网络)全系列(一)
Deconvolution popular detailed analysis and nn Convtranspose2d important parameter interpretation
Memory ==c language 1
fiddler-AutoResponder
Google Colab装载Google Drive(Google Colab中使用Google Drive)
随机推荐
fiddler-AutoResponder
The combination of over clause and aggregate function in SQL Server
2022.7.4DAY596
ArcGIS operation: batch modify attribute table
SQLyog数据库怎么取消自动保存更改
C logging method
C#记录日志方法
【acwing】786. 第k个数
IPv4套接字地址结构
Download Text, pictures and ab packages used by unitywebrequest Foundation
This article explains the complex relationship between MCU, arm, muc, DSP, FPGA and embedded system
ISP、IAP、ICP、JTAG、SWD的编程特点
ES6中的函数进阶学习
How to cancel automatic saving of changes in sqlyog database
Official media attention! The list of top 100 domestic digital collection platforms was released, and the industry accelerated the healthy development of compliance
Methods of adding centerlines and centerlines in SolidWorks drawings
Appx code signing Guide
反卷积通俗详细解析与nn.ConvTranspose2d重要参数解释
Use of JSON extractor originals in JMeter
STM32 ADC和DMA