您的位置:首页 > 其它

文件上传与解析Excel:fileupload+poi

2018-01-16 14:00 309 查看
一:介绍

前端:文件上传原理便是数据的提交,比如Form表单提交、Ajax提交、Ajax提交Form表单等,有多种组合方式,根据需求

不同,使用不同的提交方式,但是原理相同。

后端:接收前端发送的数据(File),解析文件(本文为Excel),解析Excel有多种方式,如poi,还有网上的js-xlsx-master相关js,后者为一个开源项目实例,本文没有使用。

基本原理:读取Excel表,根据版本不同创建不同的Workbook;遍历所有的Sheet;遍历所有row;遍历所有cell;

row为List<Object>,最终re为List<List<Object>>,当然根据需要不同,也可以返回不同类型,比如一个Sheet组成一个List<List<Object>>进行返回,根据需求不同返回不同。

以下测试开发使用Spring mvc框架,使用的包主要有commons-fileupload-1.3.3.jar和org.apache.poi包,网上有说必须要有commons-io包,因为fileupload依赖于他(因为开发为一个模块,这些包原来都有了,并没有测试)。

二、后台函数

Controller函数:该方法接收传递数据(File),调用工具类和服务层方法进行处理,分别为获取List和对数据进行处理,

本处为数据入库。如果读取为部分数据,可以:1.数据库设置默认值2.new Object时构造赋值3.插入时sql中赋值。

/**
* 数据上传导入
* @param file
* @param model
* @param request
* @param res
*/
@RequestMapping("/upload.json")
public ModelMap uploadExcel(ModelMap model,HttpServletRequest request,@RequestParam("excelFile")MultipartFile file){
System.out.println("upload");
int num=0;
try {
List<S>list=FileUtil.doUploadFile(file, request);
num=sListService.doUploadFile(list);
} catch (Exception e) {
e.printStackTrace();
System.out.println("导入失败");
return new ModelMap("info", "导入失败");
}
//		model.addAttribute("info", ""+num+"条记录导入成功");
System.out.println(num+"条记录导入成功");
return new ModelMap("info", num+"条记录导入成功");
}

FileUtil工具类:文件保存部分因为FileUtils报错而且不用就注掉了
该类调用工具类对Excel进行处理,获得处理结果List<List<Object>>,将处理结果进行处理,变为List<Clsss>

public static List<S> doUploadFile(MultipartFile file, HttpServletRequest request) throws Exception {

//        if (!file.isEmpty()) {
//            try {
//                // 这里将上传得到的文件保存指定目录下
//                FileUtils.copyInputStreamToFile(file.getInputStream(),
//                        new File("d:\\upload\\file\\", System.currentTimeMillis() + file.getOriginalFilename()));
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
List<S> list=new ArrayList<S>();
InputStream in = null;
List<List<Object>> listob = null;
in = file.getInputStream();
listob = new ImportExcelUtil().getBankListByExcel(in, file.getOriginalFilename());
// 该处可调用service相应方法进行数据保存到数据库中,现只对数据输出
for (int i = 0; i < listob.size(); i++) {
List<Object> lo = listob.get(i);
//            System.out.println("-----"+i+"--------");
//            System.out.println("size="+lo.size());
//            for(int j=0;j<lo.size();j++){
//            	System.out.println("lo("+j+")="+lo.get(j));
//            }
S s = new S();
s.setId(Integer.parseInt((String) lo.get(0)));
s.setYyy(String.valueOf(lo.get(1)));

if("是".equals(lo.get(14))){
s.setXxx("1");
}else{
s.setXxx("0");
}
s.setXxx(String.valueOf(lo.get(15)));

if(lo.size()==17){
if("".equals(String.valueOf(lo.get(16)))){
s.setLzsj(null);
}else{
Date d=new SimpleDateFormat("yyyy-mm-dd").parse(String.valueOf(lo.get(16)));
s.setXxx(new java.sql.Date(d.getTime()));
}
}
System.out.println("s="+s);
list.add(s);

}
return list;
}

ImportExcelUtil工具类:

import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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;

public class ImportExcelUtil {
private final static String excel2003L = ".xls"; // 2003- 版本的excel
private final static String excel2007U = ".xlsx"; // 2007+ 版本的excel

/**
* 描述:获取IO流中的数据,组装成List<List<Object>>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public List<List<Object>> getBankListByExcel(InputStream in, String fileName) throws Exception {

}

/**
* 描述:根据文件后缀,自适应上传文件的版本
*
* @param inStr,fileName
* @return
* @throws Exception
*/
public Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {

}

/**
* 描述:对表格中数值进行格式化
*
* @param cell
* @return
*/
public Object getCellValue(Cell cell) {

}

}

描述:获取IO流中的数据,组装成List<List<Object>>对象 

