POI实现Excel导入和导出(源码测试)

news2024/11/26 20:29:50

        因为实际开发中很多需求都需要实现Excel批量导入和导出,所以今天就来写一个后端demo实现Excel的导入和导出。

        需求

        Excel的导入

        1对文件路径为D:\Users\Mixi\IdeaProjects\javapoi-anli\product-test.xlsx 的Excel文件导入到数据库;

        Excel的导出

        2将数据库product表的数据导出到文件路径为D:\Users\Mixi\IdeaProjects\javapoi-anli\product-test1.xlsx的Excel中;

Excel的导入

1原有数据库product表中数据

2需要导入的excel文件数据

文件路径:D:\Users\Mixi\IdeaProjects\javapoi-anli\product-test.xlsx

 3Excel导入执行结果

 

 Excel的导出

1原有数据库product表中数据

2Excel导出执行结果

 

源码:

1层级关系

 web层的Show类:可以理解为Controller层,接收前端的请求实现Excel的导入和导出

/**
 * 模仿前端发送请求到后端
 * 前端传递的应该是一个axios请求到后端,然后将文件的路径传递到后端
 * 后端通过判断是导入还是导出,根据文件地址进行写入数据库或者导出数据库数据到Excel
 * */
public class Show {
    public static void main(String[] args) throws IOException {
        //通过键盘录入Scanner
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你要选择的功能: 1.导入 2.导出");
        int num = sc.nextInt();
        ProductService productService = new ProductServiceImpl();
        if (num == 1) {
            /**
             * 1.导入(导入就是将Excel中的数据存储到数据库)
             * 1.1读取excel表中的数据
             * 前端选择一个路径下的Excel文件进行导入到数据库
             * */
            System.out.println("请输入您要读取的文件位置(不包含空格)");
            String path = sc.next();
            // add
            path = URLDecoder.decode(path, "UTF-8");
            // 将excel文件进行读取(读取成一个个的Product集合)
            List<Product> productList = read(path);
            System.out.println(productList);
            //1.2将数据写入到数据库中(导入)
            productService.save(productList);
            System.out.println("数据已存入数据库中!");
        } else if (num == 2) {
            /**
             * 2.导出(Excel导出==就是将数据库中的数据读取处理啊)
             * 2.1 读取数据库中的数据(从数据库读取的数据是Product的集合)
             * findAll查找到所有的数据
             * */
            List<Product> productList = productService.findAll();
            System.out.println(productList);
            //2.2将数据写入到excel表格中
            System.out.println("请输入要写入的文件位置:");
            String path = sc.next();
            // 将数据库中的所有数据写入到Excel表中并存放在指定位置
            write(productList, path);
            System.out.println("写入成功!");
        } else {
            System.out.println("输入有误,请重新启动");
        }
    }
    /**
     * read方法是用来将Excel文件中的数据导入到数据库
     */
    public static List<Product> read(String path) throws IOException {
        /**
         * 存放多个Product,就是多条数据
         * */
        List<Product> productList = new ArrayList<>();
        //1.获取工作薄 path就是需要导出的Excel文件路径
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(path);
        //2.获取工作表
        XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
        // 获取到最后一行
        int lastRowNum = sheet.getLastRowNum();
        // 从第一行进行获取数据
        for (int i = 1; i <= lastRowNum; i++) {
            // 工作表获取到每一行
            XSSFRow row = sheet.getRow(i);
            // 空值校验
            if (row != null) {
                List<String> list = new ArrayList<>();
                // 对行进行遍历获取单元格
                for (Cell cell : row) {
                    // 空值校验
                    if (cell != null) {
                        // 为了避免有的单元格不是String类型,所以统一设置成String格式
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        // 再获取单元格中的数据(从而避免类型转换异常)
                        String value = cell.getStringCellValue();//读取数据
                        /**
                         * 将每一行中单元格中的数据获取到过后存储到String类型的list集合当中
                         * 最后将list集合中的每个数据使用有参构造的方式封装到Product对象中
                         * */
                        if (value != null && !"".equals(value)) {
                            list.add(value);
                        }
                    }
                }
                /**
                 * 最后将list集合中的每个数据使用有参构造的方式封装到Product对象中
                 * 通过下标的方式
                 * */
                // 集合的size()大于0
                if (list.size() > 0) {
                    // 因为Product中的类型不一样,需要转换
                    Product product = new Product(Integer.parseInt(list.get(0)), list.get(1), Double.parseDouble(list.get(2)), Integer.parseInt(list.get(3)));
                    // 添加到Product类型的集合中去
                    productList.add(product);
                }
            }
        }
        // 返回集合
        return productList;

    }
    /**
     * 导出Excel
     * write方法是用来导出Excel
     * 传递的集合是数据库中的所有数据,和导出Excel存放的地址
     */
    public static void write(List<Product> productList, String path) throws IOException {
        //1.创建一个工作薄
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
        //2.创建工作表
        XSSFSheet sheet = xssfWorkbook.createSheet("商品");
        //创建单元格样式
        XSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.PINK.getIndex());
        cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        //字体样式
        XSSFFont font = xssfWorkbook.createFont();
        font.setFontName("黑体");
        font.setColor(IndexedColors.BLUE.getIndex());
        cellStyle.setFont(font);

