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 {

    /** 主键 */
    @ExcelIgnore
    private 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";
        // 构建ExcelWriter
        ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();
        // 构建sheet
        WriteSheet writeSheet = EasyExcel.writerSheet("切刀管控台账数据").head(CutterControl.class).build();
        // 写sheet
        excelWriter.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 {

    /** 主键 */
    @ExcelIgnore
    private 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 {

    /** 主键 */
    @ExcelIgnore
    private 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);

            @Override
            public void invoke(CutterControl data, AnalysisContext context) {
                cachedDataList.add(data);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
            }

            /**
             * 加上存储数据库
             */
            private void saveData() {
                cutterControlService.batchInsertCutterControl(cachedDataList);
                log.info("{}条数据,开始存储数据库!", cachedDataList.size());
                log.info("存储数据库成功!");
            }
        }).sheet().doRead();
        return R.ok();
    }
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用Java导出Excel合并单元格的示例代码: ```java import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelExportDemo { public static void main(String[] args) throws Exception { // 创建工作簿 Workbook workbook = new XSSFWorkbook(); // 创建工作表 XSSFSheet sheet = (XSSFSheet) workbook.createSheet("Sheet1"); // 创建单元格样式 XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle(); // 设置单元格对齐方式 style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); // 创建字体 XSSFFont font = (XSSFFont) workbook.createFont(); font.setFontName("宋体"); font.setFontHeightInPoints((short) 14); font.setBold(true); // 设置字体颜色 font.setColor(IndexedColors.BLACK.getIndex()); // 将字体应用到单元格样式 style.setFont(font); // 创建单元格合并区域 CellRangeAddress region = new CellRangeAddress(0, 0, 0, 3); // 将单元格合并到工作表中 sheet.addMergedRegion(region); // 创建表头行 List<String> headers = new ArrayList<>(); headers.add("序号"); headers.add("姓名"); headers.add("年龄"); headers.add("性别"); // 创建表头单元格 for (int i = 0; i < headers.size(); i++) { sheet.createRow(1).createCell(i).setCellValue(headers.get(i)); } // 写入数据 for (int i = 0; i < 10; i++) { sheet.createRow(i + 2).createCell(0).setCellValue(i + 1); sheet.getRow(i + 2).createCell(1).setCellValue("张三" + i); sheet.getRow(i + 2).createCell(2).setCellValue(20 + i); sheet.getRow(i + 2).createCell(3).setCellValue("男"); } // 设置表头样式 for (int i = 0; i < headers.size(); i++) { sheet.getRow(1).getCell(i).setCellStyle(style); } // 设置列宽 for (int i = 0; i < headers.size(); i++) { sheet.setColumnWidth(i, 20 * 256); } // 输出Excel文件 FileOutputStream outputStream = new FileOutputStream("test.xlsx"); workbook.write(outputStream); outputStream.close(); workbook.close(); } } ``` 这段代码将创建一个名为“Sheet1”的Excel工作表,并在第一行合并四个单元格,作为表头。然后,它将在第二行创建表头单元格,并在第三行及以下写入数据。最后,将输出Excel文件“test.xlsx”。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾十方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值