刚开始使用new HSSFWorkbook(new FileInputStream(excelFile))来读取Workbook,对Excel2003以前(包括2003)的版本没有问题,但读取Excel2007时发生如下异常:
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
该错误意思是说,文件中的数据是用Office2007+XML保存的,而现在却调用OLE2 Office文档处理,应该使用POI不同的部分来处理这些数据,比如使用XSSF来代替HSSF。
于是按提示使用XSSF代替HSSF,用new XSSFWorkbook(excelFile)来读取Workbook,对Excel2007没有问题了,可是在读取Excel2003以前(包括2003)的版本时却发生了如下新异常:
org.apache.poi.openxml4j.exceptions.InvalidOperationException: Can't open the specified file: '*.xls'
该错误是说,操作无效,不能打开指定的xls文件。
下载POI的源码后进行单步调试,发现刚开始的时候还是对的,但到ZipFile类后就找不到文件了,到网上查了下,原来是XSSF不能读取Excel2003以前(包括2003)的版本,这样的话,就需要在读取前判断文件是2003前的版本还是2007的版本,然后对应调用HSSF或XSSF来读取。
这是初步的想法,但这种做法比较麻烦,看了下API,发现XSSF和HSSF虽然在不同的包里,但却引用了同一接口Workbook,于是想到了这样的读取方法:
Workbook book = null;
try {
book = new XSSFWorkbook(excelFile);
} catch (Exception ex) {
book = new HSSFWorkbook(new FileInputStream(excelFile));
}
在各版本的Excel中测试,没有发生异常,问题解决。
另外提供其他网友的解决方案:
//创建相关的文件流对象
in = new FileInputStream(excelFile);
//声明相关的工作薄对象
Workbook wb =null;
//声明相关的excel抽取对象
ExcelExtractor extractor=null;
String fileName = excelFile.getName();
String hz = fileName.substring(fileName.lastIndexOf("."),fileName.length());
if(hz.equals(".xls"))//针对2003版本
{
//创建excel2003的文件文本抽取对象
wb=new HSSFWorkbook(new POIFSFileSystem(in));
extractor =new org.apache.poi.hssf.extractor.ExcelExtractor((HSSFWorkbook)wb);
}else{ //针对2007版本
wb = new XSSFWorkbook(in);
//创建excel2007的文件文本抽取对象
extractor =new XSSFExcelExtractor((XSSFWorkbook)wb);
}
建议:
我觉得如果用异常来判断Excel版本的话 用org.apache.poi.poifs.filesystem.OfficeXmlFileException这个异常比较好
我在new HSSFWorkbook时new2007的会报这个错 直接用Exception有点太笼统了吧 因为我还知道一个org.apache.poi.hssf.OldExcelFormatException的错 这是弄Ecxel5.0/95出的错 这个用XSSF也处理不了
我自己处理的代码部分:
/**
* @description 导入表格
* @param filename
* @return
* @throws Exception
* @throws TException
*/
@RequestMapping(value = "/uploadWfdl", method = RequestMethod.POST, produces = {"application/text;charset=UTF-8"})
@ResponseBody
public String importData(@RequestParam("filename") MultipartFile filename,
HttpServletRequest request,
HttpServletResponse response
) throws TException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
InputStream inputStream = null;
try {
inputStream = filename.getInputStream(); // 取得输入流
} catch (IOException e) {
logger.info("importData------------------------>InputStream IOException");
}
Workbook workbook = null;
try {
workbook = new XSSFWorkbook(inputStream); // 解析2007版本
} catch (Exception ex) {
logger.info("importData------------------------>XSSFWorkbook Read InputStream Exception");
try {
POIFSFileSystem pfs = new POIFSFileSystem(filename.getInputStream()); // 解析2003版本
workbook = new HSSFWorkbook(pfs);
} catch (IOException e) {
logger.info("importData------------------------>HSSFWorkbook Read InputStream Exception");
}
}
Sheet hssfSheet = workbook .getSheetAt(0);
int rowCount = hssfSheet.getPhysicalNumberOfRows(); // 获取总行数
String msg = "";
if(hssfSheet!=null) {
for (int i = 1; i<= rowCount; i++) {
Row excelData = hssfSheet.getRow(i);
if (excelData == null)
continue;
}
}
}