文档章节

使用Apache POI生成和读取excel文件

阿信sxq
 阿信sxq
发布于 2017/06/05 15:30
字数 1681
阅读 98
收藏 2

在项目中经常出现的需求就是,需要将表格形式的数据导出或者将表格形式的数据导入,当然我们可以使用简单的文本格式,使用csv作为后缀,客户也可以使用excel打开,但是那样会出现各种奇怪的问题,比较常见的就是乱码。

在java里面其实已经有了很好的操作库,可以很容易的进行excel文件的操作,那就是Apache POI,本文将延时如何使用poi中的接口,对表格形式数据进行导出和导入。

注:poi还有操作其他文档的库,就不做讨论了。

添加依赖

我们使用maven进行项目的构建管理,在依赖中添加下面的配置即可

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

由于excel文件一般有xls后缀和xlsx后缀,这两种文件有较大差异,操作的api是单独的,上面的依赖是操作xlsx所必须的依赖,maven会自动寻找它所以来的poi的组件,如果仅仅是需要操作xls文件,那么可以直接配置

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

本文的项目为了演示两种api的操作,使用的poi-ooxml的组件。

关于项目代码已经上传到了码云,https://git.oschina.net/songxinqiang/BlogExampleCode,可以自行查看

准备

为了演示的需要,我准备了一个模型类,用于表示表格的“一行”,就是一个简单的POJO

public class User implements Serializable {

    private static final long serialVersionUID = 5643553301653588278L;

    private int id;
    private String username;

    public User() {}

    public User(int id, String username) {
        this.id = id;
        this.username = username;
    }

    @Override
    public String toString() {
        return "{id:" + id + ",username:" + username + "}";
    }

    //set、get

}

为了实现导出,我们还需要准备一些数据

List<User> userList = new ArrayList<>();
userList.add(new User(1, "test1"));
userList.add(new User(2, "test2"));
userList.add(new User(3, "test3"));
userList.add(new User(4, "test4"));
userList.add(new User(5, "test5"));
userList.add(new User(6, "test6"));
userList.add(new User(7, "test7"));
userList.add(new User(8, "test8"));

导出表格到文件

将前面的list数据保存到一个文件中,我们需要建立一个excel文件的描述对象,在这个对象中添加数据即可。

如开始时所述,xls和xlsx的文件时不同的,下面分别给出两个方法,首先是操作xls文件的

    /**
     * 将用户列表转换存入xls文件
     *
     * @param userList
     *            用户信息列表
     * @return 保存的临时文件的信息对象,用于后续操作
     */
    public File userListToFile(List<User> userList) {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet spreadsheet = workbook.createSheet("用户列表");

        // 用于第一行的样式,当做标题
        HSSFFont font = workbook.createFont();
        font.setFontHeightInPoints((short) 14);
        font.setItalic(true);
        font.setBold(true);
        HSSFCellStyle style = workbook.createCellStyle();
        style.setFont(font);

        HSSFRow row;
        Cell cell;
        int rowid = 0;
        int cellid = 0;
        row = spreadsheet.createRow(rowid++);
        row.setRowStyle(style);
        row.setHeightInPoints(27);

        cell = row.createCell(cellid);
        cell.setCellValue("编号");
        spreadsheet.setColumnWidth(cellid, 18 * 256);
        cellid++;

        cell = row.createCell(cellid);
        cell.setCellValue("用户名");
        spreadsheet.setColumnWidth(cellid, 18 * 256);
        cellid++;

        for (User user : userList) {
            try {
                cellid = 0;
                row = spreadsheet.createRow(rowid++);

                cell = row.createCell(cellid++);
                cell.setCellValue(user.getId());
                cell = row.createCell(cellid++);
                cell.setCellValue(user.getUsername());
            } catch (Exception e) {
                logger.error("parse list error," + e.getMessage());
            }
        }
        // 文件只是临时文件,在方法返回之后,对文件进行后续的移动位置等操作
        File file = new File("/tmp/userlist.xls");
        try {
            FileOutputStream fos = new FileOutputStream(file);
            workbook.write(fos);
        } catch (Exception e) {
            logger.error("write file failed," + e.getMessage());
        } finally {
            try {
                workbook.close();
            } catch (IOException e1) {
                logger.error("close workbook error," + e1.getMessage());
            }
        }
        return file;
    }

