Java导出Excel并合并单元格

需求:需要在导出excel时合并指定的单元格

 ruoyi excel

项目基于若伊框架二次开发,本着能用现成的就不自己写的原则,先是尝试了@Excel注解中needMerge属性

     /*** 是否需要纵向合并单元格,应对需求:含有list集合单元格)*/public boolean needMerge() default false;

查了一圈别人的使用,大致是需要定义一个List集合,集合元素为对象,对象中的属性标注@Excel注解,并表明name属性

照葫芦画瓢

@Getter
@Setter
@ToString
public class CutterControlVO {/** 主键 */private Long id;/** 工厂编码 */@Excel(name = "工厂编码",needMerge = true)private String factoryCode;/** 产线编码 */@Excel(name = "产线编码",needMerge = true)private String productionLineCode;/** 设备编号 */@Excel(name = "设备编号",needMerge = true)private String deviceNumber;/** 设备名称 */@Excel(name = "设备名称",needMerge = true)private String deviceName;@Excel(name = "检测刀具编码",needMerge = true)private String cutterCode;/** 换刀时间 */@JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@Excel(name = "换刀时间",dateFormat = "yyyy-MM-dd HH:mm:ss",needMerge = true)private Date cutterChangeTime;/** 上刀数 */@Excel(name = "上刀数",needMerge = true)private Integer upperKnifeNumber;/** 下刀数 */@Excel(name = "下刀数",needMerge = true)private Integer lowerKnifeNumber;@Excel(name = "更换人员",needMerge = true)private String modifyUser;/** 备注 */@Excel(name = "备注",needMerge = true)private String remark;@Excel(name = "换刀位置")private List<CutterVO> cutterChangePosition;@Excel(name = "累计分切米数")private List<CutterVO> accumulatedCuttingMeters;}
@Getter
@Setter
@ToString
public class CutterVO {@Excel(name = "上刀左")private Integer upperKnifeLeft;@Excel(name = "上刀中")private Integer upperKnifeCenter;@Excel(name = "上刀右")private Integer upperKnifeRight;@Excel(name = "下刀左")private Integer lowerKnifeLeft;@Excel(name = "下刀中")private Integer lowerKnifeCenter;@Excel(name = "下刀右")private Integer lowerKnifeRight;
}
@PostMapping("/export")
public void export(HttpServletResponse response) throws Exception{List<CutterControl> cutterControlList = cutterControlService.getCutterControlList();//设置导出的数据表格式List<CutterControlVO> cutterControlVOList = new ArrayList<>();CutterControlVO cutterControlVO = null;for (CutterControl cutterControl : cutterControlList) {cutterControlVO = new CutterControlVO();CutterVO cutterPosition = new CutterVO();cutterPosition.setUpperKnifeLeft(cutterControl.getCutterChangePositionUpperKnifeLeft());cutterPosition.setUpperKnifeCenter(cutterControl.getCutterChangePositionUpperKnifeCenter());cutterPosition.setUpperKnifeRight(cutterControl.getCutterChangePositionUpperKnifeRight());cutterPosition.setLowerKnifeLeft(cutterControl.getCutterChangePositionLowerKnifeLeft());cutterPosition.setLowerKnifeCenter(cutterControl.getCutterChangePositionLowerKnifeCenter());cutterPosition.setLowerKnifeRight(cutterControl.getCutterChangePositionLowerKnifeRight());CutterVO accumulatedCuttingMeters = new CutterVO();accumulatedCuttingMeters.setUpperKnifeLeft(cutterControl.getAccumulatedCuttingMetersUpperKnifeLeft());accumulatedCuttingMeters.setUpperKnifeCenter(cutterControl.getAccumulatedCuttingMetersUpperKnifeCenter());accumulatedCuttingMeters.setUpperKnifeRight(cutterControl.getAccumulatedCuttingMetersUpperKnifeRight());accumulatedCuttingMeters.setLowerKnifeLeft(cutterControl.getAccumulatedCuttingMetersLowerKnifeLeft());accumulatedCuttingMeters.setLowerKnifeCenter(cutterControl.getAccumulatedCuttingMetersLowerKnifeCenter());accumulatedCuttingMeters.setLowerKnifeRight(cutterControl.getAccumulatedCuttingMetersLowerKnifeRight());BeanUtils.copyProperties(cutterControl,cutterControlVO);cutterControlVO.setCutterChangePosition(Arrays.asList(cutterPosition));cutterControlVO.setAccumulatedCuttingMeters(Arrays.asList(accumulatedCuttingMeters));cutterControlVOList.add(cutterControlVO);}ExcelUtil<CutterControlVO> util = new ExcelUtil<CutterControlVO>(CutterControlVO.class);util.exportExcel(response,cutterControlVOList,"切刀管控台账数据");
}

