热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java使用poi5.0解析Excel工作簿的例子

写在之前Excel文档是日常办公中非常普遍的一种数据记录模式。在业务场景中,往往有“导入Excel到某某系统中”的需求,所以这里记录一种使用poi5.0系

写在之前

Excel文档是日常办公中非常普遍的一种数据记录模式。在业务场景中,往往有“导入Excel到某某系统中”的需求,所以这里记录一种使用poi 5.0系列的jar包解析为Java实体类的方法。

由于对Excel工作簿的理解有限,写代码水平有限;本例子更多的是经验记录和练习,参考意义因人而异。有不妥之处,还请批评指正。

一、需求

根据指定的Sheet顺序号,从每个Sheet指定的行以下,读取Excel工作簿数据为包含常用数据对象的实体类对象。

二、思路

结合poi的org.apache.poi.ss.usermodel.WorkBook接口,先将Excel工作簿抽象为工作表、标题、数据行。通过HSSFWorkbookXSSFWorkbook实现类的方法,将Sheet顺序号和指定的行号作为可配置的参数,获取有关对象后转换为实体类。

三、实现

1.Excel实体类ExcelBean

package com.myself.pottest;
import java.util.List;
import java.util.Map;
/**
* 描述一个Excel工作簿其中的一个工作表的实体类
*/
public class ExcelBean {
/*
工作表名
*/
private String sheetname = null;
/*
表格标题
*/
private Map columntitle = null;
/*
表格主体部分
*/
private List> rows = null;
public ExcelBean() {
}
public ExcelBean(String sheetname, Map columntitle, List> row) {
this.sheetname = sheetname;
this.columntitle = columntitle;
this.rows = row;
}
public String getSheetname() {
return sheetname;
}
public void setSheetname(String sheetname) {
this.sheetname = sheetname;
}
public Map getColumntitle() {
return columntitle;
}
public void setColumntitle(Map columntitle) {
this.columntitle = columntitle;
}
public List> getRows() {
return rows;
}
public void setRows(List> rows) {
this.rows = rows;
}
@Override
public String toString() {
return "ExcelBean{" +
"sheetname='" + sheetname + '\'' +
", columntitle=" + columntitle +
", rows=" + rows +
'}';
}
}

2.工具类ExcelParser

 

