POI结合bootstrap-fileinput上传Excel内容到数据库

一、准备工作

前言:

近期 本人在开发《订单管理系统》项目的时候,需要从SAP系统中导出物料编码信息,然后利用Excel导入数据到订单管理系统数据库中。本篇使用SSM+BootStrap-InputFile+poi的结合方式,写一个完整的导入Excel的例子。有需要的同学可以参考。

1.1、POI依赖
如果是maven项目,在pom.xml中添加下面的依赖:

  <!--POI 实现Excel的导入导出-->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.15</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.15</version>
    </dependency>
     <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
	 <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.7</version>
    </dependency>

workbook需要引入的jar包下载:https://download.csdn.net/download/kay523393/85404288

1.2、bootstrap-fileinput插件下载:

bootstrap-fileinput中文文档:
http://www.bootstrap-fileinput.com/examples.html

bootstrap-fileinput插件下载:
https://download.csdn.net/download/kay523393/85404018

二、代码部分

2.1、在html页面中引入BootStrap-InputFile所需要的js和css,并在html中添加Bootstrap的model弹框。


<!-- 导入excel fileinput.css-->
<link href="${pageContext.request.contextPath}/static/css/bootstrap-fileinput/fileinput.css" rel="stylesheet"> 

<!-- 导入excel fileinput.js -->
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/bootstrap-fileinput/fileinput.js"></script>


<!-- 导入Excel模态框(Modal) -->
<div class="modal fade" id="importTpl">
   <div class="modal-dialog" style="width:800px">
       <div class="modal-content">
           <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true" onclick="clear_batchAdd()" id="btn_close_batchAdd">&times;</button>
               <h3 class="modal-title" id="batchAddOilDailyLabel">导入Excel</h3>
           </div>
           <div class="modal-body">
               <div class="col-md-9 input-group">
                   <input id="excelUpload" type="file" name="file" class="form-control"/>
               </div>
           </div>
           <div class="modal-body">
					<input type="checkbox" id="updateSupport" name="updateSupport" title="如果数据已经存在,更新这条数据。">是否更新已经存在的数据
					 &nbsp;	<a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
					 <p><font color="red">提示:仅允许导入“xls”或“xlsx”格式文件!</font></p>
		   </div>
           <div class="modal-footer">
               <button type="button" class="btn btn-success" data-dismiss="modal">关闭</button>
           </div>
       </div>
   </div>
</div>

2.2、js代码中增加点击按钮弹出模态框功能和文件上传功能,增加的代码如下:

$(function(){
    
    initUpload();
   
    $("#upload").on("click",function(){
        $("#myModal").modal("show");
    });
   
})


