工作需要用java操作Excel,现在网上搜索了一下,决定选取POI包来操作。pom内容如下:

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.8</version>
        </dependency>

两个版本需要一致,否则会出错。

excel 03和07版本对应不同的操作类,分别是HSSFWorkbook和XSSFWorkbook。他们都继承自接口Workbook,所以在打开文件的时候,判断是哪一个版本,然后使用Workbook操作:

private static Workbook createWorkBook(String path) {
        try {
            InputStream in = new FileInputStream(path);
            if (!in.markSupported()) {
                in = new PushbackInputStream(in, 8);
            }
            if (POIFSFileSystem.hasPOIFSHeader(in)) {
                return new HSSFWorkbook(in);
            }
            if (POIXMLDocument.hasOOXMLHeader(in)) {
                return new XSSFWorkbook(OPCPackage.open(in));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new IllegalArgumentException("打开excel文件(" + path + ")错误");
    }

相应的Sheet,Row 和 Cell也都使用最上层的接口类:

private static Sheet getSheetByName(Workbook workbook, String s) {
        Sheet sheet = workbook.getSheet(s);
        if (sheet == null)
            sheet = workbook.createSheet(s);
        return sheet;
    }

private static Row getRowFromSheet(Sheet sheet, int rowNum) {
        Row row;
        row = sheet.getRow(rowNum);
        if (row != null)
            return row;
        else {
            row = sheet.createRow(rowNum);
            return row;
        }
    }

以Sheet为例, workbook.getSheet(i)是获得第i个sheet表单,如果不存在,则返回空。 workbook.createSheet(i)是创建表单,会覆盖原有表单。

从Cell中读取数据,有时候使用poi读取出来的单元格式会和在excel中看到的不一样。所以在读取数据时需要多判断一下类型,在poi源码的基础上修改一下:

private static String handleCellV1(Cell cell, int type) { // 读取日期形式单元格数据,返回字符串数据
        String var1 = null;
        int cellType = cell.getCellType();
        switch (cellType) {
            case 0: // numeric
                if (DateUtil.isCellDateFormatted(cell)) { // 如果是日期格式
                    SimpleDateFormat sdf = null;
                    if (type == 1) {
                        sdf = new SimpleDateFormat(DATE); // String DATE = "yyyy-MM-dd";
                    } else {
                        sdf = new SimpleDateFormat(TIME);
                    }
                    Date date = cell.getDateCellValue();
                    var1 = sdf.format(cell.getDateCellValue());
                } else {                                        // 有时候也会变成数字格式
                    String res = String.valueOf(cell.getNumericCellValue());
                    BigDecimal bd = new BigDecimal(res);    // 数字格式在excel中都是double,所以需要去掉小数点后的数(直接int??)
                    res = bd.toPlainString();
                    String[] ss = res.split("\\.");

                    res = ss[0];
                    var1 = res;
                }
                break;
            case 1: // text
                var1 = cell.getStringCellValue();
                break;
            default: // #unknown cell type
                var1 = "Unknown Cell Type: " + cell.getCellType();
                var1 = null;
        }
        return var1;
    }

写入excel单元格数据,可以使普通的写入:

Row row = sheet.createRow(rowNum);
row.createCell().setCellValue("日期");

也可以写入公式:

row.createCell().setCellFormula("IF(B" + rowNum + "=\"初始\",(SUMIFS(F:F,E:E,E" + rowNum + ",C:C,C" + rowNum + ",D:D,D" + rowNum + ",B:B,\"初始\")" +
                "-SUMIFS(F:F,E:E,E" + rowNum + ",C:C,C" + rowNum + ",D:D,D" + rowNum + ",B:B,\"平\"))" +
                "/COUNTIFS(E:E,E" + rowNum + ",C:C,C" + rowNum + ",D:D,D" + rowNum + ",B:B,B" + rowNum + "),IF(B" + rowNum + "=\"开\",F" + rowNum + ",F" + rowNum + "))");

写入公示后读取公式的结果摸索了一阵,网上有两种说法:

FormulaEvaluator evaluator = new XSSFFormulaEvaluator((XSSFWorkbook)workbook);
 CellValue cellValue = evaluator.evaluate(cell1);
String res = cellValue.getStringValue();
try {
value = String.valueOf(cell.getNumericCellValue());
 } catch (IllegalStateException e) {
value = String.valueOf(cell.getRichStringCellValue());
}

尝试了之后发现都不能正确读出来。

后来无意中发现,需要手动把写入公式的excel文件打开再保存一下,就可以正常读取。保存之后,在知道类型的情况下直接使用简单语句:

row.getCell(9).getNumericCellValue();

写入excel文件:

FileOutputStream fout = null;
        Workbook workbook = null;// 创建工作薄

        try {
            workbook = createWorkBook(dir + filename);
//            workbook = createWorkBook(dir+"test123.xlsx");
//            workbook = new XSSFWorkbook();
            Sheet sheet0 = getSheetByName(workbook, sheet1Name);
            Sheet sheet1 = getSheetByName(workbook, sheet2Name);

           //       ....      //

            fout = new FileOutputStream(dir + filename);
//            fout = new FileOutputStream(dir + "test123.xlsx");
            workbook.write(fout);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fout != null) {
                    fout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

java, poi, excel的更多相关文章

  1. java POI excel 导出复合样式(一个单元格两个字体)

    前言:java poi 导出 excel 时,需要设置一个单元格有多个字体样式,有点类似于富文本. 想要达到的效果(一个单元格里): 我使用的 poi 版本是 <dependency> & ...

  2. java POi excel 写入大批量数据

    直接贴代码: package jp.co.misumi.mdm.batch.common.jobrunner; import java.io.File; import java.io.FileNotF ...

  3. java poi excel 生成表格的工具封装

    效果如下: 代码如下: import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import ...

  4. Java POI Excel 导入导出

    这个东西很容易懂,不是特别难,难就难在一些复杂的计算和Excel格式的调整上. 近期写了一个小列子,放上来便于以后使用. POI.jar下载地址:http://mirror.bit.edu.cn/ap ...

  5. java POI Excel 单元格样式

    正如Html需要CSS一样,我们的POI生成的Excel同样需要样式才能更完美的表现我们的数据.下面还是从简单的例子出发,学习和了解POI的样式设计. 一.我的位置. 1 package com.my ...

  6. java poi excel操作 下拉菜单 及数据有效性

    1 private InputStream updateTemplateStyleHSSF(InputStream inputStream,CsCustCon csCustCon) throws IO ...

  7. java poi excel导入模板设置下拉框

    import org.apache.poi.hssf.usermodel.DVConstraint; import org.apache.poi.hssf.usermodel.HSSFCell; im ...

  8. java poi Excel导入 整数浮点数转换问题解决

    /**     * 获取单元格数据     */    protected static String getCellValue(Cell cell) {        String cellValu ...

  9. java poi excel操作 把第一列放到最后去

    @Override public void adjustExcleColumnPosition(String filePath,int col) throws Exception{ File file ...

随机推荐

  1. 关于谷歌浏览器 表单元素获取焦点后自动增加外边线的问题解决CSS代码

    input,textarea:focus { outline: none;} /*去除表单元素默认边框*/

  2. 寻找研究基于NS2研究覆盖网络的小伙伴:)

    如题,本人菜鸟刚刚入门,想找些基于NS2研究覆盖网络方面的小伙伴,具体点是关于覆盖网络中QoS服务调度方法方面的,有的小伙伴可以留下联系方式,或者加我QQ:245939069  :P:P:P

  3. Linux中查看文件编码

    在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱 ...

  4. 对于unallocated space的翻译 我想说几句话

    在sqlserver中,当我们使用sp_spaceused查看数据库空间使用情况的时候 会看到属性unallocated space.所有的中文翻译都是“未保留供数据库对象使用的数据库空间”, 作为中 ...

  5. 腾讯优测优分享 | 探索react native首屏渲染最佳实践

    腾讯优测是专业的移动云测试平台,旗下的优分享不定时提供大量移动研发及测试相关的干货~ 此文主要与以下内容相关,希望对大家有帮助. react native给了我们使用javascript开发原生app ...

  6. css+div

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  7. Learning to write a compiler

    http://stackoverflow.com/questions/1669/learning-to-write-a-compiler?rq=1 Big List of Resources: A N ...

  8. mvc 4 razor语法讲解和使用

    1.这里的  @{Layout="文件路径";}  代码块指定了整个项目默认所使用的布局文件(如图:) @RenderBody()对于所有的页面默认的情况下都会使用这个布局(Web ...

  9. 在Windows上,迁移VisualSVN server

    最近在搭建自动化测试框架,顺便了解了一下SVN的搭建.对于一般的使用场景,VisualSVN还是挺方便的,而且上手特别快. 由于是第一个demo,后期要迁移到其他服务器上面,所以就熟悉了一下serve ...

  10. Flume1.5.0的安装、部署、简单应用(含伪分布式、与hadoop2.2.0、hbase0.96的案例)

    目录: 一.什么是Flume? 1)flume的特点 2)flume的可靠性 3)flume的可恢复性 4)flume 的 一些核心概念 二.flume的官方网站在哪里? 三.在哪里下载? 四.如何安 ...