easyexcel内容追加与单元格合并

这篇具有很好参考价值的文章主要介绍了easyexcel内容追加与单元格合并。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

    这里的需求是,如果表格不存在,则新建表格,并填入数据,如果表格存在,那么就追加内容,并且支持单元格合并。

    内容追加,需要分两种方式插入,第一种就是没有表格,需要生成表头,并且插入内容,第二种就是已经有了表格,这个表格作为模板并,不用设置表头,直接追加内容,这里需要生成一个新的表格,如果有必要,最后还要删除老的表格。

    关于单元格合并,网上有这样的示例,使用easyexcel来实现,我们就是需要定义一个CellWriteHandler的接口实现,在实现类中,覆盖afterCellDispose()方法,本例中就是CustomCellWriteHandler类。

    这里为了验证我们的结果,我们利用springboot构建两个不同的请求,一个是创建excel,一个是追加excel。

    主要代码如下:

    依赖文件: 

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel-core</artifactId>
	<version>3.2.1</version>
</dependency>

     控制器类:

import com.example.service.ExcelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/excel")
public class ExcelController {

    @Autowired
    private ExcelService excelService;

    @GetMapping("/create")
    public ResponseEntity create() {
        return ResponseEntity.ok(excelService.create());
    }

    @GetMapping("/append")
    public ResponseEntity append() {
        return ResponseEntity.ok(excelService.append());
    }
}

    服务类:

package com.example.service;

import com.alibaba.excel.EasyExcel;
import com.example.config.CustomCellWriteHandler;
import com.example.dao.ExcelDao;
import com.example.model.ExcelData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;

@Service
public class ExcelService {

    @Autowired
    private ExcelDao excelDao;

    private String fileName = "e:\\test\\student.xlsx";

    private String tempName = "e:\\test\\temp.xlsx";

    private int mergeRowIndex = 0;

    private int[] mergeColumnIndexes = {0, 1, 2};

    public boolean create() {
        File out = new File(fileName);
        EasyExcel.write(out, ExcelData.class)
                .sheet("student")
                .registerWriteHandler(new CustomCellWriteHandler(mergeRowIndex,mergeColumnIndexes))
                .doWrite(excelDao.createData());
        return true;
    }

    public boolean append() {
        File out = new File(fileName);
        File temp = new File(tempName);
        if (out.exists()) {
            // 采用模板方式写入
            EasyExcel.write(out).needHead(false)
                    .withTemplate(out)
                    .file(temp)
                    .sheet("student")
                    .registerWriteHandler(new CustomCellWriteHandler(mergeRowIndex,mergeColumnIndexes))
                    .doWrite(excelDao.appendData());
            // out.delete();
            // temp.renameTo(out);
        }
        return true;
    }


}

    数据接口模拟类:

package com.example.dao;

import com.example.model.ExcelData;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class ExcelDao {
    public List<ExcelData> createData() {
        List<ExcelData> list = new ArrayList<>();
        list.add(new ExcelData("罗芳",18, "female","语文",100));
        list.add(new ExcelData("罗芳",18, "female","数学",99));
        list.add(new ExcelData("王芳",17, "female","语文",80));
        list.add(new ExcelData("王芳",17, "female","数学",60));
        return list;
    }

    public List<ExcelData> appendData() {
        List<ExcelData> list = new ArrayList<>();
        list.add(new ExcelData("张雪琴",18, "female","语文",88));
        list.add(new ExcelData("张雪琴",18, "female","数学",75));
        list.add(new ExcelData("王勇",18, "male","语文",80));
        list.add(new ExcelData("王勇",18, "male","数学",92));
        return list;
    }
}

     表格实体类:

package com.example.model;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class ExcelData {
    @ExcelProperty("学生姓名")
    private String name;

    @ExcelProperty("年龄")
    private int age;

    @ExcelProperty("性别")
    private String gender;

    @ExcelProperty({"课程", "课程名称"})
    private String courseName;

    @ExcelProperty({"课程", "分数"})
    private double score;
}

    表格单元格合并策略类:

package com.example.config;

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;
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;


public class CustomCellWriteHandler implements CellWriteHandler {

    private int mergeRowIndex;
    private int[] mergeColumnIndexes;

