Excel导入导出

提供Excel导入导出功能

一、安装依赖


    cn.gjing
    tools-excel
    1.0.2

二、注解说明

1、@Excel

使用在类上,表明这个类要绑定excel,注解参数如下

参数 描述
value Excel文件名,优先级低于方法传入
type Excel文档类型,默认XLS

2、@ExcelField

使用在字段上,表明这是Excel的列表头,注解参数如下

参数 描述
value 列表头名字
pattern 如果是时间需要转换指定格式,需要指定
width 这个列表头单元格的宽度

3、@DateValid

时间校验注解,使用在字段上,表明我这个列表头下的数据要进行校验,XLSX文档不支持,注解参数如下

参数 描述
validClass 校验器class, 可以指定自己的校验器, 不指定则走默认
boxLastRow 数据校验最多校验多少行,默认是正文第一行
pattern 校验的时间格式,默认yyyy-MM-dd
operatorType 操作类型,默认OperatorType.BETWEEN
expr1 表达式1
expr2 表达式2
showErrorBox 是否弹出错误框,默认true
showPromptBox 是否立即弹出,默认true
allowEmpty 是否允许空值,默认true
rank 提示框级别,默认Rank.WARING警告级别
errorTitle 错误框标题
errorContent 详细错误内容

4、@ExplicitValid

明确范围内容校验,使用在注解上,注解参数如下

参数 描述
validClass 校验器class, 可以指定自己的校验器, 不指定则走默认
combobox 范围值,数组类型
boxLastRow 数据校验最多校验多少行,默认为列表头下一行
showErrorBox 是否弹出错误框,默认true
showPromptBox 是否立即弹出,默认true
rank 提示框级别,默认Rank.WARING警告级别
errorTitle 错误框标题
errorContent 详细错误内容

5、@NumericValid

数据类型校验,使用在字段上,注解参数如下

参数 描述
validClass 校验器class, 可以指定自己的校验器, 不指定则走默认
boxLastRow 数据校验最多校验多少行,默认为列表头下一行
operatorType 操作类型,默认OperatorType.EQUAL
validationType 校验类型,必填
expr1 表达式1,在表达式2前面,必填
expr2 表达式2,在操作类型为BETWEENNOT_BETWEEN情况下必填
showErrorBox 是否弹出错误框,默认true
showPromptBox 是否立即弹出,默认true
allowEmpty 是否允许空值,默认true
rank 提示框级别,默认Rank.WARING警告级别
errorTitle 错误框标题
errorContent 详细错误内容

6、@Convert

枚举转换器,使用在枚举类型的字段上,注解参数如下

参数 描述
convert 实现了EnumConvert接口的类Class

三、使用说明

1、创建Excel对应的实体

@Excel(value = "用户列表")
public class User {
    @ExcelField("id值")
    private Long id;

    @ExcelField("用户名")
    private String name;

    @ExcelField("用户地址")
    private String userAddress;

    @ExcelField("城市")
    private String userCity;
}

2、导出空的Excel

/**
 * @author Gjing
 **/
@RestController
public class UserController {

    @GetMapping("/excel")
    @ApiOperation(value = "excel空文件导出")
    public void downExcel2(HttpServletResponse response) {
        ExcelFactory.createWriter(User.class, response).write();
    }
}

3、导出有数据的Excel

这里只说明如何使用,不提供访问数据库层的代码

/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/excel")
    @ApiOperation(value = "excel导出")
    public void downExcel(HttpServletResponse response) {
        List userList = userService.listUser();
        ExcelFactory.createWriter(User.class, response, userList).write();
    }
}

4、导出有大标题的Excel

需要传入BigTitle对象,该对象中包含了lastRowcontent两个参数,分别为大标题占用行(默认2行)、大标题内容(默认空)

/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/excel")
    @ApiOperation(value = "excel导出")
    public void downExcel(HttpServletResponse response) {
        List userList = userService.listUser();
        ExcelFactory.createWriter(User.class, response, userList).bigTitle(BigTitle::new).write();
    }
}

5、导出自定义样式的Excel

如果想自定义列表头、正文、大标题的样式,可以实现ExcelStyle接口,然后想修改哪块区域样式就调用对应区域设置样式的方法时传入你自己定义的即可

a、实现自己的样式类

/**
 * @author Gjing
 **/
public class MyStyle implements ExcelStyle {
    @Override
    public CellStyle style(CellStyle cellStyle) {
        // TODO: 2019/9/20 这里自定义配置 
        return cellStyle;
    }
}

b、使用

