EasyExcel导入导出操作

ops/2024/12/23 6:27:36/

一、导出操作

1、简单数据导出

1.1 导出示例

java">//import com.alibaba.excel.EasyExcel;
//import com.alibaba.excel.support.ExcelTypeEnum;
//import com.alibaba.excel.write.metadata.style.WriteCellStyle;
//import com.alibaba.excel.write.metadata.style.WriteFont;
//import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
//import org.apache.poi.ss.usermodel.HorizontalAlignment;
//import org.apache.poi.ss.usermodel.IndexedColors;	/*** 导出报表信息*/
@SneakyThrows
@GetMapping("/exportReport")
public void exportReport(HttpServletResponse response) {String fileNameOri = "销售信息报表.xlsx";// 文件名中文名需要转义String fileName = URLEncoder.encode(fileNameOri, "UTF-8");String contentType = 		MediaTypeFactory.getMediaType(fileName).map(MimeType::toString).orElse("application/vnd.ms-excel");response.setContentType(contentType);response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);// 这里需要设置不关闭流WriteCellStyle headWriteCellStyle = new WriteCellStyle();//设置背景颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 11);headWriteCellStyle.setWriteFont(headWriteFont);//内容策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 10);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);//填充数据List<WebSalesReportExportVO> webSalesReportExportVOS = new ArrayList<>();EasyExcel.write(response.getOutputStream(), WebSalesReportExportVO.class).autoCloseStream(Boolean.FALSE).excelType(ExcelTypeEnum.XLSX).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//自动列宽策略.sheet("销售信息")//获取数据填充.doWrite(webSalesReportExportVOS);
}

1.2 导出实体

