用Java玩转Excel,竟然如此easy~

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 用Java玩转Excel,竟然如此easy~


点击上方 好好学java ,选择 星标 公众号

重磅资讯,干货,第一时间送达今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客:点击前往,查看更多

来源:https://www.cnblogs.com/deng-cc

1、POI是什么

Apache POI - the Java API for Microsoft Documents,顾名思义,Apache的三方包,用来操作微软office文档的,多数时候用来操作excel,所以这里就以excel方面来说明。

需要引入两个包,maven地址如下(version 3.9‍


<dependency>    <groupId>org.apache.poi</groupId>    <artifactId>poi</artifactId>    <version>3.9</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency>    <groupId>org.apache.poi</groupId>    <artifactId>poi-ooxml</artifactId>    <version>3.9</version></dependency>

POI的组件列表中,针对excel的主要是HSSF和XSSF组件,前者针对97-2007的通用版excel,即后缀xls;后者针对2007或更高版的excel,即后缀xlsx。官方概要如下:


HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format.XSSF is the POI Project's pure Java implementation of the Excel 2007 OOXML (.xlsx) file format.

2、POI核心类

面向对象面向对象,既然如此,自然去找找一些能表示excel中内容的类。

2.1 工作簿 Workbook

创建或维护Excel工作簿的所有类的超接口,Workbook,属于org.apache.poi.ss.usermodel包。其下有两个实现类:

  • HSSFWorkbook : 有读取.xls 格式和写入Microsoft Excel文件的方法。它与微软Office97-2003版本兼容- XSSFWorkbook : 有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容
    XSSFWorkbook : 有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容

所以在针对不同版本的excel时,需要对应以上使用不同的Workbook。构造函数中,常用的:

HSSFWorkbook


//直接创建新的HSSFWorkbook()
//通过输入流创建HSSFWorkbook(java.io.InputStream s)

XSSFWorkbook


//直接创建新的XSSFWorkbook()
//通过File类创建XSSFWorkbook(java.io.File file)
//通过输入流创建XSSFWorkbook(java.io.InputStream is)

2.2 标签页 Sheet

HSSFSheet 和 XSSFSheet 都是Sheet接口的实现类,Sheet可以使用Workbook的两个方法获得:


workbook.createSheet();workbook.createSheet(String sheetName);

2.3 行 Row

同理,Row是 HSSFRow 和 XSSFRow 的接口,通过Sheet获取:


sheet.createRow(int rownum);

2.4 单元格 Cell

同理,Cell是 HSSFCell 和 XSSFCell 的接口,通过Row获取:


row.createCell(int column);row.createCell(int column, int type);

3、创建和读取

其实如果能理解面向对象,就很简单了,另外包括字体,公式,超链接等,都有对应的封装类,此处只提出了核心的几个,需要了解更多的需要自行展开。

例子的话,直接从别人教程里摘出来吧,另,读取的workbook,可以debug瞅瞅内容。

3.1 创建空白工作簿


import java.io.*;import org.apache.poi.xssf.usermodel.*;public class CreateWorkBook{   public static void main(String[] args)throws Exception   {      //Create Blank workbook      XSSFWorkbook workbook = new XSSFWorkbook();      //Create file system using specific name      FileOutputStream out = new FileOutputStream(      new File("createworkbook.xlsx"));      //write operation workbook using file out object      workbook.write(out);      out.close();      System.out.println("      createworkbook.xlsx written successfully");   }}

3.2 打开现有的工作簿

 


import java.io.*;import org.apache.poi.xssf.usermodel.*;public class OpenWorkBook
   public static void main(String args[])throws Exception      File file = new File("openworkbook.xlsx");      FileInputStream fIP = new FileInputStream(file);      //Get the workbook instance for XLSX file      XSSFWorkbook workbook = new XSSFWorkbook(fIP);      if(file.isFile() && file.exists())      {         System.out.println(         "openworkbook.xlsx file open successfully.");      }      else      {         System.out.println(         "Error to open openworkbook.xlsx file.");      }   }}

4、方法示例:任意对象List转至为Excel文档(可用注解定义标签名和列名)

写了个方法,可以将某个类的List转换为对应的Excel文档,列名如果在不使用注解的情况下默认为属性名:

类:


@Excel(name = "学生标签页")public class Student {
    @Excel(name = "姓名")    private String name;
    private boolean male;
    @Excel(name = "身高")    private int height;
    public String getName() {        return name;    }
    public void setName(String name) {        this.name = name;    }
    public boolean isMale() {        return male;    }
    public void setMale(boolean male) {        this.male = male;    }
    public int getHeight() {        return height;    }
    public void setHeight(int height) {        this.height = height;    }}

测试方法:


public static void main(String[] args) {    List<Student> list = new ArrayList<Student>();    Student student1 = new Student();    student1.setName("小红");    student1.setMale(false);    student1.setHeight(167);
    Student student2 = new Student();    student2.setName("小明");    student2.setMale(true);    student2.setHeight(185);
    list.add(student1);    list.add(student2);
    File file = new File("C:/Users/Dulk/Desktop/1314.xls");    createExcel(list, file);}

输出结果:

 

注解:


import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)public @interface Excel {    //设置名称    public String name() default "";}

方法:


import org.apache.log4j.Logger;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.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;
/** * Excel的操作工具类 */public class ExcelUtil {    private static Logger log = Logger.getLogger(ExcelUtil.class);
    /**     * 获取某个File文件对应的Workbook工作簿对象     */    public static Workbook gainWorkbook(File file) throws ExcelException {        if (!isExcel(file)) {            throw new ExcelException("文件不是Excel类型");        }        //如果文件不存在则新建        if (!file.exists()) {            try {                OutputStream os = new FileOutputStream(file);                Workbook workbook = isOlderEdition(file) ? new HSSFWorkbook() : new XSSFWorkbook();                workbook.write(os);                log.debug("文件不存在,新建该Excel文件");                os.close();
            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }        }
        try {            InputStream is = new FileInputStream(file);            return isOlderEdition(file) ? new HSSFWorkbook(is) : new XSSFWorkbook(is);
        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }
        return null;    }
    /**     * 判断某个Excel文件是否是2003-2007通用旧版     */    private static boolean isOlderEdition(File file) {        return file.getName().matches(".+\\.(?i)xls");    }
    /**     * 判断文件是否是一个Excel文件     */    private static boolean isExcel(File file) {        String fileName = file.getName();        String regXls = ".+\\.(?i)xls";        String regXlsx = ".+\\.(?i)xlsx";        return fileName.matches(regXls) || fileName.matches(regXlsx);    }
    /**     * 将某个对象的List转换为Excel工作簿     */    public static <E> Workbook createExcel(List<E> list, File file) {        String sheetName = "default";        if (list.size() == 0) {            return null;        }
        Workbook workbook = null;        try {            Class clazz = list.get(0).getClass();            Field[] fields = clazz.getDeclaredFields();            if (clazz.isAnnotationPresent(Excel.class)) {                Excel excel = (Excel) clazz.getAnnotation(Excel.class);                sheetName = excel.name();            }
            workbook = gainWorkbook(file);            Sheet sheet = workbook.createSheet(sheetName);            //创建首行            Row line = sheet.createRow(0);            for (int k = 0; k < fields.length; k++) {                Cell cell = line.createCell(k);                String columnName = fields[k].getName();                if (fields[k].isAnnotationPresent(Excel.class)) {                    Excel excel = fields[k].getAnnotation(Excel.class);                    columnName = excel.name();                }                cell.setCellValue(columnName);            }            //创建数据            for (int i = 1; i <= list.size(); i++) {                Row row = sheet.createRow(i);                for (int j = 1; j <= fields.length; j++) {                    Cell cell = row.createCell(j - 1);                    String fieldName = fields[j - 1].getName();                    String fieldFirstLetterUpper = fieldName.substring(0, 1).toUpperCase();                    String prefix = "get";                    if ("boolean".equals(fields[j - 1].getType().getName())) {                        prefix = "is";                    }                    String methodName = prefix + fieldFirstLetterUpper + fieldName.substring(1);                    Method method = clazz.getMethod(methodName);                    cell.setCellValue(String.valueOf(method.invoke(list.get(i - 1))));                }            }            log.debug("List读入完毕");            OutputStream os = new FileOutputStream(file);            workbook.write(os);            os.close();
        } catch (ExcelException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return workbook;    }}

推荐文章


原创电子书历时整整一年总结的 Java面试+ Java入门技术学习指南,这是本人这几年及校招的总结,各种异步面试题已经全部进行总结,按照章节复习即可,已经拿到了了大厂提供。

原创思维导图
扫码或者微信搜 程序员的技术圈子 回复 面试 领取原创电子书和思维导图。

原文地址:https://sihai.blog.csdn.net/article/details/113362169

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 用Java玩转Excel,竟然如此easy~


 上一篇
CTO——再写if-else,逮着一个罚款1000! CTO——再写if-else,逮着一个罚款1000!
点击上方 好好学java ,选择 星标 公众号 重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客:点击前往,查看更多 设计更好
2021-04-04
下一篇 
Spring 中经典的 9 种设计模式,打死也要记住啊! Spring 中经典的 9 种设计模式,打死也要记住啊!
点击上方 好好学java ,选择 星标 公众号 重磅资讯,干货,第一时间送达今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客:点击前往,查看更多 Spring中
2021-04-04