    public CustomCellWriteHandler(int mergeRowIndex, int[] mergeColumnIndexes) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndexes = mergeColumnIndexes;
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> 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 < mergeColumnIndexes.length; i++) {
                if (curColIndex == mergeColumnIndexes[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Row prevRow = cell.getSheet().getRow(curRowIndex - 1);
        if (prevRow != null) {
            Cell prevCell = prevRow.getCell(curColIndex);
            Object prevData = prevCell.getCellType() == CellType.STRING ? prevCell.getStringCellValue() : prevCell.getNumericCellValue();
            boolean isDataSame = curData.equals(prevData);
            if (isDataSame) {
                Sheet sheet = writeSheetHolder.getSheet();
                List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
                boolean isMerged = false;
                for (int i = 0; i < mergeRegions.size(); i++) {
                    CellRangeAddress cellRangeAddress = mergeRegions.get(i);
                    if (cellRangeAddress.isInRange(curRowIndex - 1, curColIndex)) {
                        sheet.removeMergedRegion(i);
                        cellRangeAddress.setLastRow(curRowIndex);
                        sheet.addMergedRegionUnsafe(cellRangeAddress);
                        isMerged = true;
                    }
                }
                if (!isMerged) {
                    CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                    sheet.addMergedRegion(cellRangeAddress);
                }
            }
        }
    }


}

    运行示例,分别访问 http://localhost:8080/excel/create 和 http://localhost:8080/excel/append 。

    最后会生成两个文件,分别是e:\test\student.xlsx  e:\test\temp.xlsx,内容如下所示:

easyexcel内容追加与单元格合并

    内容是符合预期的,第一个只有两个学生信息,第二个表格因为是追加的,所以有四个学生信息。但是单元格合并,我们指定的是0,1,2三列,也就是姓名,年龄,性别需要合并,实际中他们确实合并了,但是似乎合并的超出了范围。我们希望合并的是同样学生的年龄和性别,而不是所有数值一样的年龄、性别。

    解决办法就是在合并策略里面增加一个判断,如果合并行的列值(当前属性列age,gender)相同,而且第一列值(唯一属性name)也相同那么合并,而不是列的内容相同就合并。

    变更过的合并策略主体逻辑:

private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
	Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
	Row prevRow = cell.getSheet().getRow(curRowIndex - 1);
	Row curRow = cell.getSheet().getRow(curRowIndex);
	if (prevRow == null) {
		prevRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
	}
	Cell prevFirstColCell = prevRow.getCell(0);
	Cell curFirstColCell = curRow.getCell(0);
	Object prevFirstColData = prevFirstColCell.getCellType() == CellType.STRING ? prevFirstColCell.getStringCellValue() : prevFirstColCell.getNumericCellValue();
	Object curFirstColData = curFirstColCell.getCellType() == CellType.STRING ? curFirstColCell.getStringCellValue() : curFirstColCell.getNumericCellValue();
	Cell prevCell = prevRow.getCell(curColIndex);
	Object prevData = prevCell.getCellType() == CellType.STRING ? prevCell.getStringCellValue() : prevCell.getNumericCellValue();
	boolean isDataSame = curData.equals(prevData) && curFirstColData.equals(prevFirstColData);
	if (isDataSame) {
		Sheet sheet = writeSheetHolder.getSheet();
		List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
		boolean isMerged = false;
		for (int i = 0; i < mergeRegions.size(); i++) {
			CellRangeAddress cellRangeAddress = mergeRegions.get(i);
			if (cellRangeAddress.isInRange(curRowIndex - 1, curColIndex)) {
				sheet.removeMergedRegion(i);
				cellRangeAddress.setLastRow(curRowIndex);
				sheet.addMergedRegionUnsafe(cellRangeAddress);
				isMerged = true;
			}
		}
		if (!isMerged) {
			CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
			sheet.addMergedRegion(cellRangeAddress);
		}
	}

}

    生成的表格: 

easyexcel内容追加与单元格合并

    单元格合并范围超出问题似乎解决了,完美。 

    有的代码里面,在获取上一行记录某列的时候,代码是这样的:

