EasyExce复杂场景应用(动态合并标题,填充导出联合使用)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
一、EasyExcel是什么?
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
github地址: https://github.com/alibaba/easyexcel
官方文档: https://www.yuque.com/easyexcel/doc/easyexcel
B站视频: https://www.bilibili.com/video/BV1Ff4y1U7Qc
二、使用步骤
1.引入库
代码如下(示例):
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
2.组装填充数据
代码如下(示例):
List<EvaluateOpinionVo> evaluateOpinionVoList = empEvaluateDetailBizService
.getEvaluateCapacityVoList(evaluateInstancePo, queryDto, t.getTargetUserId());
if (CollectionUtils.isNotEmpty(evaluateOpinionVoList)) {
String finalName = evaluateOpinionVoList.stream().map(EvaluateOpinionVo::getEvaluateUserName)
.collect(Collectors.joining("\n"));
String finalRoleName = t.getEmpRoleName() + "\n";
String finalOrgName = t.getEmpOrgName() + "\n";
paramMap.put("finalName", finalName);
paramMap.put("finalId", Joiner.on("\n")
.join(evaluateOpinionVoList.stream().map(EvaluateOpinionVo::getEvaluateUserId)
.collect(Collectors.toList())));
paramMap.put("finalOrgName", finalOrgName);
paramMap.put("finalRoleName", finalRoleName);
}
paramMap.put("title", evaluateInstancePo.getEvaluateName());
paramMap.put("targetName", t.getTargetUserName());
paramMap.put("targetId", String.valueOf(t.getTargetUserId()));
if (ExamineEnum.AbilityModeCode.LEAD.getCode().equals(templateInstancePo.getAbilityMode())) {
paramMap.put("targetOrgName", t.getOrgName());
paramMap.put("targetRoleName", t.getRoleName());
} else {
paramMap.put("targetOrgName", t.getEmpOrgName());
paramMap.put("targetRoleName", t.getEmpRoleName());
}
该处模拟数据查找的数据,不用纠结代码。
3.填充数据
代码如下(示例):
WriteSheet sheet = EasyExcel
.writerSheet(t.getEvaluateInstanceId() + t.getTargetUserName() + t.getTargetUserId())
.registerWriteHandler(
new ExcelFillCellMergeStrategy(mergeColumnIndex, mergeRowIndex, standardColumnIndex))
.build();
我这边业务场景比较复杂。填充多个模板就预先定义了多个空白目标,sheet名称按规则命名
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//原模板只有一个sheet,通过poi复制出需要的sheet个数的模板
XSSFWorkbook workbook = new XSSFWorkbook(in);
if (CollectionUtils.isNotEmpty(sheetName)) {
// workbook.setSheetName(0, sheetName.get(0));
//复制空白sheet
for (int j = 0; j < sheetName.size(); j++) {
workbook.createSheet(sheetName.get(j));
}
}
if (CollectionUtils.isNotEmpty(targetPos)) {
//设置模板的第一个sheet的名称
workbook.setSheetName(0, "sheet1");
for (int i = 0; i < targetPos.size() - 1; i++) {
//复制模板,得到第i个sheet
workbook.cloneSheet(0,
targetPos.get(i).getEvaluateInstanceId() + targetPos.get(i).getTargetUserName() + targetPos
.get(i).getTargetUserId());
}
//克隆sheet小于1就不用操作
if (targetPos.size() > 1) {
workbook.removeSheetAt(0);
workbook.cloneSheet(sheetName.size(),
targetPos.get(targetPos.size() - 1).getEvaluateInstanceId() + targetPos
.get(targetPos.size() - 1).getTargetUserName() + targetPos.get(targetPos.size() - 1)
.getTargetUserId());
}
if (targetPos.size() == 1) {
workbook.cloneSheet(0, targetPos.get(targetPos.size() - 1).getEvaluateInstanceId() + targetPos
.get(targetPos.size() - 1).getTargetUserName() + targetPos.get(targetPos.size() - 1)
.getTargetUserId());
workbook.removeSheetAt(0);
}
}
填充多个模板需要预先定义sheet不然会报错哦
4.拦截器(实现动态合并重点)
代码如下(示例):
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
private int[] mergeColumnIndex;
private int mergeRowIndex;
private int standardColumnIndex;
/**
* 当前单元格向上合并
*
* @param writeSheetHolder
* @param cell 当前单元格
* @param curRowIndex 当前行
* @param curColIndex 当前列
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
// 获取上一行第0列单元格和本行第0列单元格
Cell preRowFirstCell = cell.getSheet().getRow(curRowIndex - 1).getCell(standardColumnIndex);
Object preRowFirstData = preRowFirstCell.getCellTypeEnum() == CellType.STRING ? preRowFirstCell.getStringCellValue() : preRowFirstCell.getNumericCellValue();
Cell curRowFirstCell = cell.getSheet().getRow(curRowIndex).getCell(standardColumnIndex);
Object curRowFirstData = curRowFirstCell.getCellTypeEnum() == CellType.STRING ? curRowFirstCell.getStringCellValue() : curRowFirstCell.getNumericCellValue();
// 当前列不为标杆列,根据标杆列上下两个单元格值是否一致来合并
// 当前列为标杆列并且上下两个单元格一致则合并
if ((curColIndex == standardColumnIndex && preData.equals(curData)) || (curColIndex != standardColumnIndex && preRowFirstData.equals(curRowFirstData) && preData.equals(curData)) && preData != "") {
Sheet sheet = writeSheetHolder.getSheet();
List mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = (CellRangeAddress) mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
public ExcelFillCellMergeStrategy() {
}
public ExcelFillCellMergeStrategy(int[] mergeColumnIndex, int mergeRowIndex, int standardColumnIndex) {
this.mergeColumnIndex = mergeColumnIndex;
this.mergeRowIndex = mergeRowIndex;
this.standardColumnIndex = standardColumnIndex;
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
//当前行
int curRowIndex = cell.getRowIndex();
//当前列
int curColIndex = cell.getColumnIndex();
Sheet sheet = writeSheetHolder.getSheet();
Workbook workbook = sheet.getWorkbook();
// xlsx格式,如果是老版本格式的话就用 HSSFRichTextString
XSSFRichTextString richString = new XSSFRichTextString(cell.getStringCellValue());
if (!StringUtils.isBlank(String.valueOf(richString))) {
Font font = workbook.createFont();
if (cell.getStringCellValue().equals("负责人")) {
font.setBold(true);
font.setFontHeightInPoints((short) 10);
richString.applyFont(font);
// 再设置回每个单元格里
cell.setCellValue(richString);
//遍历循环前列同行的数据设置样式
for (int i = 1; i < curColIndex; i++) {
Cell preCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex - i);
XSSFRichTextString str = new XSSFRichTextString(preCell.getStringCellValue());
if (StringUtils.isBlank(String.valueOf(str))) {
continue;
}
str.applyFont(font);
// 再设置回每个单元格里
preCell.setCellValue(str);
}
} else if (cell.getStringCellValue().equals("参与人") || cell.getStringCellValue().equals("未参与")) {
font.setColor(IndexedColors.GREY_50_PERCENT.getIndex());
richString.applyFont(font);
// 再设置回每个单元格里
cell.setCellValue(richString);
//遍历循环前列同行的数据设置样式
for (int j = 1; j < curColIndex; j++) {
Cell preCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex - j);
XSSFRichTextString str = new XSSFRichTextString(preCell.getStringCellValue());
if (StringUtils.isBlank(String.valueOf(str))) {
continue;
}
str.applyFont(font);
// 再设置回每个单元格里
preCell.setCellValue(str);
}
}
}
if (mergeColumnIndex == null) {
return;
}
if (curRowIndex > mergeRowIndex) {
for (int i = 0; i < mergeColumnIndex.length; i++) {
if (curColIndex == mergeColumnIndex[i]) {
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
break;
}
}
}
}
}
就是导出数据前对规则进行一些拦截
5.组织导出数据
代码如下(示例):
ArrayList<CarrerEvadataVo> vos = new ArrayList<>();
//从团队名称开始组装数据
targetDetailSelfList.forEach(s -> {
List<CareerTeamValueVo> carrerEvadata = s.getCarrerEvadata();
if (CollectionUtils.isEmpty(carrerEvadata)) {
carrerEvadata.addAll(careerTeamValueVos);
}
for (int i = 0; i < carrerEvadata.size(); i++) {
//事项名称
CarrerEvadataVo carrerEvadataVo1 = new CarrerEvadataVo();
carrerEvadataVo1.setName(carrerEvadata.get(i).getTeamName());
carrerEvadataVo1.setAbilt(s.getDimensionName());
carrerEvadataVo1.setSelfEvaResult(s.getSelfEvaluateResult());
carrerEvadataVo1.setSelfEvaReason(s.getSelfEvaluateComment());
if (CollectionUtils.isNotEmpty(evaluateOpinionVoList)) {
StringBuffer finalEvaResult = new StringBuffer();
StringBuffer finalEvaReason = new StringBuffer();
evaluateOpinionVoList.forEach(e -> {
for (int d = 0; d < e.getResultDetailPoList().size(); d++) {
if (s.getExamineScoreRuleDimensionInstanceId()
.equals(e.getResultDetailPoList().get(d)
.getExamineScoreRuleDimensionInstanceId())) {
if (evaluateOpinionVoList.size() > 1) {
finalEvaResult
.append(e.getEvaluateUserName() + ": " + e.getResultDetailPoList()
.get(d).getEvaluateGrade() + "\n");
finalEvaReason
.append(e.getEvaluateUserName() + ": " + e.getResultDetailPoList()
.get(d).getDimensionOpinion() + "\n");
} else {
finalEvaResult
.append(e.getResultDetailPoList().get(d).getEvaluateGrade() + "\n");
finalEvaReason.append(e.getResultDetailPoList().get(d).getDimensionOpinion()
+ "\n");
}
carrerEvadataVo1.setFinalEvaResult(finalEvaResult.toString());
carrerEvadataVo1.setFinalEvaReason(finalEvaReason.toString());
break;
}
}
});
}
vos.add(carrerEvadataVo1);
ArrayList<CareerTeamValueTaskVo> newList = new ArrayList<>();
Integer count = 0;
initData(carrerEvadata.get(i).getTeamValueTaskList(), newList, count);
//Collections.reverse(newList);
for (int j = 0; j < newList.size(); j++) {
CarrerEvadataVo carrerEvadataVo3 = new CarrerEvadataVo();
if (newList.get(j).getLevel() == 1) {
carrerEvadataVo3.setFirstTaskName(newList.get(j).getTaskName());
} else if (newList.get(j).getLevel() == 2) {
carrerEvadataVo3.setSecondTaskName(newList.get(j).getTaskName());
} else {
carrerEvadataVo3.setThirdTaskName(newList.get(j).getTaskName());
}
carrerEvadataVo3.setType(Joiner.on(",")
.join(newList.get(j).getValueTypeList().stream().map(ValueTypeVo::getTagName)
.collect(Collectors.toList())));
carrerEvadataVo3.setRelation(Joiner.on(",")
.join(newList.get(j).getOrgList().stream().map(OrgVo::getName)
.collect(Collectors.toList())));
carrerEvadataVo3.setTarget(newList.get(j).getValueGoal());
carrerEvadataVo3.setResult(newList.get(j).getAchievement());
carrerEvadataVo3.setRole(newList.get(j).getRoleName());
carrerEvadataVo3.setAbilt(s.getDimensionName());
carrerEvadataVo3.setSelfEvaResult(s.getSelfEvaluateResult());
carrerEvadataVo3.setSelfEvaReason(s.getSelfEvaluateComment());
if (CollectionUtils.isNotEmpty(evaluateOpinionVoList)) {
StringBuffer finalEvaResult = new StringBuffer();
StringBuffer finalEvaReason = new StringBuffer();
evaluateOpinionVoList.forEach(e -> {
for (int d = 0; d < e.getResultDetailPoList().size(); d++) {
if (s.getExamineScoreRuleDimensionInstanceId()
.equals(e.getResultDetailPoList().get(d)
.getExamineScoreRuleDimensionInstanceId())) {
if (evaluateOpinionVoList.size() > 1) {
finalEvaResult.append(e.getEvaluateUserName() + ": " + e
.getResultDetailPoList().get(d).getEvaluateGrade() + "\n");
finalEvaReason.append(e.getEvaluateUserName() + ": " + e
.getResultDetailPoList().get(d).getDimensionOpinion() + "\n");
} else {
finalEvaResult
.append(e.getResultDetailPoList().get(d).getEvaluateGrade()
+ "\n");
finalEvaReason
.append(e.getResultDetailPoList().get(d).getDimensionOpinion()
+ "\n");
}
carrerEvadataVo3.setFinalEvaResult(finalEvaResult.toString());
carrerEvadataVo3.setFinalEvaReason(finalEvaReason.toString());
break;
}
}
});
}
vos.add(carrerEvadataVo3);
}
}
});
excelWriter.fill(paramMap, sheet);
excelWriter.fill(vos, sheet);
最后导出填充一起执行
6.导出效果数据
效果如下(示例):
比较潦草多多见谅
总结
提示:这里对文章进行总结:
以上就是今天要讲的内容,本文仅仅简单介绍了easyExcel的使用,而easyExcel提供了大量能使我们快速便捷地处理数据的函数和方法。!