查看导出效果:

黑人问号脸?

突然想到别人都是采用的是一个List集合,于是我注释了一个List,此时效果如下:

 可以看到,一个List效果是正常显示的,数据获取和显示也是正常的。

若伊使用的Excel导出工具类底层采用apache poi ,只能导出简单的excel表格,涉及复杂excel表格或者需要自定义表格时就比较难操作

使用阿里的easyExcel来实现复杂excel表格的导出

easyExcel

首先引入POM依赖

    <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.7</version></dependency>

1、不合并单元格的写法

实体类

@Getter
@Setter
public class CutterControl {/** 主键 */@ExcelIgnoreprivate Long id;/** 工厂编码 */@ExcelProperty(value = "工厂编码")private String factoryCode;/** 产线编码 */@ExcelProperty(value = "产线编码")private String productionLineCode;/** 设备编号 */@ExcelProperty(value = "设备编号")private String deviceNumber;/** 设备名称 */@ExcelProperty(value = "设备名称")private String deviceName;@ExcelProperty(value = "检测刀具编码")private String cutterCode;@ExcelProperty(value = "上刀左")private Integer cutterChangePositionUpperKnifeLeft;@ExcelProperty(value = "上刀中")private Integer cutterChangePositionUpperKnifeCenter;@ExcelProperty(value = "上刀右")private Integer cutterChangePositionUpperKnifeRight;@ExcelProperty(value = "下刀左")private Integer cutterChangePositionLowerKnifeLeft;@ExcelProperty(value = "下刀中")private Integer cutterChangePositionLowerKnifeCenter;@ExcelProperty(value = "下刀右")private Integer cutterChangePositionLowerKnifeRight;@ExcelProperty(value = "上刀左")private Integer accumulatedCuttingMetersUpperKnifeLeft;@ExcelProperty(value = "上刀中")private Integer accumulatedCuttingMetersUpperKnifeCenter;@ExcelProperty(value = "上刀右")private Integer accumulatedCuttingMetersUpperKnifeRight;@ExcelProperty(value = "下刀左")private Integer accumulatedCuttingMetersLowerKnifeLeft;@ExcelProperty(value = "下刀中")private Integer accumulatedCuttingMetersLowerKnifeCenter;@ExcelProperty(value = "下刀右")private Integer accumulatedCuttingMetersLowerKnifeRight;/** 换刀时间 */@JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@ExcelProperty(value = "换刀时间")@ColumnWidth(20)private Date cutterChangeTime;/** 上刀数 */@ExcelProperty(value = "上刀数")private Integer upperKnifeNumber;/** 下刀数 */@ExcelProperty(value = "下刀数")private Integer lowerKnifeNumber;@ExcelProperty(value = "更换人员")private String modifyUser;/** 备注 */@ExcelProperty(value = "备注")private String remark;}

@ExcelIgnore :设置表格忽略该属性

@ColumnWidth(20): 设置列宽

