POI导入导出的简单实现

本文介绍了如何使用Apache POI库在Java中实现Excel的导入导出功能,包括创建Springboot项目,引入POI依赖,编写POI入门小程序,设置单元格样式,从数据库导出数据到Excel,以及读取Excel文件导入数据到数据库的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据的导入导出

POI简介

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

Apache POI是用Java编写的免费开源的跨平台的JavaAPI,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为"Poor Obfuscation Implementation"的首字母缩写,以为"可怜的模糊实现"。

用它可以使用Java读取和创建,修改MS Excel文件,而且还可以使用Java读取和创建MS Word和MSPowerPoint文件,Apache POI提供Java操作Excel解决方案(适用于Excel97-2008)

结构:

HSSF - 提供读写Microsoft Excel格式档案的功能。

XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。

HWPF - 提供读写Microsoft Word格式档案的功能。

HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF - 提供读写Microsoft Visio格式档案的功能。

POI入门小程序:

首先搭建一个工程,这里我就用Springboot快速搭建,之后引入我们的POI坐标,我们要使用POI当然要先引入它的坐标。然后创建一个class,来写我们的小程序。

POM坐标:

<!-- 引入poi不会自动加入另外需要的包
        引入poi-ooxml就会自动引入操作xlsx文件所用到的其他包 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>

入门代码:

package com.example.demo.testpoi;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class PoiDemo {
    public static void main(String[] args) {
        //创建了一个工作簿
        HSSFWorkbook wk = new HSSFWorkbook();
        //创建了一个工作表
        HSSFSheet sheet = wk.createSheet();
        //创建第一行,一定要先创建行后在创建单元格,不需要创建列
        //下标从0开始,为第一行
        HSSFRow row = sheet.createRow(0);
        //创建单元格,列的索引也是从0开始
        HSSFCell cell = row.createCell(0);
        //给单元格赋值
        cell.setCellValue("测试");

        //保存测试的这个excel,用一个文件输出流
        try {
            FileOutputStream fos = new FileOutputStream("f://poitest.xls");
            wk.write(fos);
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最后展示一下效果:

几个简单的关于POI在入门程序中用到的API已经在注释中阐明。

如果要设置样式呢?比如列宽:

//设置列宽
        sheet.setColumnWidth(0,5000);

第一个代表哪个单元格,第二个参数为宽度,效果为这样:

width:这个参数的大小跟字体有关,每个字符大小乘以256即为列的宽度

POI连接数据库导出excel文件

首先搭建一套springboot+mybatis查询的项目。

POM文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入poi不会自动加入另外需要的包
        引入poi-ooxml就会自动引入操作xlsx文件所用到的其他包 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>
        <!--mysql连接依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
        <!--mybatis启动依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--数据库连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

在这个pom文件中我们引入了springboot的启动依赖,mybatis的启动依赖,以及我们要用到的poi的面向对象操作的依赖,lombok和druid等的依赖不细说。

yml配置:

server:
  port: 8091

mybatis:
  mapper-locations: classpath:dao/*.xml
spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shiro?characterEncoding=UTF-8

先写一个接口用来查询数据:

dao:

@Mapper
public interface ExportService {

    /**
     * 查询所有数据
     * @return
     */
    List<ExcelEntity> selectOne();
    
}

 service

@Service
public interface ExportService {

    /**
     * 查询所有数据
     * @return
     */
    List<ExcelEntity> selectOne();

    
}

serviceimpl

@Service
public class ExportServiceImpl implements ExportService {

    @Autowired
    private IexportDao iexportDao;

    @Override
    public List<ExcelEntity> selectOne() {
        List<ExcelEntity> excelEntities = iexportDao.selectOne();
        return excelEntities;
    }

   
}

 controller

@RestController
@RequestMapping("/export")
public class ExportController {
    @Autowired
    private ExportService exportService;

    /**
     * 查询数据
     * @return
     */
    @GetMapping("/select")
    public List<ExcelEntity> select(){
        List<ExcelEntity> excelEntities = exportService.selectOne();
        return excelEntities;
    }

}

mapper文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.testpoi.export.dao.IexportDao">
    <select id="selectOne" resultType="com.example.demo.testpoi.export.pojo.ExcelEntity">
        select * from sheet2
    </select>
</mapper>

 

postman测试:

一个查询接口就写完了。

POI导出

下面编写POI导出的接口:

首先dao层:

@Mapper
public interface IexportDao {

    /**
     * 查询所有数据
     * @return
     */
    List<ExcelEntity> selectOne();

    /**
     * 导出数据
     * @param os
     */
    void export(OutputStream os);
}

在接口中传入一个文件输出流的对象

service:

public interface ExportService {

    /**
     * 查询所有数据
     * @return
     */
    List<ExcelEntity> selectOne();

    /**
     * 导出数据
     * @param os
     */
    void export(OutputStream os);
}

serviceimpl:

@Service
public class ExportServiceImpl implements ExportService {

    @Autowired
    private IexportDao iexportDao;

    @Override
    public List<ExcelEntity> selectOne() {
        List<ExcelEntity> excelEntities = iexportDao.selectOne();
        return excelEntities;
    }

    /**
     * 导出数据
     * @param os
     */
    @Override
    public void export(OutputStream os) {
        //获取要导出的数据列表
        List<ExcelEntity> excelEntities = iexportDao.selectOne();
        //创建了一个工作簿
        HSSFWorkbook wk = new HSSFWorkbook();
        //创建了一个工作表
        HSSFSheet sheet = wk.createSheet("excel1");
        //创建第一行,一定要先创建行后在创建单元格,不需要创建列
        //下标从0开始,为第一行,写标题
        HSSFRow row = sheet.createRow(0);
        //将表头放入一个数组
        String[] header = {"设备名称","横坐标","纵坐标"};
        //先定义一个cell;
        HSSFCell cell=null;
        //遍历数组
        for (int i = 0; i <header.length ; i++) {
            //在遍历数组的同时创建单元格
            cell=row.createCell(i);
            //在遍历中给创建好的单元格赋值
            cell.setCellValue(header[i]);
        }
        //导出的内容
        /**因为表头为0,所以表中的数据从下标1开始*/
        int rowCount=1;
        for (ExcelEntity excelEntity : excelEntities) {
            row=sheet.createRow(rowCount);
            //设备名称
            row.createCell(0).setCellValue(excelEntity.getSbmc());
            //横坐标
            row.createCell(1).setCellValue(excelEntity.getX());
            //纵坐标
            row.createCell(2).setCellValue(excelEntity.getY());
            //添加完数据之后自增一行
            rowCount++;
        }

        try {
            wk.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                wk.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

具体的代码注释已经标明在代码中

下面是导出的controller:

@RestController
@RequestMapping("/export")
public class ExportController {
    @Autowired
    private ExportService exportService;

    /**
     * 查询数据
     * @return
     */
    @GetMapping("/select")
    public List<ExcelEntity> select(){
        List<ExcelEntity> excelEntities = exportService.selectOne();
        return excelEntities;
    }

    /**
     * 导出数据
     */
    @GetMapping("/dc")
    public void export(HttpServletResponse response,HttpServletRequest request){
        String fileName = "设备表";
        try {
            //响应对象
            ServletOutputStream outputStream = response.getOutputStream();
            //设置输出流的格式,实现下载,指定为excel
           setResponseHeader(response,fileName,request);
            exportService.export(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 公共方法
     * @param response
     * @param fileName
     * @param request
     */
    public void setResponseHeader(HttpServletResponse response, String fileName, HttpServletRequest request) {
        try {
            try {
                String userAgent=request.getHeader("user-agent");
                if (userAgent!=null && userAgent.indexOf("Firefox")>=0 || userAgent.indexOf("Chrome")>=0){
                    fileName = new String(fileName.getBytes(), "ISO8859-1")+".xls";
                }else{
                    fileName = URLEncoder.encode(fileName, "UTF-8")+".xls";
                }
            } catch (UnsupportedEncodingException var4) {
                var4.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception var5) {
            var5.printStackTrace();
        }
    }
}

导出效果:

 

 导出excel就完成了

POI导入

导入需求是需要我们上传一份excel文件,上传之后将数据库中没有的内容进行新增操作,已经有的数据则根据数据库要改变的表中的一个字段进行判断,如果这个字段中的内容已经有了,上传的excel文件也有了,则证明是重复的一条数据,就进行更新操作,如果表中没有就进行新增操作。

首先我们已经有了一个新增的接口,再来编写一个更新的接口:

dao层:


    /**
     * 更新数据
     * @param sbmc
     */
    void update(String sbmc,String x,String y);

 

 

 

 

 

 

 

mapper文件: 

<!--根据设备名称更新sql-->
    <update id="update" parameterType="String">
        update sheet0 set sbmc='${sbmc}',x='${x}',y='${y}' where sbmc='${sbmc}'
    </update>

 因为目前我们暂时不需要在控制层用到这个更新的方法,所以暂时不写service层的更新方法,那么接下来就是我们导入的主角方法登场了:

service层:

 /**
     * 导入数据
     * @param ip
     */
    void doImport(InputStream ip) throws IOException;

service实现类:

/**
     * 导入数据
     * @param ip
     */
    @Override
    public void doImport(InputStream ip) throws IOException{
        HSSFWorkbook wk=null;
        try {
            wk = new HSSFWorkbook(ip);
            //拿到excel文档的第一个sheet
            HSSFSheet sheet = wk.getSheetAt(0);
            //读取数据
            //最后一行的行号
            int lastRowNum = sheet.getLastRowNum();
            ExcelEntity excelEntity = null;
            //使用最后一行作为for循环的最后一层
            for (int i=1;i<=lastRowNum;i++){
                excelEntity = new ExcelEntity();
                //设备名称列
                excelEntity.setSbmc(sheet.getRow(i).getCell(0).getStringCellValue());
                //判断是否已经存在,通过设备名称来查询
                List<ExcelEntity> excelEntities = iexportDao.selectBySbmc(excelEntity.getSbmc());
                //如果这个集合有记录
                if (excelEntities.size()>0){
                    //集合大小大于一说明根据这个名称查出了数据,将xy更新
                    excelEntity = excelEntities.get(0);
                }
                //设置x列
                excelEntity.setX(sheet.getRow(i).getCell(1).getStringCellValue());
                //设置y列
                excelEntity.setY(sheet.getRow(i).getCell(2).getStringCellValue());
                iexportDao.update(excelEntity.getSbmc(),excelEntity.getX(),excelEntity.getY());
                //如果这个集合是0就新增
                if (excelEntities.size()==0){
                    //新增
                    iexportDao.addExcelEntity(excelEntity);
                }
            }
        } finally {
            if (null != wk){
                try {
                    wk.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

controller层:

    @PostMapping("/upload")
    public String doImport(MultipartFile file) {
        try {
            exportService.doImport(file.getInputStream());
            return "上传成功";
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败";
        }
    }

导入的代码就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值