java">@Data
public class WebSalesReportExportVO {@ExcelProperty(value = "序号")private Integer rowNum;@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")@DateTimeFormat("yyyy-MM-dd")@ExcelProperty("日期")private Date sendGoodsDate;//日期@ExcelProperty("占用天数")private Integer moneyFundDay;@ContentStyle(dataFormat = 49)@ExcelProperty("毛利率%")private String dayProfitRatio;}

2、带下拉列表的模板导出

2.1 导出示例

java">//import com.alibaba.excel.EasyExcel;
//import com.alibaba.excel.support.ExcelTypeEnum;
//import com.alibaba.excel.write.metadata.style.WriteCellStyle;
//import com.alibaba.excel.write.metadata.style.WriteFont;
//import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
//import org.apache.poi.ss.usermodel.HorizontalAlignment;
//import org.apache.poi.ss.usermodel.IndexedColors;	/*** 导出报表信息*/@SneakyThrows@ApiOperation("下载订单信息模板")@GetMapping("/downloadTemp")public void downloadTemp(HttpServletResponse response) {String fileNameOri = "订单信息模板.xlsx";// 文件名中文名需要转义String fileName = URLEncoder.encode(fileNameOri, "UTF-8");String contentType = MediaTypeFactory.getMediaType(fileName).map(MimeType::toString).orElse("application/vnd.ms-excel");response.setContentType(contentType);response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);// 这里需要设置不关闭流WriteCellStyle headWriteCellStyle = new WriteCellStyle();//设置背景颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 11);headWriteCellStyle.setWriteFont(headWriteFont);//内容策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 10);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);HorizontalCellStyleStrategy horizontalCellStyleStrategy =new HorizontalCellStytleStrategy(headWriteCellStyle, contentWriteCellStyle);TmpVO tmpVO = new TmpVO();tmpVO.setOrderNo("示例");tmpVO.setProductCode("11148000001");tmpVO.setBatch("批次");tmpVO.setProductionDate(new Date());List<TmpVO> dataList = Collections.singletonList(tmpVO);EasyExcel.write(response.getOutputStream(), TmpVO.class).autoCloseStream(Boolean.FALSE).excelType(ExcelTypeEnum.XLSX).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//自动列宽策略.registerWriteHandler(new SalesOrderExcelWriteHandler()).sheet("订单信息")//获取数据填充.doWrite(dataList);}

2.2 导出模板实体

java">@Data
@ColumnWidth(15)
public class TmpVO {@NotBlank(message = "商品编码不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*商品编码", index = 0)private String productCode;@NotBlank(message = "订单号不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*订单号", index = 2)private String orderNo;@NotBlank(message = "批次不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*批次", index = 3)private String batch;@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")@DateTimeFormat("yyyy-MM-dd")
//    @ContentStyle(dataFormat = 14)@ExcelProperty(value = "生产日期", index = 4)private Date productionDate;
}

2.2 下拉列表数据处理(SalesOrderExcelWriteHandler)

2.2.1 简单的下拉(数据量小)
java">import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.util.CollectionUtils;import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;/*** Created by chenz on 2024/09/11*/
public class SalesOrderExcelWriteHandler implements SheetWriteHandler {@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {//通过sheet处理下拉信息Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();//获取下拉列表数据List<HashMap<String, Object>> unitByNames = new ArrayList<>();if (!CollectionUtils.isEmpty(unitByNames)) {List<String> unitNames = unitByNames.stream().map(stringObjectHashMap -> stringObjectHashMap.get("name").toString()).collect(Collectors.toList());//构建ArrayString[] unitNameArray = unitNames.toArray(new String[0]);//表示 第1行起第1000行终止 作用于第6列CellRangeAddress areaAddr = new CellRangeAddress(1, 1000, 6, 6);CellRangeAddressList areaRangeList = new CellRangeAddressList();areaRangeList.addCellRangeAddress(areaAddr);DataValidationConstraint areaConstraint = helper.createExplicitListConstraint(unitNameArray);DataValidation areaValidation = helper.createValidation(areaConstraint, areaRangeList);sheet.addValidationData(areaValidation);}//如果多个继续构建DataValidation使用sheet.addValidationData(areaValidation)添加}
}
2.2.2 复杂的下拉(数据量大,采用隐藏sheet页方式)
java">import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;import java.util.List;
import java.util.stream.Collectors;/*** Created by chenz on 2023/08/09*/
public class SalesOrderExcelWriteHandler implements SheetWriteHandler {@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {//通过sheet处理下拉信息Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();//获取需要填充的下拉数据List<Estate> estateList = new ArrayList<>();List<String> estateName = estateList.stream().map(Estate::getEstateName).collect(Collectors.toList());String[] estateNameArray = estateName.toArray(new String[0]);Workbook workbook = writeWorkbookHolder.getWorkbook();if (estateNameArray.length > 0) {String estateHiddenName = "下拉信息";Sheet estateHidden = workbook.createSheet(estateHiddenName);Cell estateCell = null;for (int i = 0, length = estateNameArray.length; i < length; i++) {String name = estateNameArray[i];Row row = estateHidden.createRow(i);estateCell = row.createCell(0);estateCell.setCellValue(name);}Name estateNamedCell = workbook.createName();estateNamedCell.setNameName(estateHiddenName);Integer estateNameFormulaName = estateNameArray.length;if (estateNameArray.length == 0) {estateNameFormulaName = 1;}estateNamedCell.setRefersToFormula(estateHiddenName + "!$A$1:$A$" + estateNameFormulaName);//获取新sheet页内容XSSFDataValidationConstraint estateConstraint = new XSSFDataValidationConstraint(DataValidationConstraint.ValidationType.LIST,estateNamedCell.getRefersToFormula());//表示 第1行起第1000行终止 作用于第6列CellRangeAddressList estateAddr = new CellRangeAddressList(1, 1000, 8, 8);DataValidation estateValidation = helper.createValidation(estateConstraint, estateAddr);// 将sheet设置为隐藏workbook.setSheetHidden(workbook.getSheetIndex(estateHidden), false);sheet.addValidationData(estateValidation);}//简单的下拉//获取下拉列表数据List<HashMap<String, Object>> unitByNames = new ArrayList<>();if (!CollectionUtils.isEmpty(unitByNames)) {List<String> unitNames = unitByNames.stream().map(stringObjectHashMap -> stringObjectHashMap.get("name").toString()).collect(Collectors.toList());//构建ArrayString[] unitNameArray = unitNames.toArray(new String[0]);//表示 第1行起第1000行终止 作用于第6列CellRangeAddress areaAddr = new CellRangeAddress(1, 1000, 6, 6);CellRangeAddressList areaRangeList = new CellRangeAddressList();areaRangeList.addCellRangeAddress(areaAddr);DataValidationConstraint areaConstraint = helper.createExplicitListConstraint(unitNameArray);DataValidation areaValidation = helper.createValidation(areaConstraint, areaRangeList);sheet.addValidationData(areaValidation);}}
}

3、自定义标题导出

3.1 导出示例

java">//import com.alibaba.excel.EasyExcel;
//import com.alibaba.excel.support.ExcelTypeEnum;
//import com.alibaba.excel.write.metadata.style.WriteCellStyle;
//import com.alibaba.excel.write.metadata.style.WriteFont;
//import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
//import org.apache.poi.ss.usermodel.HorizontalAlignment;
//import org.apache.poi.ss.usermodel.IndexedColors;	@SneakyThrows@Overridepublic R exportFeePayTmp(FeePayTmpPO feePayTmpPO) {//变动表头标题行String dateTitle = ""收费记录表"(截止到" + LocalDateTimeUtil.formatNormal(LocalDateTime.now()) + ")";HttpServletResponse response = WebUtils.getResponse();String fileNameOri = "收费记录.xlsx";// 文件名中文名需要转义String fileName = URLEncoder.encode(fileNameOri, "UTF-8");String contentType = MediaTypeFactory.getMediaType(fileName).map(MimeType::toString).orElse("application/vnd.ms-excel");response.setContentType(contentType);response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);try {//获取的填充数据List<PayTmpVO> payTmpVoList = new ArrayList<>();// 这里需要设置不关闭流WriteCellStyle headWriteCellStyle = new WriteCellStyle();//设置背景颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 11);headWriteCellStyle.setWriteFont(headWriteFont);//内容策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 10);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);HorizontalCellStyleStrategy horizontalCellStyleStrategy =new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);List<FeeTempExcelExportVO> dataList = new ArrayList<>();payTmpVoList.forEach(feePayTmpVO -> {FeeTempExcelExportVO feeTempExcelExportVO = new FeeTempExcelExportVO();BeanUtils.copyProperties(feePayTmpVO, feeTempExcelExportVO);dataList.add(feeTempExcelExportVO);});EasyExcel.write(response.getOutputStream()).autoCloseStream(Boolean.FALSE).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new FeeTempExcelExportVO.CustomizeColumnWidth()).head(FeeTempExcelExportVO.myriadPeopleHead(title)).sheet("收费统计")//获取数据填充.doWrite(dataList);return null;} catch (Exception e) {e.printStackTrace();// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");}return R.failed("导出失败");}

3.2 导出模板实体(自定义标题处理)

java">import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** 收费导出*/
@Data
@ColumnWidth(15)
public class FeeTempExcelExportVO implements Serializable {private static final long serialVersionUID = 1911240458081823913L;@ExcelProperty(value = "收款金额", index = 0)private String price;@ExcelProperty(value = "付款方式", index = 1)private String payType;@ExcelProperty(value = "应收", index = 2)private String payPrice;@ExcelProperty(value = "实收", index = 3)private String realPrice;@ExcelProperty(value = "备注", index = 4)private String remark;//可自定义指定列的宽度public static class CustomizeColumnWidth extends AbstractColumnWidthStyleStrategy {@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean isHead) {CellStyle cellStyle = cell.getCellStyle();if (isHead && cell.getRowIndex() == 1) {int columnWidth = cell.getStringCellValue().getBytes().length;int cellIndex = cell.getColumnIndex();switch (cellIndex) {case 0:columnWidth = 25;break;case 4:columnWidth = 25;break;default:columnWidth = 15;break;}writeSheetHolder.getSheet().setColumnWidth(cellIndex, columnWidth * 200);} else if (!isHead && cell.getRowIndex() != 1) {int cellIndex = cell.getColumnIndex();if (cellIndex == 0) {cell.setCellValue(DateUtil.format(DateUtil.parse(cell.getStringCellValue()), "yyyy/MM/dd HH:mm:ss"));cell.setCellType(CellType.STRING);cellStyle.setDataFormat((short) 164);}if (cellIndex == 5) {cell.setCellType(CellType.STRING);cellStyle.setDataFormat((short) 49);}}if ( cell.getRowIndex()==0){writeSheetHolder.getSheet().getRow(0).setHeight((short) 600);}}}/*** 自定义标题** @param title 传入的标题* @return*/public static List<List<String>> myriadPeopleHead(String title) {//进行表头拼接List<List<String>> list = new ArrayList<>();List<String> head0 = new ArrayList<>();head0.add(title);head0.add("收款金额");List<String> head1 = new ArrayList<>();head1.add(title);head1.add("付款方式");List<String> head2 = new ArrayList<>();head2.add(title);head2.add("应收");List<String> head3 = new ArrayList<>();head3.add(title);head3.add("实收");List<String> head4 = new ArrayList<>();head4.add(title);head4.add("备注");list.add(head0);list.add(head1);list.add(head2);list.add(head3);list.add(head4);return list;}
}

4、自定义表头导出

4.1 导出示例

java">//import com.alibaba.excel.EasyExcel;
//import com.alibaba.excel.support.ExcelTypeEnum;
//import com.alibaba.excel.write.metadata.style.WriteCellStyle;
//import com.alibaba.excel.write.metadata.style.WriteFont;
//import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
//import org.apache.poi.ss.usermodel.HorizontalAlignment;
//import org.apache.poi.ss.usermodel.IndexedColors;	@SneakyThrows@Overridepublic R statisticsAreaExport() {String fileName = "estate类型统计表.xlsx";// 文件名中文名需要转义fileName = URLEncoder.encode(fileName, "UTF-8");// 文件名中文名需要转义String contentType = MediaTypeFactory.getMediaType(fileName).map(MimeType::toString).orElse("application/vnd.ms-excel");HttpServletResponse response = WebUtils.getResponse();response.setContentType(contentType);response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);try {//获取所有的数据集合  key代表的每一行的数据标识Map<String, List<EstateTypeAreaStatisticVO>> statisticsAreaAllMap = new HashMap<>();WriteCellStyle headWriteCellStyle = new WriteCellStyle();//设置背景颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 11);headWriteCellStyle.setWriteFont(headWriteFont);//内容策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 10);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);HorizontalCellStyleStrategy horizontalCellStyleStrategy =new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);//渲染的结果数据List<List<String>> dataListResult = new ArrayList<>();List<EstateTypeAreaStatisticVO> estateTypeAreaStatisticHeaderList = new ArrayList<>();//每一行的数据整理 key为行标识for (Map.Entry<String, List<EstateTypeAreaStatisticVO>> entity : statisticsAreaAllMap.entrySet()) {String marketName = entity.getKey();List<EstateTypeAreaStatisticVO> estateTypeAreaStatisticVOS = entity.getValue();if (estateTypeAreaStatisticHeaderList.size() == 0) {estateTypeAreaStatisticHeaderList = estateTypeAreaStatisticVOS;//使用内容数据作为表头依据}//每一行数据List<String> data = new ArrayList<>();data.add(marketName);//循环构建一行的所有数据for (EstateTypeAreaStatisticVO estateTypeAreaStatisticVO : estateTypeAreaStatisticVOS) {String estateTypeName = estateTypeAreaStatisticVO.getEstateTypeName();String buildingArea = estateTypeAreaStatisticVO.getBuildingArea();String saledArea = estateTypeAreaStatisticVO.getSaledArea();String canRentArea = estateTypeAreaStatisticVO.getCanRentArea();String rentedArea = estateTypeAreaStatisticVO.getRentedArea();String selfUseArea = estateTypeAreaStatisticVO.getSelfUseArea();String backRentArea = estateTypeAreaStatisticVO.getBackRentArea();String backRentedArea = estateTypeAreaStatisticVO.getBackRentedArea();String canRentRatio = estateTypeAreaStatisticVO.getCanRentRatio();String averageRent = estateTypeAreaStatisticVO.getAverageRent();String propertyFee = estateTypeAreaStatisticVO.getPropertyFee();//根据表头顺序填充if ("公共".equals(estateTypeName)) {data.add(buildingArea);data.add(estateTypeAreaStatisticVO.getUseArea());} else {data.add(buildingArea);data.add(saledArea);data.add(canRentArea);data.add(rentedArea);data.add(selfUseArea);data.add(backRentArea);data.add(backRentedArea);data.add(canRentRatio);data.add(averageRent);data.add(propertyFee);}}//所有行数据dataListResult.add(data);}EasyExcel.write(response.getOutputStream()).autoCloseStream(Boolean.FALSE).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new EstateTypeAreaStatisticExcelExportVO.CustomizeColumnWidth()).head(EstateTypeAreaStatisticExcelExportVO.myriadPeopleHead(estateTypeAreaStatisticHeaderList)).sheet("物业类型统计表")//获取数据填充.doWrite(dataListResult);return null;} catch (Exception e) {e.printStackTrace();// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");}return R.failed("导出失败");}

4.2 导出模板实体(自定义标题处理)

java">import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;import java.util.ArrayList;
import java.util.List;/*** 物业类型面积统计导出VO** @author chenz* @date 2021-09-28 15:04:02*/
@Data
public class EstateTypeAreaStatisticExcelExportVO {//自定义列宽public static class CustomizeColumnWidth extends AbstractColumnWidthStyleStrategy {@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean isHead) {CellStyle cellStyle = cell.getCellStyle();if (isHead && cell.getRowIndex() == 1) {int columnWidth = cell.getStringCellValue().getBytes().length;int cellIndex = cell.getColumnIndex();switch (cellIndex) {case 0:columnWidth = 25;break;default:columnWidth = 15;break;}writeSheetHolder.getSheet().setColumnWidth(cellIndex, columnWidth * 200);}}}/*** 自定义表头** @param estateTypeAreaStatisticVOList 每=一行的数据集* @return*/public static List<List<String>> myriadPeopleHead(List<EstateTypeAreaStatisticVO> estateTypeAreaStatisticVOList) {String title = "estate类型报表";List<List<String>> list = new ArrayList<>();List<String> head0 = new ArrayList<>();head0.add(title);head0.add("项目");list.add(head0);//循环所有数据构造行级表头estateTypeAreaStatisticVOList.forEach(estateTypeAreaStatisticVO -> {String estateTypeName = estateTypeAreaStatisticVO.getEstateTypeName();if ("公共".equals(estateTypeName)) {for (int i = 0; i < 2; i++) {List<String> head1 = new ArrayList<>();head1.add(title);head1.add(estateTypeAreaStatisticVO.getEstateTypeName());String headerName;switch (i) {case 0:headerName = "建筑面积(㎡)";break;case 1:headerName = "使用面积(㎡)";break;default:headerName = "建筑面积(㎡)";break;}head1.add(headerName);list.add(head1);}} else {for (int i = 0; i < 10; i++) {List<String> head1 = new ArrayList<>();head1.add(title);head1.add(estateTypeAreaStatisticVO.getEstateTypeName());String headerName;switch (i) {case 0:headerName = "建筑面积(㎡)";break;case 1:headerName = "已售面积(㎡)";break;case 2:headerName = "自持可租总面积(㎡)";break;case 3:headerName = "自持已租总面积(㎡)";break;case 4:headerName = "自持自用总面积(㎡)";break;case 5:headerName = "已售返租面积(㎡)";break;case 6:headerName = "返租已租面积(㎡)";break;case 7:headerName = "可租出租率";break;case 8:headerName = "平均租金(元/年)";break;case 9:headerName = "物业费标准(元/年)";break;default:headerName = "建筑面积(㎡)";break;}head1.add(headerName);list.add(head1);}}});return list;}
}

4.3 参考内容实体

java">import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/*** 类型面积统计** @author chenz* @date 2021-09-28 15:04:02*/
@Data
public class EstateTypeAreaStatisticVO {@ApiModelProperty(value = "类型名称")private String estateTypeName;@ApiModelProperty(value = "建筑面积")private String buildingArea;@ApiModelProperty(value = "使用面积")private String useArea;@ApiModelProperty(value = "已售面积")private String saledArea;@ApiModelProperty(value = "可租总面积")private String canRentArea;@ApiModelProperty(value = "已租总面积")private String rentedArea;@ApiModelProperty(value = "自用总面积-未售+自用")private String selfUseArea;@ApiModelProperty(value = "已售返租总面积")private String backRentArea;@ApiModelProperty(value = "返租已租总面积")private String backRentedArea;@ApiModelProperty(value = "可租出租率")private String canRentRatio;@ApiModelProperty(value = "平均租金")private String averageRent;@ApiModelProperty(value = "物业费标准")private String propertyFee;
}

5、合并列导出

5.1 导出示例

java">//import com.alibaba.excel.EasyExcel;
//import com.alibaba.excel.support.ExcelTypeEnum;
//import com.alibaba.excel.write.metadata.style.WriteCellStyle;
//import com.alibaba.excel.write.metadata.style.WriteFont;
//import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
//import org.apache.poi.ss.usermodel.HorizontalAlignment;
//import org.apache.poi.ss.usermodel.IndexedColors;	@SneakyThrows@Overridepublic void exportPayDetail() {String fileName = "收费明细.xlsx";// 文件名中文名需要转义fileName = URLEncoder.encode(fileName, "UTF-8");// 文件名中文名需要转义String contentType = MediaTypeFactory.getMediaType(fileName).map(MimeType::toString).orElse("application/vnd.ms-excel");HttpServletResponse response = WebUtils.getResponse();response.setContentType(contentType);response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);try {//获取需要导出的数据List<DetailVO> detailVOList = new ArrayList<>();WriteCellStyle headWriteCellStyle = new WriteCellStyle();//设置背景颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 11);headWriteCellStyle.setWriteFont(headWriteFont);//内容策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 10);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);HorizontalCellStyleStrategy horizontalCellStyleStrategy =new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);List<PayDetailExportVO> dataList = new ArrayList<>();for (DetailVO detailVO : detailVOList) {PayDetailExportVO p = new PayDetailExportVO();BeanUtils.copyProperties(detailVO, p);dataList.add(p);}//需要合并的列int[] mergeColumeIndex = {1, 2, 3, 4, 5, 6, 7, 8};//从第二行后开始合并int mergeRowIndex = 1;EasyExcel.write(response.getOutputStream(), DetailExportVO.class).autoCloseStream(Boolean.FALSE).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new MultiColumnMergeStrategyHandler(mergeRowIndex, mergeColumeIndex)).sheet("收费明细")//获取数据填充.doWrite(dataList);} catch (Exception e) {e.printStackTrace();// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");}}

5.2 导出模板实体

java">package com.entity4cloud.entity.admin.api.vo.excel;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import io.swagger.annotations.ApiModel;
import lombok.Data;import java.math.BigDecimal;
import java.util.Date;/*** Created by chenz on 2023/11/30*/
@Data
@ColumnWidth(15)
@ApiModel(value = "收费单含明细导出数据")
public class DetailExportVO {@ContentStyle(dataFormat = 49)@ExcelProperty(value = "合同名称")private String contractName;@DateTimeFormat("yyyy/MM/dd")@ExcelProperty(value = "合同开始日期")private Date contractStartDate;@DateTimeFormat("yyyy/MM/dd")@ExcelProperty(value = "合同结束日期")private Date contractEndDate; 
}

5.3 合并列处理(MultiColumnMergeStrategyHandler)

java">import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
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.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
/*** 指定列相同 合并单元格策略** Created by chenz on 2023/11/30*/
public class MultiColumnMergeStrategyHandler implements CellWriteHandler {private int[] mergeColumnIndex;private int mergeRowIndex;public MultiColumnMergeStrategyHandler() {}/*** //需要合并的列(参与合并的列) 从1开始* int[] mergeColumeIndex = {1, 3};* //从第二行后开始合并* int mergeRowIndex = 2;** @param mergeRowIndex    //需要合并的列* @param mergeColumnIndex*/public MultiColumnMergeStrategyHandler(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {//当前行int curRowIndex = cell.getRowIndex();//当前列int curColIndex = cell.getColumnIndex();if (curRowIndex > mergeRowIndex) {for (int i = 0; i < mergeColumnIndex.length; i++) {if (curColIndex == mergeColumnIndex[i] - 1) {mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);break;}}}}/*** 当前单元格向上合并** @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).getCell(curColIndex);Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();// 将当前单元格数据与上一个单元格数据比较Boolean dataBool = preData.equals(curData);Boolean bool = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue());if (dataBool && bool) {Sheet sheet = writeSheetHolder.getSheet();List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();boolean isMerged = false;for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {CellRangeAddress cellRangeAddr = 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);}}}
}

二、导入操作

1 导入示例

java">    @SneakyThrows@ApiOperation("导入订单信息")@PostMapping("/import")public R<List<AgencySalesOrderDetailVO>> importSaleOrderDetails(@RequestPart MultipartFile file, HttpServletRequest request) {ListAnalysisEventListener<AgencySalesOrderDetailTmpVO> readListener = BeanUtils.instantiateClass(ListAnalysisEventListener.class);EasyExcel.read(file.getInputStream(), AgencySalesOrderDetailTmpVO.class, readListener).registerConverter(LocalDateStringConverter.INSTANCE).registerConverter(LocalDateTimeStringConverter.INSTANCE).ignoreEmptyRow(true).sheet().doRead();List<AgencySalesOrderDetailTmpVO> dataRowList = readListener.getList();String errors = readListener.getErrorInfo();if (!StrUtil.isEmpty(errors)) {return R.failed(errors);}if (CollectionUtils.isEmpty(dataRowList)) {return R.failed("内容为空");}//业务处理return agencySalesOrderDetailVOR;}

2 导入日期转换(LocalDateStringConverter)

java">import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;/*** Created by chenz on 2024/09/05*/
public enum LocalDateStringConverter implements Converter<LocalDate> {INSTANCE;private LocalDateStringConverter() {}@Overridepublic Class supportJavaTypeKey() {return LocalDate.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}public LocalDate convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException {if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern(contentProperty.getDateTimeFormatProperty().getFormat());return LocalDate.parse(cellData.getStringValue(), formatter);} else {return LocalDate.parse(cellData.getStringValue());}}@Overridepublic WriteCellData<String> convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {DateTimeFormatter formatter;if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {formatter = DateTimeFormatter.ofPattern(contentProperty.getDateTimeFormatProperty().getFormat());} else {formatter = DateTimeFormatter.ISO_LOCAL_DATE;}return new WriteCellData(value.format(formatter));}
}
javascript">import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;/*** Created by chenz on 2024/09/05*/
public enum LocalDateTimeStringConverter implements Converter<LocalDateTime> {INSTANCE;private static final String MINUS = "-";private LocalDateTimeStringConverter() {}@Overridepublic Class supportJavaTypeKey() {return LocalDateTime.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException {String stringValue = cellData.getStringValue();String pattern;if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {pattern = contentProperty.getDateTimeFormatProperty().getFormat();} else {pattern = switchDateFormat(stringValue);}DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);return LocalDateTime.parse(cellData.getStringValue(), formatter);}@Overridepublic WriteCellData<String> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {String pattern;if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {pattern = contentProperty.getDateTimeFormatProperty().getFormat();} else {pattern = "yyyy-MM-dd HH:mm:ss";}DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);return new WriteCellData(value.format(formatter));}private static String switchDateFormat(String dateString) {int length = dateString.length();switch (length) {case 10:return "yyyy-MM-dd";case 11:case 12:case 13:case 15:case 16:case 18:default:throw new IllegalArgumentException("can not find date format for:" + dateString);case 14:return "yyyyMMddHHmmss";case 17:return "yyyyMMdd HH:mm:ss";case 19:return dateString.contains("-") ? "yyyy-MM-dd HH:mm:ss" : "yyyy/MM/dd HH:mm:ss";}}
}

3 导入解析事件监听器(ListAnalysisEventListener)

java">import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;/*** excel列表解析事件监听器* 处理异常信息* Created by chenz on 2024/09/05*/
public class ListAnalysisEventListener<T> extends AnalysisEventListener<T> {private static final Logger log = LoggerFactory.getLogger(ListAnalysisEventListener.class);private final List<T> list = new ArrayList<>();private final List<ErrorMessage> errorMessageList = new ArrayList<>();private Long lineNum = 1L;public ListAnalysisEventListener() {}@Overridepublic void invoke(T o, AnalysisContext analysisContext) {Long var3 = this.lineNum;Long var4 = this.lineNum = this.lineNum + 1L;Set<ConstraintViolation<Object>> violations = Validators.validate(o);if (!violations.isEmpty()) {Set<String> messageSet = (Set) violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());this.errorMessageList.add(new ErrorMessage(this.lineNum, messageSet));} else {this.list.add(o);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.debug("Excel read analysed");}public List<T> getList() {return this.list;}public List<ErrorMessage> getErrors() {return this.errorMessageList;}/*** 为空则无错误信息** @return*/public String getErrorInfo() {List<ErrorMessage> errors = this.errorMessageList;if (errors.size() > 0) {StringBuilder sb = new StringBuilder();for (ErrorMessage error : errors) {Long lineNum = error.getLineNum();Set<String> errorSet = error.getErrors();String errMsg = errorSet.iterator().next();sb.append("第").append(lineNum).append("行").append(errMsg).append(";");}return sb.toString();}return null;}public static class Validators {private static final Validator validator;public Validators() {}public static <T> Set<ConstraintViolation<T>> validate(T object) {return validator.validate(object);}static {ValidatorFactory factory = Validation.buildDefaultValidatorFactory();validator = factory.getValidator();}}
}

1.4 模板示例

java">import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;/*** 模板vo* Created by chenz on 2024/09/05*/
@Data
@ColumnWidth(15)
public class AgencySalesOrderDetailTmpVO {@NotBlank(message = "商品编码不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*商品编码", index = 0)private String productCode;@NotBlank(message = "产地不能为空")@ExcelProperty(value = "*产地", index = 1)private String place;@NotBlank(message = "订单号不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*订单号", index = 2)private String orderNo;@NotBlank(message = "批次/厂号不能为空")@ContentStyle(dataFormat = 49)@ExcelProperty(value = "*批次/厂号", index = 3)private String batch;@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")@DateTimeFormat("yyyy-MM-dd")@ExcelProperty(value = "生产日期", index = 4)private Date productionDate;
}

http://www.ppmy.cn/ops/117625.html

相关文章

LabVIEW提高开发效率技巧----利用第三方库和工具

LabVIEW开发不仅依赖于自身强大的图形化编程能力&#xff0c;还得益于其庞大的用户社区和丰富的第三方库。这些工具和库能够帮助开发者快速解决问题&#xff0c;提升开发效率&#xff0c;避免从头开始编写代码。 1. LabVIEW工具网络&#xff08;NI Tools Network&#xff09; …

Git 使用方法

简介 Git常用命令 Git 全局设置 获取Git 仓库 方法二用的比较多 将仓库链接复制 在 git base here ----> git clone 仓库链接 工作区、暂存区、版本库 Git 工作区中文件中的状态 本地仓库的操作 远程仓库操作 git pull 将代码推送到远程仓库 1. git add 文件名 ---放…

基于微信开发助手企鹅音乐微信小程序的设计与实现(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

【CSS/HTML】圣杯布局和双飞翼布局实现两侧宽度固定,中间宽度自适应及其他扩展实现

前沿简介 圣杯布局和双飞翼布局是前端重要的布局方式。两者的功能相同&#xff0c;都是为了实现一个两侧宽度固定&#xff0c;中间宽度自适应的三栏布局。 圣杯布局来源于文章In Search of the Holy Grail,双飞翼布局来源于淘宝UED。 两者的实现方式有差异&#xff0c;但是都…

【图像处理】多幅不同焦距的同一个物体的平面图象,合成一幅具有立体效果的单幅图像原理(一)

合成一幅具有立体效果的单幅图像&#xff0c;通常是利用多个不同焦距的同一物体的平面图像&#xff0c;通过图像处理技术实现的。以下是该过程的基本原理&#xff1a; 1. 立体视觉原理 人眼的立体视觉是通过双眼观察物体的不同视角而获得的。两只眼睛的位置不同&#xff0c;使…

C语言进阶之泛型列表(Generic List)

1.前言 数据结构是需要泛型的,而在C语言中实现泛型就只能去用指针魔法了,来跟我一起实现吧!所有代码经测试未发现明显bug,可放心食用. 2.代码截图展示 1.list.h 2.main.c 3.list.c 3.结语 这次分享的列表采用动态数组的方式实现,下次我会去用链表实现,两种实现方式各有优劣,希…

JS设计模式之组合模式:打造灵活高效的对象层次结构

引言 当我们构建复杂的应用程序时&#xff0c;经常会遇到处理对象层次结构的情况。这些层次结构通常是树形结构&#xff0c;由组合节点和叶子节点组成。在这样的情况下&#xff0c;JavaScript 设计模式之一的组合模式就能派上用场。 组合模式是一种结构型设计模式&#xff0c…

Vue3 中 this 一分钟了解

Vue3 中 this 在Vue3的开发过程中&#xff0c;this的使用方式和Vue2有着显著的不同&#xff0c;特别是在组合式API&#xff08;Composition API&#xff09;的引入后。本文将深入探讨Vue3中this的使用&#xff0c;解析其底层源码&#xff0c;并探讨这种设计背后的原因&#xff…