Spring MVC导入Excel(POI)

一、效果如下

导入Excel

二、写代码前要引入依赖

1. commons-fileupload

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

文件上传是项目开发中最常见的功能,为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data,只有这样浏览器才会把用户选择的文件以二进制数据发送给服务器。 Spring MVC为文件上传提供了直接的支持(即插即用的MultipartResolver),Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。因此,SpringMVC的文件上传需要依赖Apache Commons FileUpload的组件。

SpringMVC.xml配置

<!-- 多部分文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--定义上传的最大大小,单位为byte-->
    <property name="maxUploadSize" value="104857600" />
    <property name="maxInMemorySize" value="4096" />
    <!-- 设置默认编码 -->
    <property name="defaultEncoding" value="UTF-8"></property>
</bean>

2. Apache POI

此外需要添加Apache POI依赖,Apache POI是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。

<!--添加ApachePOI依赖-->
<!--导出03excel支持-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.11</version>
</dependency>
<!--导出07支持-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.11</version>
</dependency>

三、前端JSP页面
<div class="box-tools">
	<form method="post" enctype="multipart/form-data" action="/product/upload">
        <input type="file" id="upload" name="mulFile" class="btn bg-olive btn-xs" style="width:180px"/>
        <br />
        <input type="submit" value="导入" class="btn bg-olive btn-xs" style="width:80px"/>
    </form>
</div>

使用的是Spring Mvc框架提供对象MultipartFile,该对象可以作为控制器方法的参数,参数的名称必须和表单file元素的name属性取值一致。


四、Controller层

编写Ctroller层,Ctroller使用Excel工具类,读取Excel数据封装为实体类对象,再调用Service插入方法,实现导入功能。

/**
 * @param request 请求对象
 * @param mulFile 参数名称必须与页面元素名称一致:<input type="file" name="mulFile">
 * @throws Exception
 */
@RequestMapping("/upload")
public String upload(HttpServletRequest request, MultipartFile mulFile) throws Exception {

    InputStream in = mulFile.getInputStream();
    //判断是否上传文件
    if (in != null) {

        String fileName = mulFile.getOriginalFilename();
        //判断是否为excel类型文件
        if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) {
            throw new Exception("文件不是excel类型");
        }
        else {
            List<List<Object>> lists = ReadExcelUtil.getDataFromExcel_07(in);
            for (List<Object> list : lists) {

                Product product = new Product();
                product.setId(Long.valueOf(list.get(0).toString()));
                product.setProductNum((String) list.get(1));
                product.setProductName((String) list.get(2));
                product.setCityName((String) list.get(3));
                product.setDepartureTime(Timestamp.valueOf(list.get(4).toString()));
                product.setProductPrice(Double.valueOf(list.get(5).toString()));
                product.setProductDesc((String) list.get(6));
                product.setProductStatus(Integer.valueOf(list.get(7).toString()));

                // 调用service,保存
               productService.saveProduct(product);
            }
        }
        return "redirect:/product/findAll";
    }
    return "";
}

注意list<Object>如何封装为实体类,Object->String, Object->Long, Object->Double, Obejct->Integer, Object->Timestamp


五、工具类

1. 2003 Excel

/**
* @Description(2003 Excel 导入)
 * @Param: [in]
 * @return: java.util.List<java.util.List < java.lang.Object>>
 * @Date: 2019/5/18
 */
public static List<List<Object>> getDataFromExcel(InputStream in) throws Exception {

    List<List<Object>> list = new ArrayList<List<Object>>();
    Workbook workbook = new HSSFWorkbook(in);

    //遍历sheet
    for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
        Sheet sheet = workbook.getSheetAt(i);
        if (sheet == null) {
            continue;
        }
        //遍历某个sheet行
        for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
            Row row = sheet.getRow(j);
            //跳过空行和每个sheet第一行,如果没有表头需要修改
            if (row == null || row.getFirstCellNum() == j) {
                continue;
            }
            List<Object> li = new ArrayList<Object>();
            for (int m = row.getFirstCellNum(); m < row.getLastCellNum(); m++) {
                Cell cell = row.getCell(m);
                li.add(getRightTypeCell(cell));
            }
            list.add(li);
        }
    }
    return list;
}

