POI导入Excel表格(xls,xlsx)

一、Excel导入导出的应用场景
1、数据导入:减轻录入工作量
2、数据导出:统计信息归档
3、数据传输:异构系统之间数据传输
二、POI简介(Apache POI)
1、什么是POI  Apache POI - the Java API for Microsoft Documents
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
    HSSF - 提供读写Microsoft Excel格式档案的功能。(.xls)
XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。(.xlsx
HWPF - 提供读写Microsoft Word格式档案的功能。
HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF - 提供读写Microsoft Visio格式档案的功能。
The Apache POI project is the master project for developing pure Java ports of file formats based on Microsoft's OLE 2 Compound Document Format. OLE 2 Compound Document Format is used by Microsoft Office Documents, as well as by programs using MFC property sets to serialize their document objects.
Apache POI is also the master project for developing pure Java ports of file formats based on Office Open XML (ooxml). OOXML is part of an ECMA / ISO standardisation effort. This documentation is quite large, but you can normally find the bit you need without too much effort! ECMA-376 standard is here, and is also under the Microsoft OSP.
2、官网
http://poi.apache.org/
官网可以找到文档和每个版本的下载地址

POI导入Excel表格(xls,xlsx)_第1张图片

三 使用Java代码实现写入Excel 

1 创建项目
(1)创建一个普通的maven项目
项目名:excel-poi
(2)pom中引入xml相关依赖


    
    
        org.apache.poi
        poi
        3.9
    

    
    
        org.apache.poi
        poi-ooxml
        3.9
    

    
    
        joda-time
        joda-time
        2.10.1
    

    
    
        junit
        junit
        4.12
    

2 xls写-03和07的区别
(1)03

public class ExcelWriteTest {
    @Test
    public void testWriter03() throws IOException {
        //1 创建新的Excel 工作簿
        Workbook workbook = new HSSFWorkbook();
        // 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
        //Sheet sheet = workbook.createSheet();
        //2 如要新建一名为"会员登录统计"的工作表,其语句为:
        Sheet sheet = workbook.createSheet("会员登录统计");
        //3 创建行(row 1)
        Row row1 = sheet.createRow(0);
        //4 创建单元格(col 1-1)
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("今日人数");
        //5 创建单元格 col 1-2
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue(666);
        //6 创建行(row 2)
        Row row2 = sheet.createRow(1);
        //7 创建单元格 (col 2-1)
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue("统计时间");
        //8 创建单元格 (col 2-2)
        Cell cell22 = row2.createCell(1);
        cell22.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
        //9 新建一个输出文件流 (注意:要先创建文件夹)
        File file = new File("E:/excel-poi/test-write03.xls");
        FileOutputStream outputStream = new FileOutputStream(file);
        //10 把相应的Excel 工作簿存盘
        workbook.write(outputStream);
        outputStream.close();
        System.out.println("文件生成成功");
    }
}

(2)07

@Test
public void testWriter07() throws IOException {
    //1 创建新的Excel 工作簿
    Workbook workbook = new XSSFWorkbook();
    // 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
    //Sheet sheet = workbook.createSheet();
    //2 如要新建一名为"会员登录统计"的工作表,其语句为:
    Sheet sheet = workbook.createSheet("会员登录统计");
    //3 创建行(row 1)
    Row row1 = sheet.createRow(0);
    //4 创建单元格(col 1-1)
    Cell cell11 = row1.createCell(0);
    cell11.setCellValue("今日人数");
    //5 创建单元格 col 1-2
    Cell cell12 = row1.createCell(1);
    cell12.setCellValue(666);
    //6 创建行(row 2)
    Row row2 = sheet.createRow(1);
    //7 创建单元格 (col 2-1)
    Cell cell21 = row2.createCell(0);
    cell21.setCellValue("统计时间");
    //8 创建单元格 (col 2-2)
    Cell cell22 = row2.createCell(1);
    cell22.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
    //9 新建一个输出文件流 (注意:要先创建文件夹)
    File file = new File("E:/excel-poi/test-write07.xlsx");
    FileOutputStream outputStream = new FileOutputStream(file);
    //10 把相应的Excel 工作簿存盘
    workbook.write(outputStream);
    outputStream.close();
    System.out.println("文件生成成功");
}

注意:如果针对不同版本的Excel使用了不适合的类库,则会报告异常
org.apache.poi.POIXMLException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Package should contain a content type part [M1.13]

3 大文件写-HSSF、XSSF和SXSSF
(1)使用HSSF
缺点:最多只能处理65536行,否则会抛出异常
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快

    @Test
    public void testBigDataWriter03() throws IOException {
        long begin = System.currentTimeMillis();
        //1 创建新的Excel 工作簿
        Workbook workbook = new HSSFWorkbook();
        // 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
        //Sheet sheet = workbook.createSheet();
        //2 如要新建一名为"会员登录统计"的工作表,其语句为:
        Sheet sheet = workbook.createSheet("会员登录统计");
        //xls文件最大支持65536行
        for (int i = 0; i < 65536; i++) {
//        for (int i = 0; i < 65537; i++) {//报错版  Invalid row number (65536) outside allowable range (0..65535)

            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {//创建单元格
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        System.out.println("done");
        //9 新建一个输出文件流 (注意:要先创建文件夹)
        File file = new File("E:/excel-poi/test-write03-bigData.xls");
        FileOutputStream outputStream = new FileOutputStream(file);
        //10 把相应的Excel 工作簿存盘
        workbook.write(outputStream);
        outputStream.close();
        long end = System.currentTimeMillis();
        System.out.println("用时" + (double) (end - begin) / 1000 + "秒文件生成成功");//用时2.784秒文件生成成功
    }

(2)使用XSSF
缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条
优点:可以写较大的数据量,如20万条

 @Test
    public void testBigDataWriter07() throws IOException {
        long begin = System.currentTimeMillis();
        //1 创建新的Excel 工作簿
        Workbook workbook = new XSSFWorkbook();
        // 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
        //Sheet sheet = workbook.createSheet();
        //2 如要新建一名为"会员登录统计"的工作表,其语句为:
        Sheet sheet = workbook.createSheet("会员登录统计");

//        for (int i = 0; i < 65536; i++) {
        for (int i = 0; i < 65537; i++) {//不报错  加一行或所用时间 用时6.28秒文件生成成功
            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {//创建单元格
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        /*
        缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条
        优点:可以写较大的数据量,如20万条
         */
        System.out.println("done");
        //9 新建一个输出文件流 (注意:要先创建文件夹)
        File file = new File("E:/excel-poi/test-write07-bigData.xlsx");
        FileOutputStream outputStream = new FileOutputStream(file);
        //10 把相应的Excel 工作簿存盘
        workbook.write(outputStream);
        outputStream.close();
        long end = System.currentTimeMillis();
 System.out.println("用时" + (double) (end - begin) / 1000 + "秒文件生成成功");//用时5.304秒文件生成成功
    }

(3)使用SXSSF

/**
     * 优点:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存
     *注意:
     *过程中会产生临时文件,需要清理临时文件(C:\Users\helen\AppData\Local\Temp)
     *默认由100条记录被保存在内存中,如果查过这数量,则最前面的数据被写入临时文件
     *如果想自定义内存中数据的数量,可以使用new SXSSFWorkbook(数量)
     * @throws IOException
     */
    @Test
    public void testBigDataFastWriter07() throws IOException {
        long begin = System.currentTimeMillis();
        //1 创建新的Excel 工作簿
        Workbook workbook = new SXSSFWorkbook();
        // 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
        //Sheet sheet = workbook.createSheet();
        //2 如要新建一名为"会员登录统计"的工作表,其语句为:
        Sheet sheet = workbook.createSheet("会员登录统计");

//        for (int i = 0; i < 65536; i++) {//用时1.616秒文件生成成功
//        for (int i = 0; i < 65537; i++) {//不报错  用时1.599秒文件生成成功
        for (int i = 0; i < 165537; i++) {//不报错  用时2.594秒文件生成成功
            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {//创建单元格
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        System.out.println("done");
        //9 新建一个输出文件流 (注意:要先创建文件夹)
        File file = new File("E:/excel-poi/test-write07-bigData-fast.xlsx");
        FileOutputStream outputStream = new FileOutputStream(file);
        //10 把相应的Excel 工作簿存盘
        workbook.write(outputStream);
        outputStream.close();

        //清除临时文件
        ((SXSSFWorkbook) workbook).dispose();
        long end = System.currentTimeMillis();
        System.out.println("用时" + (double) (end - begin) / 1000 + "秒文件生成成功");
    }

SXSSFWorkbook-来至官方的解释:实现“BigGridDemo”策略的流式XSSFWorkbook版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。
请注意,仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释......仍然只存储在内存中,因此如果广泛使用,可能需要大量内存。

四 使用Java代码实现读取Excel

1 xls读-03和07
(1)03

public class ExcelReadTest {
    @Test
    public void testRead03() throws IOException{
        FileInputStream inputStream = new FileInputStream("E:/excel-poi/xxx.xls");
        Workbook workbook = new HSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);
        //读取第一行 第一列
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(0);
        // 输出单元格内容
        String stringCellValue = cell.getStringCellValue();
        System.out.println(stringCellValue);
        inputStream.close();

    }

(2)07

@Test
public void testRead07() throws IOException{
    FileInputStream inputStream = new FileInputStream("E:/excel-poi/test-write07-bigData-fast.xlsx");
    Workbook workbook = new XSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    //读取第一行 第一列
    Row row = sheet.getRow(0);
    Cell cell = row.getCell(0);
    // 输出单元格内容
    String stringCellValue = cell.getStringCellValue();
    System.out.println(stringCellValue);
    inputStream.close();

}

2 读取不同类型的数据
(1)读取不同的数据类型

@Test
public void testReadCellType03() throws IOException{
    FileInputStream inputStream = new FileInputStream("E:/excel-poi/xxxx.xls");
    Workbook workbook = new HSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    //读取标题所内容
    Row rowTitle = sheet.getRow(0);
    if(rowTitle!=null){//行不为空
        //读取cell
        int cellCount = rowTitle.getPhysicalNumberOfCells();
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            Cell cell = rowTitle.getCell(cellNum);
            if(cell!=null){
                int cellType = cell.getCellType();
                String cellValue = cell.getStringCellValue();
                System.out.print(cellValue + "|");
            }
        }
        System.out.println();
    }
    FormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
    //读取商品列表数据
    int rowCount = sheet.getPhysicalNumberOfRows();
    for (int rowNum = 1; rowNum < rowCount; rowNum++) {
        Row rowData = sheet.getRow(rowNum);
        if(rowData!=null){//行不为空
        //读取cell
            int cellCount = rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                System.out.print("【" + (rowNum + 1) + "-" + (cellNum + 1) + "】");
                Cell cell = rowData.getCell(cellNum);
                if(cell!=null){
                    int cellType = cell.getCellType();
                    //判断单元格格式
                    String cellValue ="";
                    switch (cellType){
                        case HSSFCell.CELL_TYPE_STRING://字符串
                            System.out.print("【STRING】");
                            cellValue = cell.getStringCellValue();
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN://布尔值
                            System.out.print("【BOOLEAN】");
                            cellValue = String.valueOf(cell.getBooleanCellValue());
                            break;
                        case HSSFCell.CELL_TYPE_BLANK://空值
                            System.out.print("【BLANK】");
                            break;
                        case Cell.CELL_TYPE_FORMULA://2  公式
                            //得到公式
                            String formula = cell.getCellFormula();
                            System.out.println(formula);
                            CellValue evaluate = formulaEvaluator.evaluate(cell);
                            //String cellValue = String.valueOf(evaluate.getNumberValue());
                            cellValue = evaluate.formatAsString();
                            System.out.println(cellValue);
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC:
                            System.out.print("【NUMERIC】");
                            //cellValue = String.valueOf(cell.getNumericCellValue());
                            if (HSSFDateUtil.isCellDateFormatted(cell)){//如果是日期
                                System.out.print("【日期】");
                                Date date = cell.getDateCellValue();
                                cellValue=new DateTime(date).toString();
                            }else {//不是日期格式,则防止当数字过长时,以科学计数法显示
                                System.out.print("【转换字符串】");
                                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                cellValue=cell.toString();
                            }
                            break;
                        case Cell.CELL_TYPE_ERROR:
                            System.out.print("【数据类型错误】");
                            break;
                    }
                    System.out.println(cellValue);
                }
            }
        }

    }
    inputStream.close();

}

(2)计算公式

@Test
    public void testFormula() throws Exception{
    FileInputStream inputStream = new FileInputStream("E:/excel-poi/xxx.xls");
    Workbook workbook = new XSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    //读取第五行第一列
    Row row = sheet.getRow(4);
    Cell cell = row.getCell(0);
    //公式计算器
    FormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
    int cellType = cell.getCellType();
    switch (cellType){
        case Cell.CELL_TYPE_FORMULA://2
            //得到公式
            String formula = cell.getCellFormula();
            System.out.println(formula);
            CellValue evaluate = formulaEvaluator.evaluate(cell);
            //String cellValue = String.valueOf(evaluate.getNumberValue());
            String cellValue = evaluate.formatAsString();
            System.out.println(cellValue);
            break;

    }

}

 

转载于:https://my.oschina.net/u/4152198/blog/3095434

你可能感兴趣的:(java)