Apache POI 实现对 Excel 文件读写

本文介绍如何使用 Apache POI 库在 Java 中读写 Microsoft Excel 文件。通过示例展示了创建 Excel 文件、设置样式及从 Excel 文件中读取数据的方法。

1. Apache POI 简介

     Apache POI是Apache软件基金会的开放源码函式库。

     提供API给Java应用程序对Microsoft Office格式档案读和写的功能。

     老外起名字总是很谦虚,POI为(Poor Obfuscation Implementation)的首字母缩写,意为“可怜的模糊实现”。

     如果你查看过 Apache 开源库中的任意项目的源码,你会发现恰到好处的设计模式、高内聚低耦合的模块关系、

     到位的接口抽象、优雅的实现方式,这样的一些特点。

     o(︶︿︶)o 唉 需要多严谨的思维、多大的代码实现量,多少项目的设计积累,才能达到那样的高度?

     POI 中主要提供的读写 Microsoft Office 功能点如下:

  •  HSSF -- 提供读写Microsoft Excel格式档案的功能。
  •  XSSF -- 提供读写Microsoft Excel OOXML格式档案的功能。
  •  HWPF -- 提供读写Microsoft Word格式档案的功能。
  •  HSLF -- 提供读写Microsoft PowerPoint格式档案的功能。
  •  HDGF -- 提供读写Microsoft Visio格式档案的功能。

     本文借一次使用POI 实现读写 Excel 的过程,记述其中具体POI运用的方式。

     由搜索引擎点进来的同学,上面这一句话就是本文的主旨句。若能解决你问题,请往下细看。

     项目中使用的是最新的 poi-3.14-20160307.jar,百度云地址:http://pan.baidu.com/s/1bnWFWg3 密码: kame

     Oschina  收录地址:https://www.oschina.net/p/poi

     官方 Demo : http://poi.apache.org/spreadsheet/examples.html#hssf-only

2.一点点实现前的设计

     因项目比较大,下面为单独新建工程后的例子。

   

3.POI 写 Excel

     上图左侧用例图为 POI 写 Excel

    a.getExcelData: 获取需要输出到Excel数据,这里的数据获取可以是从持久层,页面展示层......

      (例子中的数据为Mysql自有数据库中表help_categroy 表记录),其中的 JavaBean建立 与 数据库获取的过程这里就不说了。

      获取数据的数据类型是这样的 List<HelpCategory>    

     b.POI Write Workbook:这里才是关键的地方,使用POI 将数据实例化为 HSSFWorkbook。核心代码如下:

  Core Code

     获取JavaBean字段值作为表头,并设置表头的样式:

复制代码
        HSSFRow row = sheet.createRow(0);
        HSSFCell cell;
        HelpCategory category = new HelpCategory();
        Field[] fields = category.getClass().getDeclaredFields();
        for (int j = 0; j < fields.length; j++) {
            cell = row.createCell(j);
            cell.setCellValue(fields[j].getName());
            cell.setCellStyle(this.textAlignCenter);
        }
复制代码

     获取JavaBean HelpCategory 中字段的值填充到对应的表格中,并设置样式:

复制代码
     for (int i = 0; i < helpCategories.size(); i++) {
            category = helpCategories.get(i);
            row = sheet.createRow(i + 1);
            for (int k = 0; k < fields.length; k++) {
                Field field = fields[k];
                Object o = invokeGet(category, field.getName());
                cell = row.createCell(k);
                cell.setCellValue(o != null ? o.toString() : "");
                cell.setCellStyle((k == 0 || k == 1) ? this.textAlignCenter : this.textAlignLeft);
            }
        }
复制代码

      这里面用的了一点反射的东西,来获取javaBean属性的值。

      如果你觉得反射的效率有点差劲,可以自己构造一个Map数据集合,同样能达到这样的效果。

复制代码
  private Object invokeGet(Object o, String fieldName) {
        Method method = getGetMethod(o.getClass(), fieldName);
        try {
            return method.invoke(o, new Object[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Method getGetMethod(Class objectClass, String fieldName) {
        StringBuilder sb = new StringBuilder();
        sb.append("get");
        sb.append(fieldName.substring(0, 1).toUpperCase());
        sb.append(fieldName.substring(1));
        try {
            return objectClass.getMethod(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
复制代码

        同样你可以设置表格样式、边框样式:

复制代码
    private void createSheetStyle(HSSFWorkbook _workbook, HSSFSheet _sheet) {
        // 设置表字体
        HSSFFont font10 = _workbook.createFont();
        font10.setFontHeightInPoints((short) 12);
        font10.setFontName("黑体");
        // 设置表样
        this.textAlignCenter = getCellStyle(_workbook, font10, HSSFCellStyle.ALIGN_CENTER);
        this.textAlignLeft = getCellStyle(_workbook, font10, HSSFCellStyle.ALIGN_LEFT);
        // 设置列宽
        _sheet.setColumnWidth(0, 4000);
        _sheet.setColumnWidth(1, 4000);
        _sheet.setColumnWidth(2, 10000);
        _sheet.setColumnWidth(3, 10000);
    }
复制代码

   上面的样式设置,如果还满足不了你的功能需求,更多的设置请参考博客:

   http://langhua9527.iteye.com/blog/388005

   http://blog.csdn.net/tolcf/article/details/48346697

4.POI 读 Excel

      上图左侧用例图为 POI 写 Excel

      a.getExcleFile:获取要读取的Excel文件...这里就不说了。(注意:判断获取的文件后缀名)

复制代码
        String fileName = excel.getName();
        int iIndex = fileName.lastIndexOf(".");
        String ext = (iIndex < 0) ? "" : fileName.substring(iIndex + 1).toLowerCase();
        if (!"xls,xlsx".contains(ext) || "".contains(ext)) {
            System.out.println("文件类型不是EXCEL!");
        }
复制代码

      b.POI Read Workbook:这里就是重点啦,使用POI读取Excel文件,解析并进行保存到你自己数据类型当中。

复制代码
           ArrayList<HelpCategory> categories = new ArrayList<>();
        try {
            POIFSFileSystem poifsFileSystem = new POIFSFileSystem(new FileInputStream(excel));
            HSSFWorkbook workbook = new HSSFWorkbook(poifsFileSystem);
            HSSFSheet sheet = workbook.getSheetAt(0);

            HelpCategory category = new HelpCategory();
            Field[] declaredField = category.getClass().getDeclaredFields();
            for (int k = 1; k <= sheet.getLastRowNum(); k++) {
                HSSFRow row = sheet.getRow(k);
                category = new HelpCategory();
                for (int j = 0; j < declaredField.length; j++) {
                    HSSFCell cell = row.getCell(j);
                    invokeSet(category, declaredField[j].getName(), cell.getStringCellValue());
                }
                categories.add(category);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
复制代码

       上面也同样用到了一些反射的东西,这里获取JavaBean 的set方法,来设置具体的属性。

复制代码
   public void invokeSet(Object o, String fieldName, Object value) {
        Method method = getSetMethod(o.getClass(), fieldName);
        try {
            method.invoke(o, new Object[]{value});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Method getSetMethod(Class objectClass, String fieldName) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = objectClass.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            StringBuffer sb = new StringBuffer();
            sb.append("set");
            sb.append(fieldName.substring(0, 1).toUpperCase());
            sb.append(fieldName.substring(1));
            Method method = objectClass.getMethod(sb.toString(), parameterTypes);
            return method;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值