2. 2007 Excel

/**
 * @Description(2007 Excel 导入)
 * @Param: [in]
 * @return: java.util.List<java.util.List < java.lang.Object>>
 * @Date: 2019/5/18
 */
public static List<List<Object>> getDataFromExcel_07(InputStream in) throws Exception {

    List<List<Object>> list = new ArrayList<List<Object>>();
    Workbook workbook = new XSSFWorkbook(in);

    //遍历sheet
    for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
        Sheet sheet = workbook.getSheetAt(i);
        if (sheet == null) {
            continue;
        }
        //遍历某个sheet行
        for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
            Row row = sheet.getRow(j);
            //跳过空行和每个sheet第一行,如果没有表头需要修改
            if (row == null || row.getFirstCellNum() == j) {
                continue;
            }
            List<Object> li = new ArrayList<Object>();
            for (int m = row.getFirstCellNum(); m < row.getLastCellNum(); m++) {
                Cell cell = row.getCell(m);
                li.add(getRightTypeCell(cell));
            }
            list.add(li);
        }
    }
    return list;
}

3. 读取Excel单元格的值(03/07都可用)

/**
 * @Description(把Cell原有数据转换成String类型 2003/2007 都可用)
 * @Param: [cell]
 * @return: java.lang.String
 * @Date: 2019/5/18
 */
public static String getRightTypeCell(Cell cell) {

    if (cell == null) {
        return "";
    }

    String cellString = "";
    switch (cell.getCellType()) {
        case HSSFCell.CELL_TYPE_STRING: // 字符串
            cellString = cell.getStringCellValue();
            break;
        case HSSFCell.CELL_TYPE_NUMERIC: // 数字
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                //用于转化为日期格式
                Date d = cell.getDateCellValue();
                DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                cellString = formater.format(d);
            } else {
                //DecimalFormat df = new DecimalFormat("###");  只保留数字的整数部分
                // 用于格式化数字,只保留两位小数
                DecimalFormat df = new DecimalFormat("#.##");
                cellString = df.format(cell.getNumericCellValue());
            }
            break;
        case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
            cellString = String.valueOf(cell.getBooleanCellValue());
            break;
        case HSSFCell.CELL_TYPE_FORMULA: // 公式
            cellString = String.valueOf(cell.getCellFormula());
            break;
        case HSSFCell.CELL_TYPE_BLANK: // 空值
            cellString = "";
            break;
        case HSSFCell.CELL_TYPE_ERROR: // 故障
            cellString = "";
            break;
        default:
            cellString = "ERROR";
            break;
    }
    return cellString;
}

六、补充

1. DecimalFormat 保留小数

0: 
    比实际数字的位数多,不足的地方用0补上。
    new DecimalFormat("00.00").format(3.14)  //结果:03.14
    new DecimalFormat("0.000").format(3.14)  //结果: 3.140
    new DecimalFormat("00.000").format(3.14)  //结果:03.140
    比实际数字的位数少:整数部分不改动,小数部分,四舍五入
    new DecimalFormat("0.000").format(13.146)  //结果:13.146
    new DecimalFormat("00.00").format(13.146)  //结果:13.15
    new DecimalFormat("0.00").format(13.146)  //结果:13.15
#: 
    比实际数字的位数多,不变。
    new DecimalFormat("##.##").format(3.14)  //结果:3.14
    new DecimalFormat("#.###").format(3.14)  //结果: 3.14
    new DecimalFormat("##.###").format(3.14)  //结果:3.14
    比实际数字的位数少:整数部分不改动,小数部分,四舍五入
    new DecimalFormat("#.###").format(13.146)  //结果:13.146
    new DecimalFormat("##.##").format(13.146)  //结果:13.15
    new DecimalFormat("#.##").format(13.146)  //结果:13.15

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值