上传excel文件实现批量导入数据及导出数据为excel文件

前段时间要做一个excel表格的上传下载功能,上网找了各种资料及源码,最后借鉴别人的代码及思路完成了符合自己需求的代码,总结一下excel的上传下载实质是通过第三方的类库比如poi,jxl等对excel单元格的设置与读写,通过类库的api,你可以发现各种各样的操作excel的方法,基本上只要你能在office的excel上进行的基本操作通过代码都能实现。

上传文件:

首先新建一个工具类,我命名为ImportExcelUtil,代码如下:

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;
        
        list = new ArrayList<List<Object>>();
        //遍历Excel中所有的sheet
        int s=work.getNumberOfSheets();
        for (int i = 0; i < work.getNumberOfSheets(); i++) {
            sheet = work.getSheetAt(i);
            if(sheet==null){continue;}
            int s2=sheet.getLastRowNum();
            //遍历当前sheet中的所有行
            for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
                row = sheet.getRow(j);
                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);
                    li.add(this.getCellValue(cell));
                }
                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;
    }
}

这个工具类是支持2003和2007的,excel2003和2007所用到的包是不一样的,所以如何你的工程师maven构建的话需要在pom.xml上引入下面两个包:

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.14</version>
</dependency>

工具类写好以后,接下来就可以在具体业务逻辑实现方法里调用了,我这边有个上传的controller

public class UploadExcelControl {
    @Autowired
    DetailInfoVoService detailInfoVoService;
    /**
     * 描述:通过传统方式form表单提交方式导入excel文件
     * @param request
     * @throws Exception
     */
    @RequestMapping(value="upload.do",method={RequestMethod.GET,RequestMethod.POST})
    public  String  uploadExcel(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;  
        System.out.println("通过传统方式form表单提交方式导入excel文件!");
        
        InputStream in =null;
        List<List<Object>> listob = null;
        MultipartFile file = multipartRequest.getFile("upfile");
        if(file.isEmpty()){
            throw new Exception("文件不存在!");
        }
        in = file.getInputStream();
        listob = new ImportExcelUtil().getBankListByExcel(in,file.getOriginalFilename());
        in.close();
        //因为要导入的excel比较特殊,不是常规的一行类别,其他行都是数据,所以我需要根据具体模板来读取excel
        for (int i = 0; i < listob.size(); i+=11) {
            DetailInfoVo vo = new DetailInfoVo();
            vo.setSiteId(String .valueOf(listob.get(i).get(1)));
            vo.setSiteName(String.valueOf(listob.get(i).get(3)));
            vo.setSitePhone(String.valueOf(listob.get(i).get(5)));
            vo.setSiteAddress(String.valueOf(listob.get(i+1).get(1)));
            vo.setIsOpened(String.valueOf(listob.get(i+1).get(5)));
            vo.setSiteClass(String.valueOf(listob.get(i+2).get(1)).split(",")[0]);
            vo.setSiteScale(String.valueOf(listob.get(i+2).get(1)).split(",")[1]);
            vo.setSiteDetail(String.valueOf(listob.get(i+3).get(0)));
            vo.setIsPartnership(String.valueOf(listob.get(i+4).get(1)));
            vo.setReason(String.valueOf(listob.get(i+5).get(0)));
            vo.setBossName(String.valueOf(listob.get(i+7).get(1)));
            vo.setBossAge(String.valueOf(listob.get(i+7).get(3)));
            vo.setBossJiguan(String.valueOf(listob.get(i+7).get(5)));
            vo.setBossYear(String.valueOf(listob.get(i+8).get(1)));
            vo.setBossPeople(String.valueOf(listob.get(i+8).get(3)));
            vo.setOthers(String.valueOf(listob.get(i+9).get(1)));
            vo.setEventLog(String.valueOf(listob.get(i+10).get(0)));
            int resultCode=detailInfoVoService.insert(vo);
            if(resultCode!=0){
                System.out.println("=======");
            }
        }
        return "result";
    }
}

前台使用的是form表单提交的方式,首先在jsp页面定义一个form,action指向对应的controller

<form class="form-inline clearfix " method="POST" enctype="multipart/form-data" id="form1" action="../uploadExcel/upload.do"> 
      <div class="row">
         <div class="form-group col-xs-12">
           <label class="fl">上传文件: </label> 
          <input type="file" class="form-control" id="upfile" name="upfile"> 
        </div> 
      </div>
 </form> 

上传的内容就介绍完了,相比上传,下载更加容易。
导出excel:
=======
新建一个工具类ExportExcelUtil:

public class ExportExcelUtil {
    
