java使用poi读取跨行跨列excel

  • 1.需求背景
  • 2.实现思路分析
  • 3.重要代码片码说明
  • 4.完整的代码类如下:
  • 5.完整的demo代码提供如下
  • 6.demo执行结果

1.需求背景

最近有一个工作任务是用户提供了一个基础的excel文件,要求首先将excel中的数据解析并入库,然后再做后续的一些业务处理,因此涉及到excel的数据读取,正常如果是一行一行数据的excel的读取,还是比较简单,但用户提供的数据涉及跨行跨列问题,就稍有点麻烦,比如数据样例如下:

需要将跨行跨列数据也读取出来最后进行入库处理,比如要解析成如下的数据并入库。

2.实现思路分析

首先以上的excel样例数据中,第一列共2个跨行区域,天河区和番禺区,每个跨行区域中在第二列又存在子跨行数据的问题,查看了poi的api,如获取到excel的工作表sheet后(通过如XSSFSheet sheet = xssfWorkbook.getSheetAt(0);获取),有个sheet.getNumMergedRegions()方法,此方法会返回excel中的所有关于合并单元格的信息,每个信息中包含了这个合并单元格的开始行,结束行,开始列,结束列。合并单元格的数据能通过第一行第一列获取到。

因此,可以采用一个hashmap将以上的合并单元格的信息进行预先读取,将存在合并单元格的列记录入put进hashmap, 如key为行号+下划线+列号组成,value为记录了合并单元格的起始行号和起始列号组成的数组

有了上面的hashmap之后,就可以按常规的遍历excel的行,然后再遍历excel的列进行数据的读取处理了,对每一个单元格进行判断,判断此单元格的行号+列号组成的key是不是在hashmap中存在,存在的话说明是一个合并单元格,读取数据就从value中取出合并单元格的起始行号和起始列号,通过合并单元格的起始行号和起始列号组成的单元格读取真正的数据(合并单元格的组据在首行和首列,其他行和列是空白)比如,以下的510075的数据,要通过读B2这一格才能读到数据

3.重要代码片码说明

  1. 获取存在合并单元格的列记录并以行号列号为key组成的map
 //将存在合并单元格的列记录入put进hashmap并返回public Map<String,Integer[]> getMergedRegionMap(Sheet sheet){Map<String,Integer[]> result = new HashMap<String,Integer[]>();//获取excel中的所有合并单元格信息int sheetMergeCount = sheet.getNumMergedRegions();//遍历处理for (int i = 0; i < sheetMergeCount; i++) {//拿到每个合并单元格,开始行,结束行,开始列,结束列CellRangeAddress range = sheet.getMergedRegion(i);  int firstColumn = range.getFirstColumn();  int lastColumn = range.getLastColumn();  int firstRow = range.getFirstRow();  int lastRow = range.getLastRow();//构造一个开始行和开始列组成的数组Integer[] firstRowNumberAndCellNumber = new Integer[]{firstRow,firstColumn};//遍历,将单元格中的所有行和所有列处理成由行号和下划线和列号组成的key,然后放在hashmap中for(int currentRowNumber = firstRow; currentRowNumber <= lastRow; currentRowNumber++) {for(int currentCellNumber = firstColumn; currentCellNumber <= lastColumn; currentCellNumber ++) {result.put(currentRowNumber+"_"+currentCellNumber, firstRowNumberAndCellNumber);}}}return result;}

4.完整的代码类如下:

package poitest;import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class ExcelMergegionReadTest {private Logger logger = LoggerFactory.getLogger(this.getClass());public static void main(String[] args) {new ExcelMergegionReadTest().excelRegionReadStart();}public void excelRegionReadStart(){long start = System.currentTimeMillis();InputStream inputStream = null;// 输入流对象XSSFWorkbook xssfWorkbook = null; //工作簿try {inputStream = this.getClass().getClassLoader().getResourceAsStream("datatest.xlsx");//定义工作簿xssfWorkbook = new XSSFWorkbook(inputStream);//获取第一个sheetXSSFSheet sheet = xssfWorkbook.getSheetAt(0);//获取合并单元格信息的hashmapMap<String,Integer[]> mergedRegionMap = getMergedRegionMap(sheet);//拿到excel的最后一行的索引int lastRowNum = sheet.getLastRowNum();//从excel的第二行索行开始,遍历到最后一行(第一行是标题,直接跳过不读取)for(int i = 1; i<=lastRowNum ; i++) {//拿到excel的行对象XSSFRow row = sheet.getRow(i);//获取excel的行中有多个列int cellNum = row.getLastCellNum();//对每行进行列遍历,即一列一列的进行解析for(int j=0; j<cellNum; j++) {//拿到了excel的列对象Cell cell = row.getCell(j);//将列对象的行号和列号+下划线组成key去hashmap中查询,不为空说明当前的cell是合并单元列Integer[] firstRowNumberAndCellNumber = mergedRegionMap.get(i+"_"+j);//如果是合并单元列,就取合并单元格的首行和首列所在位置读数据,否则就是直接读数据if(firstRowNumberAndCellNumber != null) {XSSFRow rowTmp = sheet.getRow(firstRowNumberAndCellNumber[0]);Cell cellTmp = rowTmp.getCell(firstRowNumberAndCellNumber[1]);System.out.println(getCellValue(cellTmp));}else{System.out.println(getCellValue(cell));}}System.out.println("================================================");}} catch (Exception e) {logger.error("error",e);} finally {// 关闭文件流if (inputStream != null) {try {inputStream.close();} catch (IOException e) {logger.error("error",e);}}// 关闭工作簿if(xssfWorkbook != null){try {xssfWorkbook.close();} catch (IOException e) {logger.error("error",e);}}}long end = System.currentTimeMillis();System.out.println("spend ms: " + (end - start) + " ms.");}//将存在合并单元格的列记录入put进hashmap并返回public Map<String,Integer[]> getMergedRegionMap(Sheet sheet){Map<String,Integer[]> result = new HashMap<String,Integer[]>();//获取excel中的所有合并单元格信息int sheetMergeCount = sheet.getNumMergedRegions();//遍历处理for (int i = 0; i < sheetMergeCount; i++) {//拿到每个合并单元格,开始行,结束行,开始列,结束列CellRangeAddress range = sheet.getMergedRegion(i);  int firstColumn = range.getFirstColumn();  int lastColumn = range.getLastColumn();  int firstRow = range.getFirstRow();  int lastRow = range.getLastRow();//构造一个开始行和开始列组成的数组Integer[] firstRowNumberAndCellNumber = new Integer[]{firstRow,firstColumn};//遍历,将单元格中的所有行和所有列处理成由行号和下划线和列号组成的key,然后放在hashmap中for(int currentRowNumber = firstRow; currentRowNumber <= lastRow; currentRowNumber++) {for(int currentCellNumber = firstColumn; currentCellNumber <= lastColumn; currentCellNumber ++) {result.put(currentRowNumber+"_"+currentCellNumber, firstRowNumberAndCellNumber);}}}return result;}/**   * 获取单元格的值   * @param cell   * @return   */    public String getCellValue(Cell cell){    if(cell == null) return "";    if(cell.getCellType() == CellType.STRING){    return cell.getStringCellValue();    }else if(cell.getCellType() == CellType.BOOLEAN){    return String.valueOf(cell.getBooleanCellValue());    }else if(cell.getCellType() == CellType.FORMULA){    return cell.getCellFormula() ;    }else if(cell.getCellType() == CellType.NUMERIC){    return String.valueOf(cell.getNumericCellValue());    }return "";}  }

5.完整的demo代码提供如下

github: https://github.com/jxlhljh/excelmergeregiontest.git

gitee: https://gitee.com/jxlhljh/excelmergeregiontest.git

6.demo执行结果

java使用poi读取跨行跨列excel相关推荐

  1. 使用POI导出跨行跨列

    https://q.cnblogs.com/q/52096/ @RequestMapping("/export3") public void export3(HttpServlet ...

  2. html跨行跨列学生报名表,HTML表格跨行、跨列操作(rowspan、colspan)

    一般使用 元素的colspan属性来实现单元格跨列操作,使用元素的rowspan属性来实现单元格的跨行操作. colspan属性规定单元格可横跨的列数,所有浏览器都支持colspan属性.其取值为nu ...

  3. JAVA对excle创建、读取、设置单元格颜色、背景色、跨行跨列

    pom.xml依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</a ...

  4. 压缩包里面excel 导出 (跨行跨列)

    压缩包里面excel 导出 (跨行跨列) 创建好 excel模板  直接读取内容即可的方法 1. List content = new ArrayList(); InputStream istream ...

  5. Java使用POI读取和写入Excel指南

    Java使用POI读取和写入Excel指南 做项目时经常有通过程序读取Excel数据,或是创建新的Excel并写入数据的需求: 网上很多经验教程里使用的POI版本都比较老了,一些API在新版里已经废弃 ...

  6. java使用poi读取存储excel表格,包括xls和xlsx格式

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java使用poi读取存储excel表格,包括xls和xlsx格式. 需要导入的包 poi-3.14.jar poi-ooxml-3.14.jar ...

  7. java poi 模板填数据库,java使用POI读取excel模版并向固定表格里填写数据详解

    java使用POI读取excel模版并向固定表格里填写数据详解:public class ExportExcelDemo { private HSSFWorkbook workbook = null; ...

  8. java通过poi读取excel中的日期类型数据或自定义类型日期

    java通过poi读取excel中的日期类型数据或自定义类型日期 Java 读取Excel表格日期类型数据的时候,读出来的是这样的  12-十月-2019,而Excel中输入的是 2019/10/12 ...

  9. java使用poi.xssf 写入内容到excel表格中 和 读取 表格里面的数据

    一.java使用poi.xssf 写入内容到excel表格中 public class TestExcel {//创建一个excel工作簿public static String outputFile ...

最新文章

  1. 抽取、转换和装载介绍(八)实时的意义(待续)
  2. 【PC工具】微软OneNote使用笔记,onenote无法连接网络无法同步解决方法
  3. 大二暑假周进度总结07
  4. jquery easyui datagrid mvc server端分页排序筛选的实现
  5. script id=tp type=text/html,demo.html
  6. UFLDL教程: Exercise:Self-Taught Learning
  7. Promise 到底是什么?看这个小故事
  8. 【java】java 的网络地址类 InetSocketAddress
  9. 恢复html的初始选定状态,jQuery实现点击旋转,再点击恢复初始状态动画效果示例...
  10. Linux环境下命令行下载DM8
  11. 科研笔记1:科研绘图
  12. 定积分求导例题_定积分典型例题
  13. 变量的定义、类型、注释、拼接字符串、选择循环结构、读取文件
  14. 【Markdown简单语法练习】
  15. Bing Maps-----微软
  16. 计算机应用高级教程,计算机应用高级教程(本科)
  17. Windows 2016 修改密码时提示密码不符合规则
  18. redis基本命令和help使用
  19. 计算机考研数学和英语难吗,英语难还是数学难
  20. ps 粗糙的练习磨皮小结实现的步骤---粗略的版本

热门文章

  1. 使用 Task.Wait()?立刻死锁(deadlock)
  2. 基于JAVA宠物托管系统计算机毕业设计源码+系统+lw文档+部署
  3. python图片转文字
  4. 论文阅读:A Unified Span-Based Approach for Opinion Mining with Syntactic Constituents
  5. 我从外包公司辞职了!
  6. np.add.at和np.negative.at
  7. 将APP变成黑白的颜色
  8. html是用cdn资源,网站常用前端公共库CDN服务资源(百度+360)
  9. Linux版本_Linux版本说明及应用领域
  10. 解决联通宽带域名劫持