2019独角兽企业重金招聘Python工程师标准>>>
已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools
我们在做用POI读物 Excel文件时,往往会忽略了Excel的版本,到底是2003还是2007。于是在读取或写入Excel文件时,用2003版本的Excel和用2007版本的Excel文件,会出现不兼容情况。抛出异常,大概信息如下: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以上的版本(包含2007),要我们用XSSF来代替HSSF。
于是我们开始替换我们的代码,用XSSF代替HSSF。可是我们却意外的发现poi.jar包中,并不包含XSSF,那么XSSF到底从哪来的呢?百度一下发现,他们来自不同的星球:
(1)XSSFWorkbook:poi-ooxml-.jar org.apache.poi.xssf.usermodel.XSSFWorkbook
(2)HSSFWorkbook:poi.jar org.apache.poi.hssf.usermodel.HSSFWorkbook
查看源码:
多么的巧合啊!HSSFWorkbook 和 XSSFWorkbook 都实现了 Workbook 接口!
所以思路就来了,我们用时引入这两种jar包,在判断出Excel的版本号,根据Excel版本的不同来用HSSFWorkbook 或者XSSFWorkbook 的实现 Workbook。下面就直接上代码吧!
POI的版本号:
3.12
org.apache.poi
poi
${poi.version}
org.apache.poi
poi-ooxml
${poi.version}
读取Excel文件的Java类:
/**
* @package :com.changhongit.andy.util
* @author :wanglongjie
* @createDate :2015年8月31日下午1:37:32
*/
package com.changhongit.andy.util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* @package :com.changhongit.andy.util
* @file :ExcelReader.java
* @describe :读取 Excel 文件
* @author :wanglongjie
* @createDate :2015年8月31日下午1:37:32
* @updater :
* @updateDate :
* @updateContent :
*/
public class ExcelReader {
static private Workbook wb;
static private Sheet sheet;
static private Row row;
/**
*
* @method :readExcelTitle
* @describe :读取 Excel 文件
* @author :wanglongjie
* @createDate :2015年8月31日下午2:41:25
* @param fileName
* :Excel 文件路径
* @return String[]
*/
public static String[] readExcelTitle(String fileName) {
InputStream is;
try {
is = new FileInputStream(fileName);
String postfix = fileName.substring(fileName.lastIndexOf("."),
fileName.length());
if (postfix.equals(".xls")) {
// 针对 2003 Excel 文件
wb = new HSSFWorkbook(new POIFSFileSystem(is));
sheet = wb.getSheetAt(0);
} else {
// 针对2007 Excel 文件
wb = new XSSFWorkbook(is);
sheet = wb.getSheetAt(0);
}
} catch (IOException e) {
e.printStackTrace();
}
sheet = wb.getSheetAt(0);
row = sheet.getRow(0);// 获取第一行(约定第一行是标题行)
int colNum = row.getPhysicalNumberOfCells();// 获取行的列数
String[] titles = new String[colNum];
for (int i = 0; i < titles.length; i++) {
titles[i] = getCellFormatValue(row.getCell(i));
}
return titles;
}
/**
*
* @method :readExcelContent
* @describe :读取 Excel 内容
* @author :wanglongjie
* @createDate :2015年8月31日下午3:12:06
* @param fileName
* :Excel 文件路径
* @return List
主要的思路就是,我们在定义成员变量时不在定义某一种实现类,而是定义成接口:
static private Workbook wb;
static private Sheet sheet;
static private Row row;
然后根据上传文件的后缀名,判断是2003Excel还是2007Excel,再决定用不同的类实现成员变量的接口,从而达到代码既支持2003Excel有支持2007Excel:
InputStream is = new FileInputStream(fileName);
String postfix = fileName.substring(fileName.lastIndexOf("."),
fileName.length());
if (postfix.equals(".xls")) {
// 针对 2003 Excel 文件
wb = new HSSFWorkbook(new POIFSFileSystem(is));
sheet = wb.getSheetAt(0);
} else {
// 针对2007 Excel 文件
wb = new XSSFWorkbook(is);
sheet = wb.getSheetAt(0);
}
最后纠结了半天的问题终于解决了,欧耶
已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools