文章目录

  • poi解析excel&插入数据库详解
    • 说明
    • 一、目的
    • 二、准备工作
    • 三、思路分析
    • 四、流程图分析
    • 五、核心代码
      • 1:上传文件
      • 2:获取输入流
      • 3:初始化excel表
      • 4:遍历行和列
      • 5:连接数据库
      • 6:前台反馈
    • 六、效果展示

poi解析excel&插入数据库详解

说明

1:在写此博文之前博主已经写过类似的一篇关于就exce文本中的数据插入到数据库之中。
        2:此文章就是一篇最简单无任何条件限制的直接读取excel文本中的数据,然后insert到数据库中。
        3:没有对excel表格中的数据进行文本,日期,数值的处理,只是单纯的全部作为文本进行了处理。
        4:也没有进行在数据库中select以此来和excel表中的数据进行对比查重。
        5:前台页面也没有提示插入多少行数据,成功导入多少行数据,重复多少行数据。
基于以上几点,此篇博文是对poi解析&插入到数据库中的一个更新版本


因为excel文件分为两种版本,一种是以.xls后缀结尾的03版,一种是以.xlsx结尾的07版,所以为了兼顾两种版本的excel文件,对于此次选取poi-3.8进行解析。
        具体详情可以参考:https://www.aliyun.com/jiaocheng/574164.html

一、目的

1:将excel中的数据通过解析导入到mysql数据库中
        2:和数据库对比使重复的数据不进行导入
        3:前台页面也反馈出导入的具体情况

二、准备工作

1:获取poi-3.8解析包相关文件:https://download.csdn.net/download/jiajikang_jjk/10698866
        2:excel文件模板

        3:数据库对应表单

三、思路分析

1:上传文件

上传文件到指定的路径,换句话说也就是将要解析的excel文件上传到指定的绝对路径下。

2:获取文件输入流

获取上传的文件(也就是获取第一步上传要解析的excel文件)的文件名

3:解析

解析获取的上传的文件,解析二字听着挺高大上的,个人对它的理解就去处理它的数据(日期,数值,文本),使程序能够原封不动的按照excel文本中的格式原模原样的插入到数据库中。

4:存入list集合

将解析后的excel中的数据存入到list集合之中

5:连接数据库

解析完成之后,就是开始连接数据库,实现数据的插入

6:查重

在将excel解析的数据进行插入数据库之前,要判断一下数据库中的表单是否有数据存在且在存在数据的情况下,进行判断是否和即将要插入的excel文件中的数据是否重复的一个判定。

a:要是重复,记录重复的行数以及一共重复的个数。

b:将没有重复的数据,执行插入到数据库中。

c:前台界面要反馈出:一共插入多少行数据,成功插入多少行数据,重复多少行数据。

7:前台反馈

前台界面要反馈出:一共插入多少行数据,成功插入多少行数据,重复多少行数据。

四、流程图分析

五、核心代码

1:上传文件

// 创建接收上传文件的对象// 需导入import="com.jspsmart.upload.*" lib下导入servlet.jar和jspsmartupload.jar包SmartUpload myUpload=new SmartUpload(); myUpload.initialize(pageContext); //获取jsp的pageContext//从pageContext中接收要上载的文件,//pageContext中可以含有超文本表单提交的多个file域,且还可以包含超文本表单提交的其他字段myUpload.upload();//上传,这里有可能报错,一般是没导入servlet.jar包System.out.println("\n222222222222222222222222222222222222222222222222");String in_filename=""; //指向上载好的temp目录中的文件名String in_filedir=""; //服务器上temp目录中含文件名的绝对物理路径// long startTime = System.currentTimeMillis();    //获取开始时间    String err_code="0x00";//用于异常判定的代码int num = 0;try{//以新给定的文件名进行存储,要对上载的文件一个一个地依次进行处理for (int i=0; i < myUpload.getFiles().getCount(); i++) //myUpload.getFiles().getCount();要上传的文件数量{com.jspsmart.upload.File my_file=myUpload.getFiles().getFile(i); //获取文件对象//如果文件不存在if (my_file.isMissing())       {     // 报错//err_code="ERR_A";            throw new Exception("『back::_self』服务器无法接收此文件,上载文件失败!");}//用操作系统的根目录作为存盘时相对路径的根目录in_filename=my_file.getFileName();//文件名不变in_filedir=dqz_str.StrReplace(WEB_ROOT03,"/","\\")+in_filename;//in_filedir为文件夹位置加上文件名System.out.println("\nin_filedir = " + in_filedir);my_file.saveAs(in_filedir,myUpload.SAVE_PHYSICAL);//保存文件到指定目录下}}catch(Exception e){throw new Exception("『back::_self』文件没有上传成功!");  }