然后是xlsx文件的

    /**
     * 将用户列表转换存入xlsx文件
     *
     * @param userList
     *            用户信息列表
     * @return 保存的临时文件的信息对象,用于后续操作
     */
    public File userListToFile(List<User> userList) {
        XSSFWorkbook workbook = new XSSFWorkbook(XSSFWorkbookType.XLSX);
        XSSFSheet spreadsheet = workbook.createSheet("用户列表");

        // 用于第一行的样式,当做标题
        XSSFFont font = workbook.createFont();
        font.setFontHeightInPoints((short) 14);
        font.setItalic(true);
        font.setBold(true);
        XSSFCellStyle style = workbook.createCellStyle();
        style.setFont(font);

        XSSFRow row;
        Cell cell;
        int rowid = 0;
        int cellid = 0;
        row = spreadsheet.createRow(rowid++);
        row.setRowStyle(style);
        row.setHeightInPoints(27);

        cell = row.createCell(cellid);
        cell.setCellValue("编号");
        spreadsheet.setColumnWidth(cellid, 18 * 256);
        cellid++;

        cell = row.createCell(cellid);
        cell.setCellValue("用户名");
        spreadsheet.setColumnWidth(cellid, 18 * 256);
        cellid++;

        for (User user : userList) {
            try {
                cellid = 0;
                row = spreadsheet.createRow(rowid++);

                cell = row.createCell(cellid++);
                cell.setCellValue(user.getId());
                cell = row.createCell(cellid++);
                cell.setCellValue(user.getUsername());
            } catch (Exception e) {
                logger.error("parse list error," + e.getMessage());
            }
        }
        // 文件只是临时文件,在方法返回之后,对文件进行后续的移动位置等操作
        File file = new File("/tmp/userlist.xlsx");
        try {
            FileOutputStream fos = new FileOutputStream(file);
            workbook.write(fos);
        } catch (Exception e) {
            logger.error("write file failed," + e.getMessage());
        } finally {
            try {
                workbook.close();
            } catch (IOException e1) {
                logger.error("close workbook error," + e1.getMessage());
            }
        }
        return file;
    }

可以看到,他们在操作上大体的方法是一样的,只有少许的差异,具体的代码的意义,还是需要查询javadoc文档的,通过这个方法我们就得到了一个保存有列表中数据的File对象,可以用于后续的处理,在这里我们直接用于文件中数据导入的数据源。

导入表格数据到程序

和导出一样,导入也需要分文件类型进行操作,下面首先是导入xls文件数据的

    /**
     * 读取文件中的值得到记录列表
     *
     * @param file
     *            文件描述信息
     * @return 记录对象列表
     */
    public List<User> fileToList(File file) {
        List<User> userList = new ArrayList<>();
        HSSFWorkbook workbook = null;
        try {
            NPOIFSFileSystem poifs = new NPOIFSFileSystem(file);
            workbook = new HSSFWorkbook(poifs);
        } catch (Exception e) {
            logger.error("read file error:" + e.getMessage());
            return userList;
        }
        HSSFSheet spreadsheet = workbook.getSheetAt(0);
        int rowCount = spreadsheet.getLastRowNum();
        HSSFRow row;
        // 第一行忽略
        for (int rowId = 1; rowId <= rowCount; rowId++) {
            row = spreadsheet.getRow(rowId);

            User user = new User();

            // 这里获取“数字”类型的值得到的是double
            user.setId((int) row.getCell(0).getNumericCellValue());
            user.setUsername(row.getCell(1).getStringCellValue());

            userList.add(user);
        }
        try {
            workbook.close();
        } catch (IOException e) {}

        return userList;
    }

接下来,是xlsx文件的操作

    /**
     * 读取文件中的值得到记录列表
     *
     * @param file
     *            文件描述信息
     * @return 记录对象列表
     */
    public List<User> fileToList(File file) {
        List<User> userList = new ArrayList<>();
        XSSFWorkbook workbook = null;
        try {
            workbook = new XSSFWorkbook(file);
        } catch (Exception e) {
            logger.error("read file error:" + e.getMessage());
            return userList;
        }
        XSSFSheet spreadsheet = workbook.getSheetAt(0);
        int rowCount = spreadsheet.getLastRowNum();
        XSSFRow row;
        // 第一行忽略
        for (int rowId = 1; rowId <= rowCount; rowId++) {
            row = spreadsheet.getRow(rowId);

            User user = new User();

            // 这里获取“数字”类型的值得到的是double
            user.setId((int) row.getCell(0).getNumericCellValue());
            user.setUsername(row.getCell(1).getStringCellValue());

            userList.add(user);
        }
        try {
            workbook.close();
        } catch (IOException e) {}

        return userList;
    }

