Java读取Excel文件汇总
2017-03-28 14:58
302 查看
相信很多程序猿朋友碰到上传、读取Excel文件的问题,做个小结,权当是笔记收着吧。
之前做金融报表,是把Excel内嵌到页面中的,技术上采用ZK结合POI读取和插入Excel数据,后台方法比较死,比较程式化。
目前新需求是把Excel表格上传到服务器,读取到里边的数据做处理。
一、首先上传Excel
1、页面添加文件域
Java代码
<form id="uploadExcel" action="/auth/user/toHandleBatchRobotExcel.do"
enctype="multipart/form- data" method="POST" >
<input type="file" id="excel" name="excelFile"/>
<input type="button" id="uploadExcel" />
</form>
2、使用ajax提交表单(需导入jquery.form.js)
Java代码
var excel=$("#excel").val();
var location=$('#excel').val();
var point = location.lastIndexOf(".");
var type = location.substr(point);
//type是Excel表格的格式.xls\.xlsx
$("#uploadExcel").ajaxSubmit({
data:{ext:type},
success:function(data){
var dataJson = eval("("+data+")");
console.log(data);
if(dataJson.code==100){
alert(dataJson.message);
}else{
alert("成功上传"+dataJson.attribute.robotNum+"条记录");
}
}
});
二、后台读取
我尝试了两种方式来读取,jxl和poi。
1、jxl读取
jxl操作也是比较方便的,上代码吧。
Jar包:jxl-2.6.jar
读取Excel:
Java代码
@RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
public void handleExcel(HttpServletResponse response,
MultipartHttpServletRequest request, String ext) {
logger.info("处理Excel表格");
logger.info("开始解析...");
logger.info(ext);
MultipartFile fileFile = request.getFile("excelFile");
InputStream in = fileFile.getInputStream();
//获取Excel文件对象
Workbook wb = Workbook.getWorkbook(in);
//获取文件的指定工作表默认的第一个
Sheet sheet = wb.getSheet(0);
// 单元格
Cell cell;
//获取行数
Int rows = sheet.getRows();
Map<Integer, String> map = new HashMap<Integer, String>();
List<UserInfoVo> list = new LinkedList<UserInfoVo>();
if (rows.size() > 0 && rows!= null) {
for (int i = 1; i < rows.size(); i++) {
for (int j = 0; j < sheet.getColumns(); j++) {
cell =sheet.getCell(j,i);
map.put(j,cell.getContents());
}
//Excel数据对应的实体类,根据情况自己设定
UserInfoVo userInfoVo = new UserInfoVo();
userInfoVo.setNickName(map.get(1));
userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
.getTime());
userInfoVo.setState(1);
list.add(userInfoVo);
}
}
}
这样读取到的list中就包括了excel表中的各行数据。
但是在使用过程中发现,有些用户上传2007版的Excel表格,这样的话就会出现读取错误的情况
jxl.read.biff.BiffException: Unable to recognize OLE stream,这是因为jxl久未更新,没法读取新版本的 Excel,就是.xlsx格式的文件。
于是,换种思路,使用兼容性更好的poi进行读取。
2、poi读取
poi是读取Excel最佳工具,功能丰富,对读取不同版本的excel都做了对应处理。
jar包:
poi-3.11.jar 针对03版excel,即后缀为.xls的文件。
poi-ooxml-3.11.jar 针对07版excel,即后缀为.xlsx的文件。
读取Excel:
Java代码
@RequestMapping(value = UrlMappings.HAN
1f494
DLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
public void handleExcel(HttpServletResponse response,
MultipartHttpServletRequest request, String ext) {
logger.info("处理Excel表格");
logger.info("开始解析...");
//excel格式 .xls\.xlsx
logger.info(ext);
// 得到上传的文件
MultipartFile fileFile = request.getFile("excelFile");
try {
// 转换成输入流
InputStream in = fileFile.getInputStream();
// 单元格
Cell cell;
List<Row> rsRows = new ExcelUtils().readExcel(ext, in);
// 实例化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Map<Integer, String> map = new HashMap<Integer, String>();
List<UserInfoVo> list = new LinkedList<UserInfoVo>();
if (rsRows.size() > 0 && rsRows != null) {
for (int i = 1; i < rsRows.size(); i++) {
for (int j = 0; j < rsRows.get(i).getLastCellNum(); j++) {
cell = rsRows.get(i).getCell(j);
map.put(j, new ExcelUtils().getCellValue(cell));
}
UserInfoVo userInfoVo = new UserInfoVo();
userInfoVo.setNickName(map.get(1));
userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
.getTime());
userInfoVo.setState(1);
list.add(userInfoVo);
}
}
}
List中即是excel表中的数据。这其中要用到一个工具类ExcelUtils。
Java代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
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.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelUtils {
// %%%%%%%%-------常量部分 开始----------%%%%%%%%%
/**
* 默认的开始读取的行位置为第一行(索引值为0)
*/
private final static int READ_START_POS = 0;
/**
* 默认结束读取的行位置为最后一行(索引值=0,用负数来表示倒数第n行)
*/
private final static int READ_END_POS = 0;
/**
* 默认Excel内容的开始比较列位置为第一列(索引值为0)
*/
private final static int COMPARE_POS = 0;
/**
* 默认多文件合并的时需要做内容比较(相同的内容不重复出现)
*/
private final static boolean NEED_COMPARE = true;
/**
* 默认多文件合并的新文件遇到名称重复时,进行覆盖
*/
private final static boolean NEED_OVERWRITE = true;
/**
* 默认只操作一个sheet
*/
private final static boolean ONLY_ONE_SHEET = true;
/**
* 默认读取第一个sheet中(只有当ONLY_ONE_SHEET = true时有效)
*/
private final static int SELECTED_SHEET = 0;
/**
* 默认从第一个sheet开始读取(索引值为0)
*/
private final static int READ_START_SHEET = 0;
/**
* 默认在最后一个sheet结束读取(索引值=0,用负数来表示倒数第n行)
*/
private final static int READ_END_SHEET = 0;
/**
* 默认打印各种信息
*/
private final static boolean PRINT_MSG = true;
// %%%%%%%%-------常量部分 结束----------%%%%%%%%%
// %%%%%%%%-------字段部分 开始----------%%%%%%%%%
/**
* Excel文件路径
*/
private String excelPath = "data.xlsx";
/**
* 设定开始读取的位置,默认为0
*/
private int startReadPos = READ_START_POS;
/**
* 设定结束读取的位置,默认为0,用负数来表示倒数第n行
*/
private int endReadPos = READ_END_POS;
/**
* 设定开始比较的列位置,默认为0
*/
private int comparePos = COMPARE_POS;
/**
* 设定汇总的文件是否需要替换,默认为true
*/
private boolean isOverWrite = NEED_OVERWRITE;
/**
* 设定是否需要比较,默认为true(仅当不覆写目标内容是有效,即isOverWrite=false时有效)
*/
private boolean isNeedCompare = NEED_COMPARE;
/**
* 设定是否只操作第一个sheet
*/
private boolean onlyReadOneSheet = ONLY_ONE_SHEET;
/**
* 设定操作的sheet在索引值
*/
private int selectedSheetIdx = SELECTED_SHEET;
/**
* 设定操作的sheet的名称
*/
private String selectedSheetName = "";
/**
* 设定开始读取的sheet,默认为0
*/
private int startSheetIdx = READ_START_SHEET;
/**
* 设定结束读取的sheet,默认为0,用负数来表示倒数第n行
*/
private int endSheetIdx = READ_END_SHEET;
/**
* 设定是否打印消息
*/
private boolean printMsg = PRINT_MSG;
// %%%%%%%%-------字段部分 结束----------%%%%%%%%%
public ExcelUtils() {
}
public ExcelUtils(String excelPath) {
this.excelPath = excelPath;
}
/**
* 还原设定(其实是重新new一个新的对象并返回)
*
* @return
*/
public ExcelUtils RestoreSettings() {
ExcelUtils instance = new ExcelUtils(this.excelPath);
return instance;
}
/**
* 自动根据文件扩展名,调用对应的读取方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @throws IOException
*/
public List<Row> readExcel() throws IOException {
return readExcel(this.excelPath);
}
/**
* 自动根据文件扩展名,调用对应的读取方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param xlsPath
* @throws IOException
*/
public List<Row> readExcel(String xlsPath) throws IOException {
// 扩展名为空时,
if (xlsPath.equals("")) {
throw new IOException("文件路径不能为空!");
} else {
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件不存在!");
}
}
// 获取扩展名
String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
try {
if ("xls".equals(ext)) { // 使用xls方式读取
return readExcel_xls(xlsPath);
} else if ("xlsx".equals(ext)) { // 使用xlsx方式读取
return readExcel_xlsx(xlsPath);
} else { // 依次尝试xls、xlsx方式读取
out("您要操作的文件没有扩展名,正在尝试以xls方式读取...");
try {
return readExcel_xls(xlsPath);
} catch (IOException e1) {
out("尝试以xls方式读取,结果失败!,正在尝试以xlsx方式读取...");
try {
return readExcel_xlsx(xlsPath);
} catch (IOException e2) {
out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
throw e;
}
}
/**
* 通过判断文件的扩展名,以不同的方式读取文件
*
* @author wufei 2016年9月19日 上午10:41:27
* @Method: readExcel
* @Description: TODO
* @param @param ext
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel(String ext, InputStream in) {
try {
if (".xls".equals(ext)) { // 使用xls方式读取
return readExcel_xlsAsStream(in);
} else if (".xlsx".equals(ext)) { // 使用xlsx方式读取
return readExcel_xlsxAsStream(in);
} else { // 依次尝试xls、xlsx方式读取
out("您要操作的文件没有扩展名,正在尝试以xlsx方式读取...");
try {
return readExcel_xlsxAsStream(in);
} catch (Exception e1) {
out("尝试以xlsx方式读取,结果失败!,正在尝试以xls方式读取...");
try {
return readExcel_xlsAsStream(in);
} catch (IOException e2) {
out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
out(e.getMessage());
return null;
}
}
/**
* 自动根据文件扩展名,调用对应的写入方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @throws IOException
*/
public void writeExcel(List<Row> rowList) throws IOException {
writeExcel(rowList, excelPath);
}
/**
* 自动根据文件扩展名,调用对应的写入方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param xlsPath
* @throws IOException
*/
public void writeExcel(List<Row> rowList, String xlsPath)
throws IOException {
// 扩展名为空时,
if (xlsPath.equals("")) {
throw new IOException("文件路径不能为空!");
}
// 获取扩展名
String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
try {
if ("xls".equals(ext)) { // 使用xls方式写入
writeExcel_xls(rowList, xlsPath);
} else if ("xlsx".equals(ext)) { // 使用xlsx方式写入
writeExcel_xlsx(rowList, xlsPath);
} else { // 依次尝试xls、xlsx方式写入
out("您要操作的文件没有扩展名,正在尝试以xls方式写入...");
try {
writeExcel_xls(rowList, xlsPath);
} catch (IOException e1) {
out("尝试以xls方式写入,结果失败!,正在尝试以xlsx方式读取...");
try {
writeExcel_xlsx(rowList, xlsPath);
} catch (IOException e2) {
out("尝试以xls方式写入,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
throw e;
}
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xls(List<Row> rowList, String dist_xlsPath)
throws IOException {
writeExcel_xls(rowList, excelPath, dist_xlsPath);
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param src_xlsPath
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xls(List<Row> rowList, String src_xlsPath,
String dist_xlsPath) throws IOException {
// 判断文件路径是否为空
if (dist_xlsPath == null || dist_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断文件路径是否为空
if (src_xlsPath == null || src_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断列表是否有数据,如果没有数据,则返回
if (rowList == null || rowList.size() == 0) {
out("文档为空");
return;
}
try {
HSSFWorkbook wb = null;
// 判断文件是否存在
File file = new File(dist_xlsPath);
if (file.exists()) {
// 如果复写,则删除后
if (isOverWrite) {
file.delete();
// 如果文件不存在,则创建一个新的Excel
// wb = new HSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
} else {
// 如果文件存在,则读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
}
} else {
// 如果文件不存在,则创建一个新的Excel
// wb = new HSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
}
// 将rowlist的内容写到Excel中
writeExcel(wb, rowList, dist_xlsPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xlsx(List<Row> rowList, String dist_xlsPath)
throws IOException {
writeExcel_xls(rowList, excelPath, dist_xlsPath);
}
/**
* 修改Excel(2007版,xlsx格式)
*
* @Title: writeExcel_xlsx
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @throws IOException
*/
public void writeExcel_xlsx(List<Row> rowList, String src_xlsPath,
String dist_xlsPath) throws IOException {
// 判断文件路径是否为空
if (dist_xlsPath == null || dist_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断文件路径是否为空
if (src_xlsPath == null || src_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断列表是否有数据,如果没有数据,则返回
if (rowList == null || rowList.size() == 0) {
out("文档为空");
return;
}
try {
// 读取文档
HSSFWorkbook wb = null;
// 判断文件是否存在
File file = new File(dist_xlsPath);
if (file.exists()) {
// 如果复写,则删除后
if (isOverWrite) {
file.delete();
// 如果文件不存在,则创建一个新的Excel
// wb = new XSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
} else {
// 如果文件存在,则读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
}
} else {
// 如果文件不存在,则创建一个新的Excel
// wb = new XSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
}
// 将rowlist的内容添加到Excel中
writeExcel(wb, rowList, dist_xlsPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* //读取Excel 2007版,xlsx格式
*
* @Title: readExcel_xlsx
* @Date : 2014-9-11 上午11:43:11
* @return
* @throws IOException
*/
public List<Row> readExcel_xlsx() throws IOException {
return readExcel_xlsx(excelPath);
}
/**
* //读取Excel 2007版,xlsx格式
*
* @Title: readExcel_xlsx
* @Date : 2014-9-11 上午11:43:11
* @return
* @throws Exception
*/
public List<Row> readExcel_xlsx(String xlsPath) throws IOException {
// 判断文件是否存在
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
}
XSSFWorkbook wb = null;
List<Row> rowList = new ArrayList<Row>();
try {
FileInputStream fis = new FileInputStream(file);
// 去读Excel
wb = new XSSFWorkbook(fis);
// 读取Excel 2007版,xlsx格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/**
* 以流的形式读取excel文件 2007版xlsx
*
* @author wufei 2016年9月19日 上午10:35:40
* @Method: readExcel_xlsxAsStream
* @Description: TODO
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel_xlsxAsStream(InputStream in) throws IOException {
XSSFWorkbook wb = null;
List<Row> rowList = new ArrayList<Row>();
try {
// 去读Excel
wb = new XSSFWorkbook(in);
// 读取Excel 2007版,xlsx格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/***
* 读取Excel(97-03版,xls格式)
*
* @throws IOException
*
* @Title: readExcel
* @Date : 2014-9-11 上午09:53:21
*/
public List<Row> readExcel_xls() throws IOException {
return readExcel_xls(excelPath);
}
/***
* 读取Excel(97-03版,xls格式)
*
* @throws Exception
*
* @Title: readExcel
* @Date : 2014-9-11 上午09:53:21
*/
public List<Row> readExcel_xls(String xlsPath) throws IOException {
// 判断文件是否存在
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
}
HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
List<Row> rowList = new ArrayList<Row>();
try {
// 读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
// 读取Excel 97-03版,xls格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/**
* 以流的形式读取97-03版excel文件
*
* @author wufei 2016年9月19日 上午10:33:25
* @Method: readExcel_xlsAsStream
* @Description: TODO
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel_xlsAsStream(InputStream in) throws IOException {
HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
List<Row> rowList = new ArrayList<Row>();
try {
// 读取Excel
wb = new HSSFWorkbook(in);
// 读取Excel 97-03版,xls格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/***
* 读取单元格的值
*
* @Title: getCellValue
* @Date : 2014-9-11 上午10:52:07
* @param cell
* @return
*/
public String getCellValue(Cell cell) {
Object result = "";
if (cell != null) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
result = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_NUMERIC:
// 判断是否为日期
if (HSSFDateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
Date date = HSSFDateUtil.getJavaDate(cell
.getNumericCellValue());
result = df.format(date);
} else {
result = cell.getNumericCellValue();
}
break;
case Cell.CELL_TYPE_BOOLEAN:
result = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_FORMULA:
result = cell.getCellFormula();
break;
case Cell.CELL_TYPE_ERROR:
result = cell.getErrorCellValue();
break;
case Cell.CELL_TYPE_BLANK:
break;
default:
break;
}
}
return result.toString();
}
/**
* 通用读取Excel
*
* @Title: readExcel
* @Date : 2014-9-11 上午11:26:53
* @param wb
* @return
*/
private List<Row> readExcel(Workbook wb) {
List<Row> rowList = new ArrayList<Row>();
int sheetCount = 1;// 需要操作的sheet数量
Sheet sheet = null;
if (onlyReadOneSheet) { // 只操作一个sheet
// 获取设定操作的sheet(如果设定了名称,按名称查,否则按索引值查)
sheet = selectedSheetName.equals("") ? wb
.getSheetAt(selectedSheetIdx) : wb
.getSheet(selectedSheetName);
} else { // 操作多个sheet
sheetCount = wb.getNumberOfSheets();// 获取可以操作的总数量
}
// 获取sheet数目
for (int t = startSheetIdx; t < sheetCount + endSheetIdx; t++) {
// 获取设定操作的sheet
if (!onlyReadOneSheet) {
sheet = wb.getSheetAt(t);
}
// 获取最后行号
int lastRowNum = sheet.getLastRowNum();
if (lastRowNum > 0) { // 如果>0,表示有数据
out("\n开始读取名为【" + sheet.getSheetName() + "】的内容:");
}
Row row = null;
// 循环读取
for (int i = startReadPos; i <= lastRowNum + endReadPos; i++) {
row = sheet.getRow(i);
if (row != null) {
rowList.add(row);
out("第" + (i + 1) + "行:", false);
// 获取每一单元格的值
for (int j = 0; j < row.getLastCellNum(); j++) {
String value = getCellValue(row.getCell(j));
if (!value.equals("")) {
out(value + " | ", false);
}
}
out("");
}
}
}
return rowList;
}
/**
* 修改Excel,并另存为
*
* @Title: WriteExcel
* @Date : 2014-9-11 下午01:33:59
* @param wb
* @param rowList
* @param xlsPath
*/
private void writeExcel(Workbook wb, List<Row> rowList, String xlsPath) {
if (wb == null) {
out("操作文档不能为空!");
return;
}
Sheet sheet = wb.getSheetAt(0);// 修改第一个sheet中的值
// 如果每次重写,那么则从开始读取的位置写,否则果获取源文件最新的行。
int lastRowNum = isOverWrite ? startReadPos : sheet.getLastRowNum() + 1;
int t = 0;// 记录最新添加的行数
out("要添加的数据总条数为:" + rowList.size());
for (Row row : rowList) {
if (row == null)
continue;
// 判断是否已经存在该数据
int pos = findInExcel(sheet, row);
Row r = null;// 如果数据行已经存在,则获取后重写,否则自动创建新行。
if (pos >= 0) {
sheet.removeRow(sheet.getRow(pos));
r = sheet.createRow(pos);
} else {
r = sheet.createRow(lastRowNum + t++);
}
// 用于设定单元格样式
CellStyle newstyle = wb.createCellStyle();
// 循环为新行创建单元格
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
Cell cell = r.createCell(i);// 获取数据类型
cell.setCellValue(getCellValue(row.getCell(i)));// 复制单元格的值到新的单元格
// cell.setCellStyle(row.getCell(i).getCellStyle());//出错
if (row.getCell(i) == null)
continue;
copyCellStyle(row.getCell(i).getCellStyle(), newstyle); // 获取原来的单元格样式
cell.setCellStyle(newstyle);// 设置样式
// sheet.autoSizeColumn(i);//自动跳转列宽度
}
}
out("其中检测到重复条数为:" + (rowList.size() - t) + " ,追加条数为:" + t);
// 统一设定合并单元格
setMergedRegion(sheet);
try {
// 重新将数据写入Excel中
FileOutputStream outputStream = new FileOutputStream(xlsPath);
wb.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
out("写入Excel时发生错误! ");
e.printStackTrace();
}
}
/**
* 查找某行数据是否在Excel表中存在,返回行数。
*
* @Title: findInExcel
* @Date : 2014-9-11 下午02:23:12
* @param sheet
* @param row
* @return
*/
private int findInExcel(Sheet sheet, Row row) {
int pos = -1;
try {
// 如果覆写目标文件,或者不需要比较,则直接返回
if (isOverWrite || !isNeedCompare) {
return pos;
}
for (int i = startReadPos; i <= sheet.getLastRowNum() + endReadPos; i++) {
Row r = sheet.getRow(i);
if (r != null && row != null) {
String v1 = getCellValue(r.getCell(comparePos));
String v2 = getCellValue(row.getCell(comparePos));
if (v1.equals(v2)) {
pos = i;
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return pos;
}
/**
* 复制一个单元格样式到目的单元格样式
*
* @param fromStyle
* @param toStyle
*/
public static void copyCellStyle(CellStyle fromStyle, CellStyle toStyle) {
toStyle.setAlignment(fromStyle.getAlignment());
// 边框和边框颜色
toStyle.setBorderBottom(fromStyle.getBorderBottom());
toStyle.setBorderLeft(fromStyle.getBorderLeft());
toStyle.setBorderRight(fromStyle.getBorderRight());
toStyle.setBorderTop(fromStyle.getBorderTop());
toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
// 背景和前景
toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());
// 数据格式
toStyle.setDataFormat(fromStyle.getDataFormat());
toStyle.setFillPattern(fromStyle.getFillPattern());
// toStyle.setFont(fromStyle.getFont(null));
toStyle.setHidden(fromStyle.getHidden());
toStyle.setIndention(fromStyle.getIndention());// 首行缩进
toStyle.setLocked(fromStyle.getLocked());
toStyle.setRotation(fromStyle.getRotation());// 旋转
toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
toStyle.setWrapText(fromStyle.getWrapText());
}
/**
* 获取合并单元格的值
*
* @param sheet
* @return
*/
public void setMergedRegion(Sheet sheet) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
// 获取合并单元格位置
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstRow = ca.getFirstRow();
if (startReadPos - 1 > firstRow) {// 如果第一个合并单元格格式在正式数据的上面,则跳过。
continue;
}
int lastRow = ca.getLastRow();
int mergeRows = lastRow - firstRow;// 合并的行数
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
// 根据合并的单元格位置和大小,调整所有的数据行格式,
for (int j = lastRow + 1; j <= sheet.getLastRowNum(); j++) {
// 设定合并单元格
sheet.addMergedRegion(new CellRangeAddress(j, j + mergeRows,
firstColumn, lastColumn));
j = j + mergeRows;// 跳过已合并的行
}
}
}
/**
* 打印消息,
*
* @param msg
* 消息内容 换行
*/
private void out(String msg) {
if (printMsg) {
out(msg, true);
}
}
/**
* 打印消息,
*
* @param msg
* 消息内容
* @param tr
* 换行
*/
private void out(String msg, boolean tr) {
if (printMsg) {
System.out.print(msg + (tr ? "\n" : ""));
}
}
public String getExcelPath() {
return this.excelPath;
}
public void setExcelPath(String excelPath) {
this.excelPath = excelPath;
}
public boolean isNeedCompare() {
return isNeedCompare;
}
public void setNeedCompare(boolean isNeedCompare) {
this.isNeedCompare = isNeedCompare;
}
public int getComparePos() {
return comparePos;
}
public void setComparePos(int comparePos) {
this.comparePos = comparePos;
}
public int getStartReadPos() {
return startReadPos;
}
public void setStartReadPos(int startReadPos) {
this.startReadPos = startReadPos;
}
public int getEndReadPos() {
return endReadPos;
}
public void setEndReadPos(int endReadPos) {
this.endReadPos = endReadPos;
}
public boolean isOverWrite() {
return isOverWrite;
}
public void setOverWrite(boolean isOverWrite) {
this.isOverWrite = isOverWrite;
}
public boolean isOnlyReadOneSheet() {
return onlyReadOneSheet;
}
public void setOnlyReadOneSheet(boolean onlyReadOneSheet) {
this.onlyReadOneSheet = onlyReadOneSheet;
}
public int getSelectedSheetIdx() {
return selectedSheetIdx;
}
public void setSelectedSheetIdx(int selectedSheetIdx) {
this.selectedSheetIdx = selectedSheetIdx;
}
public String getSelectedSheetName() {
return selectedSheetName;
}
public void setSelectedSheetName(String selectedSheetName) {
this.selectedSheetName = selectedSheetName;
}
public int getStartSheetIdx() {
return startSheetIdx;
}
public void setStartSheetIdx(int startSheetIdx) {
this.startSheetIdx = startSheetIdx;
}
public int getEndSheetIdx() {
return endSheetIdx;
}
public void setEndSheetIdx(int endSheetIdx) {
this.endSheetIdx = endSheetIdx;
}
public boolean isPrintMsg() {
return printMsg;
}
public void setPrintMsg(boolean printMsg) {
this.printMsg = printMsg;
}
}
至此,读取完毕。
之前做金融报表,是把Excel内嵌到页面中的,技术上采用ZK结合POI读取和插入Excel数据,后台方法比较死,比较程式化。
目前新需求是把Excel表格上传到服务器,读取到里边的数据做处理。
一、首先上传Excel
1、页面添加文件域
Java代码
<form id="uploadExcel" action="/auth/user/toHandleBatchRobotExcel.do"
enctype="multipart/form- data" method="POST" >
<input type="file" id="excel" name="excelFile"/>
<input type="button" id="uploadExcel" />
</form>
2、使用ajax提交表单(需导入jquery.form.js)
Java代码
var excel=$("#excel").val();
var location=$('#excel').val();
var point = location.lastIndexOf(".");
var type = location.substr(point);
//type是Excel表格的格式.xls\.xlsx
$("#uploadExcel").ajaxSubmit({
data:{ext:type},
success:function(data){
var dataJson = eval("("+data+")");
console.log(data);
if(dataJson.code==100){
alert(dataJson.message);
}else{
alert("成功上传"+dataJson.attribute.robotNum+"条记录");
}
}
});
二、后台读取
我尝试了两种方式来读取,jxl和poi。
1、jxl读取
jxl操作也是比较方便的,上代码吧。
Jar包:jxl-2.6.jar
读取Excel:
Java代码
@RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
public void handleExcel(HttpServletResponse response,
MultipartHttpServletRequest request, String ext) {
logger.info("处理Excel表格");
logger.info("开始解析...");
logger.info(ext);
MultipartFile fileFile = request.getFile("excelFile");
InputStream in = fileFile.getInputStream();
//获取Excel文件对象
Workbook wb = Workbook.getWorkbook(in);
//获取文件的指定工作表默认的第一个
Sheet sheet = wb.getSheet(0);
// 单元格
Cell cell;
//获取行数
Int rows = sheet.getRows();
Map<Integer, String> map = new HashMap<Integer, String>();
List<UserInfoVo> list = new LinkedList<UserInfoVo>();
if (rows.size() > 0 && rows!= null) {
for (int i = 1; i < rows.size(); i++) {
for (int j = 0; j < sheet.getColumns(); j++) {
cell =sheet.getCell(j,i);
map.put(j,cell.getContents());
}
//Excel数据对应的实体类,根据情况自己设定
UserInfoVo userInfoVo = new UserInfoVo();
userInfoVo.setNickName(map.get(1));
userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
.getTime());
userInfoVo.setState(1);
list.add(userInfoVo);
}
}
}
这样读取到的list中就包括了excel表中的各行数据。
但是在使用过程中发现,有些用户上传2007版的Excel表格,这样的话就会出现读取错误的情况
jxl.read.biff.BiffException: Unable to recognize OLE stream,这是因为jxl久未更新,没法读取新版本的 Excel,就是.xlsx格式的文件。
于是,换种思路,使用兼容性更好的poi进行读取。
2、poi读取
poi是读取Excel最佳工具,功能丰富,对读取不同版本的excel都做了对应处理。
jar包:
poi-3.11.jar 针对03版excel,即后缀为.xls的文件。
poi-ooxml-3.11.jar 针对07版excel,即后缀为.xlsx的文件。
读取Excel:
Java代码
@RequestMapping(value = UrlMappings.HAN
1f494
DLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
public void handleExcel(HttpServletResponse response,
MultipartHttpServletRequest request, String ext) {
logger.info("处理Excel表格");
logger.info("开始解析...");
//excel格式 .xls\.xlsx
logger.info(ext);
// 得到上传的文件
MultipartFile fileFile = request.getFile("excelFile");
try {
// 转换成输入流
InputStream in = fileFile.getInputStream();
// 单元格
Cell cell;
List<Row> rsRows = new ExcelUtils().readExcel(ext, in);
// 实例化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Map<Integer, String> map = new HashMap<Integer, String>();
List<UserInfoVo> list = new LinkedList<UserInfoVo>();
if (rsRows.size() > 0 && rsRows != null) {
for (int i = 1; i < rsRows.size(); i++) {
for (int j = 0; j < rsRows.get(i).getLastCellNum(); j++) {
cell = rsRows.get(i).getCell(j);
map.put(j, new ExcelUtils().getCellValue(cell));
}
UserInfoVo userInfoVo = new UserInfoVo();
userInfoVo.setNickName(map.get(1));
userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
.getTime());
userInfoVo.setState(1);
list.add(userInfoVo);
}
}
}
List中即是excel表中的数据。这其中要用到一个工具类ExcelUtils。
Java代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
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.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelUtils {
// %%%%%%%%-------常量部分 开始----------%%%%%%%%%
/**
* 默认的开始读取的行位置为第一行(索引值为0)
*/
private final static int READ_START_POS = 0;
/**
* 默认结束读取的行位置为最后一行(索引值=0,用负数来表示倒数第n行)
*/
private final static int READ_END_POS = 0;
/**
* 默认Excel内容的开始比较列位置为第一列(索引值为0)
*/
private final static int COMPARE_POS = 0;
/**
* 默认多文件合并的时需要做内容比较(相同的内容不重复出现)
*/
private final static boolean NEED_COMPARE = true;
/**
* 默认多文件合并的新文件遇到名称重复时,进行覆盖
*/
private final static boolean NEED_OVERWRITE = true;
/**
* 默认只操作一个sheet
*/
private final static boolean ONLY_ONE_SHEET = true;
/**
* 默认读取第一个sheet中(只有当ONLY_ONE_SHEET = true时有效)
*/
private final static int SELECTED_SHEET = 0;
/**
* 默认从第一个sheet开始读取(索引值为0)
*/
private final static int READ_START_SHEET = 0;
/**
* 默认在最后一个sheet结束读取(索引值=0,用负数来表示倒数第n行)
*/
private final static int READ_END_SHEET = 0;
/**
* 默认打印各种信息
*/
private final static boolean PRINT_MSG = true;
// %%%%%%%%-------常量部分 结束----------%%%%%%%%%
// %%%%%%%%-------字段部分 开始----------%%%%%%%%%
/**
* Excel文件路径
*/
private String excelPath = "data.xlsx";
/**
* 设定开始读取的位置,默认为0
*/
private int startReadPos = READ_START_POS;
/**
* 设定结束读取的位置,默认为0,用负数来表示倒数第n行
*/
private int endReadPos = READ_END_POS;
/**
* 设定开始比较的列位置,默认为0
*/
private int comparePos = COMPARE_POS;
/**
* 设定汇总的文件是否需要替换,默认为true
*/
private boolean isOverWrite = NEED_OVERWRITE;
/**
* 设定是否需要比较,默认为true(仅当不覆写目标内容是有效,即isOverWrite=false时有效)
*/
private boolean isNeedCompare = NEED_COMPARE;
/**
* 设定是否只操作第一个sheet
*/
private boolean onlyReadOneSheet = ONLY_ONE_SHEET;
/**
* 设定操作的sheet在索引值
*/
private int selectedSheetIdx = SELECTED_SHEET;
/**
* 设定操作的sheet的名称
*/
private String selectedSheetName = "";
/**
* 设定开始读取的sheet,默认为0
*/
private int startSheetIdx = READ_START_SHEET;
/**
* 设定结束读取的sheet,默认为0,用负数来表示倒数第n行
*/
private int endSheetIdx = READ_END_SHEET;
/**
* 设定是否打印消息
*/
private boolean printMsg = PRINT_MSG;
// %%%%%%%%-------字段部分 结束----------%%%%%%%%%
public ExcelUtils() {
}
public ExcelUtils(String excelPath) {
this.excelPath = excelPath;
}
/**
* 还原设定(其实是重新new一个新的对象并返回)
*
* @return
*/
public ExcelUtils RestoreSettings() {
ExcelUtils instance = new ExcelUtils(this.excelPath);
return instance;
}
/**
* 自动根据文件扩展名,调用对应的读取方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @throws IOException
*/
public List<Row> readExcel() throws IOException {
return readExcel(this.excelPath);
}
/**
* 自动根据文件扩展名,调用对应的读取方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param xlsPath
* @throws IOException
*/
public List<Row> readExcel(String xlsPath) throws IOException {
// 扩展名为空时,
if (xlsPath.equals("")) {
throw new IOException("文件路径不能为空!");
} else {
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件不存在!");
}
}
// 获取扩展名
String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
try {
if ("xls".equals(ext)) { // 使用xls方式读取
return readExcel_xls(xlsPath);
} else if ("xlsx".equals(ext)) { // 使用xlsx方式读取
return readExcel_xlsx(xlsPath);
} else { // 依次尝试xls、xlsx方式读取
out("您要操作的文件没有扩展名,正在尝试以xls方式读取...");
try {
return readExcel_xls(xlsPath);
} catch (IOException e1) {
out("尝试以xls方式读取,结果失败!,正在尝试以xlsx方式读取...");
try {
return readExcel_xlsx(xlsPath);
} catch (IOException e2) {
out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
throw e;
}
}
/**
* 通过判断文件的扩展名,以不同的方式读取文件
*
* @author wufei 2016年9月19日 上午10:41:27
* @Method: readExcel
* @Description: TODO
* @param @param ext
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel(String ext, InputStream in) {
try {
if (".xls".equals(ext)) { // 使用xls方式读取
return readExcel_xlsAsStream(in);
} else if (".xlsx".equals(ext)) { // 使用xlsx方式读取
return readExcel_xlsxAsStream(in);
} else { // 依次尝试xls、xlsx方式读取
out("您要操作的文件没有扩展名,正在尝试以xlsx方式读取...");
try {
return readExcel_xlsxAsStream(in);
} catch (Exception e1) {
out("尝试以xlsx方式读取,结果失败!,正在尝试以xls方式读取...");
try {
return readExcel_xlsAsStream(in);
} catch (IOException e2) {
out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
out(e.getMessage());
return null;
}
}
/**
* 自动根据文件扩展名,调用对应的写入方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @throws IOException
*/
public void writeExcel(List<Row> rowList) throws IOException {
writeExcel(rowList, excelPath);
}
/**
* 自动根据文件扩展名,调用对应的写入方法
*
* @Title: writeExcel
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param xlsPath
* @throws IOException
*/
public void writeExcel(List<Row> rowList, String xlsPath)
throws IOException {
// 扩展名为空时,
if (xlsPath.equals("")) {
throw new IOException("文件路径不能为空!");
}
// 获取扩展名
String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
try {
if ("xls".equals(ext)) { // 使用xls方式写入
writeExcel_xls(rowList, xlsPath);
} else if ("xlsx".equals(ext)) { // 使用xlsx方式写入
writeExcel_xlsx(rowList, xlsPath);
} else { // 依次尝试xls、xlsx方式写入
out("您要操作的文件没有扩展名,正在尝试以xls方式写入...");
try {
writeExcel_xls(rowList, xlsPath);
} catch (IOException e1) {
out("尝试以xls方式写入,结果失败!,正在尝试以xlsx方式读取...");
try {
writeExcel_xlsx(rowList, xlsPath);
} catch (IOException e2) {
out("尝试以xls方式写入,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
throw e2;
}
}
}
} catch (IOException e) {
throw e;
}
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xls(List<Row> rowList, String dist_xlsPath)
throws IOException {
writeExcel_xls(rowList, excelPath, dist_xlsPath);
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param src_xlsPath
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xls(List<Row> rowList, String src_xlsPath,
String dist_xlsPath) throws IOException {
// 判断文件路径是否为空
if (dist_xlsPath == null || dist_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断文件路径是否为空
if (src_xlsPath == null || src_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断列表是否有数据,如果没有数据,则返回
if (rowList == null || rowList.size() == 0) {
out("文档为空");
return;
}
try {
HSSFWorkbook wb = null;
// 判断文件是否存在
File file = new File(dist_xlsPath);
if (file.exists()) {
// 如果复写,则删除后
if (isOverWrite) {
file.delete();
// 如果文件不存在,则创建一个新的Excel
// wb = new HSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
} else {
// 如果文件存在,则读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
}
} else {
// 如果文件不存在,则创建一个新的Excel
// wb = new HSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
}
// 将rowlist的内容写到Excel中
writeExcel(wb, rowList, dist_xlsPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 修改Excel(97-03版,xls格式)
*
* @Title: writeExcel_xls
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @param dist_xlsPath
* @throws IOException
*/
public void writeExcel_xlsx(List<Row> rowList, String dist_xlsPath)
throws IOException {
writeExcel_xls(rowList, excelPath, dist_xlsPath);
}
/**
* 修改Excel(2007版,xlsx格式)
*
* @Title: writeExcel_xlsx
* @Date : 2014-9-11 下午01:50:38
* @param rowList
* @throws IOException
*/
public void writeExcel_xlsx(List<Row> rowList, String src_xlsPath,
String dist_xlsPath) throws IOException {
// 判断文件路径是否为空
if (dist_xlsPath == null || dist_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断文件路径是否为空
if (src_xlsPath == null || src_xlsPath.equals("")) {
out("文件路径不能为空");
throw new IOException("文件路径不能为空");
}
// 判断列表是否有数据,如果没有数据,则返回
if (rowList == null || rowList.size() == 0) {
out("文档为空");
return;
}
try {
// 读取文档
HSSFWorkbook wb = null;
// 判断文件是否存在
File file = new File(dist_xlsPath);
if (file.exists()) {
// 如果复写,则删除后
if (isOverWrite) {
file.delete();
// 如果文件不存在,则创建一个新的Excel
// wb = new XSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
} else {
// 如果文件存在,则读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
}
} else {
// 如果文件不存在,则创建一个新的Excel
// wb = new XSSFWorkbook();
// wb.createSheet("Sheet1");
wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
}
// 将rowlist的内容添加到Excel中
writeExcel(wb, rowList, dist_xlsPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* //读取Excel 2007版,xlsx格式
*
* @Title: readExcel_xlsx
* @Date : 2014-9-11 上午11:43:11
* @return
* @throws IOException
*/
public List<Row> readExcel_xlsx() throws IOException {
return readExcel_xlsx(excelPath);
}
/**
* //读取Excel 2007版,xlsx格式
*
* @Title: readExcel_xlsx
* @Date : 2014-9-11 上午11:43:11
* @return
* @throws Exception
*/
public List<Row> readExcel_xlsx(String xlsPath) throws IOException {
// 判断文件是否存在
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
}
XSSFWorkbook wb = null;
List<Row> rowList = new ArrayList<Row>();
try {
FileInputStream fis = new FileInputStream(file);
// 去读Excel
wb = new XSSFWorkbook(fis);
// 读取Excel 2007版,xlsx格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/**
* 以流的形式读取excel文件 2007版xlsx
*
* @author wufei 2016年9月19日 上午10:35:40
* @Method: readExcel_xlsxAsStream
* @Description: TODO
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel_xlsxAsStream(InputStream in) throws IOException {
XSSFWorkbook wb = null;
List<Row> rowList = new ArrayList<Row>();
try {
// 去读Excel
wb = new XSSFWorkbook(in);
// 读取Excel 2007版,xlsx格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/***
* 读取Excel(97-03版,xls格式)
*
* @throws IOException
*
* @Title: readExcel
* @Date : 2014-9-11 上午09:53:21
*/
public List<Row> readExcel_xls() throws IOException {
return readExcel_xls(excelPath);
}
/***
* 读取Excel(97-03版,xls格式)
*
* @throws Exception
*
* @Title: readExcel
* @Date : 2014-9-11 上午09:53:21
*/
public List<Row> readExcel_xls(String xlsPath) throws IOException {
// 判断文件是否存在
File file = new File(xlsPath);
if (!file.exists()) {
throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
}
HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
List<Row> rowList = new ArrayList<Row>();
try {
// 读取Excel
wb = new HSSFWorkbook(new FileInputStream(file));
// 读取Excel 97-03版,xls格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/**
* 以流的形式读取97-03版excel文件
*
* @author wufei 2016年9月19日 上午10:33:25
* @Method: readExcel_xlsAsStream
* @Description: TODO
* @param @param in
* @param @return
* @param @throws IOException
* @return List<Row>
* @throws
*/
public List<Row> readExcel_xlsAsStream(InputStream in) throws IOException {
HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
List<Row> rowList = new ArrayList<Row>();
try {
// 读取Excel
wb = new HSSFWorkbook(in);
// 读取Excel 97-03版,xls格式
rowList = readExcel(wb);
} catch (IOException e) {
e.printStackTrace();
}
return rowList;
}
/***
* 读取单元格的值
*
* @Title: getCellValue
* @Date : 2014-9-11 上午10:52:07
* @param cell
* @return
*/
public String getCellValue(Cell cell) {
Object result = "";
if (cell != null) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
result = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_NUMERIC:
// 判断是否为日期
if (HSSFDateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
Date date = HSSFDateUtil.getJavaDate(cell
.getNumericCellValue());
result = df.format(date);
} else {
result = cell.getNumericCellValue();
}
break;
case Cell.CELL_TYPE_BOOLEAN:
result = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_FORMULA:
result = cell.getCellFormula();
break;
case Cell.CELL_TYPE_ERROR:
result = cell.getErrorCellValue();
break;
case Cell.CELL_TYPE_BLANK:
break;
default:
break;
}
}
return result.toString();
}
/**
* 通用读取Excel
*
* @Title: readExcel
* @Date : 2014-9-11 上午11:26:53
* @param wb
* @return
*/
private List<Row> readExcel(Workbook wb) {
List<Row> rowList = new ArrayList<Row>();
int sheetCount = 1;// 需要操作的sheet数量
Sheet sheet = null;
if (onlyReadOneSheet) { // 只操作一个sheet
// 获取设定操作的sheet(如果设定了名称,按名称查,否则按索引值查)
sheet = selectedSheetName.equals("") ? wb
.getSheetAt(selectedSheetIdx) : wb
.getSheet(selectedSheetName);
} else { // 操作多个sheet
sheetCount = wb.getNumberOfSheets();// 获取可以操作的总数量
}
// 获取sheet数目
for (int t = startSheetIdx; t < sheetCount + endSheetIdx; t++) {
// 获取设定操作的sheet
if (!onlyReadOneSheet) {
sheet = wb.getSheetAt(t);
}
// 获取最后行号
int lastRowNum = sheet.getLastRowNum();
if (lastRowNum > 0) { // 如果>0,表示有数据
out("\n开始读取名为【" + sheet.getSheetName() + "】的内容:");
}
Row row = null;
// 循环读取
for (int i = startReadPos; i <= lastRowNum + endReadPos; i++) {
row = sheet.getRow(i);
if (row != null) {
rowList.add(row);
out("第" + (i + 1) + "行:", false);
// 获取每一单元格的值
for (int j = 0; j < row.getLastCellNum(); j++) {
String value = getCellValue(row.getCell(j));
if (!value.equals("")) {
out(value + " | ", false);
}
}
out("");
}
}
}
return rowList;
}
/**
* 修改Excel,并另存为
*
* @Title: WriteExcel
* @Date : 2014-9-11 下午01:33:59
* @param wb
* @param rowList
* @param xlsPath
*/
private void writeExcel(Workbook wb, List<Row> rowList, String xlsPath) {
if (wb == null) {
out("操作文档不能为空!");
return;
}
Sheet sheet = wb.getSheetAt(0);// 修改第一个sheet中的值
// 如果每次重写,那么则从开始读取的位置写,否则果获取源文件最新的行。
int lastRowNum = isOverWrite ? startReadPos : sheet.getLastRowNum() + 1;
int t = 0;// 记录最新添加的行数
out("要添加的数据总条数为:" + rowList.size());
for (Row row : rowList) {
if (row == null)
continue;
// 判断是否已经存在该数据
int pos = findInExcel(sheet, row);
Row r = null;// 如果数据行已经存在,则获取后重写,否则自动创建新行。
if (pos >= 0) {
sheet.removeRow(sheet.getRow(pos));
r = sheet.createRow(pos);
} else {
r = sheet.createRow(lastRowNum + t++);
}
// 用于设定单元格样式
CellStyle newstyle = wb.createCellStyle();
// 循环为新行创建单元格
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
Cell cell = r.createCell(i);// 获取数据类型
cell.setCellValue(getCellValue(row.getCell(i)));// 复制单元格的值到新的单元格
// cell.setCellStyle(row.getCell(i).getCellStyle());//出错
if (row.getCell(i) == null)
continue;
copyCellStyle(row.getCell(i).getCellStyle(), newstyle); // 获取原来的单元格样式
cell.setCellStyle(newstyle);// 设置样式
// sheet.autoSizeColumn(i);//自动跳转列宽度
}
}
out("其中检测到重复条数为:" + (rowList.size() - t) + " ,追加条数为:" + t);
// 统一设定合并单元格
setMergedRegion(sheet);
try {
// 重新将数据写入Excel中
FileOutputStream outputStream = new FileOutputStream(xlsPath);
wb.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
out("写入Excel时发生错误! ");
e.printStackTrace();
}
}
/**
* 查找某行数据是否在Excel表中存在,返回行数。
*
* @Title: findInExcel
* @Date : 2014-9-11 下午02:23:12
* @param sheet
* @param row
* @return
*/
private int findInExcel(Sheet sheet, Row row) {
int pos = -1;
try {
// 如果覆写目标文件,或者不需要比较,则直接返回
if (isOverWrite || !isNeedCompare) {
return pos;
}
for (int i = startReadPos; i <= sheet.getLastRowNum() + endReadPos; i++) {
Row r = sheet.getRow(i);
if (r != null && row != null) {
String v1 = getCellValue(r.getCell(comparePos));
String v2 = getCellValue(row.getCell(comparePos));
if (v1.equals(v2)) {
pos = i;
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return pos;
}
/**
* 复制一个单元格样式到目的单元格样式
*
* @param fromStyle
* @param toStyle
*/
public static void copyCellStyle(CellStyle fromStyle, CellStyle toStyle) {
toStyle.setAlignment(fromStyle.getAlignment());
// 边框和边框颜色
toStyle.setBorderBottom(fromStyle.getBorderBottom());
toStyle.setBorderLeft(fromStyle.getBorderLeft());
toStyle.setBorderRight(fromStyle.getBorderRight());
toStyle.setBorderTop(fromStyle.getBorderTop());
toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
// 背景和前景
toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());
// 数据格式
toStyle.setDataFormat(fromStyle.getDataFormat());
toStyle.setFillPattern(fromStyle.getFillPattern());
// toStyle.setFont(fromStyle.getFont(null));
toStyle.setHidden(fromStyle.getHidden());
toStyle.setIndention(fromStyle.getIndention());// 首行缩进
toStyle.setLocked(fromStyle.getLocked());
toStyle.setRotation(fromStyle.getRotation());// 旋转
toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
toStyle.setWrapText(fromStyle.getWrapText());
}
/**
* 获取合并单元格的值
*
* @param sheet
* @return
*/
public void setMergedRegion(Sheet sheet) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
// 获取合并单元格位置
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstRow = ca.getFirstRow();
if (startReadPos - 1 > firstRow) {// 如果第一个合并单元格格式在正式数据的上面,则跳过。
continue;
}
int lastRow = ca.getLastRow();
int mergeRows = lastRow - firstRow;// 合并的行数
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
// 根据合并的单元格位置和大小,调整所有的数据行格式,
for (int j = lastRow + 1; j <= sheet.getLastRowNum(); j++) {
// 设定合并单元格
sheet.addMergedRegion(new CellRangeAddress(j, j + mergeRows,
firstColumn, lastColumn));
j = j + mergeRows;// 跳过已合并的行
}
}
}
/**
* 打印消息,
*
* @param msg
* 消息内容 换行
*/
private void out(String msg) {
if (printMsg) {
out(msg, true);
}
}
/**
* 打印消息,
*
* @param msg
* 消息内容
* @param tr
* 换行
*/
private void out(String msg, boolean tr) {
if (printMsg) {
System.out.print(msg + (tr ? "\n" : ""));
}
}
public String getExcelPath() {
return this.excelPath;
}
public void setExcelPath(String excelPath) {
this.excelPath = excelPath;
}
public boolean isNeedCompare() {
return isNeedCompare;
}
public void setNeedCompare(boolean isNeedCompare) {
this.isNeedCompare = isNeedCompare;
}
public int getComparePos() {
return comparePos;
}
public void setComparePos(int comparePos) {
this.comparePos = comparePos;
}
public int getStartReadPos() {
return startReadPos;
}
public void setStartReadPos(int startReadPos) {
this.startReadPos = startReadPos;
}
public int getEndReadPos() {
return endReadPos;
}
public void setEndReadPos(int endReadPos) {
this.endReadPos = endReadPos;
}
public boolean isOverWrite() {
return isOverWrite;
}
public void setOverWrite(boolean isOverWrite) {
this.isOverWrite = isOverWrite;
}
public boolean isOnlyReadOneSheet() {
return onlyReadOneSheet;
}
public void setOnlyReadOneSheet(boolean onlyReadOneSheet) {
this.onlyReadOneSheet = onlyReadOneSheet;
}
public int getSelectedSheetIdx() {
return selectedSheetIdx;
}
public void setSelectedSheetIdx(int selectedSheetIdx) {
this.selectedSheetIdx = selectedSheetIdx;
}
public String getSelectedSheetName() {
return selectedSheetName;
}
public void setSelectedSheetName(String selectedSheetName) {
this.selectedSheetName = selectedSheetName;
}
public int getStartSheetIdx() {
return startSheetIdx;
}
public void setStartSheetIdx(int startSheetIdx) {
this.startSheetIdx = startSheetIdx;
}
public int getEndSheetIdx() {
return endSheetIdx;
}
public void setEndSheetIdx(int endSheetIdx) {
this.endSheetIdx = endSheetIdx;
}
public boolean isPrintMsg() {
return printMsg;
}
public void setPrintMsg(boolean printMsg) {
this.printMsg = printMsg;
}
}
至此,读取完毕。
相关文章推荐
- 将后台数据读取到前台的EXCEL文件中去,用javascript实现,asp.net,javacript(发一个原创)
- 使用JAVA读取EXCEL文件里面的数据
- java读取word-excel-ppt文件
- java 读取excel 文件 Unable to recognize OLE stream 错误
- JAVA读取WORD,EXCEL,POWERPOINT,PDF文件的方法
- JAVA读取WORD,EXCEL,POWERPOINT,PDF文件的方法
- 从JAVA直接读取EXCEL、WORD并生成PDF文件
- java读取word-excel-ppt文件代码
- 在Java中读取并保存EXCEL文件中图片
- JAVA读取WORD,EXCEL,POWERPOINT,PDF文件的方法
- 使用Java读取Excel文件内容
- 用java读取EXCEL文件
- java读取excel 文件
- JAVA读取WORD,EXCEL,PDF,TXT,RTF,HTML文件文本内容的方法示例
- 使用JAVA读取EXCEL文件里面的数据
- 用JAVA在读取EXCEL文件时如何判断列隐藏?
- JAVA读取WORD,EXCEL,POWERPOINT,PDF文件的方法
- 使用Java读取Excel文件内容
- java读取本地excel文件代码
- Java读取Excel文件