2:获取输入流

虽然poi-3.8已经兼容03和07,但是博主这里依然为了用户查看源码时更能一目了然依然进行了判别:

// 开始解析//  获取文件输入流FileInputStream excelfile = new FileInputStream(in_filedir);//读取指定位置中的文件,就是刚才保存在指定文件夹中的上传文件System.out.println("\n文件位置:"+excelfile);System.out.println("000000000000000000000000000");Workbook wb = null;    if(in_filename.endsWith(".xlsx")){wb = new XSSFWorkbook(excelfile);//07版System.out.println("\n111111111111111111111");}else{wb = new HSSFWorkbook(excelfile);// 03版System.out.println("\n222222222222222222222");}// 初始化工作表Sheet sheet = null; // excel工作表sheetRow row = null;     // excel工作表行Cell cell = null;   // excel工作表列int SUM_cf=0;       // 记录数据库中重复的条数(使用序列号作为唯一标识符)int SUM_cg=0;       // 成功插入的条数List<Integer> hang = new ArrayList<Integer>();// 作为记录重复的行编号sheet= wb.getSheet("丙机房发射机备件定额"); //  获取xssfworkbook对象--以此得到sheet(工作表)对象:丙机房发射机备件定额// 第二步// 判断获取的工作表(丙机房发射机备件定额)是否为空// 使用工作表之前要检查行对象是否为null,否则会报空指针异常sheet = wb.getSheetAt(0);//读取下标为0的表(也就是第一张表:sheet1)

3:初始化excel表

 // 初始化工作表Sheet sheet = null; // excel工作表sheetRow row = null;     // excel工作表行Cell cell = null;   // excel工作表列int SUM_cf=0;       // 记录数据库中重复的条数(使用序列号作为唯一标识符)int SUM_cg=0;       // 成功插入的条数List<Integer> hang = new ArrayList<Integer>();// 作为记录重复的行编号sheet= wb.getSheet("丙机房发射机备件定额"); //  获取xssfworkbook对象--以此得到sheet(工作表)对象:丙机房发射机备件定额// 第二步// 判断获取的工作表(丙机房发射机备件定额)是否为空// 使用工作表之前要检查行对象是否为null,否则会报空指针异常sheet = wb.getSheetAt(0);//读取下标为0的表(也就是第一张表:sheet1)if(null==sheet){System.out.println("工作表0【默认名为 Sheet1 】为空");  throw new Exception("『back::_self』错误:工作表为空!");        }System.out.println("\n3333333333333333333333333333");// 第三步(在满足第二步的基础上进行):获取一共的行数和列数// 行数int allRowNum= sheet.getLastRowNum(); // 获取一共的行数,因为从0行开始算起的,所以不+1就少一行System.out.println("一共 " + allRowNum + " 行");// 列数row=sheet.getRow(0);//System.out.println("检测:"+row); // 初始化: A1,B1,C1,,,M1int allCellNum1 = row.getLastCellNum();//int allCellNum2 = Row.getPhysicalNumberOfCells();System.out.println("一共 " + allCellNum1 + " 列");//System.out.println("有效物理列:"+allCellNum2);// 获取03,07版的行和列数结束

4:遍历行和列