        //3.创建行【第一行】
        XSSFRow row = sheet.createRow(0);
//       row.createCell(0).setCellValue("商品编号");
//       row.createCell(1).setCellValue("商品名称");
//       row.createCell(2).setCellValue("商品价格(单位:元/斤)");
//       row.createCell(3).setCellValue("商品库存(单位:吨)");

        XSSFCell cell = row.createCell(0);
        cell.setCellValue("商品编号");
        // 设计样式
        cell.setCellStyle(cellStyle);

        XSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("商品名称");
        cell1.setCellStyle(cellStyle);

        XSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("商品价格(单位:元/斤)");
        cell2.setCellStyle(cellStyle);

        XSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("商品库存(单位:吨)");
        cell3.setCellStyle(cellStyle);

        for (int i = 0; i < productList.size(); i++) {
            // 从第二行开始创建
            XSSFRow row1 = sheet.createRow(i + 1);
            // 创建单元格进行赋值
            row1.createCell(0).setCellValue(productList.get(i).getPid());
            row1.createCell(1).setCellValue(productList.get(i).getPname());
            row1.createCell(2).setCellValue(productList.get(i).getPrice());
            row1.createCell(3).setCellValue(productList.get(i).getPstock());
        }
        // 创建文件输出流【IO流的方式】
        FileOutputStream fileOutputStream = new FileOutputStream(path);
        // 将文件输出流写到Excel中
        xssfWorkbook.write(fileOutputStream);
        // 刷新
        fileOutputStream.flush();
        // 关流
        fileOutputStream.close();
        xssfWorkbook.close();
    }
}

  ProductService:Show类中调用的接口

public interface ProductService {

    void save(List<Product> productList);

    List<Product> findAll();

}

 ProductServiceImpl:接口的实现类

public class ProductServiceImpl implements ProductService {
    private ProductDao productDao = new ProductDaoImpl();

    /**
     * 导入
     * 将Excel中的每行数据封装成Product对象再封装到集合当中进行遍历保存到数据库
     */
    @Override
    public void save(List<Product> productList) {
        for (Product product : productList) {
            productDao.save(product);
        }

    }

    /**
     * 导出
     */
    @Override
    public List<Product> findAll() {

        return productDao.findAll();
    }
}

ProductDao

public interface ProductDao {
    /**
     * Excel导入到数据库
     */
    void save(Product product);

    /**
     * 数据库导出到Excel
     */
    List<Product> findAll();

}

ProductDaoImpl:JDBC来实现增删改查,使用xml文件书写也是可以的

public class ProductDaoImpl implements ProductDao {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 保存,用来Excel的导入
     */
    @Override
    public void save(Product product) {
        // https://www.cnblogs.com/TestAndDevelp/p/12378898.html 参考文章
        String sql = "insert into product values(?,?,?,?)";
        // 将sql中的占位符进行一个替换
        jdbcTemplate.update(sql, product.getPid(), product.getPname(), product.getPrice(), product.getPstock());

    }

    /**
     * 查找数据,用来Excel的导出
     */
    @Override
    public List<Product> findAll() {
        String sql = "select * from product";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Product>(Product.class));
    }


}

domain层的Product:实体类