getNumberOfSheets():sheet数目:1->n

getFirstRowNum、getLastRowNum:row位置:0-n

getFirstCellNum、getLastCellNum:Cell位置:0-n+1

/**
* 描述:获取IO流中的数据,组装成List<List<Object>>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public List<List<Object>> getBankListByExcel(InputStream in, String fileName) throws Exception {
List<List<Object>> list = null;

// 创建Excel工作薄
Workbook work = this.getWorkbook(in, fileName);
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null;
Row row = null;
Cell cell = null;

list = new ArrayL
4000
ist<List<Object>>();
// 遍历Excel中所有的sheet
for (int i = 0; i < work.getNumberOfSheets(); i++) {
sheet = work.getSheetAt(i);
if (sheet == null) {
continue;
}
// 遍历当前sheet中的所有行
for (int j = sheet.getFirstRowNum(); j < sheet.getLastRowNum() + 1; j++) {

row = sheet.getRow(j);
//getFirstRowNum/getFirstCellNum-->从0开始取
//去除第一行row.getFirstCellNum() == j == 0
if (row == null || row.getFirstCellNum() == j) {
continue;
}

// 遍历所有的列
List<Object> li = new ArrayList<Object>();
for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
cell = row.getCell(y);

//					System.out.println("cell="+cell);
//					System.out.println("getCellValue="+this.getCellValue(cell));

li.add(this.getCellValue(cell));
}
list.add(li);
}
}
//		work.close();
//		((InputStream) work).close();
return list;
}

描述:根据文件后缀,自适应上传文件的版本 
读取Sheet,根据需求不同改变处理和返回值

/**
* 描述:根据文件后缀,自适应上传文件的版本
*
* @param inStr,fileName
* @return
* @throws Exception
*/
public Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
Workbook wb = null;
String fileType = fileName.substring(fileName.lastIndexOf("."));
if (excel2003L.equals(fileType)) {
wb = new HSSFWorkbook(inStr); // 2003-
} else if (excel2007U.equals(fileType)) {
wb = new XSSFWorkbook(inStr); // 2007+
} else {
throw new Exception("解析的文件格式有误!");
}
return wb;
}

描述:对表格中数值进行格式化:按需修改

原来没有if(cell==null),因为报错而加

/**
* 描述:对表格中数值进行格式化
*
* @param cell
* @return
*/
public Object getCellValue(Cell cell) {
Object value = null;
DecimalFormat df = new DecimalFormat("0"); // 格式化number String字符
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); // 日期格式化
DecimalFormat df2 = new DecimalFormat("0.00"); // 格式化数字

System.out.println("cell="+cell);

if(cell==null){
return "";
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if ("General".equals(cell.getCellStyle().getDataFormatString())) {
value = df.format(cell.getNumericCellValue());
} else if ("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) {
value = sdf.format(cell.getDateCellValue());
} else {
value = df2.format(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_BOOLEAN:
value = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK:
value = "";
break;
default:
break;
}
return value;
}

三、前台
使用Ajax+Form提交方式。此处前后台交互遇到问题,开始使用ModelAndView model.addAttribute,前台Ajax收不到data,

后来改用session.setAttribute方式,但是js中session为undefined无法使用,最后使用了ModelMap才可以,没有找到原因。

过滤:accept=".xlsx,application/vnd.ms-excel,application/vnd.openxmlformat-officedocument.spreadsheetml.sheet"

<p>
<font style="font-family: sans-serif;"><b>信息导入:</b></font>
</p>
<form id="uploadE" enctype="multipart/form-data">
<input id="excelFile" type="file" name="excelFile"
accept=".xlsx,application/vnd.ms-excel,application/vnd.openxmlformat-officedocument.spreadsheetml.sheet" />

<input id="excel_button" type="button" value="导入" onclick="uploadExcel();"
style="background-color: #004B97;color:white;font-family:SimSun;
font-size:10px;width: 10%;height: 5%;" />

<input type="button" value="下载模板" onclick="downloadTemplate()"
style="background-color: #004B97;color:white;font-family:SimSun;
font-size:10px;width: 10%;height: 5%;" />

</form>

function

function uploadExcel(){
var excelFile=$("#excelFile").val();
if(excelFile==""||excelFile.length==0){
alert("请选择文件路径!(.xlsx)");
return;
}
if(excelFile.indexOf(".xlsx")==-1){
alert("请选择正确格式文件!(.xlsx)");
return;
}
var action = "<c:url value='upload.json'/>";
var option={
url: action,
type:"POST",
dataType : "json",
clearForm:true,
success:function(data){
console.log("data.info="+ data.info);
$.messager.alert('导入结果', data.info);
}
};
$("#uploadE").ajaxSubmit(option);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