function initUpload(){
	//使用bootstrap-fileinput渲染
    $('#excelUpload').fileinput({
       language:'zh',   //设置语言
       uploadUrl:'${pageContext.request.contextPath}/skd/importData.action',   //上传的地址
        allowedFileExtensions:['xls','xlsx'],   //接收的文件后缀
        theme:'fa',         //主题设置
        dropZoneTitle:'可以将文件拖放到这里',
        uploadAsync:true,            //默认异步上传
        showPreview:true,            //是否显示预览
        showUpload: true,//是否显示上传按钮
        showRemove: true, //显示移除按钮
        showCancel:true,   //是否显示文件上传取消按钮。默认为true。只有在AJAX上传过程中,才会启用和显示
        showCaption: true,//是否显示文件标题,默认为true
        browseClass: "btn btn-success", //文件选择器/浏览按钮的CSS类。默认为btn btn-primary
        dropZoneEnabled: true,//是否显示拖拽区域
        maxFileSize: 0,//最大上传文件数限制,单位为kb,如果为0表示不限制文件大小
        minFileCount: 1, //每次上传允许的最少文件数。如果设置为0,则表示文件数是可选的。默认为0
        maxFileCount: 1, //每次上传允许的最大文件数。如果设置为0,则表示允许的文件数是无限制的。默认为0
        previewFileIcon: "<i class='glyphicon glyphicon-king'></i>",//当检测到用于预览的不可读文件类型时,将在每个预览文件缩略图中显示的图标。默认为<i class="glyphicon glyphicon-file"></i>
        previewFileIconSettings: {
            'docx': '<i ass="fa fa-file-word-o text-primary"></i>',
            'xlsx': '<i class="fa fa-file-excel-o text-success"></i>',
            'xls': '<i class="fa fa-file-excel-o text-success"></i>',
            'pptx': '<i class="fa fa-file-powerpoint-o text-danger"></i>',
            'jpg': '<i class="fa fa-file-photo-o text-warning"></i>',
            'pdf': '<i class="fa fa-file-archive-o text-muted"></i>',
            'zip': '<i class="fa fa-file-archive-o text-muted"></i>',
        },
        msgFilesTooMany: "选择上传的文件数量({n}) 超过允许的最大数值{m}!",//字符串,当文件数超过设置的最大计数时显示的消息 maxFileCount。默认为:选择上传的文件数({n})超出了允许的最大限制{m}。请重试您的上传!
        elErrorContainer:'#kartik-file-errors'
    }).on('change',function () {
    }).on('fileuploaded',function (event,data,previewId,index) {//异步上传成功处理
        swal('系统提示',data.response.result,data.response.type);
          //关闭文件上传的模态对话框
        $('#importTpl').modal('hide');
        //重新刷新bootstrap-table数据
        $('#bootstrap-table').bootstrapTable('refresh');
        //清除文件输入 此方法清除所有未上传文件的预览,清除ajax文件堆栈,还清除本机文件输入
        $('#excelUpload').fileinput('clear');
        $('#excelUpload').fileinput('clear').fileinput('disable');
    }).on('fileerror',function (event,data,msg) {           //异步上传失败处理
        swal('系统提示','文件上传失败','error');
    });
}