在遍历行和列的时候,进行了对excel中单元格数据进行了分析,然后存入到list集合中。其中在进行将String型转化为int型时博主使用的是此方法实现的。

 // 开始一行一行解析---一行解析出来的就是个数组----------全部就是一个list集合// 遍历行List<List<String>>list=new ArrayList<List<String>>();for(int i2=2;i2<=sheet.getLastRowNum();i2++){    System.out.println("\n开始遍历第" + i2 + " 行"); // 从最初有效行开始遍历// 获取当前行row=sheet.getRow(i2);if(null==row){//row="";continue;   }// 单元格列表List<String> dataList= new ArrayList<String>(); for (int j1 = row.getFirstCellNum();j1<=allCellNum1;j1++) { String cellValue = "";Cell cell2 = row.getCell(j1);// 获取当前行的单元格System.out.println("当前单元格cell2:"+cell2);if(null==cell2){// 非空验证//cell2="";continue;}try {if(cell2.getCellType()==Cell.CELL_TYPE_NUMERIC){// 数值型  if(HSSFDateUtil.isCellDateFormatted(cell2)){// 日期 poi 3.8// System.out.println("日期格式");// System.out.println("cell2内容:"+cell2);Date date = cell2.getDateCellValue();// 获取日期// System.out.println("date01:"+date);// Sun Sep 09 00:00:00 CST 2018SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");cellValue= simpleDateFormat.format(date); // 将获取去的单元格值(日期)设置为日期格式// System.out.println("cellValue02:"+cellValue);  // }else{// System.out.println("\n数字格式");HSSFDataFormatter hSSFDataFormatter = new HSSFDataFormatter();cellValue = hSSFDataFormatter.formatCellValue(cell2); // 使用EXCEL原来格式的方式取得值// System.out.println("cellValue03:"+cellValue);} }else{// 非数值类型// System.out.println("\n非日期格式");HSSFDataFormatter hSSFDataFormatter = new HSSFDataFormatter();cellValue = hSSFDataFormatter.formatCellValue(cell2); // 使用EXCEL原来格式的方式取得值// System.out.println("cellValue04:"+cellValue);}// 将上面cellValue判断获取的值进行添加到集合dataList中dataList.add(cellValue);//System.out.println("dataList.size():"+dataList.size());// 12}catch (Exception e) {e.printStackTrace();}}//遍历当前行中所有单元格结束              list.add(dataList);// 此处是将单元格值的dataList集合添加到list集合中!!!//System.out.println("\nlist.add(dataList):"+ list.size());// 133-2= 131}// 解析完毕System.out.println("\n4444444444444444444444444444444444444");

5:连接数据库

在连接数据库完成之后,下一步就执行插入数据到mysql数据库对应的表单之中。其中在插入前,进行了判别是否和数据库中已有的数据重复,其中判断数据查重操作博主依靠的此案例进行实现的查重

