当前位置:网站首页>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 From0Turn 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));
}
}
边栏推荐
- 柏拉图和他的三个弟子的故事:如何寻找幸福?如何寻找理想伴侣?
- Programming features of ISP, IAP, ICP, JTAG and SWD
- C#记录日志方法
- 虚数j的物理意义
- PDF文档签名指南
- 电表远程抄表拉合闸操作命令指令
- The request object parses the request body and request header parameters
- Appx代码签名指南
- 2022.7.4DAY596
- China's first electronic audio category "Yamano electronic audio" digital collection is on sale!
猜你喜欢

【二开】【JeecgBoot】修改分页参数

Postman interface test VII

Google colab loads Google drive (Google drive is used in Google colab)
![[learning notes - Li Hongyi] Gan (generation of confrontation network) full series (I)](/img/94/b4df1ce2861a851fcd8de3e08540b0.png)
[learning notes - Li Hongyi] Gan (generation of confrontation network) full series (I)

Win10安装VS2015

A wave of open source notebooks is coming

ORM model -- associated fields, abstract model classes

Pit encountered by vs2015 under win7 (successful)

对存储过程进行加密和解密(SQL 2008/SQL 2012)

fiddler-AutoResponder
随机推荐
Guid primary key
【acwing】786. 第k个数
PDF文档签名指南
Delete a record in the table in pl/sql by mistake, and the recovery method
Interface test
Postman interface test IV
Pytest learning - dayone
Bean operation domain and life cycle
STM32 ADC and DMA
运用tensorflow中的keras搭建卷积神经网络
China's first electronic audio category "Yamano electronic audio" digital collection is on sale!
ES6中的函数进阶学习
Horizontal split of database
【acwing】789. Range of numbers (binary basis)
Some thoughts on the testing work in the process of R & D
The request object parses the request body and request header parameters
【acwing】789. 数的范围(二分基础)
ES类和对象、原型
Agile course training
Learning records - high precision addition and multiplication