项目架构:spring+struts2+hibernate4+oracle

需求:用户导入excel文件,导入到相应的数据表中,要求提供导入模板,支持xls和xlsx文件

思路分析:

1、提供一个下载链接,点击下载,可以使超链接,src直接是项目路径加文件名。

2、通过上传文件,服务器接收上传,返回一个上传后的服务器本地路径,通过ajax异步赋值到jsp的路径隐藏域。

3、ajax异步提交导入请求,后台处理,将路径转换成File,File转换成MultipartFile,将文件读取转换成一个数组类型的集合。

4、循环集合这种的数据,每一行excel数据,是一个元素,将元素转换成相应的java对象进行保存。

一、所需jar包

一共是6个jar包。

二、前端jsp代码部分

  1. <input type="hidden" id="excelFilePath" name="excelFilePath" value="" />
  2. <tr>
  3. <td>选择文件:</td>
  4. <td><input type="file" name="uploadFile" id="excelFile"></input></input>
  5. <span id="uploadMsg"></span></td>
  6. </tr>
  7. <tr>
  8. <td></td>
  9. <td> <input type="button" value="上传" onclick="fileUpload()">
  10. &nbsp;
  11. <input type="button" value="导入" id="btnOk" disabled="true" onclick="importEmp()"/>
  12. </td>
  13. </tr>
  1. <script type="text/javascript">
  2. // 文件上传
  3. function fileUpload(){
  4. $("#fileTypeError").html("");
  5. $("#btnOk").attr("disabled",true);
  6. var fileName = $("#excelFile").val();
  7. var fileType = fileName.substr(fileName.length-4,fileName.length);
  8. if(fileType == ".xls" || fileType == "xlsx"){
  9.  
  10. var uploadFileUrl = "${basePath}/public/uploadFile.action";
  11. var formData = new FormData($("#mainForm")[0]);
  12. $.ajax({
  13. type: "POST",
  14. url: uploadFileUrl,
  15. data: formData,
  16. cache: false,
  17. processData: false,
  18. contentType: false,
  19. dataType : "json",
  20. success: function(data){
  21. if(null != data){
  22. if (data.dataStatus == "1") {
  23. $("#uploadMsg").html("<font color='green'>上传成功!</font>");
  24. $("#btnOk").attr("disabled",false);
  25. $("#excelFilePath").attr("value",data.dataMain);
  26. //alert($("#excelFilePath").val());
  27. } else {
  28. if (data.errorMsg != null
  29. && data.errorMsg.length > 0) {
  30. alert(data.errorMsg);
  31. $("#uploadMsg").html("<font color='red'>" +data.errorMsg + "请仔细阅读操作说明!</font>");
  32. }
  33. }
  34. }
  35. },
  36. error : function(XMLHttpRequest, textStatus,
  37. errorThrown) {
  38. alert("系统异常[" + textStatus + "]:" + errorThrown);
  39. }
  40. });
  41. }else{
  42. $("#uploadMsg").html("<font color='red'>上传文件类型错误,支持类型: .xls .xlsx</font>");
  43.  
  44. }
  45. }
  46. //Excel文件导入到数据库中
  47. function importEmp(){
  48. var importExcelURL = "${basePath}/public/importResultExaminee.action";
  49. var excelFilePath = $("#excelFilePath").val();
  50. $.ajax({
  51. type: "POST",
  52. url: importExcelURL,
  53. data: {"excelFilePath":excelFilePath},
  54. cache: false,
  55. dataType : "json",
  56. success: function(data){
  57. if(null != data){
  58. if (data.dataStatus == "1") {
  59. $("#btnOk").attr("disabled",false);
  60. alert("本次成功导入数量:" + data.dataMain);
  61. }else{
  62. if (data.errorMsg != null
  63. && data.errorMsg.length > 0) {
  64. alert(data.errorMsg);
  65. }
  66. }
  67. }
  68. },
  69. error : function(XMLHttpRequest, textStatus,
  70. errorThrown) {
  71. alert("系统异常[" + textStatus + "]:" + errorThrown);
  72. }
  73.  
  74. })
  75. }
  76. </script>

