springboot整合EasyExcel

springboot整合EasyExcel

easyexcel是阿里开源的解析excel的工具,可以把它看作对poi的优化版。

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

easyexcel核心功能

功能描述参考:Java解析excel工具easyexcel 助你快速简单避免OOM_成长中的巨人-CSDN博客_excel解析 

  • 读任意大小的03、07版Excel不会OOM
  • 读Excel自动通过注解,把结果映射为java模型
  • 读Excel支持多sheet
  • 读Excel时候是否对Excel内容做trim()增加容错
  • 写小量数据的03版Excel(不要超过2000行)
  • 写任意大07版Excel不会OOM
  • 写Excel通过注解将表头自动写入Excel
  • 写Excel可以自定义Excel样式 如:字体,加粗,表头颜色,数据内容颜色
  • 写Excel到多个不同sheet
  • 写Excel时一个sheet可以写多个Table
  • 写Excel时候自定义是否需要写表头

1、引入依赖

  

<dependency>
     <groupId>com.alibaba</groupId>
	 <artifactId>easyexcel</artifactId>
	 <version>1.1.2-beta5</version>
</dependency>

依赖包是目前最新的版本 

2、实体类

package com.xxx.xxxutils.utils;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.*;


@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TableHeaderExcelProperty  extends BaseRowModel{

    /**
     * value: 表头名称
     * index: 列的号, 0表示第一列
     */
    @ExcelProperty(value = "姓名", index = 0)
    private String name;

    @ExcelProperty(value = "年龄",index = 1)
    private int age;

    @ExcelProperty(value = "学校",index = 2)
    private String school;





}

3、excel工具方法

package com.xxx.xxxutils.utils;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.xxx.xxxutils.listener.ExcelListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.poifs.filesystem.FileMagic;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@Slf4j
public class ExcelUtil{

    /**
     * 从Excel中读取文件,读取的文件是一个DTO类,该类必须继承BaseRowModel
     * 导入方法  第一个参数文件输入流,第二个参数实体类,必须继承自BaseRowModel
     * 参考:https://github.com/alibaba/easyexcel
     * 字符流必须支持标记,FileInputStream 不支持标记,可以使用BufferedInputStream 代替
     * BufferedInputStream bis = new BufferedInputStream(new FileInputStream(...));
     */
    public static <T extends BaseRowModel> List<T> readExcel(final InputStream inputStream, final Class<? extends BaseRowModel> clazz) {
        if (null == inputStream) {
            throw new NullPointerException("the inputStream is null!");
        }
        ExcelListener<T> listener = new ExcelListener<>();
        // ExcelListener,读取大于1000行的数据才需要传入此参数
        ExcelReader reader = new ExcelReader(inputStream,  valueOf(inputStream), null, listener);
        reader.read(new Sheet(1, 1, clazz));

        return listener.getRows();
    }



     /**
     * 从Excel中读取文件,读取的文件是一个DTO类,该类必须继承BaseRowModel
     * 导出方法  第一个参数文件,第二个参数实体类集合,必须继承自BaseRowModel
     */
    public static void writeExcel(final File file, List<? extends BaseRowModel> list) {
        try (OutputStream out = new FileOutputStream(file)) {
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
            //写第一个sheet,  有模型映射关系
            Class<? extends BaseRowModel> t = list.get(0).getClass();
            Sheet sheet = new Sheet(1, 0, t);
            writer.write(list, sheet);
            writer.finish();
        } catch (IOException e) {
            log.warn("fail to write to excel file: file[{}]", file.getName(), e);
        }
    }