/**
 * Excel表对应的实体类
 * */
public class Product {
    private Integer pid;
    private String pname;
    private double price;
    private int pstock;

    @Override
    public String toString() {
        return "Product{" +
                "pid=" + pid +
                ", pname='" + pname + '\'' +
                ", price=" + price +
                ", pstock=" + pstock +
                '}';
    }

    public Product(Integer pid, String pname, double price, int pstock) {
        this.pid = pid;
        this.pname = pname;
        this.price = price;
        this.pstock = pstock;
    }

    public Product() {
    }

    public Integer getPid() {
        return pid;
    }

    public void setPid(Integer pid) {
        this.pid = pid;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getPstock() {
        return pstock;
    }

    public void setPstock(int pstock) {
        this.pstock = pstock;
    }
}

测试:执行main方法,输入1或者2,输入导入文件的路径或Excel文件需要导出的路径

1测试导入功能

2测试导出功能

gitee源码链接:javapoi-excel: POI实现Excel的导入和导出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/50121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP 采购订单免费标识自动勾选的判断依据

SAP采购订单的免费标识没有专门的字段存储,是根据发票收据和项目类别计算出来的 写程序的时候折磨判断呢? 1.EKPO-REPOS <> ‘X’ AND EKPO-PSTYP <> ‘2’ AND EKPO-PSTYP <> ‘7’ &#xff0c;则系统会自动勾选上这个免费项目 2.如果要求不是很精密&…

机器学习之MATLAB代码--LSTM-SVRNN(五)

机器学习之MATLAB代码--LSTM-SVRNN&#xff08;五&#xff09;代码数据结果代码 1、cdmnn.m文件 %% 组合模型 %% %% 数据导入 clc;clear;warning off; data xlsread(nndata.xlsx, sheet1, A2:G350); load LSTMoutput load SVMoutput %% nwholelength(data); %计算数据长度…

Vue笔记_transition组件(过渡样式)

目录transition组件作用过渡时机语法1语法2使用-animation侦动画使用-过渡动画总结transition组件 作用 transition组件的作用是 给 单个 元素/组件 添加过渡效果&#xff1b; transition-group组件的作用是给 多个 元素/组件 添加过渡效果&#xff1b; 过渡时机 vue只有在…

【pen200-lab】10.11.1.13

pen200-lab 学习笔记 【pen200-lab】10.11.1.13 &#x1f525;系列专栏&#xff1a;pen200-lab &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月30日&#x1f334; &#x1f36d;作…

turtlebot2利用turtlebot_exploration_3d进行自主建图

安装octomap_ros和rviz插件 sudo apt-get install ros-indigo-octomap*源码安装&#xff1a;turtlebot_exploration_3d(本机为Ubuntu16对应的ros版本为kinetic&#xff0c;但是无对应的版本&#xff0c;用的是ubuntu14的indigo&#xff0c;版本向前兼容&#xff0c;故可以运行&…

AXWWriter兼容的Word处理元素

AXWWriter兼容的Word处理元素 AXWWriter是一个与MS Word兼容的Word处理元素。该部件不需要设置任何其他库或软件。 AXWWriter使用DOCXReadWrite一起工作,DOCXReadWriter也包含在内。有关其他属性,请查看DOCXReadWrite。AXWWriter不难使用。如果您了解DOCXReadWrite,那么您已…

岩藻多糖-聚已内酯 Fucoidan-PCL 聚已内酯-PEG-岩藻多糖

岩藻多糖-聚已内酯 Fucoidan-PCL 聚已内酯-PEG-岩藻多糖 中文名称&#xff1a;岩藻多糖-聚已内酯 英文名称&#xff1a;Fucoidan-PCL 别称&#xff1a;PCL修饰岩藻多糖&#xff0c;PCL-岩藻多糖 聚己内酯&#xff08;Polycaprolactone&#xff0c;PCL&#xff0c;CAS号…

第4部分 RIP

动态路由协议包括距离向量路由协议和链路状态路由协议。RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是使用最广泛的距离微向量路由协议。RIP 是为小型网络环境设计的&#xff0c;国为这类协议是路由学习及路由更新将产生较大的流量&…

一文看懂MySQL的行锁

MySQL的全局锁和表锁可以看这篇文章&#xff1a;MySQL的全局锁和表锁 进入正文 行锁 行锁是由各个存储引擎自己实现的&#xff0c;并不是所有的引擎都支持行锁。 MyISAM引擎就不支持行锁&#xff0c;同一时刻一张表只能有一个更新在执行。 现在说InnoDB的行锁&#xff0c;行…

[附源码]计算机毕业设计springboot家庭医生签约服务管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

你在终端启动的进程,最后都是什么下场?(上)

你在终端启动的进程&#xff0c;最后都是什么下场&#xff1f;&#xff08;上&#xff09; 前言 在本篇文章当中&#xff0c;主要给大家介绍我们在终端启动的进程都是怎么结束的&#xff0c;在我们登录终端和退出终端都发生了什么&#xff1f; 基本介绍 首先我们需要了解的…

从Android系统启动→app启动→activity启动和渲染的整个流程

引言 本文讲解从开机到app显示画面的流程&#xff0c;但不分析源码&#xff0c;如果想阅读源码请到参考文章中查阅。 本文把这段流程分为三部分&#xff1a; 从开机到显示应用列表从点击应用图标到Activity创建成功从Activity创建成功到显示画面 从开机到显示应用列表 先看…

Java-CC

漏洞原理 TransformedMap这个类的decorate函数可以将一个普通的Map转换为一个TransformedMap&#xff0c;其第2、3参数分别对应当key改变和value改变时需要做的操作。所以此时如果修改其中的任意key或value&#xff0c;就会触发我们预先定义好的某些操作来对Map进行处理&#…

pytorch初学笔记(十四):损失函数

目录 一、损失函数 1.1 L1损失函数 1.1.1 简介 1.1.2 参数设定 1.1.3 代码实现 1.2 MSE损失函数&#xff08;平方和&#xff09; 1.2.1 简介 1.2.2 参数介绍 1.2.3 代码实现 1.3 损失函数的作用 二、在神经网络中使用loss function 2.1 使用交叉熵损失函数 2.2 …

【软件测试】资深测试聊一聊,测试架构师是怎么样的,做一名成功的测试工程师......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试架构师 测试架…

利尔达5G模组NE16U-CN通过华为OpenLab基于R16标准的认证测试

近日&#xff0c;利尔达5G R16模组NE16U-CN 率先顺利通过了华为OpenLab的认证测试&#xff0c;成为首批基于展锐V516芯片平台通过华为认证测试的5G模组&#xff0c;实现了基于3GPP R16协议版本的业务验证。 这表明&#xff0c;利尔达NE16U-CN模组已支持3GPP R16所具有的5G LAN、…

Overview of Computer Graphics

ContentsWhat is Computer Graphics?Why study Computer Graphics?ApplicationsFundamental Intellectual ChallengesTechnical ChallengesCourse TopicsRasterization (光栅化)Curves and Meshes (曲线和曲面)Ray Tracing (光线追踪)Animation / Simulation (动画 / 模拟)Re…

ANACONDA的进阶理解和思考

0. 继续深入了解anaconda 0.1 Anaconda 是 Python 的一个开源发行版本 里面集成了很多关于 python 科学计算的第三方库&#xff0c;主要面向科学计算且安装方便&#xff0c;而 python 是一个编译器 如果不使用 anaconda&#xff0c;那么安装库的时候&#xff0c;库的依赖安装起…

力扣LeetCode算法题 第6题-Z 字形变换

要求&#xff1a; 一开始看到题目&#xff0c;第一想到的思路&#xff0c;就被题目要求的思路给带偏了。 内容是Z字型输出内容 就一直想着把字符串输出成上面这种格式 总是想着把字符串放入到二维数组中进行展示。 这样一来思路就受到了限制。 一直使用先写入数组中。 //将…

直播邀请函 | 第12届亚洲知识产权营商论坛:共建创新价值 开拓崭新领域

由香港特别行政区政府、香港贸易发展局及香港设计中心共同举办的亚洲知识产权营商论坛&#xff0c;每年为世界各地知识产权业界专家、商界领袖提供一个理想平台&#xff0c;共同探讨亚洲知识产权市场的最新发展&#xff0c;发掘更多商机。 去年&#xff0c;论坛共邀请70余位国…