三、核心处理类POIUtils代码:

  1. package com.sinotn.utils;
  2.  
  3. import java.io.FileNotFoundException;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. import org.apache.log4j.Logger;
  10. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  11. import org.apache.poi.ss.usermodel.Cell;
  12. import org.apache.poi.ss.usermodel.Row;
  13. import org.apache.poi.ss.usermodel.Sheet;
  14. import org.apache.poi.ss.usermodel.Workbook;
  15. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  16. import org.springframework.web.multipart.MultipartFile;
  17.  
  18. /**
  19. * excel导出导入工具类
  20. * Copyright (c) 2018 by Sinotn
  21. * @author Libin
  22. * @date 2018年4月8日 上午9:39:50
  23. */
  24. public class POIUtils {
  25.  
  26. private static Logger logger = Logger.getLogger(POIUtils.class);
  27. private final static String XLS = "xls";
  28. private final static String XLSX = "xlsx";
  29. /**
  30. * 读取excel文件
  31. * @param formFile
  32. * @return
  33. * @throws IOException
  34. */
  35. public static List<String[]> readExcel(MultipartFile formFile) throws IOException {
  36. // 检查文件
  37. checkFile(formFile);
  38. //获得Workbook工作薄对象
  39. Workbook workbook = getWorkBook(formFile);
  40. //创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
  41. List<String[]> list = new ArrayList<String[]>();
  42. if (null != workbook) {
  43. for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets();sheetNum++) {
  44. //获得当前sheet工作表
  45. Sheet sheet = workbook.getSheetAt(sheetNum);
  46. if (null == sheet) {
  47. continue;
  48. }
  49. //获得当前sheet的开始行
  50. int firstRowNum = sheet.getFirstRowNum();
  51. //获得当前sheet的结束行
  52. int lastRowNum = sheet.getLastRowNum();
  53. //循环除了第一行的所有行
  54. for (int rowNum = firstRowNum + 1;rowNum <= lastRowNum;rowNum++) {
  55. //获得当前行
  56. Row row = sheet.getRow(rowNum);
  57. if(row == null){
  58. continue;
  59. }
  60. //获得当前行的开始列
  61. int firstCellNum = row.getFirstCellNum();
  62. //获得当前行的列数
  63. int lastCellNum = row.getPhysicalNumberOfCells();
  64. String[] cells = new String[row.getPhysicalNumberOfCells()];
  65. //循环当前行
  66. for (int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++) {
  67. Cell cell = row.getCell(cellNum);
  68. cells[cellNum] = getCellValue(cell);
  69. }
  70. list.add(cells);
  71. }
  72. }
  73. workbook.close();
  74. }
  75. return list;
  76.  
  77. }
  78.  
  79. /**
  80. * 获取当前行数据
  81. * @param cell
  82. * @return
  83. */
  84. @SuppressWarnings("deprecation")
  85. private static String getCellValue(Cell cell) {
  86. String cellValue = "";
  87. if(cell == null){
  88. return cellValue;
  89. }
  90. //把数字当成String来读,避免出现1读成1.0的情况
  91. if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
  92. cell.setCellType(Cell.CELL_TYPE_STRING);
  93. }
  94. //判断数据的类型
  95. switch (cell.getCellType()){
  96. case Cell.CELL_TYPE_NUMERIC: //数字
  97. cellValue = String.valueOf(cell.getNumericCellValue());
  98. break;
  99. case Cell.CELL_TYPE_STRING: //字符串
  100. cellValue = String.valueOf(cell.getStringCellValue());
  101. break;
  102. case Cell.CELL_TYPE_BOOLEAN: //Boolean
  103. cellValue = String.valueOf(cell.getBooleanCellValue());
  104. break;
  105. case Cell.CELL_TYPE_FORMULA: //公式
  106. cellValue = String.valueOf(cell.getCellFormula());
  107. break;
  108. case Cell.CELL_TYPE_BLANK: //空值
  109. cellValue = "";
  110. break;
  111. case Cell.CELL_TYPE_ERROR: //故障
  112. cellValue = "非法字符";
  113. break;
  114. default:
  115. cellValue = "未知类型";
  116. break;
  117. }
  118. return cellValue;
  119. }
  120.  
  121. /**
  122. * 获得Workbook工作薄对象
  123. * @param formFile
  124. * @return
  125. */
  126. private static Workbook getWorkBook(MultipartFile formFile) {
  127. //获得文件名
  128. String fileName = formFile.getName();
  129. //创建Workbook工作薄对象,表示整个excel
  130. Workbook workbook = null;
  131. try {
  132. //获取excel文件的io流
  133. InputStream is = formFile.getInputStream();
  134. //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
  135. if(fileName.endsWith(XLS)){
  136. //2003
  137. workbook = new HSSFWorkbook(is);
  138. }else if(fileName.endsWith(XLSX)){
  139. //2007
  140. workbook = new XSSFWorkbook(is);
  141. }
  142. } catch (IOException e) {
  143. logger.info(e.getMessage());
  144. }
  145. return workbook;
  146. }
  147. /**
  148. * 检查文件
  149. * @param formFile
  150. * @throws IOException
  151. */
  152. private static void checkFile(MultipartFile formFile) throws IOException {
  153. //判断文件是否存在
  154. if(null == formFile){
  155. logger.error("文件不存在!");
  156. throw new FileNotFoundException("文件不存在!");
  157. }
  158. //获得文件名
  159. String fileName = formFile.getName();
  160. //判断文件是否是excel文件
  161. if(!fileName.endsWith(XLS) && !fileName.endsWith(XLSX)){
  162. logger.error(fileName + "不是excel文件");
  163. throw new IOException(fileName + "不是excel文件");
  164. }
  165.  
  166. }
  167.  
  168. }

四、action层代码

POIUtil.readExcel方法读取excel文件后,把一行中的值按先后顺序组成一个数组,所有的行作为一个集合返回。我们可以在代码中循环这个集合,把数组赋值到实体类对象中。