    /**
     * 描述:根据文件路径获取项目中的文件
     * @param fileDir 文件路径
     * @return
     * @throws Exception
     */
    public  File getExcelDemoFile(String fileDir) throws Exception{
        String classDir = null;
        String fileBaseDir = null;
        File file = null;
        classDir = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
        fileBaseDir = classDir.substring(0, classDir.lastIndexOf("classes"));
        
        file = new File(fileBaseDir+fileDir);
        if(!file.exists()){
            throw new Exception("模板文件不存在!");
        }
        return file;
    }
    
    public  Workbook writeNewExcel(File file,String sheetName,List<DetailInfoVo> lis) throws Exception{
        Workbook wb = null;
        Row row = null; 
        Cell cell = null;
        
        FileInputStream fis = new FileInputStream(file);
        wb = new ImportExcelUtil().getWorkbook(fis, file.getName());    //获取工作薄
        Sheet sheet = wb.getSheet(sheetName);
        
        //循环插入数据
        int lastRow = sheet.getLastRowNum()+1;    //插入数据的数据ROW
        CellStyle cs = setSimpleCellStyle(wb);    //Excel单元格样式
        for (int i = 0; i < lis.size(); i++) {
            row = sheet.createRow(lastRow+i); //创建新的ROW,用于数据插入
            
            //按项目实际需求,在该处将对象数据插入到Excel中
            DetailInfoVo vo  = lis.get(i);
            if(null==vo){
                break;
            }
            //Cell赋值开始
            cell = row.createCell(0);
            cell.setCellValue(vo.getSiteId());
            cell.setCellStyle(cs);
            
            cell = row.createCell(1);
            cell.setCellValue(vo.getSiteName());
            cell.setCellStyle(cs);
            
            cell = row.createCell(2);
            cell.setCellValue(vo.getSiteAddress());
            cell.setCellStyle(cs);
            
            cell = row.createCell(3);
            cell.setCellValue(vo.getSiteClass());
            cell.setCellStyle(cs);
            
            cell = row.createCell(4);
            cell.setCellValue(vo.getSiteScale());
            cell.setCellStyle(cs);
            
            cell = row.createCell(5);
            cell.setCellValue(vo.getIsPartnership());
            cell.setCellStyle(cs);
            
            cell = row.createCell(6);
            cell.setCellValue(vo.getSitePhone());
            cell.setCellStyle(cs);
            
            cell = row.createCell(7);
            cell.setCellValue(vo.getIsOpened());
            cell.setCellStyle(cs);
        }
        return wb;
    }
    
    /**
     * 描述:设置简单的Cell样式
     * @return
     */
    public  CellStyle setSimpleCellStyle(Workbook wb){
        CellStyle cs = wb.createCellStyle();
        
        cs.setBorderBottom(CellStyle.BORDER_THIN); //下边框
        cs.setBorderLeft(CellStyle.BORDER_THIN);//左边框
        cs.setBorderTop(CellStyle.BORDER_THIN);//上边框
        cs.setBorderRight(CellStyle.BORDER_THIN);//右边框

        cs.setAlignment(CellStyle.ALIGN_CENTER); // 居中
        
        return cs;
    }

}

具体的实现类如下

public class ExportExcelControl {
    @Autowired
    DetailInfoVoService detailInfoVoService;
    @RequestMapping(value="export.do",method={RequestMethod.GET,RequestMethod.POST})
    public  String  exportExcel(HttpServletRequest request,HttpServletResponse response) throws Exception {
        OutputStream os = null;  
        Workbook wb = null;    //工作薄
        List<DetailInfoVo> list=detailInfoVoService.findList();
        try {
            List<DetailInfoVo> lo = new ArrayList<DetailInfoVo>();
            for (int i = 0; i < list.size(); i++) {
                //根据具体需求向excel即将导出的vo模型填充数据
                DetailInfoVo vo = new DetailInfoVo();
                vo.setSiteId(list.get(i).getSiteId());
                vo.setSiteName(list.get(i).getSiteName());
                vo.setSiteAddress(list.get(i).getSiteAddress());
                vo.setSiteClass(list.get(i).getSiteClass());
                vo.setSiteScale(list.get(i).getSiteScale());
                vo.setIsPartnership(list.get(i).getIsPartnership());
                vo.setSitePhone(list.get(i).getSitePhone());
                vo.setIsOpened(list.get(i).getIsOpened());
                lo.add(vo);
            }
            
            //导出Excel文件数据
            ExportExcelUtil util = new ExportExcelUtil();
            File file =util.getExcelDemoFile("/ExcelDemoFile/模板.xlsx");
            String sheetName="sheet1";  
            wb = util.writeNewExcel(file, sheetName,lo); 
            
            String fileName="导出信息.xlsx";
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
            os = response.getOutputStream();
            wb.write(os);  
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            os.flush();
            os.close();
            wb.close();
        } 
        return null;
    }
}

更详细的代码我就不贴了,主要是上传下载这个思路大家要理清,原理搞清楚了啥都会搞了,比如加特技,通过poi提供的api让你的excel更加炫酷。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容