这里,我们只关心里面的数据,所以导入的时候并没有关心格式那些,代码旧比较简单,有时候可能会关心格式,甚至关心数据的类型那些,具体处理起来就会麻烦一些。

同时,我们同样会发现,其实两种文件的处理代码还是差不多的。

测试

测试的代码比较简单,就是准备数据,调用方法处理,然后观察结果

    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "test1"));
        userList.add(new User(2, "test2"));
        userList.add(new User(3, "test3"));
        userList.add(new User(4, "test4"));
        userList.add(new User(5, "test5"));
        userList.add(new User(6, "test6"));
        userList.add(new User(7, "test7"));
        userList.add(new User(8, "test8"));

        PoiXlsxService poiXlsx = new PoiXlsxService();
        File xlsx = poiXlsx.userListToFile(userList);
        PoiXlsService poiXls = new PoiXlsService();
        File xls = poiXls.userListToFile(userList);

        userList = poiXlsx.fileToList(xlsx);
        System.out.println(Arrays.toString(userList.toArray()));
        userList = poiXls.fileToList(xls);
        System.out.println(Arrays.toString(userList.toArray()));
    }

小结

文中演示的只是基本简单的操作,基本的数据导出和导入,具体的操作还有很多奇妙的地方,还需要仔细发现。

© 著作权归作者所有

共有 人打赏支持
阿信sxq

阿信sxq

粉丝 226
博文 82
码字总数 72407
作品 1
成都
后端工程师
私信 提问
Spring MVC-集成(Integration)-生成Excel示例(转载实践)

以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_excel.htm 说明:示例基于Spring MVC 4.1.6。 以下示例显示如何使用Spring Web MVC框架生成Excel。首先,让我们使用E...

easonjim
2017/09/10
0
0
使用Apache POI读取Excel文件

网上关于介绍Apache POI操作Excel的文章已经很多了,但都讲得比较复杂。poi的API 与实际使用中的Excel很类似,可以说是POI把Excel中的workbook、sheet、cell等对象化了,在实际使用中极易理解...

zlikun
2013/05/13
0
4
Unity3d游戏项目客户端配置数据编辑器实现步骤

客户端编辑器主要的作用是把配置文件(格式是Excel)序列化生成二进制文件,在游戏中进行加载使用。 通过对别的项目的编辑器的学习,了解到一种实现方式: 1.使用Flex生成桌面程序,利用as3...

小姚
2014/08/30
0
2
excel 转换和解析 ndb 文件工具--excel2db

目的: 游戏开放中有原型数据,而原型数据经常都是通过excel进行编写,关于程序如何去读取excel中的数据,方法有很多种,比如: 1.将excel导入mysql中,然后由程序去读取数据库,但是客户端无法...

ksfzhaohui
2016/11/28
527
1
Excel2db-excel转成二进制文件

目的: 游戏开放中有原型数据,而原型数据经常都是通过excel进行编写,关于程序如何去读取excel中的数据,方法有很多种,比如: 1.将excel导入mysql中,然后由程序去读取数据库,但是客户端无法...

ksfzhaohui
2015/09/08
346
0

没有更多内容

加载失败,请刷新页面

加载更多

什么是自然语言处理技术

自然语言处理(NLP)是计算机科学,人工智能,语言学关注计算机和人类(自然)语言之间的相互作用的领域。自然语言处理是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计...

本宫没空2
1分钟前
0
0
移动端关闭虚拟键盘

$("#select_date").focus(function(){ document.activeElement.blur(); });

niuhongxia
1分钟前
0
0
Ubuntu18.04安装RabbitMQ(正确安装)

1、安装erlang 由于rabbitMq需要erlang语言的支持,在安装rabbitMq之前需要安装erlang sudo apt-get install erlang-nox 2、安装Rabbitmq 更新源 sudo apt-get update 安装 sudo apt-get ins...

hansonwong
11分钟前
0
0
如何在以太坊开发发行自己的ERC-20数字货币

今天我将向你展示如何在以太坊区块链上开发你自己的加密货币并将其出售!我将向你展示如何使用以太坊智能合约逐步创建自己的ERC-20代币和众筹销售,如何测试智能合约,如何将智能合约部署到以...

geek12345
11分钟前
0
0
Vlock用于有多个用户访问控制台的共享 Linux 系统

当你在共享的系统上工作时,你可能不希望其他用户偷窥你的控制台中看你在做什么。如果是这样,我知道有个简单的技巧来锁定自己的会话,同时仍然允许其他用户在其他虚拟控制台上使用该系统。 ...

linuxprobe16
12分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部