触发场景描述 参照demo中的CustomSheetWriteHandler,生成包含下拉框的Excel文件,下拉框中数据包含有符号时,生成的Excel打开报错,提示:部分内容有问题。 从数据中去掉包含有特殊符号的两条数据后,再次生成的文件可以正常打开; 触发Bug的代码
// 测试用的数据为:"经济型:1 勿动","大众(测试)"
提示的异常或者没有达到的效果
触发场景描述 参照demo中的CustomSheetWriteHandler,生成包含下拉框的Excel文件,下拉框中数据包含有符号时,生成的Excel打开报错,提示:部分内容有问题。 从数据中去掉包含有特殊符号的两条数据后,再次生成的文件可以正常打开; 触发Bug的代码
// 测试用的数据为:"经济型:1 勿动","大众(测试)"
提示的异常或者没有达到的效果
windows中不存在这个情况,能提供一下mac的excel版本吗?
我拿官网demo测试了下,没有发现问题 同上,可能是excel版本的问题, 我之前实验的时候碰到过文件打不开的情况是因为我build出来的writer没有调用finish()
windows中不存在这个情况,能提供一下mac的excel版本吗?
1、MAC下的office版本是16.30(19101301),我找了个windows电脑看这个文件,同样是打不开;
新问题
2、我调整了下数据,去掉了一些包含特殊符号的数据,生成的文件可以正常打开了,但是将依赖的版本从2.0.5升级到2.1.1之后,同样数据生成的文件又出现同样的问题;
下面是2.1.1版本生成的异常文件如下,文件的大小比正常生成的小很多:
要下载的是一个空的模板文件,所以write的时候是个null,代码如下:
// 导出操作
EasyExcel.write(MuscleapeExcelUtil.getOutputStream(fileName, response), Model.class)
.registerWriteHandler(writeHandler)
.sheet("导入模板")
.doWrite(null);
/**
* MuscleapeExcelUtil.getOutputStream
* 导出文件时为Writer生成OutputStream
*/
public static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
try {
fileName = new String(fileName.getBytes(), "ISO-8859-1");
response.addHeader("Content-Disposition", "filename=" + fileName);
return response.getOutputStream();
} catch (IOException e) {
throw new ExcelGenerateException("创建文件失败!");
}
}
我拿官网demo测试了下,没有发现问题 同上,可能是excel版本的问题, 我之前实验的时候碰到过文件打不开的情况是因为我build出来的writer没有调用finish()
因为需求是生成一个空的模板文件,所以write的时候是个null,代码如下:
// 导出操作
EasyExcel.write(MuscleapeExcelUtil.getOutputStream(fileName, response), Model.class)
.registerWriteHandler(writeHandler)
.sheet("导入模板")
.doWrite(null);
/**
* MuscleapeExcelUtil.getOutputStream
* 导出文件时为Writer生成OutputStream
*/
public static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
try {
fileName = new String(fileName.getBytes(), "ISO-8859-1");
response.addHeader("Content-Disposition", "filename=" + fileName);
return response.getOutputStream();
} catch (IOException e) {
throw new ExcelGenerateException("创建文件失败!");
}
}
你上面发的这个文件是正常的,我window版本可以打开,只不过是个完全空的文件,有可能是版本不同(我的是wps2019),导致无法打开,可能需要调查一下。 另外,如果只想输出空白表头,推荐将null替换成空集合,例如Collections.emptyList()
// 导出操作
EasyExcel.write(fileName, Model.class)
.registerWriteHandler(new CustomSheetWriteHandler())
.sheet("导入模板")
.doWrite(Collections.emptyList());
输出null时,在内部做了空判断,没有继续执行输出逻辑,源代码: com.alibaba.excel.write.ExcelBuilderImpl#addContent(java.util.List, com.alibaba.excel.write.metadata.WriteSheet, com.alibaba.excel.write.metadata.WriteTable)
@Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) {
try {
if (data == null) {
return;
}
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable);
if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) {
finish();
throw e;
} catch (Throwable e) {
finish();
throw new ExcelGenerateException(e);
}
}
也许是没有添加sheet页之类的导致的(猜测)
你上面发的这个文件是正常的,我window版本可以打开,只不过是个完全空的文件,有可能是版本不同(我的是wps2019),导致无法打开,可能需要调查一下。 另外,如果只想输出空白表头,推荐将null替换成空集合,例如Collections.emptyList()
// 导出操作 EasyExcel.write(fileName, Model.class) .registerWriteHandler(new CustomSheetWriteHandler()) .sheet("导入模板") .doWrite(Collections.emptyList());
输出null时,在内部做了空判断,没有继续执行输出逻辑,源代码: com.alibaba.excel.write.ExcelBuilderImpl#addContent(java.util.List, com.alibaba.excel.write.metadata.WriteSheet, com.alibaba.excel.write.metadata.WriteTable)
@Override public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) { try { if (data == null) { return; } context.currentSheet(writeSheet, WriteTypeEnum.ADD); context.currentTable(writeTable); if (excelWriteAddExecutor == null) { excelWriteAddExecutor = new ExcelWriteAddExecutor(context); } excelWriteAddExecutor.add(data); } catch (RuntimeException e) { finish(); throw e; } catch (Throwable e) { finish(); throw new ExcelGenerateException(e); } }
也许是没有添加sheet页之类的导致的(猜测)
针对您指出的这几处,我认为是这样的
1、生成的异常文件,用WPS可以打开,但是文件也是异常的状态,还是想排查下为啥会生成异常的文件; 2、从目前测试的情况来看,doWrite()中直接指定null并不会影响文件生成,在2.0.5版本中也是用的null数据,不包含带符号的数据时生成的文件是可以正常打开的,这样应该是可以排除使用null导致文件异常的情况;
我的下拉框数据生成方式如下
1、在SheetWriteHandler的实现类中,添加String[]类型的属性及SheetWriteHandler实现类的构造函数; 2、在开始导出文件,调用SheetWriteHandler实现的时候,new一个SheetWriteHandler的实现类,并通过构造函数将多个下拉框需要的数据传进去;
/**
* SheetWriteHandler的实现类
*/
public class TemplateSheetWriteHandler implements SheetWriteHandler {
/**
* 下拉框选项1
*/
private String[] theFirst;
/**
* 下拉框选项2
*/
private String[] theSecond;
// 构造函数
public TemplateSheetWriteHandler(String[] theFirst,String[] theSecond) {
this.theFirst = theFirst;
this.theSecond = theSecond;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo());
// 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();
// theFirst
if (ArrayUtils.isNotEmpty(theFirst)) {
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 1000, 0, 0);
DataValidationConstraint constraint = helper.createExplicitListConstraint(theFirst);
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
writeSheetHolder.getSheet().addValidationData(dataValidation);
}
// theSecond
if (ArrayUtils.isNotEmpty(theSecond)) {
CellRangeAddressList cellRangeAddressList2 = new CellRangeAddressList(1, 1000, 3, 3);
DataValidationConstraint constraint2 = helper.createExplicitListConstraint(theSecond);
DataValidation dataValidation2 = helper.createValidation(constraint2, cellRangeAddressList2);
writeSheetHolder.getSheet().addValidationData(dataValidation2);
}
}
}
TemplateSheetWriteHandler writeHandler = new TemplateSheetWriteHandler(busyType,operationCity);
// 导出操作
EasyExcel.write(MuscleapeExcelUtil.getOutputStream(fileName, response), Model.class)
.registerWriteHandler(writeHandler)
.sheet("导入模板")
.doWrite(null);
经验证,下拉框中文本长度超过255导致该问题