java poi读取excel含小数列时,与excel显示不一样

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java poi读取excel含小数列时,与excel显示不一样相关的知识,希望对你有一定的参考价值。

如下截图为excel显示值,而我后台java程序却解析到如下值:0.0290.031...0.0160.0130000000000000010.0310.0099999999999999980.0120.0099999999999999980.0130000000000000010.015就是有些列像使用了函数,自动四舍五入了。我也尝试改excel列为文本格式,但依然某些列解析会出现小数点后面还有很长一串字符。如果我再手动将excel某些列值手动输入,又可以正常解析不知各位大侠有没有碰到过这种情况,怎么解决呀?

参考技术A 浮点型是有损精度的,可以用BigDecimal 参考技术B 按字符串处理,就不会 。。。。。。。按double,才会,JAVA的特点

java poi学习 Excel的读取与写

一、Excel的写操作

  在Excel为我们提供了两种文件类型.XLS和.XLSX文件,这两种文件的读取方式都是一致的.xls文件使用的是HSSF对象,.xlsx使用的是XSSF对象,因为两种方式是一样的,所以我们来看一个HSSF读取的例子

  1.导入maven

 <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <!--时间工具类-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.1</version>
        </dependency>

  2.Excel的写操作

  我们先看看我们最终要生成的表格:

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.usermodel.*;
import org.joda.time.DateTime;


import java.io.FileOutputStream;
public class Demo {


    public static void main(String[] args) throws Exception {
        showHSSF();
    }


    /**
     * 对HSSF表格文件进行写操作
     * 
     */
    public static void showHSSF() throws Exception {

        // 首先创建Excel 工作簿
        Workbook workbook=new HSSFWorkbook();

        // 在Excel工作簿中建一工作表,即创建sheet,取名为测试表格
        Sheet sheet=workbook.createSheet("测试表格");

        // 创建行,创建了2行
        //值为0表示第一行
        Row row1=sheet.createRow(0);

        //值为1表示第二行
        Row row2=sheet.createRow(1);

        //创建单元格样式
        CellStyle cellStyle=workbook.createCellStyle();
        //设置水平对齐的样式为居中对齐;
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        //设置垂直对齐的样式为居中对齐;
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        //创建单元格
        //这个单元格位置:1-1
        Cell row1Cell1=row1.createCell(0);
        //对单元格赋值
        row1Cell1.setCellValue("姓名");
        //设置样式
        row1Cell1.setCellStyle(cellStyle);

        //这个单元格位置:1-2
        Cell row1Cell2=row1.createCell(1);
        row1Cell2.setCellValue("年龄");
        row1Cell2.setCellStyle(cellStyle);

        //这个单元格位置:1-3,1-4的合并单元格
        Cell row1Cell3to4=row1.createCell(2);
        row1Cell3to4.setCellValue("课程");
        row1Cell3to4.setCellStyle(cellStyle);
        //合并单元格(4个参数,分别为起始行,结束行,起始列,结束列)
        //表格的行和列都是从0开始
        CellRangeAddress coursRegion = new CellRangeAddress(0, 0, 2, 3);
        sheet.addMergedRegion(coursRegion);


        //这个单元格位置:2-1
        Cell row2Cell1=row2.createCell(0);
        row2Cell1.setCellValue("小明");
        row2Cell1.setCellStyle(cellStyle);

        //这个单元格位置:2-2
        Cell row2Cell2=row2.createCell(1);
        row2Cell2.setCellValue(16);
        row2Cell2.setCellStyle(cellStyle);

        //这个单元格位置:2-3
        Cell row2Cell3=row2.createCell(2);
        row2Cell3.setCellValue("语文");
        row2Cell3.setCellStyle(cellStyle);

        //这个单元格位置:2-4
        Cell row2Cell4=row2.createCell(3);
        row2Cell4.setCellValue("数学");
        row2Cell4.setCellStyle(cellStyle);

        //这个单元格位置:1-5、2-5的合并单元格
        //要注意的是如果是行与行的合并,必须对第一行中的单元格赋值
        Cell row1to2Cell5=row1.createCell(4);
        String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
        row1to2Cell5.setCellValue(dateTime);
        row1to2Cell5.setCellStyle(cellStyle);

        //合并单元格
        //合并单元格(4个参数,分别为起始行,结束行,起始列,结束列)
        //表格的行和列都是从0开始
        CellRangeAddress timeRegion=new CellRangeAddress(0,1,4,4);
        sheet.addMergedRegion(timeRegion);

        // 输出文件
        FileOutputStream out = new FileOutputStream("E:\\\\static\\\\poi\\\\写操作测试工作簿.xls");
        workbook.write(out);
        // 操作结束,关闭文件
        out.close();
        System.out.println("文件生成成功");
    }
}

  HSSF文件和XSSF文件两种操作方式是一样的,但是二者又有很大的区别:HSSF写的速度很快,但是最多只能写65536条数据;XSSF能够写大量的数据,但是写的速度很慢,其次XSSF的写操作是直接在内存中写数据,写完后再复制到磁盘,这样就会造成内存溢出的问题,因此为了解决内存溢出问题,poi有为我们提供了一个SXSSF对象进行.xlsx文件的操作。

  由于文件是在内存中写的,所以我们需要清理一次内存的操作,关闭文件后添加代码:

