Java 读写 excel 实战完全解析
本文微信公众号「AndroidTraveler」首发。
背景
时值毕业季,很多毕业生初入职场。
因此,这边也写了一些新手相关的 Android 技术点。
比如上一篇的 Android 开发你需要了解的那些事 就是列举了一些小点,避免新手 Android 开发者踩坑。
同时,也是恰逢暑假,因此大学生处于放假阶段。
这一篇主要是来自一位大学生的提问。
因此这边分享一下我个人的解题思路和方法,希望能够对他有所启发。
欢迎大家交流分享。
题目
使用语言:JAVA
需求:读取一个Excel表格里面的数据(例如:姓名+分数),对其进行重新排序(按分数高低),然后输出在另一个Excel表格。
分析
一般对需求我们都采取拆分思维。
将大问题拆成小问题,小问题解决了,整个大问题也就解决了。
这个需求很明确,需要解决三个问题:
- 读取 Excel 表格数据
- 对数据排序
- 将数据写入另一个 Excel 表格
我们这里要求使用 Java 语言,而 Java 语言一个很重要的点就是面向对象。
因此首先我们要考虑一下,这个题目里面有哪些类需要我们创建。
大概可以想象需要下面这些类:
读取数据类:ExcelReader
写入数据类:ExcelWriter
数据排序类:由于 Java API 自带,所以不需要重复造轮子
数据模型类:StudentScore
启动类:ParserStart,带有 main 方法
大概的 UML 图如下:
此时我们可以写出 v0.1 代码:
ExcelReader.java:
import java.util.List;
public class ExcelReader {
public List<StudentScore> read(String fileName) {
//TODO
return null;
}
}
ExcelWriter.java:
import java.util.List;
public class ExcelWriter {
public void write(String fileName, List<StudentScore> list) {
//TODO
}
}
StudentScore.java:
public class StudentScore {
private String name;
private int score;
public StudentScore(String name, int score) {
super();
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
ParserStart.java:
import java.util.List;
public class ParserStart {
public static void main(String[] args) {
// 第一步:读取数据
List<StudentScore> dataList = new ExcelReader().read("input.xls");
// 第二步:排序
//TODO
// 第三部:写入数据
new ExcelWriter().write("output.xls", dataList);
}
}
好了,基本框架搭好了。接下来就一步一步来实现我们的方法。
v0.2 代码:完善 ExcelReader 的 read 方法
Excel 的读取方法有第三方的库可以使用,因此我们不需要自己写。
我们这里使用的是第三方的 Apache 提供的 POI 库。
下载链接地址:https://poi.apache.org/download.html
写这篇文章时使用到的版本是 4.1.0
解压然后将 jar 包引入 Eclipse 项目即可。
接下来就是实际编写代码了,详情见注释。
我们要读取的文件示例如下:
ExcelReader.java:
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.EncryptedDocumentException;
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.ss.usermodel.WorkbookFactory;
public class ExcelReader {
public List<StudentScore> read(String fileName) throws EncryptedDocumentException, IOException {
if (fileName == null) return null;
File xlsFile = new File(fileName);
if (!xlsFile.exists()) return null;
// 工作表
Workbook workbook = WorkbookFactory.create(xlsFile);
// 表个数
int numberOfSheets = workbook.getNumberOfSheets();
// System.out.println(numberOfSheets);
if (numberOfSheets <= 0) return null;
List<StudentScore> list = new ArrayList<>();
//我们的需求只需要处理一个表,因此不需要遍历
Sheet sheet = workbook.getSheetAt(0);
// 行数
int rowNumbers = sheet.getLastRowNum() + 1;
// System.out.println(rowNumbers);
StudentScore score;
// 读数据,第二行开始读取
for (int row = 1; row < rowNumbers; row++) {
Row r = sheet.getRow(row);
// System.out.println(r.getPhysicalNumberOfCells());
//我们只需要前两列
if (r.getPhysicalNumberOfCells() >= 2) {
score = new StudentScore(r.getCell(0).toString(), (int) Double.parseDouble(r.getCell(1).toString()));
list.add(score);
}
}
return list;
}
}
v0.3 代码:对读取后的数据做排序处理
在 v0.2 版本中,我们成功读取了数据,但是我们读取的数据是按照 Excel 里面的顺序的,因此我们需要做排序处理。Java 函数库有对集合进行排序的方法。不过我们需要对 Model 进行额外处理,添加排序规则。因为排序可以是从小到大排,也可以是从大到小排。
StudentScore.java:
public class StudentScore implements Comparable<StudentScore>{
private String name;
private int score;
public StudentScore(String name, int score) {
super();
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "StudentScore [name=" + name + ", score=" + score + "]";
}
@Override
public int compareTo(StudentScore o) {
return o.score - this.score;
}
}
ParserStart.java:
import java.util.Collections;
import java.util.List;
public class ParserStart {
public static void main(String[] args) throws Exception{
// 第一步:读取数据
List<StudentScore> dataList = new ExcelReader().read("resource/input.xls");
System.out.println(dataList);
// 第二步:排序
Collections.sort(dataList);
System.out.println(dataList);
// 第三部:写入数据
// new ExcelWriter().write("output.xls", dataList);
}
}
v0.4 代码:将排序后的数据写入另一个 excel 表中
在 v0.3 版本中,我们完成了数据的排序,接下来我们需要将排好序的数据写到 output.xls 中。
ExcelWriter.java
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class ExcelWriter {
public void write(String fileName, List<StudentScore> list) {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("StudentScore");
// 创建Excel标题行,第一行
HSSFRow headRow = sheet.createRow(0);
headRow.createCell(0).setCellValue("姓名");
headRow.createCell(1).setCellValue("分数");
// 往Excel表中遍历写入数据
for (StudentScore studentScore : list) {
createCell(studentScore, sheet);
}
File xlsFile = new File(fileName);
try {
// 或者以流的形式写入文件 workbook.write(new FileOutputStream(xlsFile));
workbook.write(xlsFile);
} catch (IOException e) {
// TODO
} finally {
try {
workbook.close();
} catch (IOException e) {
// TODO
}
}
}
// 创建Excel的一行数据。
private void createCell(StudentScore studentScore, HSSFSheet sheet) {
HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);
dataRow.createCell(0).setCellValue(studentScore.getName());
dataRow.createCell(1).setCellValue(studentScore.getScore());
}
}
ParserStart.java
import java.util.Collections;
import java.util.List;
public class ParserStart {
public static void main(String[] args) throws Exception {
// 第一步:读取数据
List<StudentScore> dataList = new ExcelReader().read("resource/input.xls");
System.out.println(dataList);
// 第二步:排序
Collections.sort(dataList);
System.out.println(dataList);
// 第三部:写入数据
new ExcelWriter().write("resource/output.xls", dataList);
}
}
到此,通过几个版本的迭代,我们的需求就实现了。
NOTE:
在本项目中,input.xls 放在 resource 文件夹下面。所以最终版本传入的路径是 resource/input.xls。另外输出的时候这边发现 Eclipse 没有显示出来 output.xls,需要刷新一下。
此外,下载我的项目运行验证时,可能需要修改下 JRE。
另外 jar 包不要引入错位置了:
当然,还有几个待完善的点需要说明下:
- 这里没有对输入表的数据做合法性校验,比如分数为负数的情况是否需要做一些提示之类的操作。
- 这里判断文件不存在时,直接返回 null。而且没有判断文件是否为 excel 文件。这里就交由大家完善。而且这边异常没有做处理,直接 throws。
- 这里因为简单就没有做抽象。但是考虑可能需要读写 word 或者 pdf 或者其他文件,所以可以考虑引入继承和多态。抽取基类。
- 合理组织文件夹和命名。
另外说一下有什么应用场景吧,其实还真有。
移动端有多语言,想象一下产品给你一张带有多语言的 excel 表。
如果你一个一个拷贝到多个语言的资源文件下,这效率难以想象。
而如果你用了这一节的内容,分分钟读取 excel 按照你要的规则组装后输出到控制台。
想想就有点 6 啊。
好了,本期内容到此结束,欢迎留言交流讨论。
如果你有想了解的知识点,欢迎公众号留言私信,也许下一个 pick 的就是你。
源码获取地址:
https://github.com/nesger/JavaSamples/tree/master/ParseExcel
参考链接:
Java读取Excel数据:基于Apache POI(一)
Java读取和解析Excel数据:基于Apache POI(二)
Java导出数据行写入到Excel表格:基于Apache POI
Java 读写 excel 实战完全解析的更多相关文章
- java读写excel文件( POI解析Excel)
package com.zhx.base.utils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi ...
- C++读写EXCEL文件OLE,java读写excel文件POI 对比
C++读写EXCEL文件方式比较 有些朋友问代码的问题,将OLE读写的代码分享在这个地方,大家请自己看.http://www.cnblogs.com/destim/p/5476915.html C++ ...
- Java读写Excel之POI超入门
转自:http://rensanning.iteye.com/blog/1538591 Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给J ...
- Java读写Excel之POI超入门(转)
Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能.Apache POI ...
- java读写excel文件
近期处理的数据规模比较大,正好又是统计合并的事情,想着借助excel就可以完成了,然后就了解了下java读取excel的事情. 读取的文件主要分两类:xls文件.xlsx文件.xls文件的相关操作用的 ...
- 利用java读写Excel文件
一.读取Excel文件内容 java 代码 public static String readExcel(File file){ StringBuffer sb = new StringBuffer( ...
- JXL包大解析;Java程序生成excel文件和解析excel文件内容
最近需求变化,需要把excel导入 我以前没有做过,所以我查了一些资料 和参考别人的代码 以下是多种方式: import java.io.File; import java.io.FileInputS ...
- JAVA 读写Excel
ExcelUtil.java package pers.kangxu.datautils.utils; import java.io.File; import java.io.FileInputStr ...
- Java读写Excel
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId ...
随机推荐
- DELPHI之关于String的内存分配(引)
在函数.过程或者方法中定义一个字符串变量时,由于我们知道在函数.过程或者方法中定义的变量为局部变量,它的内存 是在栈中分配的,但是这里有个小细节我们要注意,对于一个局部的字符串变量,它的大小为4字节, ...
- Homebrew 1.0.0 发布,MacOS 上的包管理器,比如安装qt5keychain
神器,没有它不知道怎么用macos https://www.oschina.net/news/77367/homebrew-1-0-0 Mac OS X用户,qt5keychain可以使用homebr ...
- Qt之Model-View架构(雨田哥的博客)
Qt之Model-View架构 Qt之Model-View架构 简述 效果图 代码 结尾 简述 为什么会用这个模式,这里我就不解释了,可以看下 豆子哥的见解 .这里我只是如何去使用的.供大家共同探讨学 ...
- face='Webdings' 的字体对照表
刚才研究动网论坛代码,发现一个页面提示标记 i 感觉很神奇,看了半天才明白原来是一种叫“Webdings”的字体,其实很简单,只需要<font face='webdings' size=&quo ...
- 3016C语言_函数
第六章 函数 6.1 函数概述 定义 函数:是具有一定功能的一个程序块:是C语言的基本组成单位. 在前面各章的例子及读者自己编写的C语言程序中都用到了以“main“开头的主函数,并且在程序中频繁地调用 ...
- 美好生活从java开始
小编将会在接下来的日子里不断更新.分享一些IT方面的技术,以及自己的一些心得体会,希望大家能在我这有所收获.有所成长,那么我们就从java开始. 我们要想学习一样东西并且学好它,首先我们要弄清楚我们将 ...
- linux Apache设置https访问以及加载mod_ssl.so模块以及问题解决
开始之前的话: 1.配置好服务器防火墙的443端口规则: 2.购买好证书文件,我是沃通证书,准备好证书,这里不演示证书的购买和安装. 3.根据服务器类型下载文件,apache一共有4个文件 这里提供沃 ...
- 关于Jvm类加载机制,这一篇就够了
前言 一个月没更新了,这个月发生了太多的事情,导致更新的频率大大降低,不管怎样收拾心情,技术的研究不能落下! jvm作为每个java程序猿必须了解的知识,博主推荐一本书<深入理解Java虚拟机& ...
- 强制等待&隐士等待&显示等待&元素定位方法封装
前言 问题 学习selenium的同学估计大多数都遇见过一个问题 明明页面已经精准的定位到了元素,但是执行脚本的时候却经常报错没找到元素.其实原因很简单,就是脚本执行的速度很快,而浏览器加载页面的时候 ...
- 算法与数据结构基础 - 堆栈(Stack)
堆栈基础 堆栈(stack)具有“后进先出”的特性,利用这个特性我们可以用堆栈来解决这样一类问题:后续的输入会影响到前面的阶段性结果.线性地遍历输入并用stack处理,这类问题较简单,求解时间复杂度一 ...