<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.6version>
dependency>
javabean
/**
* 这里使用了lombok和validation简化javabean代码
*/
@Data /* setter/getter */
@NoArgsConstructor /* 无参构造器 */
@AllArgsConstructor /* 全参构造器 */
public class Student {
//使用@ExcelProperty注解来为生成的Excel设置标头
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("详情")
private String details;
@ExcelProperty("学号")
private Integer sno;
@DateTimeFormat("yyyy-MM-dd")
@ExcelProperty("创建时间")
private Date createTime;
}
运行代码
/**
* 写入方式一
*/
@Test
public void test01(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test01.xlsx";
//添加模型数据
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("zhangsan",11,"hahaha",202101,new Date()));
stus.add(new Student("zhangsan",12,"saaa",202102,new Date()));
stus.add(new Student("zhangsan",13,"hahaha",202103,new Date()));
stus.add(new Student("zhangsan",14,"hahaha",202104,new Date()));
stus.add(new Student("zhangsan",10,"hahaha",202105,new Date()));
//将list中的数据写入excel中的第一个sheet中,这种方式文件流会自动关闭
EasyExcel.write(filename,Student.class).sheet("学生信息").doWrite(stus);
}
运行代码
/**
* 写入方式二
*/
@Test
public void test02(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test02.xlsx";
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("zhangsan",11,"hahaha",202101,new Date()));
stus.add(new Student("zhangsan",12,"saaa",202102,new Date()));
stus.add(new Student("zhangsan",13,"hahaha",202103,new Date()));
stus.add(new Student("zhangsan",14,"hahaha",202104,new Date()));
stus.add(new Student("zhangsan",10,"hahaha",202105,new Date()));
//创建Excel写入对象
ExcelWriter writer = EasyExcel.write(filename,Student.class).build();
//创建Sheet对象一个sheet对象就是一张sheet工作簿
WriteSheet writeSheet = EasyExcel.writerSheet("学生信息").build();
//将工作表写入到Excel中
writer.write(stus,writeSheet);
//关闭
writer.finish();
}
/**
* 排除字段
*/
@Test
public void test03(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test03.xlsx";
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("zhangsan",11,"hahaha",202101,new Date()));
stus.add(new Student("zhangsan",12,"saaa",202102,new Date()));
stus.add(new Student("zhangsan",13,"hahaha",202103,new Date()));
stus.add(new Student("zhangsan",14,"hahaha",202104,new Date()));
stus.add(new Student("zhangsan",10,"hahaha",202105,new Date()));
//设置排除属性字段
Set<String> set = new HashSet<String>();
set.add("details");
//排除属性字段
EasyExcel.write(filename,Student.class).excludeColumnFiledNames(set)
.sheet("用户信息").doWrite(stus);
}
/**
* 排除字段
*/
@Test
public void test04(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test04.xlsx";
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("zhangsan",11,"hahaha",202101,new Date()));
stus.add(new Student("zhangsan",12,"saaa",202102,new Date()));
stus.add(new Student("zhangsan",13,"hahaha",202103,new Date()));
stus.add(new Student("zhangsan",14,"hahaha",202104,new Date()));
stus.add(new Student("zhangsan",10,"hahaha",202105,new Date()));
//设置包含属性字段
Set<String> set = new HashSet<String>();
set.add("name");
set.add("age");
//包含属性字段
EasyExcel.write(filename,Student.class).includeColumnFiledNames(set)
.sheet("用户信息").doWrite(stus);
}
运行写入方式
通过设置@ExcelProperty的index来设置字段所在的列
/**
* 这里使用了lombok简化javabean代码
*/
@Data /* setter/getter */
@NoArgsConstructor /* 无参构造器 */
@AllArgsConstructor /* 全参构造器 */
public class Student {
//通过设置index来设置字段所在的列
@ExcelProperty(value = "姓名",index = 1)
private String name;
@ExcelProperty(value = "年龄",index = 2)
private Integer age;
@ExcelProperty(value = "详情",index = 4)
private String details;
@ExcelProperty(value = "学号",index = 3)
private Integer sno;
@DateTimeFormat("yyyy-MM-dd")
@ExcelProperty(value = "创建时间",index = 5)
private Date createTime;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
//复杂头设置
@ExcelProperty({"教师汇总","姓名"})
private String name;
@ExcelProperty({"教师汇总","年龄"})
private Integer age;
@ExcelProperty({"教师汇总","详情"})
private String details;
@ExcelProperty({"教师汇总","课程"})
private String course;
@ExcelProperty({"教师汇总","日期"})
@DateTimeFormat("yyyy-MM-dd")
private Date date;
}
运行代码
@Test
public void test06(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test06.xlsx";
List<Teacher> teachers = new ArrayList<Teacher>();
teachers.add(new Teacher("zhaoliu",34,"nihao","yuwen",new Date()));
teachers.add(new Teacher("zhaoliu",34,"nihao","shuxue",new Date()));
teachers.add(new Teacher("zhaoliu",24,"nihao","yingyu",new Date()));
teachers.add(new Teacher("zhaoliu",66,"nihao","yingyue",new Date()));
teachers.add(new Teacher("zhaoliu",53,"nihao","yuwen",new Date()));
teachers.add(new Teacher("zhaoliu",54,"nihao","yuwen",new Date()));
//将list中的数据写入excel中的第一个sheet中,这种方式文件流会自动关闭
EasyExcel.write(filename,Teacher.class).sheet("老师信息").doWrite(teachers);
}
5种方式
@Data
@NoArgsConstructor
public class ImageData {
private File file;
private InputStream inputStream;
/**
* 如果string类型 必须指定转换器,string默认转换成string
*/
@ExcelProperty(converter = StringImageConverter.class)
private String string;
private byte[] byteArray;
/**
* 根据url导出
*/
private URL url;
}
运行代码
/**
* 图片导出
* 1. 创建excel对应的实体对象 参照{@link ImageData}
* 2. 直接写即可
*/
@Test
public void imageWrite() throws Exception {
String fileName = "src/main/resources/test07.xlsx";
// 如果使用流 记得关闭
InputStream inputStream = null;
try {
List<ImageData> list = new ArrayList<ImageData>();
ImageData imageData = new ImageData();
list.add(imageData);
String imagePath = "src/main/resources/test.png";
// 放入五种类型的图片 实际使用只要选一种即可
//1、将图片以二进制数组的形式存入对象
imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
//2、以文件的形式存入对象
imageData.setFile(new File(imagePath));
//3、以字符串的形式存入对象(会通过StringImageConverter将图片转换为字符串)
imageData.setString(imagePath);
//4、通过流的方式存入对象
inputStream = FileUtils.openInputStream(new File(imagePath));
imageData.setInputStream(inputStream);
//5、通过URL的方式存入对象
imageData.setUrl(new URL(
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2853553659,1775735885&fm=26&gp=0.jpg"));
EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
运行效果
使用以下三个注解来设置
//注解在类或方法上都可
@HeadRowHeight(30) //设置标题高度
@ContentRowHeight(100) //设置内容高度
@ColumnWidth(50) //设置列宽
用7的案例
运行效果(注释在类上)
方式一:用注解
使用写入方式一运行
在Studnet类上使用这些注解
类和方法都可以注释
//类和方法都可以注释
//标题样式设置 字体样式 背景样式 LEMON_CHIFFON(26),
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 26)
//设置标题字体 大小
@HeadFontStyle(fontHeightInPoints = 40)
//内容样式设置 字体样式 背景样式 IndexedColors SKY_BLUE(40)
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 40)
//设置内容字体 大小
@ContentFontStyle(fontHeightInPoints = 20)
运行效果
方式二
运行方法
/**
* 自定义样式
* 1. 创建excel对应的实体对象 参照{@link DemoData}
*
2. 创建一个style策略 并注册
*
3. 直接写即可
*/
@Test
public void styleWrite() {
String fileName = "src/main/resources/test08.xlsx";
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景设置为红色
headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
//字体默认设置
WriteFont headWriteFont = new WriteFont();
//设置头部字体大小
headWriteFont.setFontHeightInPoints((short)20);
//通过字体的其他默认设置来设置头部字体
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 背景绿色
contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short)20);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
List<Teacher> teachers = new ArrayList<Teacher>();
teachers.add(new Teacher("zhaoliu",34,"nihao","yuwen",new Date()));
teachers.add(new Teacher("zhaoliu",34,"nihao","shuxue",new Date()));
teachers.add(new Teacher("zhaoliu",24,"nihao","yingyu",new Date()));
teachers.add(new Teacher("zhaoliu",66,"nihao","yingyue",new Date()));
teachers.add(new Teacher("zhaoliu",53,"nihao","yuwen",new Date()));
teachers.add(new Teacher("zhaoliu",54,"nihao","yuwen",new Date()));
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, Teacher.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
.doWrite(teachers);
}
javabean
@Data
@NoArgsConstructor
@AllArgsConstructor
//合并行索引为1-3列索引为1-3的单元格
@OnceAbsoluteMerge(firstRowIndex = 1,lastRowIndex = 3,firstColumnIndex = 1,lastColumnIndex = 3)
public class MergeCell {
@ExcelProperty("单元格名字")
@ContentLoopMerge(eachRow = 2) //合并列
private String cellName;
@ExcelProperty("长")
private Integer width;
@ExcelProperty("宽")
private Integer heigth;
}
运行代码
@Test
public void test09(){
//创建文件保存位置,以及文件名
String filename = "src/main/resources/test09.xlsx";
List<MergeCell> mergeCells = new ArrayList<MergeCell>();
mergeCells.add(new MergeCell("cell1",17,15));
mergeCells.add(new MergeCell("cell2",16,16));
mergeCells.add(new MergeCell("cell3",15,17));
mergeCells.add(new MergeCell("cell4",14,18));
mergeCells.add(new MergeCell("cell5",13,19));
mergeCells.add(new MergeCell("cell6",12,20));
EasyExcel.write(filename,MergeCell.class).sheet("test01").doWrite(mergeCells);
}
运行效果
运行代码
@Test
public void testRead01(){
String fileName = "src/main/resources/test11.xlsx";
//实现AnalysisEventListener监听器
EasyExcel.read(fileName, new AnalysisEventListener<User>() {
//每读取一行,执行一次
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println("读取到的数据:"+user);
}
//读取完后运行
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("执行完毕");
}
}).sheet("用户表").doRead();
}
同写入下标指定方式点击既达
自定义格式转换器
/**
* 配置自定义转换器实现 Converter接口
*/
public class CustomStringStringConverter implements Converter<String> {
public Class supportJavaTypeKey() {
return String.class;
}
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里读的时候会调用
*/
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return "自定义:" + cellData.getStringValue();
}
/**
* 这里是写的时候会调用 不用管
*/
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(value);
}
}
java对象
@Data
public class ConverterData {
/**
* 可以通过converter属性设置自定义转换器。为该属性值前加上”自定义“
*/
@ExcelProperty(converter = CustomStringStringConverter.class)
private String string;
/**
* 这里用string 去接日期才能格式化。我想接收年月日格式
*/
@DateTimeFormat("yyyy年MM月dd日")
private String date;
/**
* 我想接收百分比的数字
*/
@NumberFormat("#.##%")
private String doubleData;
}
运行方法
/**
* 日期、数字或者自定义格式转换
*
* 默认读的转换器{@link DefaultConverterLoader#loadDefaultReadConverter()}
*
1. 创建excel对应的实体对象 参照{@link ConverterData}.里面可以使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
*
2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link ConverterDataListener}
*
3. 直接读即可
*/
@Test
public void converterRead() {
String fileName = "src/main/resources/test12.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet
EasyExcel.read(fileName, ConverterData.class, new AnalysisEventListener<ConverterData>() {
public void invoke(ConverterData data, AnalysisContext context) {
System.out.println("获取数据:"+data);
}
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("数据获取完毕");
}
})
// 这里注意 我们也可以registerConverter来指定自定义转换器, 但是这个转换变成全局了, 所有java为string,excel为string的都会用这个转换器。
// 如果就想单个字段使用请使用@ExcelProperty 指定converter
// .registerConverter(new CustomStringStringConverter())
// 读取sheet
.sheet().doRead();
}
.headRowNumber(2)
运行方法
@Test
public void test12(){
String fileName = "src/main/resources/test06.xlsx";
EasyExcel.read(fileName, Teacher.class, new AnalysisEventListener<Teacher>() {
public void invoke(Teacher teacher, AnalysisContext context) {
System.out.println("获取数据:"+teacher);
}
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("数据获取完毕");
}
}).sheet("老师信息")
// 这里可以设置1,因为头就是一行。如果多行头,可以设置其他值。不传入也可以,因为默认会根据DemoData 来解析,他没有指定头,也就是默认1行
.headRowNumber(2).doRead();
}
javabean
@Data
public class FillData {
@ExcelProperty("姓名")
private String name;
@ExcelProperty("数字")
private double number;
}
/**
* 最简单的填充
*
*/
@Test
public void simpleFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// 模板中的变量要与javabean中的一致
String templateFileName = "src/main/resources/model.xlsx";
// 方案1 根据对象填充
String fileName = "src/main/resources/test13.xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
// doFill方法中传入填充数据
EasyExcel.write(fileName,FillData.class).withTemplate(templateFileName).sheet().doFill(fillData);
// 方案2 根据Map填充
fileName = "src/main/resources/test14.xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "张三");
map.put("number", 5.2);
EasyExcel.write(fileName,FillData.class).withTemplate(templateFileName).sheet().doFill(map);
}
运行方法
/**
* 填充列表
*
* @since 2.1.1
*/
@Test
public void listFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// 填充list 的时候还要注意 模板中{.} 多了个点 表示list
String templateFileName = "src/main/resources/model2.xlsx";
// 方案1 一下子全部放到内存里面 并填充
String fileName = "src/main/resources/test15.xlsx";
List<FillData> data = new ArrayList<FillData>();
data.add(new FillData("zhangsan",11));
data.add(new FillData("zhangsan",12));
data.add(new FillData("zhangsan",13));
data.add(new FillData("zhangsan",14));
data.add(new FillData("zhangsan",15));
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
EasyExcel.write(fileName,FillData.class).withTemplate(templateFileName).sheet().doFill(data);
// 方案2 分多次 填充 会使用文件缓存(省内存)
fileName = "src/main/resources/test13.xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName,FillData.class).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(data, writeSheet);
excelWriter.fill(data, writeSheet);
// 千万别忘记关闭流
excelWriter.finish();
}
模板
运行结果
运行方法
/**
* 复杂的填充
*
* @since 2.1.1
*/
@Test
public void complexFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName = "src/main/resources/model3.xlsx";
String fileName = "src/main/resources/test16.xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
List<FillData> data = new ArrayList<FillData>();
data.add(new FillData("zhangsan",11));
data.add(new FillData("zhangsan",12));
data.add(new FillData("zhangsan",13));
data.add(new FillData("zhangsan",14));
data.add(new FillData("zhangsan",15));
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
// 如果数据量大 list不是最后一行 参照下一个
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(data, fillConfig, writeSheet);
excelWriter.fill(data, fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
}
模板
运行结果
运行方法
/**
* 横向的填充
*
* @since 2.1.1
*/
@Test
public void horizontalFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName = "src/main/resources/model4.xlsx";
String fileName = "src/main/resources/test17.xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
//通过FillConfig配置横向填充
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
List<FillData> data = new ArrayList<FillData>();
data.add(new FillData("zhangsan",11));
data.add(new FillData("zhangsan",12));
data.add(new FillData("zhangsan",13));
data.add(new FillData("zhangsan",14));
data.add(new FillData("zhangsan",15));
excelWriter.fill(data, fillConfig, writeSheet);
excelWriter.fill(data, fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// 别忘记关闭流
excelWriter.finish();
}
模板