此例为maven项目,实现学生模块列表信息的导入Excel操作。所用框架为SSM框架。
工具类 ImportExcelUtil.java 中均为公用方法,无论任何框架项目都可直接调用类中方法,只需将对应的参数传到方法中即可。
1.jar包
在maven项目中增加如下配置即可。若非maven项目,将jar包下载后导入项目中。
<!-- 支持Excel表格操作 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
2.JSP 构建一个隐藏文件域,当点击导入时,自动点击弹出选择文件框
<a href="javascript:void(0)" class="easyui-linkbutton" id="importExcel" iconCls="icon-import" plain="true">导入Excel</a>
<%-- 导入Excel start --%>
<input type="file" id="fileElement" name="fileElement" style="filter:alpha(opacity=0);opacity:0;width: 0;height: 0;"/>
<%-- 导入Excel end --%>
3.JS 采用ajaxFileUpload的方式进行上传,需在jsp页面中引入ajaxfileupload.js文件,该文件在百度搜索即可。
/**
* 页面初始化
*/
$(document).ready(function () {
$("#importExcel").on("click",importExcel); //导入Excel绑定事件
});
/**
* 导入Excel操作
* @returns
*/
function importExcel(){
//导入表格url
var url = "../file/demoStudentFile/importExcel";
//文件域ID
var fileId = "fileElement";
//文件类型名称,用于提示信息
var fileTypeName = "Excel";
//文件类型,用于判断文件后缀是否有效
var fileType = "xls;xlsx";
//向后台传输的数据,格式为{id:"111"}
var d = {};
//调用公用JS文件中的方法
importUtil(url,d,fileId,fileTypeName,fileType);
}
/** 以下为公用JS中的公用方法,所有导入或上传文件均可直接调用,将文件域ID,文件类型等传递到方法中即可 **/
/**
* 点击导入或上传按钮,绑定文件域事件,模拟点击,打开文件选择框
* @param url
* @param fileId 文件域ID
* @param fileTypeName 上传的文件类型名称(Word、Excel、PPT...),用于提示信息
* @param fileType 要求上传的文件类型,各个类型间用英文;隔开 (xls;xlsx),用于判断文件后缀是否有效
* @returns
*/
function importUtil(url,d,fileId,fileTypeName,fileType){
//Excel文件域绑定改变事件
$("#"+fileId).change( function() {
importFileUtil(url,d,fileId,fileTypeName,fileType);
});
$("#"+fileId).trigger("click");
}
/**
* 传输文件
* @param url
* @param fileId 文件域ID
* @param fileTypeName 上传的文件类型名称(Word、Excel、PPT...),用于提示信息
* @param fileType 要求上传的文件类型,各个类型间用英文;隔开 (xls;xlsx),用于判断文件后缀是否有效
* @returns
*/
function importFileUtil(url,d,fileId,fileTypeName,fileType){
if(checkFileType(fileId,fileTypeName,fileType)){
$.ajaxFileUpload({
url: url,
secureuri: false, //是否需要安全协议,一般设置为false
fileElementId: fileId, //文件上传域的ID
dataType:"JSON",
data : d,
success: function (data, status){ //服务器成功响应处理函数
var result = $.parseJSON(data);
$("#"+fileId).val("");
$.messager.show({ title: '提示', msg: result.msg, timeout: 1000, style: {} });
},
error: function (data, status, e){ //服务器响应失败处理函数
alert("导入失败");
}
});
return false;
}
}
/**
* 校验文件类型
* @param fileId 文件域ID
* @param fileTypeName 上传的文件类型名称(Word、Excel、PPT...),用于提示信息
* @param fileType 要求上传的文件类型,各个类型间用英文;隔开 (xls;xlsx),用于判断文件后缀是否有效
* @returns
*/
function checkFileType(fileId,fileTypeName,fileType){
var fileDir = $("#"+fileId).val();
if("" == fileDir){
ts("请选择有效的"+fileTypeName+"文件!");
return false;
}
var suffix = fileDir.substr(fileDir.lastIndexOf(".")+1);
var fileTypes = fileType.split(";");
if(fileTypes.indexOf(suffix)==-1){
ts("请选择有效的"+fileTypeName+"文件!");
return false;
}
return true;
}
4.实体类 DemoStudent.java
package com.project.entity.demo;
import com.project.entity.BaseEntity;
/**
* @author hmz 2017年12月25日 下午5:05:03 学生实体类
*/
@SuppressWarnings("serial")
public class DemoStudent extends BaseEntity {
private String stuId;// 学生id
private String name;// 学生姓名
private String sex;// 学生性别
private String phone;// 学生电话
private String address;// 学生地址
private String message;// 学生自我评价
private String fkFileId;// 附件ID
private String fkFileName;// 附件名称
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getFkFileId() {
return fkFileId;
}
public void setFkFileId(String fkFileId) {
this.fkFileId = fkFileId;
}
public String getFkFileName() {
return fkFileName;
}
public void setFkFileName(String fkFileName) {
this.fkFileName = fkFileName;
}
}
5.Controller层 DemoStudentFileController.java 主要用于获取文件并调用Service中方法
package com.project.controller.demo;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.project.entity.demo.DemoStudent;
import com.project.service.demo.DemoStudentService;
import com.project.util.cipher.CipherTransport;
/**
* @ClassName: DemoStudentFileController
* @Description: TODO
* @author: HeMengZhu
* @date: 2018年2月28日 下午3:49:22
*/
@Controller
@CipherTransport
@RequestMapping("/file/demoStudentFile")
public class DemoStudentFileController {
@Autowired
private DemoStudentService demoStudentService;
/**
* 导入Excel
* @Title: importExcel
* @Description: TODO
* @param file 导入文件 其中@RequestParam("importExcelFile")要与文件域ID一致
* @param response
* @throws IOException
* @return: ResBody<String>
*/
@ResponseBody
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public void importExcel(@RequestParam("fileElement") MultipartFile file, HttpServletResponse response) throws IOException {
JSONObject obj = demoStudentService.importExcel(file);
response.getWriter().print(obj.toString());
}
}
6.Service层 DemoStudentService.java 主要处理业务逻辑并访问公用方法获取Excel中的数据并做业务处理(此例只将表格中的数据一行一行打印出来,并未做业务处理,所以数据库层代码在此不做展现。需要注意的是,导入操作时需对每一个单元格数据进行验证,包括长度、非空以及与自己业务规则逻辑的验证,且与前台页面上的新增验证理论上应保持一致。)
package com.project.service.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.activiti.engine.impl.util.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.project.entity.demo.DemoStudent;
import com.project.mapper.demo.DemoStudentMapper;
import com.project.util.ConstUtil;
import com.project.util.file.ExportExcelUtil;
import com.project.util.file.FileConstUtil;
import com.project.util.file.FileValidateUtil;
import com.project.util.file.ImportExcelUtil;
/**
* @ClassName: DemoStudentService
* @Description: TODO
* @author: HeMengZhu
* @date: 2018年2月28日 下午3:52:03
*/
@Service
public class DemoStudentService {
@Autowired
private DemoStudentMapper demoStudentMapper;
@Autowired
private DemoFileService demoFileService;
/**
* 导入Excel
* @Title: importExcel
* @Description: TODO
* @param file
* @param response
* @return
* @throws IOException
* @return: boolean
*/
@Transactional
public JSONObject importExcel(MultipartFile file) throws IOException {
JSONObject obj = new JSONObject();
InputStream in = null;
// 定义listob存储表格数据
List<List<Object>> listob = null;
try {
// 判断文件是否存在
if (file.isEmpty()) {
obj.put("msg", FileConstUtil.ExcelMessage.FILE_EXISTS);
// throw new Exception("文件不存在!");
} else if (!FileConstUtil.ExcelMessage.EXTS.contains(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1))) {
// 判断文件类型是否正确
obj.put("msg", FileConstUtil.ExcelMessage.FILE_EXT_ERROR);
} else {
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);
DemoStudent stu = new DemoStudent();
stu.setId(UUID.randomUUID().toString());
stu.setName(String.valueOf(lo.get(1)));
stu.setSex(String.valueOf(lo.get(2)));
stu.setPhone(String.valueOf(lo.get(3)));
System.out.println("打印信息-->id:" + stu.getId() + " 名称:" + stu.getName());
}
obj.put("msg", FileConstUtil.ExcelMessage.SUCCESS_MESSAGE);
}
} catch (Exception e) {
e.printStackTrace();
obj.put("msg", FileConstUtil.ExcelMessage.ERROR_MESSAGE);
}
return obj;
}
}
7.常量类 FileConstUtil.java 主要定义导入表格中的一些常量,比如文件类型、提示信息等等
package com.project.util.file;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @ClassName: FileConstUtil
* @Description: TODO文件信息常量类
* @author: HeMengZhu
* @date: 2018年2月28日 下午4:23:43
*/
public class FileConstUtil {
/**
* 导入表格信息
* @ClassName: ExcelMessage
* @Description: TODO
* @author: HeMengZhu
* @date: 2018年3月1日 下午3:03:32
*/
public static class ExcelMessage {
/**
* 文件不存在提示信息
*/
public static final String FILE_EXISTS = "文件不存在";
/**
* 导入表格后缀格式
*/
public static final List<String> EXTS = Arrays.asList("xls", "xlsx");
/**
* 文件类型不正确提示信息
*/
public static final String FILE_EXT_ERROR = "请选择正确的文件";
/**
* 导入成功提示信息
*/
public static final String SUCCESS_MESSAGE = "导入成功";
/**
* 导入失败提示信息
*/
public static final String ERROR_MESSAGE = "导入失败";
}
}
8.工具类 ImportExcelUtil.java 主要为读取Excel表格中的数据等操作
package com.project.util.file;
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;
import org.springframework.stereotype.Service;
/**
* 导入Excel文件工具Service
* @author HMZ
* @version 2017年10月8日下午1:02:23
*/
@Service
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 {
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;
int maxRowNum;
list = new ArrayList<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);
maxRowNum = sheet.getRow(0).getLastCellNum();
if (row == null || row.getFirstCellNum() == j) {
continue;
}
// 遍历所有的列
List<Object> li = new ArrayList<Object>();
for (int y = 0; y < maxRowNum; y++) {
cell = row.getCell(y);
li.add(cell);
}
/*
* for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) { cell = row.getCell(y); li.add(this.getCellValue(cell)); }
*/
if (li.size() > 0) {
list.add(li);
}
}
}
work.close();
return list;
}
/**
* 描述:根据文件后缀,自适应上传文件的版本
* @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;
}
/**
* 描述:对表格中数值进行格式化
* @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"); // 格式化数字
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;
}
}