Cell prevCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);

    在实际中,这里可能会报空指针异常,其实数据在缓存里面,我们需要这样来获取:

Row prevRow = cell.getSheet().getRow(curRowIndex - 1);
if (prevRow == null) {
	prevRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
}

    或者,在后面的逻辑里面加上判断 if (prevRow != null) 也是可以的。文章来源地址https://www.toymoban.com/news/detail-420995.html

到了这里,关于easyexcel内容追加与单元格合并的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Pandas读取excel合并单元格的正确姿势(openpyxl合并单元格拆分并填充内容)

    在pandas读取excel经常会遇到合并单元格的问题。例如: 此时使用pandas读取到的内容为: 如果去百度,几乎所有人会说应该用如下代码: 这样看起来没问题,但是,该解决方案并不能适用于所有场景,甚至会造成数据错误。 例如: 对班级和备注填充后: 孙武空本来是数据缺

    2024年02月03日
    浏览(42)
  • 【Python COM】Word 自动纵向合并相同内容单元格

    docxtempl 库不支持动态纵向合并单元格,所以写了这段代码用来曲线救国。 需要纵向合并的单元格加上在文本末尾加上“【纵向合并】”,然后调用此函数,就会自动纵向合并相同内容的单元格。 需要安装 pywin32 库。 有一定概率会出现各种 pywintypes.com_err ,一般再多试几次就

    2024年02月12日
    浏览(31)
  • C++ 写入txt文件内容并追加内容

    咨询通义千问的“C++ 写入txt文件内容并追加内容”: 可以使用ofstream类来写入txt文件内容。若想追加内容,可以使用ios::app标志来创建输出流对象,然后在写入时将其设置为ios::app。以下是一个示例代码: 在这个例子中,我们创建了一个名为“example.txt”的输出流对象,并将

    2024年02月11日
    浏览(43)
  • C#创建文件写入及追加内容

    1.判断文件是否存在,若存在则打开写入,否则创建文件并写入 2.调用方法写入内容,其中回车用rn  3.txt文件中追加内容  4.调用追加TXT方法,并将dataGridView控件内容写入txt       

    2024年02月15日
    浏览(37)
  • java修改properties文件内容(读取、修改、追加)

    PropertiesConfiguration 是 Apache 帮我们实现按照文件的顺序读取properties文件的类,Properties类能做的它都能做。不仅如此,他还有许多方便实用的附加功能。 工具类: 除此之外,还可以 propsConfig.setEncoding(\\\"utf-8\\\") 设置编码。 需要的maven依赖:

    2024年02月06日
    浏览(41)
  • vue input获取光标位置,并追加内容

    项目中需要实现在输入框内的任意位置,追加内容,这里通过input的selectionStart属性还有setSelectionRange方法来实现。 首先来看selectionStart属性,用于获取文本框选区的开始位置,selectionEnd用于获取文本框选区结束的位置,举个栗子: 在该功能中,我们不是选择文字,主要是需要

    2024年02月16日
    浏览(35)
  • 【Azure 存储服务】使用 AppendBlobClient 对象实现对Blob进行追加内容操作

    在Azure Blob的官方示例中,都是对文件进行上传到Blob操作,没有实现对已创建的Blob进行追加的操作。如果想要实现对一个文件的多次追加操作,每一次写入的时候,只传入新的内容?   Azure Storage Blob 有三种类型: Block Blob, Append Blob 和 Page Blob。其中,只有Append Blob类型支持追

    2024年02月03日
    浏览(63)
  • EasyExcel读取EXcel文件内容

    目录 一 官方文档介绍 二 读取文件内容 1.根据文档内容建立读对象 2.创建读监听器 3.测试类代码 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一

    2024年02月14日
    浏览(55)
  • easyExcel 模版导出 中间数据纵向延伸,并且对指定列进行合并

    备注 : 模板注意 用{} 来表示你要用的变量 如果本来就有\\\"{\\\",\\\"}\\\" 特殊字符 用\\\"{\\\",\\\"}\\\"代替 // {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list 合并策略代码 : 导出部分 : 官方文档 :  填充Excel | Easy Excel 合并代码参考 :  https://www.cnblogs.com/monianxd/p/16359369.html

    2024年04月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包