easyexcel设置标题_AlibabaeasyExcel对Excel操作之复杂标
题处理
easyExcle对poi进⾏⼆次封装优化,对外提供了更加⽅便的接⼊⽅式,如果对导出Excle的标题有⽐较复杂的业务需求,那么就要⽤到官⽅提供的2中⽅式(模版填充、⾃定义标题),如果⾃定义标题也不能满⾜我们的需求,例如我们需要在标题中切⼊图⽚需求,要么采⽤第⼀种⽐较简单的模版填充⽅式,但是如果你不想使⽤模版的⽅式,倾向于使⽤java代码来实现,那么本⽂可能对你有所帮助,我们采⽤⾃定义标题加上拦截器。
业务说明,根据业务需要我们需要⽣成如下截图的excel⽂件
对导出⽂件进⾏分析:
1、第⼀⾏合并单元格
2、第⼀⾏中间显⽰图⽚,图⽚是根据其中⼀个字段⽣成的条形码
3、第⼆⾏也是标题
4、从第三⾏开始才是数据
实现⽅案:
1、采⽤模版填充的⽅式,很好实现,将需要填充的单元格⽤变量替换,在程序中使⽤map进⾏数据封装
2、采⽤⾃定义标题,纯java代码,⾃定义标题加拦截器,第⼀步在⾃定义标题中填充除了图⽚以外的数据,第⼆步在拦截器中获取该字段将其转成图⽚,再次写⼊到excel中且调整格式
这篇⽂章我们采⽤第⼆种⽅案
controller层类 ExcelExportController
@GetMapping(value = "/exportExcel")
public void exportExcel(@RequestParam(value = "id") Long id, HttpServletRespon respon) throws IOException {
//封装标题数据 省略
ExcelTitle title = new ExcelTitle();
/
/封装数据 省略
List list = new ArrayList();
ExcelUtils.writeExcel(respon,new InboundCellWriteHandler(),bBillNo(),title), list, "⽂件名称");
}
封装复杂标题head⽅法
private static List> head(String inboundNo , Exceltitle title) {
List> listHead = new ArrayList<>();
List head0 = new ArrayList<>();
head0.add(inboundNo);
head0.add("⼊库单号");
head0.add("序号");
listHead.add(head0);
List head1 = new ArrayList<>();
head1.add("");
head1.InboundBillNo());
head1.add("商品编码");
listHead.add(head1);
List head2 = new ArrayList<>();
head2.add("");
head2.add("⼊库类型");
head2.add("商品名称");
listHead.add(head2);
List head3 = new ArrayList<>();
head3.add("");
head3.BillType());
head3.add("商品条码");
listHead.add(head3);
List head4 = new ArrayList<>();
head4.add("");
head4.add("预计到仓⽇期");
head4.add("预期数量");
listHead.add(head4);
List head5 = new ArrayList<>();
head5.add("");
head5.ExpectArriveStoreTime());
head5.add("清点数量");
listHead.add(head5);
//省略其他字段
return listHead;
}
咱们先看excle的⼯具类,⽐较简单,最后在处理拦截器的逻辑
public static void writeExcel(HttpServletRespon respon,CellWriteHandler handler, List> header, List list, String fileName) throws IOException {
respon.tContentType("application/vnd.ms-excel; chart=utf-8");
respon.tCharacterEncoding("utf-8");
respon.tHeader("Content-Disposition", "attachment;filename=" + de(fileName, "utf-8") + ".xlsx");
EasyExcel.OutputStream()).head(header).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(handler).sheet("sheet1").doWrite(list);
}
最后咱们看 InboundCellWriteHandler拦截器处理逻辑
public class InboundCellWriteHandler implements CellWriteHandler {
//省略beforeCellCreate、afterCellCreate、afterCellDataConverted
@Override
public void afterCellDispo(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List cellDataList, Cell cell, Head head, Integer relativeRowIndex,
Boolean isHead) {
if (!isHead) {
return;
}
if (RowIndex() == 0 && ColumnIndex() == 0) {
Sheet sheet = Sheet();
List headNameList = HeadNameList();
if (CollectionUtils.isEmpty(headNameList)) {
return;
}
String value = null;
cell.tCellValue(value);
//先移除合并第⼀⾏标题的单元格
//再次合并单元格
CellRangeAddress region = new CellRangeAddress(0,0, 0,11);
sheet.addMergedRegionUnsafe(region);
//图⽚的⾼
short i1 = Integer.Row().getHeight() * 4 + Row().getHeight() / 4).shortValue();
|
//根据第⼀⾏标题数据⽣成条形码图⽚
byte[] generate = (0));
int i = Workbook().addPicture(generate, 6);
//⽣成画板
Drawing> drawingPatriarch = DrawingPatriarch();
if (Objects.isNull(drawingPatriarch)){
drawingPatriarch = ateDrawingPatriarch();
}
CreationHelper creationHelper = Workbook().getCreationHelper();
//锁定图⽚所在的位置
ClientAnchor clientAnchor = ateClientAnchor();
clientAnchor.tCol1(3);
clientAnchor.tCol2(5);
clientAnchor.tRow1(0);
clientAnchor.tRow2(0);
clientAnchor.tDx1(0);
clientAnchor.tDy1(0);
clientAnchor.tDx2(0);
clientAnchor.tDy2(1);
clientAnchor.tAnchorType(ClientAnchor.AnchorType.DONT_MOVE_DO_RESIZE); Picture picture = atePicture(clientAnchor, i);
//这个字段必须设置,要不然图⽚显⽰不出来
}
}
总结:对第⼆种⽅式的⼀些思考
1、提⾼了代码的复杂性,⽽且要熟悉poi的⼀些接⼝
2、⽆需另外加载远程excle模版,如果是本地,可能会出现找不到⽂件的情况
3、使⽤拦截器,提⾼excel的格式改变的灵活性
4、使⽤拦截器,能够⽅便我们在后期excel的格式进⾏⼆次修改加⼯
如您对本⽂有疑问或者有任何想说的,请点击进⾏留⾔回复,万千⽹友为您解惑!