EasyExcel导出策略

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel</artifactId>
	<version>3.3.2</version>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel-core</artifactId>
	<version>3.3.2</version>
</dependency>

1.EasyExcel通用的格式策略工具类

import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;

import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;

/**
 * EasyExcel通用的格式策略工具类
 * <p>设置了Excel的基础格式</p>
 * @author
 * @date 2024/9/2
 * @since JDK 17
 */
public class CommonCellStyleStrategy {
	/**
	 * 设置单元格样式
	 *
	 * @date 2024-09-02
	 * @return HorizontalCellStyleStrategy
	 * @since JDK 17
	 * @author
	 */
	public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
		// 表头策略
		WriteCellStyle headerCellStyle = new WriteCellStyle();
		// 表头水平对齐居中
		headerCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		// 背景色
		headerCellStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.getIndex());
		// 表头字体
		WriteFont headerFont = new WriteFont();
		// 字体大小(单位:磅)
		headerFont.setFontHeightInPoints((short) 15);

		headerCellStyle.setWriteFont(headerFont);
		// 自动换行
		headerCellStyle.setWrapped(true);

		// 内容策略
		WriteCellStyle contentCellStyle = new WriteCellStyle();
		// 设置背景色: 需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了
		// FillPatternType所以可以不指定
		//contentCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
		//contentCellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
		// 设置内容靠左对齐
		contentCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
		// 设置字体
		WriteFont contentFont = new WriteFont();
		contentFont.setFontHeightInPoints((short) 12);
		contentCellStyle.setWriteFont(contentFont);
		// 设置自动换行
		contentCellStyle.setWrapped(Boolean.FALSE);
		// 设置边框样式和颜色
		contentCellStyle.setBorderLeft(BorderStyle.MEDIUM);
		contentCellStyle.setBorderTop(BorderStyle.MEDIUM);
		contentCellStyle.setBorderRight(BorderStyle.MEDIUM);
		contentCellStyle.setBorderBottom(BorderStyle.MEDIUM);
//		contentCellStyle.setTopBorderColor(IndexedColors.RED.getIndex());
//		contentCellStyle.setBottomBorderColor(IndexedColors.GREEN.getIndex());
//		contentCellStyle.setLeftBorderColor(IndexedColors.YELLOW.getIndex());
//		contentCellStyle.setRightBorderColor(IndexedColors.ORANGE.getIndex());

		return new HorizontalCellStyleStrategy(headerCellStyle, contentCellStyle);
	}
}

2.精细化控制单元格内容

import java.util.List;

import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;

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;

/**
 * 精细化控制单元格内容
 *
 * @author
 * @date 2024/9/2
 * @since JDK 17
 */
public class CustomCellWriteHandler implements CellWriteHandler {
	/**
	 * 创建单元格之前的操作
	 */
	@Override
	public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
			Head head, Integer integer, Integer integer1, Boolean aBoolean) {
	}

	/**
	 * 创建单元格之后的操作
	 */
	@Override
	public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
			Head head, Integer integer, Boolean aBoolean) {
	}

	/**
	 * 单元格内容转换之后的操作
	 */
	@Override
	public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
			WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
	}

	/**
	 * 单元格处理后(已写入值)的操作
	 */
	@Override
	public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
			List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
		// 设置超链接
		if (isHead && cell.getRowIndex() == 0 && cell.getColumnIndex() == 0) {
			CreationHelper helper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
			Hyperlink hyperlink = helper.createHyperlink(HyperlinkType.URL);
			hyperlink.setAddress("https://github.com/alibaba/easyexcel");
			cell.setHyperlink(hyperlink);
		}
		// 精确设置单元格格式
		boolean bool = isHead && cell.getRowIndex() == 1;

		if (bool) {
			// 获取工作簿
			Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
			CellStyle cellStyle = workbook.createCellStyle();

			Font cellFont = workbook.createFont();
			cellFont.setBold(Boolean.TRUE);
			cellFont.setFontHeightInPoints((short) 14);
			cellFont.setColor(IndexedColors.SEA_GREEN.getIndex());
			cellStyle.setFont(cellFont);
			cell.setCellStyle(cellStyle);
		}
	}
}

3.自适应列宽

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;

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;

/**
 * 自适应列宽
 *
 * @author
 * @date 2024/9/2
 * @since JDK 17
 */
public class CustomCellWriteWidthConfig extends AbstractColumnWidthStyleStrategy {

	private final 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.isNotEmpty(cellDataList);

		if (needSetWidth) {
			Map<Integer, Integer> maxColumnWidthMap = CACHE.computeIfAbsent(writeSheetHolder.getSheetNo(),
					k -> new HashMap<>());

			Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
			// 单元格文本长度大于60换行
			if (columnWidth >= 0) {
				if (columnWidth > 60) {
					columnWidth = 60;
				}
				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);
				}
			}
		}
	}

	/**
	 * 计算长度
	 *
	 * @param cellDataList
	 * @param cell
	 * @param isHead
	 * @return aInteger
	 */
	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:
					// 换行符(数据需要提前解析好)
					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;
				}
			}
		}
	}
}

4.自适应行高

import java.util.Iterator;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;

import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;

/**
 * 自适应行高
 * @author
 * @date 2024/9/2
 * @since JDK 17
 */