    /**
     * 根据输入流,判断为xls还是xlsx,该方法原本存在于easyexcel 1.1.0 的ExcelTypeEnum中。
     */
    public static ExcelTypeEnum valueOf(InputStream inputStream) {
        try {
            FileMagic fileMagic = FileMagic.valueOf(inputStream);
            if (FileMagic.OLE2.equals(fileMagic)) {
                return ExcelTypeEnum.XLS;
            }
            if (FileMagic.OOXML.equals(fileMagic)) {
                return ExcelTypeEnum.XLSX;
            }
            throw new IllegalArgumentException("excelTypeEnum can not null");

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }








    /****************************************************************************/


        private static Sheet initSheet;

        static {
            initSheet = new Sheet(1, 0);
            initSheet.setSheetName("sheet");
            //设置自适应宽度
            initSheet.setAutoWidth(Boolean.TRUE);
        }

        /**
         * 导入方法,读取少于1000行数据
         * @param filePath 文件绝对路径
         * @return
         */
        public static List<Object> readLessThan1000Row(String filePath){
            return readLessThan1000RowBySheet(filePath,null);
        }

        /**
         * 导入方法,读小于1000行数据, 带样式
         * filePath 文件绝对路径
         * initSheet :
         *      sheetNo: sheet页码,默认为1
         *      headLineMun: 从第几行开始读取数据,默认为0, 表示从第一行开始读取
         *      clazz: 返回数据List<Object> 中Object的类名
         */
        public static List<Object> readLessThan1000RowBySheet(String filePath, Sheet sheet){
            if(!StringUtils.hasText(filePath)){
                return null;
            }

            sheet = sheet != null ? sheet : initSheet;

            InputStream fileStream = null;
            try {
                fileStream = new FileInputStream(filePath);
                return EasyExcelFactory.read(fileStream, sheet);
            } catch (FileNotFoundException e) {
                log.info("找不到文件或文件路径错误, 文件:{}", filePath);
            }finally {
                try {
                    if(fileStream != null){
                        fileStream.close();
                    }
                } catch (IOException e) {
                    log.info("excel文件读取失败, 失败原因:{}", e);
                }
            }
            return null;
        }



        /**
         * 导入方法,读大于1000行数据
         * @param filePath 文件觉得路径
         * @return
         */
        public static List<Object> readMoreThan1000Row(String filePath){
            return readMoreThan1000RowBySheet(filePath,null);
        }

        /**
         * 导入方法,读大于1000行数据, 带样式
         * @param filePath 文件觉得路径
         * @return
         */
        public static List<Object> readMoreThan1000RowBySheet(String filePath, Sheet sheet){
            if(!StringUtils.hasText(filePath)){
                return null;
            }

            sheet = sheet != null ? sheet : initSheet;

            InputStream fileStream = null;
            try {
                fileStream = new FileInputStream(filePath);
                ExcelListenerPlus excelListener = new ExcelListenerPlus();
                EasyExcelFactory.readBySax(fileStream, sheet, excelListener);
                return excelListener.getDatas();
            } catch (FileNotFoundException e) {
                log.error("找不到文件或文件路径错误, 文件:{}", filePath);
            }finally {
                try {
                    if(fileStream != null){
                        fileStream.close();
                    }
                } catch (IOException e) {
                    log.error("excel文件读取失败, 失败原因:{}", e);
                }
            }
            return null;
        }


        /**
         * 导出方法,生成excle
         * @param filePath  绝对路径, 如:/home/chenmingjian/Downloads/aaa.xlsx
         * @param data 数据源
         * @param head 表头
         */
        public static void writeBySimple(String filePath, List<List<Object>> data, List<String> head){
            writeSimpleBySheet(filePath,data,head,null);
        }




        /**
         * 导出方法,生成excle
         * @param filePath 绝对路径, 如:/home/chenmingjian/Downloads/aaa.xlsx
         * @param data 数据源
         * @param sheet excle页面样式
         * @param head 表头
         */
        public static void writeSimpleBySheet(String filePath, List<List<Object>> data, List<String> head, Sheet sheet){
            sheet = (sheet != null) ? sheet : initSheet;

            if(head != null){
                List<List<String>> list = new ArrayList<>();
                head.forEach(h -> list.add(Collections.singletonList(h)));
                sheet.setHead(list);
            }

            OutputStream outputStream = null;
            ExcelWriter writer = null;
            try {
                outputStream = new FileOutputStream(filePath);
                writer = EasyExcelFactory.getWriter(outputStream);
                writer.write1(data,sheet);
            } catch (FileNotFoundException e) {
                log.error("找不到文件或文件路径错误, 文件:{}", filePath);
            }finally {
                try {
                    if(writer != null){
                        writer.finish();
                    }

                    if(outputStream != null){
                        outputStream.close();
                    }

                } catch (IOException e) {
                    log.error("excel文件导出失败, 失败原因:{}", e);
                }
            }

        }






        /**
         * 导出方法,生成excle
         * @param filePath 绝对路径, 如:/home/chenmingjian/Downloads/aaa.xlsx
         * @param data 数据源
         */
        public static void writeWithTemplate(String filePath, List<? extends BaseRowModel> data){
            writeWithTemplateAndSheet(filePath,data,null);
        }





        /**
         * 导出方法,生成excle
         * @param filePath 绝对路径, 如:/home/chenmingjian/Downloads/aaa.xlsx
         * @param data 数据源
         * @param sheet excle页面样式
         */
        public static void writeWithTemplateAndSheet(String filePath, List<? extends BaseRowModel> data, Sheet sheet){
            if(CollectionUtils.isEmpty(data)){
                return;
            }

            sheet = (sheet != null) ? sheet : initSheet;
            sheet.setClazz(data.get(0).getClass());

            OutputStream outputStream = null;
            ExcelWriter writer = null;
            try {
                outputStream = new FileOutputStream(filePath);
                writer = EasyExcelFactory.getWriter(outputStream);
                writer.write(data,sheet);
            } catch (FileNotFoundException e) {
                log.error("找不到文件或文件路径错误, 文件:{}", filePath);
            }finally {
                try {
                    if(writer != null){
                        writer.finish();
                    }

                    if(outputStream != null){
                        outputStream.close();
                    }
                } catch (IOException e) {
                    log.error("excel文件导出失败, 失败原因:{}", e);
                }
            }

        }





        /**
         * 导出方法,生成多Sheet的excle
         * @param filePath 绝对路径, 如:/home/chenmingjian/Downloads/aaa.xlsx
         * @param multipleSheelPropetys
         */
        public static void writeWithMultipleSheel(String filePath,List<MultipleSheelPropety> multipleSheelPropetys){
            if(CollectionUtils.isEmpty(multipleSheelPropetys)){
                return;
            }

            OutputStream outputStream = null;
            ExcelWriter writer = null;
            try {
                outputStream = new FileOutputStream(filePath);
                writer = EasyExcelFactory.getWriter(outputStream);
                for (MultipleSheelPropety multipleSheelPropety : multipleSheelPropetys) {
                    Sheet sheet = multipleSheelPropety.getSheet() != null ? multipleSheelPropety.getSheet() : initSheet;
                    if(!CollectionUtils.isEmpty(multipleSheelPropety.getData())){
                        sheet.setClazz(multipleSheelPropety.getData().get(0).getClass());
                    }
                    writer.write(multipleSheelPropety.getData(), sheet);
                }

            } catch (FileNotFoundException e) {
                log.error("找不到文件或文件路径错误, 文件:{}", filePath);
            }finally {
                try {
                    if(writer != null){
                        writer.finish();
                    }

                    if(outputStream != null){
                        outputStream.close();
                    }
                } catch (IOException e) {
                    log.error("excel文件导出失败, 失败原因:{}", e);
                }
            }

        }


        /*********************匿名内部类开始,可以提取出去******************************/

        @Data
        public static class MultipleSheelPropety{

            private List<? extends BaseRowModel> data;

            private Sheet sheet;
        }

        /**
         * 解析监听器,读取大于一千行的数据需要传入次参数
         * 每解析一行会回调invoke()方法。
         * 整个excel解析结束会执行doAfterAllAnalysed()方法
         *
         * @author: chenmingjian
         * @date: 19-4-3 14:11
         */
        @Data
        public static class ExcelListenerPlus  extends AnalysisEventListener {

            private List<Object> datas = new ArrayList<>();

            /**
             * 逐行解析
             * object : 当前行的数据
             */
            @Override
            public void invoke(Object object, AnalysisContext context) {
                //当前行
                // context.getCurrentRowNum()
                if (object != null) {
                    datas.add(object);
                }
            }


            /**
             * 解析完所有数据后会调用该方法
             */
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                //解析结束销毁不用的资源
            }
        }