// 连接数据库boolean ok=false; //成功操作则此标志转为true//下面使用JNDI数据库连接池连接到MySQL服务器Connection my_con=null;String my_sql = "";try{String my_dbdriver=com_station_datebase_driver; //MYSQL 5.0 用的JDBC驱动String my_url=com_station_datebase_url; //MYSQL数据库名为dqz_mysql_testString my_username=com_station_datebase_user;  //数据库管理用户String my_password=com_station_datebase_password; //数据库管理密码Class.forName(my_dbdriver); //装载驱动程序my_con=DriverManager.getConnection(my_url,my_username,my_password); //连接数据库//建立远程视图Statement my_stmt=my_con.createStatement();err_code="0x01"; //成功执行到获取了远程视图System.out.println("连接数据库成功!!");// 注意:因为SQL中规定字符串值(String变量或字符串常量)必须用单引号''括起来,// 所以下面的jsp程序中在SQL语句中传递的字符串不能使用双引号,而用了单引号。// 发送并执行SQL// 进行查询数据库----判断数据库中的数据是否和要插入的数据是否重复 // 从有效数据行开始遍历  //int SUM_cf=0; // 记录数据库中重复的条数(使用序列号作为唯一标识符)int SUM_gs=0; // 记录格式错误的条数//int SUM_cg=0; // 成功插入的条数 int c = 0;  // 设置String 转 int型String dates = ""; // 获取到的数据System.out.println("\n5555555555555555555555555555555");List<String> list2= new ArrayList<String>();// 作为将查询数据库中xlh存入到list2这个集合中// List<Integer> hang = new ArrayList<Integer>();// 作为记录重复的行编号my_sql = "SELECT DISTINCT xlh FROM excel_test GROUP BY xlh"; // 查询数据库中的xlhResultSet my_rs=my_stmt.executeQuery(my_sql); //执行查询// ResultSetMetaData md = my_rs.getMetaData(); // 获取字段个数 // int columnCount = md.getColumnCount();// my_rs.last();// 移到最后一行// int count = my_rs.getRow();// 获取数据库中一共多少行// System.out.println("count:" +count);if(null!=my_rs){// 如果查询数据不为空--进行将数据添加到list2集合中while(my_rs.next()){// System.out.println("66666666666666666666666");dates = my_rs.getString("xlh");// 获取xlh的值list2.add(dates); // 将获取到的xlh存入到list2集合中System.out.println("dates:"+ dates);}  }// 添加list2 完成之后---或者查询为空时-------》进行插入操作// 遍历excel表的list集合for(int x=0;x<list.size();x++){ try{// 没有查到也就是没有重复的-----执行插入// 遍历(单元格中的数据存入到list集合中的)list集合my_sql = "INSERT INTO excel_test(xlh,xh,zwmc,gnms,cksm,C01,C02,ljyl,bfbl,ybsl,bjsl,bz) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";      // 创建一个Statment对象PreparedStatement ps = my_con.prepareStatement(my_sql);// 为sql语句中第一个问号赋值ps.setString(1, list.get(x).get(0));// 产品序列号//System.out.println("list中的内容:"+list.get(x).get(0));// 为sql语句中第二个问号赋值ps.setString(2, list.get(x).get(1));// 规格型号// 为sql语句中第三个问号赋值ps.setString(3, list.get(x).get(2));// 中文名称ps.setString(4, list.get(x).get(3));// 功能描述ps.setString(5, list.get(x).get(4));// 参考寿命// String -------转化---------int// 说明:对应的单元格中的数字不能为空--即使为空也要用0来代替if(list.get(x).get(5)!=null && list.get(x).get(5).length()>0){    c = Integer.parseInt(list.get(x).get(5));// 将list.get(x).get(5)得到的String型的数据转化为Int型ps.setInt(6, c);// C01用量    }else{ps.setInt(6,c);}   ps.setString(7, list.get(x).get(6));// C02用量ps.setString(8, list.get(x).get(7));// 两机用量ps.setString(9, list.get(x).get(8));// 备份比例ps.setString(10, list.get(x).get(9));// 应备数量ps.setString(11, list.get(x).get(10));// 备件数量ps.setString(12, list.get(x).get(11));// 备注// System.out.println("\n6666666666666666666666666666666666");// System.out.println("\nlist中的内容:"+list.get(x).get(0));boolean flag = true;if(null==list2||list2.size()==0){// 如何list2集合为空就直接进行插入System.out.println("list2集合为空,直接插入数据");ps.executeUpdate();// 执行sql语句err_code="0x02"; //成功执行了插入语句}else{// list2集合不为空// 进行判断查重// 遍历查询--list2集合是添加数据库序列号的集合for(int j=0; j<list2.size();j++){if(list.get(x).get(0).equals(list2.get(j))){// excel中获取的序列号和数据库中获取的序列进行判断是否相等(重复)flag = false;hang.add(x+3);System.out.println("hang.add(x+3)" + hang);System.out.println("第"+(x+3)+"行,"+"序列号:"+list.get(x).get(0)+",在集合list2中出现,不能重复添加");//                        break;                     }   }//  如果 boolean flag = true-->无重复if(flag){// 执行没有重复的数据---将excel中未重复的数据插入的数据库System.out.println("无重复,执行插入");ps.executeUpdate(); // 执行sql语句err_code="0x03";   //成功执行了插入语句SUM_cg++; // 添加成功的个数}else{ SUM_cf++; //记录重复个数}}}catch(Exception e2){// throw new Exception("在excel_add_list_ok.jsp 中插入数据时发生异常:" + e);err_code="0x04";   //成功执行了插入语句System.out.println("出现插入异常");}}System.out.println("\nfor循环结束");System.out.println("\n一共重复:"+ SUM_cf+"行");System.out.println("\n一共成功插入:"+SUM_cg+"行");int sum_cf = SUM_cf;// 一共重复的行数int sum_cg = SUM_cg;// 一共成功插入的行数System.out.println("sum_cf:"+sum_cf);System.out.println("sum_cg:"+sum_cg);ok=true; //处理成功my_con.close();  //关闭数据库}catch(Exception e){System.out.println("\ne:"+e);System.out.println("\nmy_sql:"+my_sql);  }finally{if(null!=my_con) my_con.close(); //在发生异常时关闭数据库连接}if(!ok){//操作失败:throw new Exception("『back::_self』添加新记录失败,请重试!");}else{System.out.println("成功!!!");    //  操作成功//throw new Exception("『wait:tps_list.jsp:_self』记录添加成功!");}

6:前台反馈

 <html><head><title>导入Excel表</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><link rel="stylesheet" href="../css/bootstrap.min.css" /><script type="text/javascript" src="../js/jquery-1.9.1.min.js"></script></head> <body><div align="center"><p><font size=15px>Excel表格信息导入成功</font></p><br/><p>一共导入<%=allRowNum-1%>行数据,成功导入<%=SUM_cg%>行数据,重复<%=SUM_cf%>条数据</p></div><div>其中重复的行编号分别是:第 <%=hang%> 行!!!</div><!--js部分--><div align="center"><a size=50px href="excel_add_test_list.jsp">返回</a></div></body>
</html>

六、效果展示