2.3、Controller增加导入excel功能


	/**
	 * 导入excel
	 * 
	 */
	@RequestMapping(value = "/importData",method = {RequestMethod.GET,RequestMethod.POST},produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String importData(@RequestParam(value = "file",required = false) MultipartFile[] file, Map<String, Integer> map){
        //System.out.println("请求路径正确");
        //获取文件名
        //String fileName= file[0].getOriginalFilename();
        //System.out.println("=========》文件名称是:"+fileName);

        try{
        	map=materialService.batchAddMaterial(file[0]);
        }catch (Exception e){
            e.printStackTrace();
            return "{\"result\":\"文件处理异常,您导入的模板格式不正确\", \"type\":\"error\" }";
        }

        
        if(map.get("successNum")>0) {
            return "{\"result\":\"恭喜您,Excel数据导入成功!您总共导入"+map.get("total")+"条,成功"+map.get("successNum")+"条\", \"type\":\"success\" }";
        }else{
            return "{\"result\":\"很抱歉,Excel数据导入失败!"+map.get("repeatNum")+"条数据已存在\", \"type\":\"warning\" }";
        }
    }


2.4、Service增加使用poi处理Excel方法

Service接口类:

/**
* 导入Excel
*/
Map<String, Integer> batchAddMaterial(MultipartFile multipartFile) throws IOException;

ServiceImpl实现类:

/**
 *  导入EXCEL
 *  错误说明:poi导入excel表格数据时报java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cell异常是因为在读取cell单元格字符串时,
 *  有number类型的数据,因此需要把它转化为纯String类型,这样就不会报错了
*/
	
    @Override
    public Map<String,Integer> batchAddMaterial(MultipartFile file) throws IOException{
    	Map<String,Integer> map = new HashMap<>();
        int total = 0; //总共上传的条数
        int successNum = 0; //成功的条数
        int repeatNum = 0;  //重复的条数
        int count = 0;
        
        //存放excel表中所有user数据
        List<SkdMaterial> skdMaterialList = new ArrayList<>();
 
        //file.getOriginalFilename()方法 得到上传时的文件名
        String fileName = file.getOriginalFilename();
        //截取文件名的后缀
        String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
 
        //file.getInputStream()方法  返回InputStream对象 读取文件的内容
        InputStream ins = file.getInputStream();
 
        Workbook wb = null;
 
        /*判断文件后缀
        XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
        HSSF - 提供读写Microsoft Excel XLS格式档案的功能。*/
        
        if(suffix.equals("xlsx")){
            wb = new XSSFWorkbook(ins);
        }else{
            wb = new HSSFWorkbook(ins);
        }
 
        //获取excel表单的sheet对象
        Sheet sheet = wb.getSheetAt(0);
        
        //总共多少列
        total=sheet.getLastRowNum()-sheet.getFirstRowNum();
        
        //如果sheet不为空,就开始遍历表中的数据
        if(null != sheet){
            //line = 1 :从表的第2行开始获取记录
            for(int line = 1; line <= sheet.getLastRowNum();line++){
 
                //excel表单的sheet的行对象
                Row row = sheet.getRow(line);
 
                //如果某行为空,跳出本行
                if(null == row){
                    continue;
                }
 
                //row.getCell(3).setCellType(CellType.NUMERIC);
                //BigDecimal outFluid=new BigDecimal(NumberToTextConverter.toText(row.getCell(3).getNumericCellValue()));
                
                //获取第一个单元格的内容 
                row.getCell(0).setCellType(CellType.STRING);
                String po = row.getCell(0).getStringCellValue();
        
                
                //获取第二个单元格的内容
                //String itemNumber = row.getCell(1).getStringCellValue();
                row.getCell(1).setCellType(CellType.STRING);
                String itemNumber = row.getCell(1).getStringCellValue();
                //Integer itemNumber=new Integer(NumberToTextConverter.toText(row.getCell(1).getNumericCellValue()));
                
                
                //获取第三个单元格的内容
                String materielNumber = row.getCell(2).getStringCellValue();
                //获取第四个单元格的内容
                String materielName = row.getCell(3).getStringCellValue();
                //获取第五个单元格的内容
                String purchaseDate = row.getCell(4).getStringCellValue();
                //获取第六个单元格的内容
                String quantity = row.getCell(5).getStringCellValue(); 
                //获取第七个单元格的内容
                String unit = row.getCell(6).getStringCellValue();
                //获取第八个单元格的内容
                String price = row.getCell(7).getStringCellValue();
                //获取第九个单元格的内容
                String totalPrice = row.getCell(8).getStringCellValue(); 
                //获取第十个单元格的内容
                String currency = row.getCell(9).getStringCellValue();
                
                SkdMaterial material = new SkdMaterial();
                material.setPo(po);
                material.setItemNumber(itemNumber);
                material.setMaterielNumber(materielNumber);
                material.setMaterielName(materielName);
                material.setPurchaseDate(purchaseDate); //采购日期
                material.setQuantity(quantity);
                material.setUnit(unit); //单位
                material.setPrice(price); //单价
                material.setTotalPrice(totalPrice);//总价
                material.setCurrency(currency); //币种
                skdMaterialList.add(material);
            }
 
            
            for(SkdMaterial skdMaterial:skdMaterialList){
                /**
                 * 判断数据库表中是否存在用户记录,若存在,则更新,不存在,则保存记录
                 */
                count = skdMaterialMapper.selectCount(skdMaterial.getPo(),skdMaterial.getItemNumber());
 
                
                if(count == 0){
                	successNum++; //成功的条数
                    skdMaterialMapper.insertSelective(skdMaterial);
                }else{
                	repeatNum++;//重复的条数
                	skdMaterialMapper.updateByPrimaryKeySelective(skdMaterial);
                }
            }
        }
        
        map.put("total", total); //总共导入的条数
        map.put("successNum", successNum); //成功导入的条数
        map.put("repeatNum", repeatNum); //重复的的条数
        
        return map;
    }

2.4、使用

前端页面
在这里插入图片描述

准备导入的excel数据
在这里插入图片描述

点击“选择“按钮,弹出弹框,选择刚刚创建的文件,并上传文件。
实现的效果如下:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值