hutool excel导出并合并行

3,211 阅读2分钟
导出是项目中最常见的功能,例如考勤记录导出,账单明细导出,订单记录导出等等。导出的工具类有许多种,目前常见的有poi,easypoi,poi...,今天我要说的是基于hutool-poi的导出,hutool-poi是将poi做了封装,简化了大量的代码编写。
使用方式:
maven
在项目的pom.xml中引入
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.3</version>
</dependency>
gradle
在项目的build.gradle中引入
compile 'cn.hutool:hutool-all:5.7.3'
我要实现的是将班级学生信息导出到excel文件中并且还要按照班级名称动态合并单元格,我先创建学生对象:
public class Student{
    private String className;

    private String stuName;

    private String sex;

    private Integer age;

    private String interesting;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getInteresting() {
        return interesting;
    }

    public void setInteresting(String interesting) {
        this.interesting = interesting;
    }

    public Student(String className, String stuName, String sex, Integer age, String interesting) {
        this.className = className;
        this.stuName = stuName;
        this.sex = sex;
        this.age = age;
        this.interesting = interesting;
    }
}

下面是控制器:
public class Controller{
@GetMapping("/export")
public void export(HttpServletResponse response){
        //模拟一些数据
	List<Student> students = new ArrayList<>();
	students.add(new Student("一班", "小明", "男", 12, "打球"));
	students.add(new Student("一班", "小蓝", "女", 14, "打乒乓"));
	students.add(new Student("一班", "小刚", "男", 16, "打台球"));
	students.add(new Student("二班", "小猪", "女", 12, "打羽毛球"));
	students.add(new Student("二班", "小猴", "女", 11, "踢鞋"));
	students.add(new Student("二班", "小马", "男", 12, "打架"));
	students.add(new Student("二班", "小鸭", "女", 13, "跑步"));
	students.add(new Student("三班", "tom", "男", 12, "找事"));
	students.add(new Student("三班", "jack", "男", 14, "喝酒"));
	students.add(new Student("三班", "marry", "女", 11, "抽烟"));
	students.add(new Student("三班", "larry", "男", 13, "打球"));
	students.add(new Student("四班", "孙悟空", "男", 12, "幽默"));
	students.add(new Student("五班", "喜喜", "女", 11, "笑话"));
	students.add(new Student("五班", "笑笑", "女", 12, "邋遢"));
	students.add(new Student("五班", "嘿嘿", "男", 12, "打球"));
	students.add(new Student("六班", "小数", "男", 12, "打球"));
            
        ExcelWriter writer = ExcelUtil.getBigWriter();
        ServletOutputStream out = null;
	try {
		CellStyle headCellStyle = writer.getHeadCellStyle();
		Font font = writer.createFont();
		font.setBold(true);

		headCellStyle.setFont(font);
		headCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
		headCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		writer.merge(3, "学生信息管理表", true);

		writer.addHeaderAlias("className", "班级").addHeaderAlias("stuName", "学生姓名")
				.addHeaderAlias("sex", "性别").addHeaderAlias("age", "年龄");
		writer.setOnlyAlias(true);
		//合并
		LinkedHashMap<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(item -> item.getClassName(),
				LinkedHashMap::new, Collectors.toList()));

		int firstRow = 2, lastRow = 2;
		for (List<Student> studentList : map.values()) {
			int size = studentList.size();
			lastRow = firstRow + size -1;
			if(size > 1){
				writer.merge(firstRow, lastRow, 0, 0, null, true);
			}
			firstRow = firstRow + size;
		}

		writer.write(students, true);
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.setHeader("Content-Disposition", "attachment;filename=PaymentDetailReport"+ DateUtil.format(new Date(),
				"yyyyMMddHHmm") +".xls");
		out = response.getOutputStream();
		writer.flush(out, true);
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		IoUtil.close(out);
		writer.close();
	}
  }
}

通过ExcelUtil.getBigWriter()创建Writer对象,BigExcelWriter用于大数据量的导出,不会引起溢出;
writer.addHeaderAlias("字段", "字段别名"),给所属的字段起别名,写在表头;
writer.setOnlyAlias(true):是指只导出定义了别名的字段;
writer.write(students, true):第二个参数是true指导出的excel是xlsx格式的,false指导出的excel是xls格式的;
writer.flush(out, true):是写出到excel中;
writer.close():关闭writer,释放内存;

LinkedHashMap<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(item -> item.getClassName(),
LinkedHashMap::new, Collectors.toList()));使用java的stream对同一个班级的学生信息进行分组,LinkedHashMap的key是班级名称,value是班级名称下对的学生信息,
调用writer.merge(firstRow, lastRow, 0, 0, null, true):合并行,第一个参数是合并行的开始行号(行号从0开始),第二个参数是合并行的结束行号,第三个参数是合并的列号开始(列号从0开始),第四个参数是合并的列号结束,第五个参数是合并后的内容,null不设置,第六个参数指是否支持设置样式,true指的是。
特别注意,如果只有一行不能调用merge方法,否则会报错。