Java 解析Excel文件为JSON

Excel转Json的需求

反正我对SSM基本不会的情况下来到现在这家公司,都是90后,感觉很好。第二天就给我开发任务,就是把用户上传的Excel文件转成JSON返回给前台用于大屏的数据展示。

解决方案

  • 方案1:百度一下,全是Java使用jxl去做的,我一开始也尝试这样做,但是卡死在一个地方,我们公司的SSM框架用户上传的File是MultipartFile的,它的流InputStream在构造Workbook时传递InputStream并不起作用,本地文件FileInputStream就可以,不知道是不是我无能,反正我没辙了。这东西感觉本来就是javase的。
  • 方案2:问了个大神,告诉我一个词叫POI。捣鼓了一天,终于解决了,对,解决方案就是 Apache的 POI(我的选择方案)

Excel的xls和xlsx的差别

  • xls 是Excel 2007以下版本的后缀名,但是所有excel都能打开,对应POI里HSSFWorkbook。
  • xlsx 是Excel 2007及以上版本的后缀名,对应POI里XSSFWorkbook。

需要的JAR包

如果只需要支持 xlspoi-3.9.jar如果只需要支持 xlsxpoi-ooxml-3.8.jarpoi-ooxml-schemas-3.10-FINAL.jarxmlbeans.jardom4j-1.6.1-hudson-1.jar

我的工具代码

import com.alibaba.fastjson.JSON;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by huangzheng on 2016/11/29.
 */