我在前台用form表单提交file文件,因为用的SpringMVC框架,后台用MultipartFile接收,代码如下:

  1. /**
  2. * 读取excel文件中的用户信息,保存在数据库中
  3. * @param excelFile
  4. */
  5. @RequestMapping("/readExcel")
  6. public void readExcel(@RequestParam(value = "excelFile") MultipartFile excelFile,HttpServletRequest req,HttpServletResponse resp){
  7. Map<String, Object> param = new HashMap<String, Object>();
  8. List<User> allUsers = new ArrayList<User>();
  9. try {
  10. List<String[]> userList = POIUtil.readExcel(excelFile);
  11. for(int i = 0;i<userList.size();i++){
  12. String[] users = userList.get(i);
  13. User user = new User();
  14. user.setUserName(users[0]);
  15. user.setPassword(users[1]);
  16. user.setAge(Integer.parseInt(users[2]));
  17. allUsers.add(user);
  18. }
  19. } catch (IOException e) {
  20. logger.info("读取excel文件失败", e);
  21. }
  22. param.put("allUsers", allUsers);
  23. this.userService.insertUsers(param);
  24. }

调用的service层方法就不贴代码了,下面就是往数据库插入数据了。

excel文件内容:

POI异步导入Excel兼容xsl和xlsx的更多相关文章

  1. poi批量导入excel文件

    package com.practice.util; import java.io.File; import java.io.FileInputStream; import java.io.FileN ...

  2. java 使用POI批量导入excel数据

    一.定义 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 二.所需jar包: 三.简单的一个读取e ...

  3. NPOI导入excel为datatable (xls xlsx xlsm)

    使用NPOI导入导出Excel(xls/xlsx)数据到DataTable中 http://www.cnblogs.com/songrun/p/3547738.html NPOI 2.0教程 – 自动 ...

  4. Asp.Net异步导入Excel

    故事:用户在页面上传一个excel文件,程序把excel里的内容入库. 技术方案:保存文件在服务器,jquey Ajax 异步读取文件中的记录到数据库,在页面实时刷新导入情况 页面前端 <%@ ...

  5. MVC异步 导入excel文件

    View页面 js文件.封装到一个js文件里面 (function ($) { //可以忽略 var defaultSettings = { url: "http://upload.zhtx ...

  6. Java入门开发POI读取导入Excel文件

    Apache POI是Apache开发的开源的跨平台的 Java API,提供API给Java程序对Microsoft Office格式档案进行各种操作. POI中Excel操作很简单,主要类有 HS ...

  7. C#:导入Excel通用类(Xlsx格式)

    一.引用插件EPPlus.dll   插件下载地址:https://pan.baidu.com/s/1jEl7iu1H_C7-j9Wq37xIRQ  提取密码:pdy6 二.定义通用类XlsxExce ...

  8. java poi 导入excel

    最近项目需要导入excel,网上有很多例子,自己整合记录下,兼容2003和2007,暂时没有添加图片处理功能. 所需jar包  http://pan.baidu.com/s/1sjPuWDR pack ...

  9. Java POI导入Excel文件

    今天在公司需要做个导入Excel文件的功能,所以研究了一下,参考网上的一些资料总算是做出来了,在此记录一下防止以后忘记怎么弄. 本人用的是poi3.8,所以需要的JAR包如下: poi-3.8.jar ...

随机推荐

  1. timeslot概念(还是不太懂呀!!)

    rules: 1. event.triggered只会保持一个time_slot,在下一个time_slot将会丢失这个标记,如果不能保证在每一个time_slot都会检测到这个标志,那么将会丢失这个 ...

  2. python 装饰器(二): 加参数

    接上篇python 闭包&装饰器(一) 一.功能函数加参数:实现一个可以接收任意数据的加法器 源代码如下: def show_time(f): def inner(*x, **y): # 形参 ...

  3. python_OS 模块

    os模块 用于提供系统级别的操作 os.getcwd() # 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") # 改变当前脚本工作目 ...

  4. Ubuntu16.04 搭建svn

    1.安装SVN 安装前先更新一下 sudo apt-get update 接下来安装 sudo apt-get install subversion 2.创建SVN版本库 1.创建home下的svn文 ...

  5. 如何在小程序实现图片lazy-load懒加载效果

    自从跳一跳出现之后小程序又开始频繁出现了,在学习过程中发现小程序虽然好但是由于api不完善导致开发过程中有很多的坑,重点是网上相对小程序出现坑时解决方案显然比较少,小程序最让人觉得痛心疾首之一就是无法 ...

  6. 复(学)习化学时突然的一个 idea

    期中考试成功探底...但是某些化学问题还是很有信息学价值的... n 烷同分异构体计数. 这个题 fanhq666 出过,就是一个 dp. 设 f[i] 表示含有 i 个节点的无标号不同构的度数限制为 ...

  7. 数字游戏(codevs 1085)

    题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共 ...

  8. 1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完

    传送门 1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1979  Solved: 705[Subm ...

  9. webmagic使用手册

    https://my.oschina.net/flashsword/blog/180623 重点 SeleniumDownloader 对于一些Javascript动态加载的网页,仅仅使用http模拟 ...

  10. python学习之-- assert断言

    assert 断言作用:断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常.举例如下:a ...