package com.myself.pottest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
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;
public class ExcelParser {
/**
*Excel文件
*/
private File file;
/**
* Workbook接口,用于根据条件实例化不同的实现类
*/
private Workbook ExcelWorkbook = null;
public ExcelParser(String filepath ) {
this.file = new File(filepath);
}
/**
* 读取文件,判断文件类型并创建有关实现类来实现Workbook接口。
*/
public void Read() {
try (FileInputStream fis = new FileInputStream(file)) {
if (file.getName().endsWith(".xls")) {
ExcelWorkbook = new HSSFWorkbook(fis);
} else if (file.getName().endsWith(".xlsx")) {
ExcelWorkbook = new XSSFWorkbook(fis);
} else {
System.out.println(file.getName()+"不是可以被本类解析的文件");
return;
}
} catch (FileNotFoundException e) {
System.out.println("文件不存在!");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取Workbook实现类的指定位置的Sheet实现类信息到Map中,并返回。
* @param SheetNum Map,存放需要读取的Excel的Sheet的顺序号及其指定行号,如第一个Sheet就写1,第一行就写1
* @return
*/
private Map GetSheet2Map(Map SheetNum) {
Map SheetMap = new LinkedHashMap<>();
if (SheetNum == null){
for (int k = 0; k Sheet sheet = ExcelWorkbook.getSheetAt(k);
SheetMap.put((k + 1), sheet.getSheetName());
}
}else if(SheetNum != null){
for (Map.Entry entry:SheetNum.entrySet()) {
Sheet sheet = ExcelWorkbook.getSheetAt(entry.getKey()-1);
SheetMap.put((entry.getKey()), sheet.getSheetName());
}
}
return SheetMap;
}
/**
* 将某个工作表的某行转换为标题的Map实现类,并返回
*
* @param sheet 要解析的工作表 Sheet对象实现类
* @param TitleRowIndex 标题位于哪一行
* @return
*/
private Map GetAnyRow2Title(Sheet sheet, int TitleRowIndex) {
Map TitleMap = new LinkedHashMap<>();
Row row = sheet.getRow(TitleRowIndex);
GetCell(sheet, row, TitleMap);
return TitleMap;
}
/**
* 将将某个工作表的某行转换为除去标题的Map实现类的List集合,并返回
*
* @param sheet 要解析的工作表 Sheet对象实现类
* @param TitleRowIndex 标题位于哪一行,默认标题以下部分是表格主体内容
* @return
*/
private List> GetRows2ListWithMap(Sheet sheet, int TitleRowIndex) {
List> TableRows = new ArrayList<>();
int rows = sheet.getPhysicalNumberOfRows();
for (int r = TitleRowIndex+1; r Row row = sheet.getRow(r);
if (row == null) {
System.out.println("工作表:" + sheet.getSheetName() + ",第" + r + "行为空行!");
} else if (row != null) {
Map RowMap = new HashMap<>();
GetCell(sheet, row, RowMap);
TableRows.add(RowMap);
}
}
return TableRows;
}
/**
* 将Sheet、Row接口的实现类转换为特定格式的Map接口的实现类,并返回。
* 转换后的Map实现类,-1位置作为工作表名,0位置作为行的序号,其余位置按照列的序号存到Map中。
*
* @param sheet 当前工作表,Sheet的实现类
* @param columnrow 当前行,Row的实现类
* @param columns 要存数据的Map实现类
*/
private void GetCell(Sheet sheet, Row columnrow, Map columns) {
if (columnrow == null) {
System.out.println(sheet.getSheetName() + "中有空行!");
return;
}
//-1位置作为工作表名
columns.put(-1, sheet.getSheetName() + "");
//0位置作为行的序号
columns.put(0, columnrow.getRowNum() + "");
//遍历Row对象,获取每行记录的每列
for (int c = 0; c Cell cell = columnrow.getCell(c);
Object value = "";
if (cell != null) {
switch (cell.getCellType()) {
//对不同类型的字段,用不同的方式获取
case FORMULA:
value = "" + cell.getCellFormula();
break;
case NUMERIC:
value = cell.getNumericCellValue();
break;
case STRING:
value = cell.getStringCellValue();
break;
case BLANK:
value = "";
break;
case BOOLEAN:
value = "" + cell.getBooleanCellValue();
break;
case ERROR:
value = "" + cell.getErrorCellValue();
break;
default:
value = "" + cell.getCellType();
}
//其余位置按照列的序号存到Map中
columns.put(cell.getColumnIndex() + 1, value);
}
}
}
/**
* 根据工作表的序号获取ExcelBean的实体类对象
* @return ExcelBean
*/
public List GetExcelBean(Map SheetNum) {
List excelBeans = new ArrayList<>();
if(ExcelWorkbook != null){
//获取所有工作表名称
Map TitleMap = GetSheet2Map(SheetNum);
//以工作表为单位来读取数据为实体类
for(Map.Entry entry:TitleMap.entrySet()){
ExcelBean excelBean = new ExcelBean();
//将TitleMap的值写入工作表属性
excelBean.setSheetname(entry.getValue().toString());
//根据TitleMap的键获取Sheet对象
Sheet sheet = ExcelWorkbook.getSheetAt(entry.getKey()-1);
//默认行号为0
int TitleNum = 0;
if(SheetNum != null){
//根据TitleMap的键到SheetNum中获取指定的行号
TitleNum = SheetNum.get(entry.getKey())-1;
}
excelBean.setColumntitle(GetAnyRow2Title(sheet,TitleNum));
excelBean.setRows(GetRows2ListWithMap(sheet,TitleNum));
excelBeans.add(excelBean);
}
}else if(ExcelWorkbook == null){
System.out.println("获取Workbook失败!");
}
return excelBeans;
}
/**
* 关闭Workbook对象
*/
public void Close(){
try {
ExcelWorkbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

 3.测试类Test 

package com.myself.pottest;
import org.apache.poi.ss.usermodel.Row;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) {
String path ="D:\\书本.xls";
ExcelParser excelpaser = new ExcelParser(path);
excelpaser.Read();
Map SheetNum = new HashMap<>();
//设置要读取的工作表顺序号及其对应的行号
SheetNum.put(1,1);
SheetNum.put(2,1);
SheetNum.put(3,2);
List excelBeanList = excelpaser.GetExcelBean(SheetNum);
for(ExcelBean Eb:excelBeanList){
System.out.println("工作表"+Eb.getSheetname());
System.out.println("表头"+Eb.getColumntitle());
List > rowList = Eb.getRows();
System.out.println("表格:");
for(Map map:rowList){
System.out.println(map);
}
}
excelpaser.Close();
}
}

4.工具类功能描述

 输入Excel文件路径,程序自动识别xls和xlsx文件类型。根据预先设置的要读取的工作表顺序号及其对应的行号、读取Excel工作簿为ExcelBean的列表,工作表名为String,标题为Map,表格为List>。

5.效果

表格数据

 运行结果

依赖的Jar包


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 标题: ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
author-avatar
我就是在刷粪_944
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有