        /****************************************************************************/










}

4、测试案例

package com.xxx.xxxutils;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.xxx.xxxutils.domain.XxxInfo;
import com.xxx.xxxutils.model.MultiLineHeadExcelModelTest1;
import com.xxx.xxxutils.model.TableHeaderExcelProperty;
import com.xxx.xxxutils.model.User;
import com.xxx.xxxutils.utils.ExcelUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ResourceUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.xxx.xxxutils.utils.ExcelToolUtils.createTestListObject;
import static com.xxx.xxxutils.utils.ExcelToolUtils.createTestListStringHead2;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UtaxExcelSaleTest {

	/**
	 * 07版本excel读数据量少于1千行数据自动转成javamodel,内部采用回调方法.
	 *
	 * @throws IOException 简单抛出异常,真实环境需要catch异常,同时在finally中关闭流
	 */
	@Test
	//导入
	public void simpleReadJavaModelV2007() throws IOException {
		/*InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("d://台账信息" +
				".xlsx");*/

		//
		//ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		//InputStream inputStream = resolver.getResource("D:\\台账信息.xlsx").getInputStream();

		InputStream   inputStream =  new FileInputStream("D:\\台账信息.xlsx");

		List<Object> data = EasyExcelFactory.read(inputStream, new Sheet(1, 2, xxxInfo.class));
		inputStream.close();
		Xxx   xxx= new Xxx();
		for (int i = 0;i<data.size();i++){
			xxx= (Xxx) data.get(i);

		}
		//print(data);
		System.out.println(data);
	}

	@Test
	//导出
	public void writeV2007() throws IOException {
		Long  startTime  = System.currentTimeMillis();
		//文件输出位置
		OutputStream out = new FileOutputStream("D:\\outTest.xlsx");
		ExcelWriter writer = EasyExcelFactory.getWriter(out);
		//写第一个sheet, sheet1  数据全是List<String> 无模型映射关系
		//MultiLineHeadExcelModelTest1是写入excel的数据模型对象
		Sheet sheet1 = new Sheet(1,3, MultiLineHeadExcelModelTest1.class,"第一个sheet",null);
		//sheet1.setSheetName("testOne");

		//设置列宽 设置每列的宽度
		/*Map columnWidth = new HashMap();
		columnWidth.put(0,10000);
columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000);
		sheet1.setColumnWidthMap(columnWidth);
		sheet1.setHead(createTestListStringHead2());*/
		//or 设置自适应宽度
		//sheet1.setAutoWidth(Boolean.TRUE);
		//参数一:写入的数据(要写入的结果集,list集合),参数二:写入的目标sheet
		writer.write1(createTestListObject(), sheet1);
		//将上下文中的最终OutputStream写入到指定文件中
		writer.finish();
		//关闭流
		out.close();
		Long  endTime  = System.currentTimeMillis();
		Long time = endTime - startTime;
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		System.out.println("excel导出共花费 "+time/1000+"秒");

	}



	@Test
	//动态生成表头(导出)
	public void writeV2() throws IOException {

		Long  startTime  = System.currentTimeMillis();
		//文件输出位置
		OutputStream out = new FileOutputStream("outTest2.xlsx");
		ExcelWriter writer = EasyExcelFactory.getWriter(out);
		//写第一个sheet, sheet1  数据全是List<String> 无模型映射关系
		Sheet sheet1 = new Sheet(1, 0);
		sheet1.setSheetName("第一个sheet");
		//创建一个表格,用于sheet中使用
        Table  table1  =  new Table(1);
		//设置列宽 设置每列的宽度
		/*Map columnWidth = new HashMap();
		columnWidth.put(0,10000);
        columnWidth.put(1,40000);
        columnWidth.put(2,10000);
        columnWidth.put(3,10000);
		sheet1.setColumnWidthMap(columnWidth);*/
		table1.setHead(createTestListStringHead2());
		//or 设置自适应宽度
		//sheet1.setAutoWidth(Boolean.TRUE);
		//参数一:写入的数据(要写入的结果集,list集合),参数二:写入的目标sheet
		writer.write1(createTestListObject(), sheet1,table1);
		//合并单元格
		writer.merge(5,6,0,4);
		//将上下文中的最终OutputStream写入到指定文件中
		writer.finish();
		//关闭流
		out.close();
		Long  endTime  = System.currentTimeMillis();
		Long time = endTime - startTime;
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		System.out.println("excel导出共花费 "+time/1000+"秒");

	}




	@Test
	//导入
	public  void  testRead(){
		try (FileInputStream inputStream = new FileInputStream(ResourceUtils.getFile("classpath:excels/2003.xls"))) {
			List<User> users = ExcelUtil.readExcel(new BufferedInputStream(inputStream), User.class);
			System.out.println(users);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}







	//========================================================================

	/**
	 * 读取少于1000行的excle(导入)
	 */
	@Test
	public void readLessThan1000Row(){
		String filePath = "outTest2.xlsx";
		List<Object> objects = ExcelUtil.readLessThan1000Row(filePath);
		objects.forEach(System.out::println);
	}


	/**
	 * 读取少于1000行的excle,可以指定sheet和从几行读起(导入)
	 */
	@Test
	public void readLessThan1000RowBySheet(){
		String filePath = "outTest2.xlsx";
		Sheet sheet = new Sheet(1, 1);
		List<Object> objects = ExcelUtil.readLessThan1000RowBySheet(filePath,sheet);
		objects.forEach(System.out::println);
	}



	/**
	 * 读取大于1000行的excle
	 * 带sheet参数的方法可参照测试方法readLessThan1000RowBySheet(),导入
	 */
	@Test
	public void readMoreThan1000Row(){
		String filePath = "outTest2.xlsx";
		List<Object> objects = ExcelUtil.readMoreThan1000Row(filePath);
		objects.forEach(System.out::println);
	}




	/**
	 * 生成excle
	 * 带sheet参数的方法可参照测试方法readLessThan1000RowBySheet(),导出
	 */
	@Test
	public void writeBySimple(){
		String filePath = "outTest1.xlsx";
		List<List<Object>> data = new ArrayList<>();
		data.add(Arrays.asList("111","222","333"));
		data.add(Arrays.asList("111","222","333"));
		data.add(Arrays.asList("111","222","333"));
		List<String> head = Arrays.asList("表头1", "表头2", "表头3");
		ExcelUtil.writeBySimple(filePath,data,head);
	}



	/**
	 * 生成excle, 带用模型
	 * 带sheet参数的方法可参照测试方法readLessThan1000RowBySheet(),导出
	 */
	@Test
	public void writeWithTemplate(){
		String filePath = "outTest4.xlsx";
		ArrayList<TableHeaderExcelProperty> data = new ArrayList<>();
		for(int i = 0; i < 4; i++){
			/*TableHeaderExcelProperty tableHeaderExcelProperty = new TableHeaderExcelProperty();
			tableHeaderExcelProperty.setName("cmj" + i);
			tableHeaderExcelProperty.setAge(22 + i);
			tableHeaderExcelProperty.setSchool("清华大学" + i);*/
			TableHeaderExcelProperty tableHeaderExcelProperty = TableHeaderExcelProperty
					.builder()
					.name("cmj" + i).age(22 + i).school("清华大学" + i)
					.build();
			data.add(tableHeaderExcelProperty);
		}
		ExcelUtil.writeWithTemplate(filePath,data);
	}




	/**
	 * 生成excle, 带用模型,带多个sheet,导出
	 */
	@Test
	public void writeWithMultipleSheel(){
		ArrayList<ExcelUtil.MultipleSheelPropety> list1 = new ArrayList<>();
		for(int j = 1; j < 4; j++){
			ArrayList<TableHeaderExcelProperty> list = new ArrayList<>();
			for(int i = 0; i < 4; i++){
				/*TableHeaderExcelProperty tableHeaderExcelProperty = new TableHeaderExcelProperty();
				tableHeaderExcelProperty.setName("cmj" + i);
				tableHeaderExcelProperty.setAge(22 + i);
				tableHeaderExcelProperty.setSchool("清华大学" + i);*/
				TableHeaderExcelProperty tableHeaderExcelProperty = TableHeaderExcelProperty.
						builder()
						.name("cmj" + i).age(22 + i).school("清华大学" + i)
						.build();
				list.add(tableHeaderExcelProperty);
			}

			Sheet sheet = new Sheet(j, 0);
			sheet.setSheetName("sheet" + j);

			ExcelUtil.MultipleSheelPropety multipleSheelPropety = new ExcelUtil.MultipleSheelPropety();
			multipleSheelPropety.setData(list);
			multipleSheelPropety.setSheet(sheet);

			list1.add(multipleSheelPropety);

		}

		ExcelUtil.writeWithMultipleSheel("outTest5.xlsx",list1);

	}


	
    
	@Test
     //遍历文件夹下文件
	public  void  testFiles() throws FileNotFoundException {
		//File file = ResourceUtils.getFile("classpath:templates/b_dfd.txt");
		File file = ResourceUtils.getFile("classpath:excels");
		if(file.exists()){
			File[] files = file.listFiles();
			if(files != null){
				for(File childFile:files){
					System.out.println(childFile.getName());

				}
			}
		}
	}





}



5、表头的添加

动态添加表头方法
 
package com.xxx.xxxutils.utils;

import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.TableStyle;
import org.apache.poi.ss.usermodel.IndexedColors;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
  *@ClassName:  ExcelToolUtils
  *@Description:   无注解模式,动态添加表头,也可自由组合复杂表头

 **/

public class ExcelToolUtils {


    /**
      *@Description:   无注解模式,动态添加表头1,也可自由组合复杂表头
    **/
    public static List<List<String>> createTestListStringHead(){
        //写sheet3  模型上没有注解,表头数据动态传入
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();

        headCoulumn1.add("第一列");headCoulumn1.add("第一列");headCoulumn1.add("第一列");
        headCoulumn2.add("第一列");headCoulumn2.add("第一列");headCoulumn2.add("第一列");

        headCoulumn3.add("第二列");headCoulumn3.add("第二列");headCoulumn3.add("第二列");
        headCoulumn4.add("第三列");headCoulumn4.add("第三列2");headCoulumn4.add("第三列2");
        headCoulumn5.add("第一列");headCoulumn5.add("第3列");headCoulumn5.add("第4列");

        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        return head;
    }


    
    /**
      *@Description:   无注解模式,动态添加表头2,也可自由组合复杂表头
    **/
    public static List<List<String>> createTestListStringHead2(){
        List<List<String>> head = new ArrayList<List<String>>();
        List<String> headCoulumn1 = new ArrayList<String>();
        List<String> headCoulumn2 = new ArrayList<String>();
        List<String> headCoulumn3 = new ArrayList<String>();
        List<String> headCoulumn4 = new ArrayList<String>();
        List<String> headCoulumn5 = new ArrayList<String>();
        List<String> headCoulumn6 = new ArrayList<String>();
        List<String> headCoulumn7 = new ArrayList<String>();

        
        //如果行列里面都是一样的数据就直接合并为一个单元格
        //第一列的第一行
        headCoulumn1.add("第一列");
        //第一列的第二行
        headCoulumn1.add("第一列");
        //第一列的第三行
        headCoulumn1.add("第一列");
        //第一列的第四行
        headCoulumn1.add("22");


        //第二列的第一行
        headCoulumn2.add("第一列");
        //第二列的第二行
        headCoulumn2.add("第一列");
        //第二列的第三行
        headCoulumn2.add("第一列");
        //第二列的第四行
        headCoulumn2.add("33");

        headCoulumn3.add("第二列");
        headCoulumn3.add("第二列");
        headCoulumn3.add("第二列");
        headCoulumn3.add("第二列");

        headCoulumn4.add("第三列");
        headCoulumn4.add("第三列2");
        headCoulumn4.add("第三列2");
        headCoulumn4.add("第三列3");

        headCoulumn5.add("第四列");
        headCoulumn5.add("41");
        headCoulumn5.add("42");
        headCoulumn5.add("43");


        headCoulumn6.add("第N列");
        headCoulumn6.add("第3列");
        headCoulumn6.add("第99列");
        headCoulumn6.add("第100列");

        headCoulumn7.add("第N列");
        headCoulumn7.add("第3列");
        headCoulumn7.add("第101列");
        headCoulumn7.add("第102列");




        head.add(headCoulumn1);
        head.add(headCoulumn2);
        head.add(headCoulumn3);
        head.add(headCoulumn4);
        head.add(headCoulumn5);
        head.add(headCoulumn6);
        head.add(headCoulumn7);
        return head;
    }





    /**
      *@Description:   往表格添加数据
    **/
    public static List<List<Object>> createTestListObject() {
        List<List<Object>> object = new ArrayList<List<Object>>();
        for (int i = 0; i < 1000; i++) {
            List<Object> da = new ArrayList<Object>();
            da.add("字符串"+i);
            da.add(Long.valueOf(187837834l+i));
            da.add(Integer.valueOf(2233+i));
            da.add(Double.valueOf(2233.00+i));
            da.add(Float.valueOf(2233.0f+i));
            da.add(new Date());
            da.add(new BigDecimal("3434343433554545"+i));
            da.add(Short.valueOf((short)i));
            object.add(da);
        }
        return object;
    }



  



    /**
      *@Description:   设置表格样式
    **/
    public  static TableStyle createTableStyle(){
        TableStyle  tableStyle  = new TableStyle();
        //设置表头样式
        Font  headFont  =  new Font();
        //字体是否加粗
        headFont.setBold(true);
        //字体大小
        headFont.setFontHeightInPoints((short)12);
        //字体
        headFont.setFontName("楷体");
        tableStyle.setTableHeadFont(headFont);
        //背景色
        tableStyle.setTableContentBackGroundColor(IndexedColors.BLUE);


        //设置表格主题样式
        Font  contentFont  =  new Font();
        contentFont.setBold(true);
        contentFont.setFontHeightInPoints((short)12);
        contentFont.setFontName("黑体");
        tableStyle.setTableContentFont(contentFont);
        tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN);
        return   tableStyle;
    }



}
通过注解方式添加表头