/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/excel")
    @ApiOperation(value = "excel导出")
    public void downExcel(HttpServletResponse response) {
        ExcelFactory.createWriter(User.class, response)
                //设置大标题样式
                .bigTitleStyle(MyStyle::new)
                //设置正文样式
                .contentStyle(MyStyle::new)
                //列表头样式
                .headerStyle(MyStyle::new)
                .write();
    }
}

6、导出有数据校验的Excel

a、改造实体

只做介绍,具体的要根据业务场景来使用

@Excel(value = "用户列表")
public class User {
    @ExcelField("id值")
    private Long id;

    @ExcelField("用户名")
    private String name;

    @ExcelField("用户地址")
    //表明这个字段长度要等于10
    @NumericValid(operatorType = OperatorType.EQUAL,validationType = ValidType.TEXT_LENGTH,expr1 = "10")
    private String userAddress;

    @ExcelField("城市")
    private String userCity;
}

b、导出

按之前的导出示例导出即可

7、导入Excel文件

如果导出的Excel模板有设置大标题,这里导入时需要通过.titleRow()方法指定对应模板导出时设置的大标题lastRow参数的值

/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @PostMapping("/excel")
    @ApiOperation(value = "excel导入")
    public void excelImport(MultipartFile file) {
        try {
            List readResult = ExcelFactory.createReader(file.getInputStream(), User.class).read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、复杂场景

1、自定义实现数据校验的逻辑

如果不想使用默认的数据校验器, 可以自己实现ExcelValidation接口, 然后在对应校验注解中validClass参数指定自己定义的校验器

a、定义自己的校验器

/**
 * @author Gjing
 **/
public class MyValid implements ExcelValidation {
    @Override
    public DataValidation valid(Sheet sheet) {
        return null;
    }
}

b、校验注解中使用

以下只举例其中一个, 其他几个校验注解也一样

@Excel("用户列表")
public class User {
    @ExcelField("性别")
    @NumericValid(validClass = MyValid.class)
    private Gender userGender;
}

2、导入导出枚举转换

如果字段的数据类型是枚举,必须指定转换器,该转换器实现EnumConvert接口,并重写其中的方法

a、定义转换器

/**
 * @author Gjing
 **/
public class MyConvert implements EnumConvert {
    //转成实体字段
    @Override
    public Gender toEntityAttribute(String s) {
        return null;
    }
    //转成数据库字段
    @Overridevalue
    public Integer toDatabaseColumn(Gender gender) {
        return null;
    }
}

b、字段上指定转换器

@Excel("用户列表")
public class User {
    @ExcelField("性别")
    @Convert(convert = MyConvert.class)
    private Gender userGender;
}

3、自定义Excel读写的解析器

a、导出解析器

实现ExcelWriterResolver接口,并实现其中的方法。除了builder()write()方法其他都可以根据自己需要决定是否要写

/**
 * @author Gjing
 **/
public class MyWriterResolver implements ExcelWriterResolver {
    @Override
    public ExcelWriterResolver builder(Workbook workbook, HttpServletResponse httpServletResponse, List list, List list1, String s) {
        return null;
    }

    @Override
    public void write(List list) {

    }

    @Override
    public void setBigTitle(BigTitle bigTitle) {

    }

    @Override
    public void setHeaderStyle(Supplier supplier) {

    }

    @Override
    public void setBigTitleStyle(Supplier supplier) {

    }

    @Override
    public void setContentStyle(Supplier supplier) {

    }

}

b、导入解析器

实现ExcelReaderResovler接口,并重写其中的方法

/**
 * @author Gjing
 **/
public class MyReadResolver implements ExcelReaderResolver {
    @Override
    public ExcelReaderResolver builder(InputStream inputStream) {
        return null;
    }

    @Override
    public void read(Class aClass, Consumer> consumer) {

    }

    @Override
    public void setEnumConvert(Supplier supplier) {

    }
}

c、项目使用

在Excel工厂创建完之后调用读或者写的changeResolver()方法改变解析器即可,该方法要在链式调用其他方法前使用,否则改变前解析器的方法进行的操作会无效

  • 导入
/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @PostMapping("/excel")
    @ApiOperation(value = "excel使用自己的解析器导入")
    public ResponseEntity excelImport(MultipartFile file) {
        try {
            ExcelFactory.createReader(file.getInputStream(), User.class)
                    .changeResolver(MyReadResolver::new)
                    .read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok("ok");
    }
}

导出,需要同时指定Workbook

/**
 * @author Gjing
 **/
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/excel")
    @ApiOperation(value = "excel导出")
    public void downExcel(HttpServletResponse response) {
        HSSFWorkbook workbook = new HSSFWorkbook();
        ExcelFactory.createWriter(User.class, response)
                .changeResolver(MyWriterResolver::new,workbook)
                .write();
    }
}

源代码地址:tools-excel

你可能感兴趣的:(java,excel)