【poi-3.8】poi解析excel插入数据库详解相关推荐

  1. poi导出excel清晰 步骤详解

    [align=center][size=large][color=red][b]poi导出excel清晰 步骤详解[/b][/color][/size][/align] [color=darkblue ...

  2. python把数据写入excel_Python读写sqlite3数据库的方法并且将数据写入Excel的实例详解...

    这篇文章主要介绍了Python实现读写sqlite3数据库并将统计数据写入Excel的方法,涉及Python针对sqlite3数据库的读取及Excel文件相关操作技巧,需要的朋友可以参考下 本文实例讲 ...

  3. php表单提交到数据库详解

    一般朋友们逛一些网站的时候,想使用网站或者看到更多网站里的内容,网站会要求用户进行新用户的注册,网站会把新用户的注册信息存入数据库中,需要的时候再进行提取. 这样网站就会首先创建自己的数据库和对应的表 ...

  4. 微信小程序云开发入门(二)-数据库详解

    微信小程序云开发入门(二)-数据库详解 接上一篇:微信小程序云开发入门(一) 摘要: 因为微信小程序云数据库有点类似传统的关系型数据库,但又有所不同.所以刚入手的时候会有点困扰,经过一段时间的学习和摸 ...

  5. LIDC-IDRI肺结节数据库详解

    LIDC-IDRI肺结节数据库详解 LIDC-IDRI (The Lung Image Database Consortium),该数据集由胸部医学图像文件(如CT.X光片)和对应的诊断结果病变标注组 ...

  6. Excel 绘制表格 详解!

    Excel 绘制表格 详解! 1.在桌面上点击Excel图标,打开工作表,纵向是1.2.3.4-的顺序号,横向是A.B.C.D-的顺序号. 2.数一下你拟打的表格的列数,比如是8列,则你将鼠标箭头移到 ...

  7. pandas读写MySQL数据库详解及实战

    pandas读写MySQL数据库详解及实战 SQLAlchemy是Python中最有名的ORM工具. 关于ORM: 全称Object Relational Mapping(对象关系映射). 特点是操纵 ...

  8. python3d动态图-Python图像处理之gif动态图的解析与合成操作详解

    本文实例讲述了Python图像处理之gif动态图的解析与合成操作.分享给大家供大家参考,具体如下: gif动态图是在现在已经司空见惯,朋友圈里也经常是一言不合就斗图.这里,就介绍下如何使用python ...

  9. python处理excel大数据-Python实现大数据收集至excel的思路详解

    一.在工程目录中新建一个excel文件 二.使用python脚本程序将目标excel文件中的列头写入,本文省略该部分的code展示,可自行网上查询 三.以下code内容为:实现从接口获取到的数据值写入 ...

最新文章

  1. ORA-01031:insufficient privileges问题解决
  2. GDLiveStreaming视频推送RTMP
  3. 对一次短路故障的分析与总结
  4. JDK8 SE安装步骤
  5. USACO2.4のP1522-牛的旅行(Cow Tours)【最短路Flody】
  6. Hive分区和桶的概念
  7. 【SpringCloud从0到6】 第一节:初识微服务微服务的雪崩效应
  8. vb.net 同时给多个属性赋值_系统小技巧:充分用好文件的时间属性
  9. 光盘中删除数据如何恢复_电脑硬盘数据恢复教程,EasyRecovery软件讲解,恢复删除数据...
  10. 电商需求分析mysql建表_电商-专题表 - 数据库设计 - 数据库表结构 - 果创云
  11. 电脑远程链接怎么删除计算机,删除远程桌面连接记录的方法
  12. 前沿科技分论坛精彩回顾 | 第二届始祖数字化可持续发展峰会
  13. VS2019打包程序安装后无法运行
  14. HMMer在Windows环境下的安装
  15. 【经典转载】一只猫和一条鱼的爱情故事
  16. use ida6.8 + windbg on win10
  17. 合泰HT66F2390单片机串口UART使用例程
  18. Matlab代码 多时间尺度优化调度 MATLAB程序含冰蓄冷空调的冷热电联供型微网多时间尺度优化调度
  19. 常见变异影响常见疾病,罕见变异影响罕见疾病?
  20. 教程--为公众号接入客服机器人

热门文章

  1. 图扑孪生工厂流水线组态图可视化
  2. 分享一个超好用的项目进度模板(包括计划进度与实际进度对比甘特图)
  3. springboot webflux 过滤器(WebFilter)
  4. linux天翼校园认证失败,天翼校园账号状态异常?这份超详细图文教程帮你解决问题!...
  5. 计算机实用软件大全pdf,常用工具软件大全.pdf
  6. 计算机组装pdf最新,新编计算机组装与维护.pdf
  7. AVB源码学习(三):AVB2.0 Init阶段安全启动流程
  8. [ZT]“你可以安全关机”解决方案
  9. 灰度图像中值滤波c语言编程,灰度图像中值滤波
  10. java Thread Dump 日志分析