public class ExcelUtils {
    /**
     * 解决思路:采用Apache的POI的API来操作Excel,读取内容后保存到List中,再将List转Json(推荐Linked,增删快,与Excel表顺序保持一致)
     *
     *          Sheet表1  ————>    List1<Map<列头,列值>>
     *          Sheet表2  ————>    List2<Map<列头,列值>>
     *
     * 步骤1:根据Excel版本类型创建对于的Workbook以及CellSytle
     * 步骤2:遍历每一个表中的每一行的每一列
     * 步骤3:一个sheet表就是一个Json,多表就多Json,对应一个 List
     *       一个sheet表的一行数据就是一个 Map
     *       一行中的一列,就把当前列头为key,列值为value存到该列的Map中
     *
     *
     * @param file  SSM框架下用户上传的Excel文件
     * @return Map  一个线性HashMap,以Excel的sheet表顺序,并以sheet表明作为key,sheet表转换json后的字符串作为value
     * @throws IOException
     */
    public static LinkedHashMap<String,String> excel2json(MultipartFile file) throws IOException {

        System.out.println("excel2json方法执行....");

        // 返回的map
        LinkedHashMap<String,String> excelMap = new LinkedHashMap<>();

        // Excel列的样式,主要是为了解决Excel数字科学计数的问题
        CellStyle cellStyle;
        // 根据Excel构成的对象
        Workbook wb;
        // 如果是2007及以上版本,则使用想要的Workbook以及CellStyle
        if(file.getOriginalFilename().endsWith("xlsx")){
            System.out.println("是2007及以上版本  xlsx");
            wb = new XSSFWorkbook(file.getInputStream());
            XSSFDataFormat dataFormat = (XSSFDataFormat) wb.createDataFormat();
            cellStyle = wb.createCellStyle();
            // 设置Excel列的样式为文本
            cellStyle.setDataFormat(dataFormat.getFormat("@"));
        }else{
            System.out.println("是2007以下版本  xls");
            POIFSFileSystem fs = new POIFSFileSystem(file.getInputStream());
            wb = new HSSFWorkbook(fs);
            HSSFDataFormat dataFormat = (HSSFDataFormat) wb.createDataFormat();
            cellStyle = wb.createCellStyle();
            // 设置Excel列的样式为文本
            cellStyle.setDataFormat(dataFormat.getFormat("@"));
        }

        // sheet表个数
        int sheetsCounts = wb.getNumberOfSheets();
        // 遍历每一个sheet
        for (int i = 0; i < sheetsCounts; i++) {
            Sheet sheet = wb.getSheetAt(i);
            System.out.println("第" + i + "个sheet:" + sheet.toString());

            // 一个sheet表对于一个List
            List list = new LinkedList();

            // 将第一行的列值作为正个json的key
            String[] cellNames;
            // 取第一行列的值作为key
            Row fisrtRow = sheet.getRow(0);
            // 如果第一行就为空,则是空sheet表,该表跳过
            if(null == fisrtRow){
                continue;
            }
            // 得到第一行有多少列
            int curCellNum = fisrtRow.getLastCellNum();
            System.out.println("第一行的列数:" + curCellNum);
            // 根据第一行的列数来生成列头数组
            cellNames = new String[curCellNum];
            // 单独处理第一行,取出第一行的每个列值放在数组中,就得到了整张表的JSON的key
            for (int m = 0; m < curCellNum; m++) {
                Cell cell = fisrtRow.getCell(m);
                // 设置该列的样式是字符串
                cell.setCellStyle(cellStyle);
                cell.setCellType(Cell.CELL_TYPE_STRING);
                // 取得该列的字符串值
                cellNames[m] = cell.getStringCellValue();
            }
            for (String s : cellNames) {
                System.out.print("得到第" + i +" 张sheet表的列头: " + s + ",");
            }
            System.out.println();

            // 从第二行起遍历每一行
            int rowNum = sheet.getLastRowNum();
            System.out.println("总共有 " + rowNum + " 行");
            for (int j = 1; j <= rowNum; j++) {
                // 一行数据对于一个Map
                LinkedHashMap rowMap = new LinkedHashMap();
                // 取得某一行
                Row row = sheet.getRow(j);
                int cellNum = row.getLastCellNum();
                // 遍历每一列
                for (int k = 0; k < cellNum; k++) {
                    Cell cell = row.getCell(k);

                    cell.setCellStyle(cellStyle);
                    cell.setCellType(Cell.CELL_TYPE_STRING);
                    // 保存该单元格的数据到该行中
        rowMap.put(cellNames[k],cell.getStringCellValue());
                }
                // 保存该行的数据到该表的List中
                list.add(rowMap);
            }
            // 将该sheet表的表名为key,List转为json后的字符串为Value进行存储
            excelMap.put(sheet.getSheetName(),JSON.toJSONString(list,false));
        }

        System.out.println("excel2json方法结束....");

        return excelMap;
    }

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java技术学习之道

Spring AOP原理分析一次看懂

1734
来自专栏游戏杂谈

webgame开发中的文件加密

一般的webgame中都会对资源、消息进行加密,这里只是简单记录一下对文件的加密过程。

1853
来自专栏小灰灰

spring-boot & zxing 搭建二维码服务

使用zxing提供二维码生成解析服务 搭建一个二维码的生成 & 解析服务, 使用java web对外提供http调用,返回base64格式的二维码图片 1. ...

1.2K6
来自专栏GIS讲堂

excel中提取中文拼音

概述:在工作时,有时候会用到汉语拼音,本文讲述如何在Excel中通过vba程序提取汉字的拼音。

2163
来自专栏ccylovehs

Web服务器与客户端三种http交互方式

近期在对接项目时用到http方式与第三方交互数据,由于中间沟通不足导致走了不少弯路,至此特意花了点时间总结服务端与客户端数据交互的方式,本地搭建两个项目一个作为...

1K1
来自专栏阮一峰的网络日志

Redux 入门教程(一):基本用法

一年半前,我写了《React 入门实例教程》,介绍了 React 的基本用法。 React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两...

4715
来自专栏SpringBoot

java微信公众号开发入门(3)--简单消息回复

1884
来自专栏Java成神之路

Java微信公众平台开发_07_JSSDK图片上传

(2)对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成...

3871
来自专栏xingoo, 一个梦想做发明家的程序员

文件上传之Apache commons fileupload使用

  文件上传的方法主要目前有两个常用的,一个是SmartUpload,一个是Apache的Commons fileupload.   我们这里主要介绍下第二个的...

2729
来自专栏Jaycekon

深入浅出Redis-Spring整合Redis

概述:    在之前的博客中,有提到过Redis 在服务端的一些相关知识,今天主要讲一下Java 整合Redis的相关内容。    下面是Jedis 的相关依赖...

3679

扫码关注云+社区

领取腾讯云代金券