public class CustomCellWriteHeightConfig extends AbstractRowHeightStyleStrategy {
	/** 默认高度 */
	private static final Integer DEFAULT_HEIGHT = 300;

	/**
	 * Sets the height of header
	 *
	 * @param row
	 * @param relativeRowIndex
	 */
	@Override
	protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
	}

	/**
	 * Sets the height of content
	 *
	 * @param row
	 * @param relativeRowIndex
	 */
	@Override
	protected void setContentColumnHeight(Row row, int relativeRowIndex) {
		Iterator<Cell> cellIterator = row.cellIterator();
		if (!cellIterator.hasNext()) {
			return;
		}
		// 默认为 1行高度
		int maxHeight = 1;
		while (cellIterator.hasNext()) {
			Cell cell = cellIterator.next();
			if (cell.getCellTypeEnum() == CellType.STRING) {
				String value = cell.getStringCellValue();
				int len = value.length();
				int num = 0;
				if (len > 50) {
					num = len % 50 > 0 ? len / 50 : len / 2 - 1;
				}
				if (num > 0) {
					for (int i = 0; i < num; i++) {
						value = value.substring(0, (i + 1) * 50 + i) + "\n"
								+ value.substring((i + 1) * 50 + i, len + i);
					}
				}
				if (value.contains("\n")) {
					int length = value.split("\n").length;
					maxHeight = Math.max(maxHeight, length) + 1;
				}
			}
		}
		row.setHeight((short) ((maxHeight) * DEFAULT_HEIGHT));
	}
}

5.导出

@ApiOperation(value = "导出")
@PostMapping("/export")
public void export(HttpServletResponse response, @RequestBody BidDesignFillPageRequest request) {
	log.info("导出-开始.请求参数:{}", JSON.toJSONString(request));

	ServletOutputStream os = null;

	try {
		this.setExcelResponseProp(response, "设计单位填报列表");
		// 查询
		List<MigrateBidDesignFillExcelVo> list = migrateBidDesignFillService.queryForExport(request);

		os = response.getOutputStream();

		EasyExcel.write(os).head(MigrateBidDesignFillExcelVo.class).excelType(ExcelTypeEnum.XLSX).sheet("设计单位填报列表")
				// 注册通用格式策略
				.registerWriteHandler(CommonCellStyleStrategy.getHorizontalCellStyleStrategy())
				// 设置自定义格式策略
				.registerWriteHandler(new CustomCellWriteHandler())
				// 自适应列宽
				.registerWriteHandler(new CustomCellWriteWidthConfig())
				// 自适应行高
				.registerWriteHandler(new CustomCellWriteHeightConfig())
				.doWrite(list);

		log.info("导出-成功.请求参数:{}", JSON.toJSONString(request));
	} catch (Exception e) {
		log.error(String.format("导出-失败.请求参数:%s", JSON.toJSONString(request)), e);
	} finally {
		IOUtils.closeQuietly(os);
	}
}

/**
 * 设置响应结果
 *
 * @param response    响应结果对象
 * @param rawFileName 文件名
 * @throws UnsupportedEncodingException 不支持编码异常
 */
private void setExcelResponseProp(HttpServletResponse response, String rawFileName)
		throws UnsupportedEncodingException {
	response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
	response.setCharacterEncoding("utf-8");
	String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
	response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
}

6.MigrateBidDesignFillExcelVo

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

/**
 * 导出设计单位填报 excel数据
 *
 * @author wenjianhai
 * @date 2024/8/26
 * @since JDK 17
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class MigrateBidDesignFillExcelVo implements Serializable {
	@Serial
	private static final long serialVersionUID = -1724305623558672671L;

	/** 指挥部名称 */
	@ExcelProperty(value = "指挥部名称", index = 0)
	// @ColumnWidth(20)
	private String districtName;

	/** 标段名称 */
	@ExcelProperty(value = "标段名称", index = 1)
	// @ColumnWidth(40)
	private String bidName;

	/** 标段编号 */
	@ExcelProperty(value = "标段编号", index = 2)
	// @ColumnWidth(20)
	private String bidCode;

	/** 涉及线路 */
	@ExcelProperty(value = "涉及线路", index = 3)
	// @ColumnWidth(30)
	private String lineName;

	/** 涉及县区 */
	@ExcelProperty(value = "涉及县区", index = 4)
	// @ColumnWidth(20)
	private String countyName;

	/** 资金类型 */
	@ExcelProperty(value = "资金类型", index = 5)
	// @ColumnWidth(30)
	private String fundTypeName;

	/** 资金名称 */
	@ExcelProperty(value = "资金名称", index = 6)
	// @ColumnWidth(20)
	private String fundName;

	/** 单位 */
	@ExcelProperty(value = "单位", index = 7)
	// @ColumnWidth(15)
	private String unit;

	/** 实物数量 */
	@ExcelProperty(value = "实物数量", index = 8)
	// @ColumnWidth(20)
	// @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT) // 左对齐
	private BigDecimal materialCount;

	/** 初设批复金额(万元) */
	@ExcelProperty(value = "初设批复金额(万元)", index = 9)
	// @ColumnWidth(20)
	// @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT) // 左对齐
	private BigDecimal designReplyAmount;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值