controller代码

  @PostMapping("/export")public void export(HttpServletResponse response) throws Exception{List<CutterControl> cutterControlList = cutterControlService.getCutterControlList();String fileName = System.getProperty("user.dir") + "/" + System.currentTimeMillis() + ".xlsx";// 构建ExcelWriterExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();// 构建sheetWriteSheet writeSheet = EasyExcel.writerSheet("切刀管控台账数据").head(CutterControl.class).build();// 写sheetexcelWriter.write(cutterControlList, writeSheet);excelWriter.finish();}
结果:

2、自定义列合并策略

参考eastExcel文档可知,在实体类上添加属性即可实现我想要的效果

写Excel | Easy Excel

@Getter
@Setter
@EqualsAndHashCode
public class ComplexHeadData {@ExcelProperty({"主标题", "字符串标题"})private String string;@ExcelProperty({"主标题", "日期标题"})private Date date;@ExcelProperty({"主标题", "数字标题"})private Double doubleData;
}

再次照葫芦画瓢

@Getter
@Setter
public class CutterControl {/** 主键 */@ExcelIgnoreprivate Long id;/** 工厂编码 */@ExcelProperty(value = "工厂编码")private String factoryCode;/** 产线编码 */@ExcelProperty(value = "产线编码")private String productionLineCode;/** 设备编号 */@ExcelProperty(value = "设备编号")private String deviceNumber;/** 设备名称 */@ExcelProperty(value = "设备名称")private String deviceName;@ExcelProperty(value = "检测刀具编码")private String cutterCode;@ExcelProperty({"换刀位置", "上刀左"})private Integer cutterChangePositionUpperKnifeLeft;@ExcelProperty({"换刀位置", "上刀中"})private Integer cutterChangePositionUpperKnifeCenter;@ExcelProperty({"换刀位置", "上刀右"})private Integer cutterChangePositionUpperKnifeRight;@ExcelProperty({"换刀位置", "下刀左"})private Integer cutterChangePositionLowerKnifeLeft;@ExcelProperty({"换刀位置", "下刀中"})private Integer cutterChangePositionLowerKnifeCenter;@ExcelProperty({"换刀位置", "下刀右"})private Integer cutterChangePositionLowerKnifeRight;@ExcelProperty({"累计分切米数", "上刀左"})private Integer accumulatedCuttingMetersUpperKnifeLeft;@ExcelProperty({"累计分切米数", "上刀中"})private Integer accumulatedCuttingMetersUpperKnifeCenter;@ExcelProperty({"累计分切米数", "上刀右"})private Integer accumulatedCuttingMetersUpperKnifeRight;@ExcelProperty({"累计分切米数", "下刀左"})private Integer accumulatedCuttingMetersLowerKnifeLeft;@ExcelProperty({"累计分切米数", "下刀中"})private Integer accumulatedCuttingMetersLowerKnifeCenter;@ExcelProperty({"累计分切米数", "下刀右"})private Integer accumulatedCuttingMetersLowerKnifeRight;/** 换刀时间 */@JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@ExcelProperty(value = "换刀时间")@ColumnWidth(20)private Date cutterChangeTime;/** 上刀数 */@ExcelProperty(value = "上刀数")private Integer upperKnifeNumber;/** 下刀数 */@ExcelProperty(value = "下刀数")private Integer lowerKnifeNumber;@ExcelProperty(value = "更换人员")private String modifyUser;/** 备注 */@ExcelProperty(value = "备注")private String remark;}

其余不用修改

效果如下:

若需要导出excel在浏览器,修改Controller代码如下:

 @GetMapping("/export")public void export(HttpServletResponse response) throws Exception{List<CutterControl> cutterControlList = cutterControlService.getCutterControlList();String fileName = new String("切刀管控台账数据.xlsx");fileName = URLEncoder.encode(fileName, "UTF-8");response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf8");response.setHeader("Content-disposition", "attachment;filename=" + fileName );EasyExcel.write(response.getOutputStream(),CutterControl.class).sheet("切刀管控台账数据").doWrite(cutterControlList);}

3、自定义行合并策略

具体业务暂时用不到,需要的可参考这个博客

https://www.cnblogs.com/monianxd/p/16359369.html

导入excel并处理同名列

由于实体类中存在excel列名重复的情况,所以如果不进行处理,会出现只有一个有值的情况,最简单的处理方式如下:

同名列添加所在位置的索引,默认从0开始

@Getter
@Setter
public class CutterControl {/** 主键 */@ExcelIgnoreprivate Long id;/** 工厂编码 */@ExcelProperty(value = "工厂编码")private String factoryCode;/** 产线编码 */@ExcelProperty(value = "产线编码")private String productionLineCode;/** 设备编号 */@ExcelProperty(value = "设备编号")private String deviceNumber;/** 设备名称 */@ExcelProperty(value = "设备名称")private String deviceName;@ExcelProperty(value = "检测刀具编码")private String cutterCode;@ExcelProperty(value = {"换刀位置", "上刀左"},index = 5)private Integer cutterChangePositionUpperKnifeLeft;@ExcelProperty(value = {"换刀位置", "上刀中"},index = 6)private Integer cutterChangePositionUpperKnifeCenter;@ExcelProperty(value = {"换刀位置", "上刀右"},index = 7)private Integer cutterChangePositionUpperKnifeRight;@ExcelProperty(value = {"换刀位置", "下刀左"},index = 8)private Integer cutterChangePositionLowerKnifeLeft;@ExcelProperty(value = {"换刀位置", "下刀中"},index = 9)private Integer cutterChangePositionLowerKnifeCenter;@ExcelProperty(value = {"换刀位置", "下刀右"},index = 10)private Integer cutterChangePositionLowerKnifeRight;@ExcelProperty(value = {"累计分切米数", "上刀左"},index = 11)private Integer accumulatedCuttingMetersUpperKnifeLeft;@ExcelProperty(value = {"累计分切米数", "上刀中"},index = 12)private Integer accumulatedCuttingMetersUpperKnifeCenter;@ExcelProperty(value = {"累计分切米数", "上刀右"},index = 13)private Integer accumulatedCuttingMetersUpperKnifeRight;@ExcelProperty(value = {"累计分切米数", "下刀左"},index = 14)private Integer accumulatedCuttingMetersLowerKnifeLeft;@ExcelProperty(value = {"累计分切米数", "下刀中"},index = 15)private Integer accumulatedCuttingMetersLowerKnifeCenter;@ExcelProperty(value = {"累计分切米数", "下刀右"},index = 16)private Integer accumulatedCuttingMetersLowerKnifeRight;/** 换刀时间 */@JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@ExcelProperty(value = "换刀时间")@ColumnWidth(20)private Date cutterChangeTime;/** 上刀数 */@ExcelProperty(value = "上刀数")private Integer upperKnifeNumber;/** 下刀数 */@ExcelProperty(value = "下刀数")private Integer lowerKnifeNumber;@ExcelProperty(value = "更换人员")private String modifyUser;/** 备注 */@ExcelProperty(value = "备注")private String remark;}

导入Controller代码

@PostMapping("/import")public R importData(@RequestParam(value = "file") MultipartFile file) throws IOException {String fileName = file.getOriginalFilename();String suffixName = fileName.substring(fileName.lastIndexOf("."));if (!(suffixName.equals(".xlsx"))) {return R.fail("请上传xlsx格式文件");}EasyExcel.read(file.getInputStream(), CutterControl.class, new ReadListener<CutterControl>() {/*** 单次缓存的数据量*/public static final int BATCH_COUNT = 100;/***临时存储*/private List<CutterControl> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Overridepublic void invoke(CutterControl data, AnalysisContext context) {cachedDataList.add(data);if (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {saveData();}/*** 加上存储数据库*/private void saveData() {cutterControlService.batchInsertCutterControl(cachedDataList);log.info("{}条数据,开始存储数据库!", cachedDataList.size());log.info("存储数据库成功!");}}).sheet().doRead();return R.ok();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/413871.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VsCode + CMake构建项目 C/C++连接Mysql数据库 | 数据库增删改查C++封装 | 信息管理系统通用代码 ---- 课程笔记

这个是B站Up主&#xff1a;程序员程子青的视频 C封装Mysql增删改查操作_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1m24y1a79o/?p6&spm_id_frompageDriver&vd_sourcea934d7fc6f47698a29dac90a922ba5a3安装mysql:mysql 下载和安装和修改MYSQL8.0 数据库存储…

小封装高稳定性振荡器 Sg2520egn / sg2520vgn, sg2520ehn / sg2520vhn

描述 随着物联网和ADAS等5G应用的实施&#xff0c;数据流量不断增长&#xff0c;网络基础设施变得比以往任何时候都更加重要。IT供应商一直在快速建设数据中心&#xff0c;并且对安装在数据中心内部/内部的光模块有很大的需求。此应用需要具有“小”&#xff0c;“低抖动”和“…

助力焊接场景下自动化缺陷检测识别,基于YOLOv5【n/s/m/l/x】全系列参数模型开发构建工业焊接场景下缺陷检测识别分析系统

焊接是一个不陌生但是对于开发来说相对小众的场景&#xff0c;在我们前面的博文开发实践中也有一些相关的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《轻量级模型YOLOv5-Lite基于自己的数据集【焊接质量检测】从零构建模型超详细教程》 《基于DeepLabV3Pl…

ReactNative中样式与布局的书写

样式 const styles StyleSheet.create({container: {flex: 1,justifyContent: center,alignItems: center,backgroundColor: #F5FCFF,}, welcome: {fontSize: 20, textAlign: center,margin: 10, }, instructions: {textAlign: center,color: #333333,marginBottom: 5,}, …

【Git】常用的Git操作集合

常用的Git操作集合 1. 分支操作1.1 查看本地所有分支git branch 1.2 查看所有分支&#xff08;包含本地远程仓库&#xff09;git branch -a 1.3 切换分支git checkout test 2. 常用基本操作2.1 查看 git 各存储区内(文件)状态git status 2.2 查看工作区与暂存区文件差异git dif…

【MCAL】ADC模块详解

目录 前言 正文 1.ADC模块介绍 2.关键概念及依赖的模块 2.1 ADC依赖的模块 3.ADC功能示例 3.1 ADC Buffer Access Mode示例 3.1.1配置&#xff08;Configuration&#xff09; 3.1.2 初始化&#xff08;Initialization&#xff09; 3.1.3 Adc_GetStreamLastPointer的使…

鸿蒙开发(五)鸿蒙UI开发概览

从用户角度来讲&#xff0c;一个软件拥有好看的UI&#xff0c;那是锦上添花的事情。再精确的算法&#xff0c;再厉害的策略&#xff0c;最终都得通过UI展现给用户并且跟用户交互。那么&#xff0c;本篇一起学习下鸿蒙开发UI基础知识&#xff0c;认识下各种基本控件以及使用方式…

Jmeter后置处理器——JSON提取器

目录 1、简介 2、使用步骤 1&#xff09;添加线程组 2&#xff09;添加http请求 3&#xff09; 添加JSON提取器 1、简介 JSON是一种简单的数据交换格式&#xff0c;允许互联网应用程序快速传输数据。JSON提取器可以从JSON格式响应数据中提取数据、简化从JSON原始数据中提取特定…

【MIdjourney】一些材质相关的关键词

1.多维剪纸(Multidimensional papercut) "Multidimensional papercut"&#xff08;多维剪纸&#xff09;是一种剪纸艺术形式&#xff0c;通过多层次的剪纸技巧和设计来创造出立体感和深度感。这种艺术形式通常涉及在不同的纸层上剪裁不同的图案&#xff0c;并将它们…

Windows连接Ubuntu桌面

平时Windows连接Ubuntu服务器都是使用Xshell、FinalShell等工具&#xff0c;但这些连接之后只能通过终端进行操作&#xff0c;无法用桌面方式与服务器交互。 本文介绍如何通过工具&#xff0c;实现Window连接远程Ubuntu服务器&#xff0c;并使用桌面方式交互。 系统版本&#x…

easyui渲染隐藏域<input type=“hidden“ />为textbox可作为分割条使用

最近在修改前端代码的时候&#xff0c;偶然发现使用javascript代码渲染的方式将<input type"hidden" />渲染为textbox时&#xff0c;会显示一个神奇的效果&#xff0c;这个textbox输入框并不会隐藏&#xff0c;而是显示未一个细条&#xff0c;博主发现非常适合…

Google 在裁员的路上一路狂奔

早上刷新闻&#xff0c;Google 在 2024 开年还没几天就宣布了今年的裁员计划。 前几天还在说我们当地的大学为了削减预算而进行裁员。 大厂谷歌却是首当其冲&#xff0c;裁员1000多人&#xff0c;涉及了核心工程、谷歌助理、Pixel手机等硬件团队的人员。 截至2023年9月30日&…