((SXSSFWorkbook)workbook).dispose();

二、Excel的读操作

  读操作两个文件没有任何区别,但是读操作最重要的是对不同数据类型的读取:

  我们要读取的表格内容,需要注意的是H列是F列和G列的求和公式得来的:

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;

public class Demo1 {


    public static void main(String[] args) throws Exception {
        String fileName = "E:\\\\static\\\\poi\\\\测试工作簿.xls";
        readExcel(fileName);

    }

    public static void readExcel(String fileName) throws Exception {
        //读取文件
        InputStream inputStream = new FileInputStream(fileName);
        //找到工作簿
        Workbook workbook = new HSSFWorkbook(inputStream);
        //找到对应的表格Sheet,0表示第一sheet
        Sheet sheet = workbook.getSheetAt(0);
        //得到物理行数
        int rowCount = sheet.getPhysicalNumberOfRows();
        //根据物理行数,读取每一格的内容
        for (int rowNum = 0; rowNum < rowCount; rowNum++) {
            // 读取每一行的内容
            Row rowData = sheet.getRow(rowNum);
            //空指针判断
            if (rowData != null) {
                // 得到物理列数,总共有多少列
                int cellCount = rowData.getPhysicalNumberOfCells();
                //读取每个单元格的数据
                for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                    //读取了数据是cell对象
                    //cell对象有多个数据类型
                    Cell cell = rowData.getCell(cellNum);
                    //空指针判断
                    if (cell != null) {
                        //获取当前单元格的数据类型
                        int cellType = cell.getCellType();
                        //最终读取的值
                        String cellValue = "";
                        //根据单元格数据类型来读取数据
                        switch (cellType) {
                            //字符串类型
                            case HSSFCell.CELL_TYPE_STRING:
                                System.out.print("字符串类型数据:");
                                //字符串类型数据获取方法
                                cellValue = cell.getStringCellValue();
                                break;
                            //布尔类型,一般不会见到这个类型的值
                            case HSSFCell.CELL_TYPE_BOOLEAN:
                                System.out.print("布尔类型的数据:");
                                //布尔类型数据获取方法
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            //空数据
                            case HSSFCell.CELL_TYPE_BLANK:
                                System.out.print("为空的数据:");
                                break;
                            //数值类型
                            //数值类型一共有两种,时间戳和数值
                            case HSSFCell.CELL_TYPE_NUMERIC:
                                //判断当前的数值是否是一个时间戳
                                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                    System.out.print("日期:");
                                    //时间数据类型转换
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");
                                } else {
                                    // 不是日期格式,则防止当数字过长时以科学计数法显示
                                    System.out.print("数值类型的数据:");
                                    //数值类型的数据转换成字符串类型
                                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                    cellValue = cell.toString();
                                }
                                break;
                            //公式类型的数据
                            case HSSFCell.CELL_TYPE_FORMULA:
                                //得到单元格使用的公式
                                String formula = cell.getCellFormula();
                                System.out.print("单元格使用的公式是:" + formula);
                                //得到计算的数据
                                double value = cell.getNumericCellValue();
                                System.out.print("计算的数据为:" + value);
                                break;
                            //错误的数据类型
                            case Cell.CELL_TYPE_ERROR:
                                System.out.print("数据类型错误");
                                break;
                        }

                        System.out.println(cellValue);

                    }

                }

            }

        }
        inputStream.close();
    }
}

  测试内容:

 

 

  

 

以上是关于java poi读取excel含小数列时,与excel显示不一样的主要内容,如果未能解决你的问题,请参考以下文章

java poi技术读取到数据库

java poi读取日期格式数据“2012-01-01 12:00:00”

java用poi读取excel文件时怎么获取每个单元格的列宽?

java使用poi读取excel时,因一些格式问题,执行excel函数错误

java poi 读取excel 数字类型

java使用poi读取excel时,电话号码变成了科学计数法,整数变成double,怎么改过来