springMVC下的后台controller层获取页面导入的excel数据并解析
文件的数据解析,首先都必须知道数据在文件中的结构。而excel由于结构清晰,用单元格对数据进行了分割,每个单元格就是唯一的一个数据。解析相对容易。实际应用也比较广泛。
这里我先给个excel的数据结构demo,然后解析这个模板内的数据。
看上图是为了让大家明白文件处在本地项目的位置,和该文件模板内的数据结构。该信息处于sheet1,模板中前两行(row)是标题和列属性。从第三行(row)开始是数据。
其中基金名称和基金代码为文本,日期为日期类型,日涨跌为double类型。一定注意文本类型,在java代码获取值才不会出问题。特别是非文本类型的最容易出问题。我会提供一个工具类来专门获取单元格中的数据。
好,下面开始前后台代码:
1.页面用submit提交表单
这里是个注意点。必须强调用form的submit来提交才行,如果用ajax的post提交方式正常的输入框参数会提交到后台,但是文件提交到后台的仅仅是文件名,只有用submit提交才能把文件内容也提交过去。
<form id="batchAddInfo" method="post" enctype="multipart/form-data">
<div style="width:95%;height:250px;">
<fieldset>
<legend style="margin-bottom:10px;"><font color="red">批量新增</font></legend>
<table>
<tr><td><span>文件导入</span></td></tr>
<tr><td><input id="importFile" name="importFile" type="file" style="width:200px;"/></td></tr>
<tr><td><a href="javascript:void(0)" class="easyui-linkbutton" style="width:100px;" onclick="fileUpload()" iconCls="icon-reload">导入</a></td></tr>
<tr><td><a href="javascript:void(0)" class="easyui-linkbutton" style="width:100px;" onclick="downloadFile()" iconCls="icon-print">模板下载</a></td></tr>
</table>
</fieldset>
</div>
</form>
对应表单提交的js代码:
//文件提交
function fileUpload(){
var importFile=$("#importFile").val();
var reg=".xlsx$";
var patrn=new RegExp(reg);
if(patrn.exec(importFile)){
//不做任何事
}else{
$.messager.alert("提示","请导入.xls形式的Excel!");
return false;
}
$("#batchAddInfo").form('submit',{
url:basepath+"jijin/fileUpload",
onSubmit:function(){},
success:function(data){
data=eval('('+data+')');
var flag=data.flag;
if(flag){
$("#batchDivDialog").window("close");
$.messager.alert('提示',"批量新增成功!");
searchInfo();
}else{
$("#batchDivDialog").window("close");
$.messager.alert('提示',"批量新增失败!");
searchInfo();
}
}
});
}
2.前台form设置
enctype="multipart/form-data"
提交表单后台处理
//批量新增,文件解析
@RequestMapping("/fileUpload")
public void fileUpload(HttpServletRequest request,HttpServletResponse response) throws IOException{
PrintWriter out=response.getWriter();
Workbook wb = FileUtils.getWorkbookFromRequest(request,response);
Map<String, Object> map = jiJinService.batchExportJiJin(wb);
JSONObject json = new JSONObject(map);
String jsonString = json.toJSONString();
out.print(jsonString);
out.flush();
out.close();
}
**************************解析工具类***************************
public static Workbook getWorkbookFromRequest(HttpServletRequest request,HttpServletResponse response) throws IOException{
InputStream is=null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/json;charset=UTF-8");
PrintWriter out=response.getWriter();
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
if(multipartResolver.isMultipart(request)){
MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;
Iterator<String> iterator = multiRequest.getFileNames();
while (iterator.hasNext()) {
MultipartFile multipartFile = multiRequest.getFile(iterator.next());
if(multipartFile !=null){
is=new ByteArrayInputStream(multipartFile.getBytes());
}
}
}
Workbook wb=new XSSFWorkbook(is);
return wb;
}
这样就在controller层拿到workbook,然后就是对表数据进行解析转成实体类进行后续处理。下面的代码是从workbook到转成实体类的部分节选。
@Override
public Map<String, Object> batchExportJiJin(Workbook wb) {
Sheet sheet = wb.getSheetAt(0);
boolean fl = false;
int count = 0;
// 获取总行数
int rows = sheet.getPhysicalNumberOfRows();
if (rows > 2) {
for (int start = 2; start < rows; start++) {
// 从第三行开始逐行获取
Row row = sheet.getRow(start);
if (row == null) {
continue;
}
JiJinBo jinBo = new JiJinBo();
for (int i = 0; i < 4; i++) {
Cell cell = row.getCell(i);
String cellValue = FileUtils.getCellValue(cell);
if (i == 0) {
jinBo.setJiJinName(cellValue);
}
if (i == 1) {
jinBo.setJiJinCode(cellValue);
}
if (i == 2) {
jinBo.setJiJinTime(StringToDate(cellValue));
}
if (i == 3) {
if(cellValue!=null && cellValue.trim()!=""){
jinBo.setDailyIncreases(Double.parseDouble(cellValue));
}
}
}
其中获取单元格数据的工具类可以拿到对应数据类型数据并返回响应类型的单元格数据。
/**
* 根据单元格的值属性来获取excel单元格的值。 日期默认返回格式自己根据需求定,这里返回yyyy-MM-dd类型和HH:mm这两种。
*
* @param cell
* @return
*/
public static String getCellValue(Cell cell) {
String result = "";
if (cell != null) {
switch (cell.getCellType()) {
// 数字类型 +日期类型
case HSSFCell.CELL_TYPE_NUMERIC:
if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
SimpleDateFormat sdf = null;
if (cell.getCellStyle().getDataFormat() == HSSFDataFormat
.getBuiltinFormat("h:mm")) {
sdf = new SimpleDateFormat("HH:mm");
} else {// 日期
sdf = new SimpleDateFormat("yyyy-MM-dd");
}
Date date = cell.getDateCellValue();
result = sdf.format(date);
} else if (cell.getCellStyle().getDataFormat() == 58) {
// 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
double value = cell.getNumericCellValue();
Date date = org.apache.poi.ss.usermodel.DateUtil
.getJavaDate(value);
result = sdf.format(date);
} else {
DecimalFormat df = new DecimalFormat();
df.setGroupingUsed(false);
result = String.valueOf(df.format(cell
.getNumericCellValue()));
}
break;
// String类型
case HSSFCell.CELL_TYPE_STRING:
result = String.valueOf(cell.getStringCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
result = "";
default:
result = "";
break;
}
}
return result;
}
这样就是一套从提交excel数据到解析成实体类的流程。其中表单提交的方式,和表单设置文件方式提交,和后台获取到workbook及把每一行数据转成一个实体类是全流程的注意点。
上一篇: 数据结构04:栈与队列
下一篇: python猫眼top数据解析画图