private List<DemoData> data() {List<DemoData> list = new ArrayList<DemoData>();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}
示例代码
DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java
最简单的写
excel示例
对象
@Datapublic class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;}
代码
/*** 最简单的写* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 直接写即可*/@Testpublic void simpleWrite() {// 写法1String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());// 写法2fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写ExcelWriter excelWriter = null;try {excelWriter = EasyExcel.write(fileName, DemoData.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();excelWriter.write(data(), writeSheet);} finally {// 千万别忘记finish 会帮忙关闭流if (excelWriter != null) {excelWriter.finish();}}}
根据参数只导出指定列
excel示例
对象
参照:对象
代码
/*** 根据参数只导出指定列* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 根据自己或者排除自己需要的列* <p>* 3. 直接写即可** @since 2.1.1*/@Testpublic void excludeOrIncludeWrite() {String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";// 根据用户传入字段 假设我们要忽略 dateSet<String> excludeColumnFiledNames = new HashSet<String>();excludeColumnFiledNames.add("date");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(data());fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";// 根据用户传入字段 假设我们只要导出 dateSet<String> includeColumnFiledNames = new HashSet<String>();includeColumnFiledNames.add("date");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板").doWrite(data());}
指定写入的列
excel示例
对象
@Datapublic class IndexData {@ExcelProperty(value = "字符串标题", index = 0)private String string;@ExcelProperty(value = "日期标题", index = 1)private Date date;/*** 这里设置3 会导致第二列空的*/@ExcelProperty(value = "数字标题", index = 3)private Double doubleData;}
代码
/*** 指定写入的列* <p>1. 创建excel对应的实体对象 参照{@link IndexData}* <p>2. 使用{@link ExcelProperty}注解指定写入的列* <p>3. 直接写即可*/@Testpublic void indexWrite() {String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());}
复杂头写入
excel示例
对象
@Datapublic class ComplexHeadData {@ExcelProperty({"主标题", "字符串标题"})private String string;@ExcelProperty({"主标题", "日期标题"})private Date date;@ExcelProperty({"主标题", "数字标题"})private Double doubleData;}
代码
/*** 复杂头写入* <p>1. 创建excel对应的实体对象 参照{@link ComplexHeadData}* <p>2. 使用{@link ExcelProperty}注解指定复杂的头* <p>3. 直接写即可*/@Testpublic void complexHeadWrite() {String fileName = TestFileUtil.getPath() + "complexHeadWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());}
重复多次写入(写到单个或者多个Sheet)
excel示例
对象
参照:对象
代码
/*** 重复多次写入* <p>* 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}* <p>* 2. 使用{@link ExcelProperty}注解指定复杂的头* <p>* 3. 直接调用二次写入即可*/@Testpublic void repeatedWrite() {// 方法1 如果写到同一个sheetString fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";ExcelWriter excelWriter = null;try {// 这里 需要指定写用哪个class去写excelWriter = EasyExcel.write(fileName, DemoData.class).build();// 这里注意 如果同一个sheet只要创建一次WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来for (int i = 0; i < 5; i++) {// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}} finally {// 千万别忘记finish 会帮忙关闭流if (excelWriter != null) {excelWriter.finish();}}// 方法2 如果写到不同的sheet 同一个对象fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";try {// 这里 指定文件excelWriter = EasyExcel.write(fileName, DemoData.class).build();// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}} finally {// 千万别忘记finish 会帮忙关闭流if (excelWriter != null) {excelWriter.finish();}}// 方法3 如果写到不同的sheet 不同的对象fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";try {// 这里 指定文件excelWriter = EasyExcel.write(fileName).build();// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}} finally {// 千万别忘记finish 会帮忙关闭流if (excelWriter != null) {excelWriter.finish();}}}
日期、数字或者自定义格式转换
excel示例
对象
@Datapublic class ConverterData {/*** 我想所有的 字符串起前面加上"自定义:"三个字*/@ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)private String string;/*** 我想写到excel 用年月日的格式*/@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")@ExcelProperty("日期标题")private Date date;/*** 我想写到excel 用百分比表示*/@NumberFormat("#.##%")@ExcelProperty(value = "数字标题")private Double doubleData;}
代码
/*** 日期、数字或者自定义格式转换* <p>1. 创建excel对应的实体对象 参照{@link ConverterData}* <p>2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解* <p>3. 直接写即可*/@Testpublic void converterWrite() {String fileName = TestFileUtil.getPath() + "converterWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());}
图片导出
excel示例
对象
@Data@ContentRowHeight(100)@ColumnWidth(100 / 8)public class ImageData {private File file;private InputStream inputStream;/*** 如果string类型 必须指定转换器,string默认转换成string*/@ExcelProperty(converter = StringImageConverter.class)private String string;private byte[] byteArray;/*** 根据url导出** @since 2.1.1*/private URL url;}
代码
/*** 图片导出* <p>* 1. 创建excel对应的实体对象 参照{@link ImageData}* <p>* 2. 直接写即可*/@Testpublic void imageWrite() throws Exception {String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx";// 如果使用流 记得关闭InputStream inputStream = null;try {List<ImageData> list = new ArrayList<ImageData>();ImageData imageData = new ImageData();list.add(imageData);String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";// 放入五种类型的图片 实际使用只要选一种即可imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));imageData.setFile(new File(imagePath));imageData.setString(imagePath);inputStream = FileUtils.openInputStream(new File(imagePath));imageData.setInputStream(inputStream);imageData.setUrl(new URL("https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg"));EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);} finally {if (inputStream != null) {inputStream.close();}}}
根据模板写入
模板excel示例
excel示例
对象
参照:对象
代码
/*** 根据模板写入* <p>1. 创建excel对应的实体对象 参照{@link IndexData}* <p>2. 使用{@link ExcelProperty}注解指定写入的列* <p>3. 使用withTemplate 写取模板* <p>4. 直接写即可*/@Testpublic void templateWrite() {String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data());}
列宽、行高
excel示例
对象
@Data@ContentRowHeight(10)@HeadRowHeight(20)@ColumnWidth(25)public class WidthAndHeightData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;/*** 宽度为50*/@ColumnWidth(50)@ExcelProperty("数字标题")private Double doubleData;}
代码
/*** 列宽、行高* <p>1. 创建excel对应的实体对象 参照{@link WidthAndHeightData}* <p>2. 使用注解{@link ColumnWidth}、{@link HeadRowHeight}、{@link ContentRowHeight}指定宽度或高度* <p>3. 直接写即可*/@Testpublic void widthAndHeightWrite() {String fileName = TestFileUtil.getPath() + "widthAndHeightWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(data());}
注解形式自定义样式
since
excel示例
对象
/*** 样式的数据类** @author Jiaju Zhuang**/@Data// 头背景设置成红色 IndexedColors.RED.getIndex()@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10)// 头字体设置成20@HeadFontStyle(fontHeightInPoints = 20)// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17)// 内容字体设置成20@ContentFontStyle(fontHeightInPoints = 20)public class DemoStyleData {// 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)// 字符串的头字体设置成20@HeadFontStyle(fontHeightInPoints = 30)// 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40)// 字符串的内容字体设置成20@ContentFontStyle(fontHeightInPoints = 30)@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;}
代码
/*** 注解形式自定义样式* <p>* 1. 创建excel对应的实体对象 参照{@link DemoStyleData}* <p>* 3. 直接写即可** @since 2.2.0-beta1*/@Testpublic void annotationStyleWrite() {String fileName = TestFileUtil.getPath() + "annotationStyleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoStyleData.class).sheet("模板").doWrite(data());}
自定义样式
excel示例
对象
参照:对象
代码
/*** 自定义样式* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 创建一个style策略 并注册* <p>3. 直接写即可*/@Testpublic void styleWrite() {String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".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);// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板").doWrite(data());}
合并单元格
since
excel示例
对象
方法1
/*** 样式的数据类** @author Jiaju Zhuang**/@Data// 将第6-7行的2-3列合并成一个单元格// @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)public class DemoMergeData {// 这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow = 2)@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;}
方法2参照:对象
代码
/*** 合并单元格* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData} {@link DemoMergeData}* <p>* 2. 创建一个merge策略 并注册* <p>* 3. 直接写即可** @since 2.2.0-beta1*/@Testpublic void mergeWrite() {// 方法1 注解String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";// 在DemoStyleData里面加上ContentLoopMerge注解// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(data());// 方法2 自定义合并单元格策略fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";// 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data());}
使用table去写入
excel示例
对象
参照:对象
代码
/*** 使用table去写入* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 然后写入table即可*/@Testpublic void tableWrite() {String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx";// 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例// 这里 需要指定写用哪个class去写ExcelWriter excelWriter = null;try {excelWriter = EasyExcel.write(fileName, DemoData.class).build();// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();// 第一次写入会创建头excelWriter.write(data(), writeSheet, writeTable0);// 第二次写如也会创建头,然后在第一次的后面写入数据excelWriter.write(data(), writeSheet, writeTable1);} finally {// 千万别忘记finish 会帮忙关闭流if (excelWriter != null) {excelWriter.finish();}}}
动态头,实时生成头写入
excel示例
对象
参照:对象
代码
/*** 动态头,实时生成头写入* <p>* 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据** <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 然后写入table即可*/@Testpublic void dynamicHeadWrite() {String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";EasyExcel.write(fileName)// 这里放入动态头.head(head()).sheet("模板")// 当然这里数据也可以用 List<List<String>> 去传入.doWrite(data());}private List<List<String>> head() {List<List<String>> list = new ArrayList<List<String>>();List<String> head0 = new ArrayList<String>();head0.add("字符串" + System.currentTimeMillis());List<String> head1 = new ArrayList<String>();head1.add("数字" + System.currentTimeMillis());List<String> head2 = new ArrayList<String>();head2.add("日期" + System.currentTimeMillis());list.add(head0);list.add(head1);list.add(head2);return list;}
自动列宽(不太精确)
excel示例
对象
@Datapublic class LongestMatchColumnWidthData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题很长日期标题很长日期标题很长很长")private Date date;@ExcelProperty("数字")private Double doubleData;}
代码
/*** 自动列宽(不太精确)* <p>* 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照* {@link LongestMatchColumnWidthStyleStrategy}重新实现.* <p>* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。** <p>* 1. 创建excel对应的实体对象 参照{@link LongestMatchColumnWidthData}* <p>* 2. 注册策略{@link LongestMatchColumnWidthStyleStrategy}* <p>* 3. 直接写即可*/@Testpublic void longestMatchColumnWidthWrite() {String fileName =TestFileUtil.getPath() + "longestMatchColumnWidthWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, LongestMatchColumnWidthData.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板").doWrite(dataLong());}private List<LongestMatchColumnWidthData> dataLong() {List<LongestMatchColumnWidthData> list = new ArrayList<LongestMatchColumnWidthData>();for (int i = 0; i < 10; i++) {LongestMatchColumnWidthData data = new LongestMatchColumnWidthData();data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i);data.setDate(new Date());data.setDoubleData(1000000000000.0);list.add(data);}return list;}
自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)
excel示例
对象
参照:对象
定义拦截器
/*** 自定义拦截器。对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel** @author Jiaju Zhuang*/public class CustomCellWriteHandler implements CellWriteHandler {private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class);@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,Head head, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {// 这里可以对cell进行任何操作LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());if (isHead && cell.getColumnIndex() == 0) {CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);hyperlink.setAddress("https://github.com/alibaba/easyexcel");cell.setHyperlink(hyperlink);}}}
/*** 自定义拦截器.对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2** @author Jiaju Zhuang*/public class CustomSheetWriteHandler implements SheetWriteHandler {private static final Logger LOGGER = LoggerFactory.getLogger(CustomSheetWriteHandler.class);@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo());// 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);writeSheetHolder.getSheet().addValidationData(dataValidation);}}
代码
/*** 下拉,超链接等自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)* <p>* demo这里实现2点。1. 对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel 2. 对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 注册拦截器 {@link CustomCellWriteHandler} {@link CustomSheetWriteHandler}* <p>* 2. 直接写即可*/@Testpublic void customHandlerWrite() {String fileName = TestFileUtil.getPath() + "customHandlerWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new CustomSheetWriteHandler()).registerWriteHandler(new CustomCellWriteHandler()).sheet("模板").doWrite(data());}
插入批注
excel示例
对象
参照:对象
定义拦截器
/*** 自定义拦截器.新增注释,第一行头加批注** @author Jiaju Zhuang*/public class CommentWriteHandler extends AbstractRowWriteHandler {@Overridepublic void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,Integer relativeRowIndex, Boolean isHead) {if (isHead) {Sheet sheet = writeSheetHolder.getSheet();Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();// 在第一行 第二列创建一个批注Comment comment =drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)1, 0, (short)2, 1));// 输入批注信息comment.setString(new XSSFRichTextString("创建批注!"));// 将批注添加到单元格对象中sheet.getRow(0).getCell(1).setCellComment(comment);}}}
代码
/*** 插入批注* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 注册拦截器 {@link CommentWriteHandler}* <p>* 2. 直接写即可*/@Testpublic void commentWrite() {String fileName = TestFileUtil.getPath() + "commentWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 这里要注意inMemory 要设置为true,才能支持批注。目前没有好的办法解决 不在内存处理批注。这个需要自己选择。EasyExcel.write(fileName, DemoData.class).inMemory(Boolean.TRUE).registerWriteHandler(new CommentWriteHandler()).sheet("模板").doWrite(data());}
不创建对象
不创建对象的写
excel示例
代码
/*** 不创建对象的写*/@Testpublic void noModelWrite() {// 写法1String fileName = TestFileUtil.getPath() + "noModelWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());}private List<List<String>> head() {List<List<String>> list = new ArrayList<List<String>>();List<String> head0 = new ArrayList<String>();head0.add("字符串" + System.currentTimeMillis());List<String> head1 = new ArrayList<String>();head1.add("数字" + System.currentTimeMillis());List<String> head2 = new ArrayList<String>();head2.add("日期" + System.currentTimeMillis());list.add(head0);list.add(head1);list.add(head2);return list;}private List<List<Object>> dataList() {List<List<Object>> list = new ArrayList<List<Object>>();for (int i = 0; i < 10; i++) {List<Object> data = new ArrayList<Object>();data.add("字符串" + i);data.add(new Date());data.add(0.56);list.add(data);}return list;}
web中的写
示例代码
DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java
对象
参照:对象 就是名称变了下
代码
/*** 文件下载(失败了会返回一个有部分数据的Excel)* <p>* 1. 创建excel对应的实体对象 参照{@link DownloadData}* <p>* 2. 设置返回的 参数* <p>* 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大*/@GetMapping("download")public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());}
web中的写并且失败的时候返回json
since
对象
参照:对象 就是名称变了下
代码
/*** 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)** @since 2.1.1*/@GetMapping("downloadFailedUsingJson")public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmantry {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这里需要设置不关闭流EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板").doWrite(data());} catch (Exception e) {// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");Map<String, String> map = new HashMap<String, String>();map.put("status", "failure");map.put("message", "下载文件失败" + e.getMessage());response.getWriter().println(JSON.toJSONString(map));}}