package com.xxx.xxxutils.model;

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

/**
 * @ClassName: MultiLineHeadExcelModelTest1
 * @Description:   复杂表头实体类
 * ExayExcel 提供注解的方式, 来方便的定义 Excel 需要的数据模型
 * ①:首先,定义的写入模型必须要继承自 BaseRowModel
 * ②:通过 @ExcelProperty 注解来指定每个字段的列名称,以及下标位置;
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MultiLineHeadExcelModelTest1  extends  BaseReadModel{

    //如果行列里面都是一样的数据就直接合并为一个单元格
    //---------------------第一列的第一行,第一列的第二行,第一列的第三行
    @ExcelProperty(value = {"表头1","表头1","表头31"},index = 0)
    private String p1;
    
   //---------------------第二列的第一行,第二列的第二行,第二列的第三行
    @ExcelProperty(value = {"表头1","表头1","表头32"},index = 1)
    private String p2;

    @ExcelProperty(value = {"表头3","表头3","表头3"},index = 2)
    private int p3;

    @ExcelProperty(value = {"表头4","表头4","表头4"},index = 3)
    private long p4;

    @ExcelProperty(value = {"表头5","表头51","表头52"},index = 4)
    private String p5;

    @ExcelProperty(value = {"表头6","表头61","表头611"},index = 5)
    private String p6;

    @ExcelProperty(value = {"表头6","表头61","表头612"},index = 6)
    private String p7;

    @ExcelProperty(value = {"表头6","表头62","表头621"},index = 7)
    private String p8;

    @ExcelProperty(value = {"表头6","表头62","表头622"},index = 8)
    private String p9;





}

 生成表头效果

6、总结

ddd博客参考:史上最全的Excel导入导出(easyexcel版)

easyexcel官方文档:easyexcel/README.md at master · alibaba/easyexcel · GitHub

easyexcel官方源码: GitHub - alibaba/easyexcel: 快速、简单避免OOM的java处理Excel工具

easyexcel博客参考:1、史上最全的Excel导入导出之easyexcel_点缀星空-CSDN博客_easyexcel

                                  2、Java解析excel工具easyexcel 助你快速简单避免OOM_成长中的巨人-CSDN博客_excel解析

                                  3、阿里开源的 5.7k star Excel工具实战!快速简单避免内存溢出。

动态表头的添加如果以日常操作excel的思维来理解还是很好弄懂的。

Spring Boot整合EasyExcel可以使得我们在使用Java编程语言操作Excel文件时更加方便快捷,无需手动处理Excel的复杂格式和数据类型转换问题。下面是一个简单的示例: 1. 引入EasyExcel依赖 在pom.xml文件中添加以下依赖: ```xml <!-- EasyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.10</version> </dependency> ``` 2. 创建Excel模板类 ```java @Data public class ExcelData { @ExcelProperty(value = "姓名", index = 0) private String name; @ExcelProperty(value = "年龄", index = 1) private Integer age; @ExcelProperty(value = "性别", index = 2) private String gender; } ``` 3. 编写Excel读取代码 ```java @Service public class ExcelService { public List<ExcelData> readExcel(MultipartFile file) throws IOException { InputStream inputStream = file.getInputStream(); List<ExcelData> list = new ArrayList<>(); ExcelReader reader = new ExcelReader(inputStream, ExcelTypeEnum.XLSX, null, new AnalysisEventListener<ExcelData>() { @Override public void invoke(ExcelData data, AnalysisContext context) { list.add(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) { } }); reader.read(new Sheet(1, 1, ExcelData.class)); return list; } } ``` 4. 编写Excel导出代码 ```java @Service public class ExcelService { public void writeExcel(HttpServletResponse response, List<ExcelData> list) throws IOException { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("测试文件.xlsx", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName); EasyExcel.write(response.getOutputStream(), ExcelData.class).sheet("测试").doWrite(list); } } ``` 以上就是Spring Boot整合EasyExcel的基本示例,可以根据自己的需求进行修改和扩展。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值