Java使用POI解析复杂Excel思维模式
来源:互联网 发布:淘宝化妆品店铺起名 编辑:程序博客网 时间:2024/06/04 19:20
功能需求:
如图这样的Excel,要求解析出来,且存储到数据库中能够呈现出层级关系。且最后一级要有自己的几何非几何属性。
需求分析:
1.首先我们发现这个Excel有这样一个规律,项目、IFD、是否标准这两个大类是样子是一一对应的,也就是说当我解析第一列的值、解析第五列的值、第十一列的值得函数可以是一样,同样第二列、第六列、第十二列也是可以一样的。。。
2.我们发现只有当Excel类型表示其没有最后一列时,才可以对应其几何信息和非几何信息。
程序分析:
1. Java中导出Excel,有两种方式,POI和JXL。优缺点就不用讲了。这里只阐述Java使用POI解析Excel
2.程序中涉及到的POI中读取特定单元格的值,Excel读取合并单元格的值
/** * 获取合并单元格的值 * @param sheet * @param row * @param column * @return */ public static String getMergedRegionValueAndInfo(Sheet sheet ,int row , int column){ String MergedVal=""; String MergedInfo=""; int sheetMergeCount = sheet.getNumMergedRegions(); for(int i = 0 ; i < sheetMergeCount ; i++){ CellRangeAddress ca = sheet.getMergedRegion(i); int firstColumn = ca.getFirstColumn(); int lastColumn = ca.getLastColumn(); int firstRow = ca.getFirstRow(); int lastRow = ca.getLastRow(); if(row >= firstRow && row <= lastRow){ if(column >= firstColumn && column <= lastColumn){ Row fRow = sheet.getRow(firstRow); Cell fCell = fRow.getCell(firstColumn); MergedVal=getCellValue(fCell); MergedInfo=String.valueOf(firstColumn)+","+String.valueOf(firstRow)+","+String.valueOf(lastColumn)+","+String.valueOf(lastRow); return MergedVal+"&"+MergedInfo ; } } } return null ; } /** * 判断合并了行 * @param sheet * @param row 行 * @param column 列 * @return */ private boolean isMergedRow(Sheet sheet,int row ,int column) { 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(); // 0 0 3 1 if(row == firstRow && row == lastRow){ if(column >= firstColumn && column <= lastColumn){ return true; } } } return false; } /** 行合并 * 判断单元格向行方向合并 * 判断指定的单元格是否是合并单元格 * @param sheet * @param row 行下标 * @param column 列下标 * @return */ public static boolean isMergedRegion(Sheet sheet,int row ,int column) { 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(); if(row >= firstRow && row <= lastRow){ if(column >= firstColumn && column <= lastColumn){ return true; } } } return false; }---读取特定单元格的值
public static String getCellVal(XSSFSheet sheet,int rowNum,int columnNum){ row=sheet.getRow(rowNum); Cell cell=row.getCell(columnNum); return getCellValue(cell); } /** * 获取单元格的值 * @param cell * @return */ public static String getCellValue(Cell cell){ if(cell == null){ return ""; } if(cell.getCellType() == Cell.CELL_TYPE_STRING){ //字符串 return cell.getStringCellValue(); }else if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){ //boolean return String.valueOf(cell.getBooleanCellValue()); }else if(cell.getCellType() == Cell.CELL_TYPE_FORMULA){ //公式 return cell.getCellFormula() ; }else if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){ //数字 return String.valueOf(cell.getNumericCellValue()); }else if(cell.getCellType() == Cell.CELL_TYPE_BLANK || cell.getCellType()==Cell.CELL_TYPE_ERROR){ //空值/故障 return ""; }else{ return ""; } }这个POI解析最基础的就是使用这两个方法。那么开始我们的分析
1.程序开始解析第一列,并适时解析第五列、第十一列。然后按照他存储起来,是一条记录
2.程序开始开始解析第二列时。这个时候就需要寻找他的父亲。
思维一:我们通过IFD读取第五列的IFD给其第六列的数据定位其父亲的唯一性
思维二:我们在数据中记录其父亲的所在行、列的二维坐标加上sheet的名称来实现父亲的唯一性
以上两种思维方式都对。但是呢?有缺陷,第一IFD是一串数字,数字编写上人为约定很有可能存在重复,那么你在寻找其父亲就没法做到唯一性。那么使用第二种?首先前提是,作为程序的编码者,要考虑用户为啥要使用Excel导入。因为客户不想麻烦,所以很有可能复制一个Excel改一改里面的某些内容,这个时候我们做到唯一性又加重了负担。
从上述的两个思维来看,我们只有在当前导入的Excel中,确定了这个父亲的唯一性。而用户更换了下一个Excel后,他的唯一性任然存在。
那么?Java中有什么方法可以实现定位到当前excel的父亲和儿子呢?
MAP
是的,我们交叉使用在第一列和第二列使用两个map,来记录其父子关系。第一个map的key是其行,value是他的值。第二个map也同样。当我们循环是,将其每一个行的值,和行号都存储,那么在儿子那一列时,我们就可以去父亲的map中用当前的key去取值。
---------------------------------------------------------------
上面我们只是找到了其父子关系,那么作为层级关系的最后一级,需要给其赋值几何和非几何属性呢?
这个逻辑灰常简单。就是确定其为最后一级
情况一:这个Excel总共就只有4级,而第四列的任然有值存在,那么他就是最后一级
情况二:我们以第二列的第五行为列。当for循环到这里时,发现其没有值,那么就要去寻找这一行的前一列是否有值,从而判断他是否为最后一列
情况三:在情况的二的基础上的对立面。如果其有值,这个时候就要判断这一行的后一列是否有值,来判断其是否为最后一列
-----------------------------------------------升华篇
我们在上诉的分析中,发现对于我们在寻找父子关系列时,使用了两个Map,我们可以假想其为奇偶map,这样对于父子判断就可以简化程序。
还有分析Excel的列关系,我们发现他是3*n+2的数据几何关系。
基于上诉的表达,我们就完全可以不怕用户的Excel变化。无论多少层级关系,我们都是剑在手。
- Java使用POI解析复杂Excel思维模式
- 《POI解析复杂Excel》
- Java使用poi解析Excel
- java使用poi实现excel解析
- java使用poi解析Excel文件
- 使用poi解析Excel
- 使用poi解析Excel
- 使用poi解析Excel
- 使用poi解析Excel
- 使用poi解析Excel
- 使用poi解析Excel
- 使用POI解析Excel
- java poi 解析excel
- java POI解析Excel
- “Java+POI+模板”打造复杂Excel 报表
- Java中使用Apache POI使用解析excel文件
- 使用POI解析excel getlastnum()
- 简单使用poi解析excel
- Json-lib的处理机制(1)--Processor接口
- 20161106#cs231n#1.最近邻分类器 Assignment1-KNN
- hadoop hdfs文件系统常用命令
- redis3.0 集群实战3 - java编程实战
- Linux_Linux命令_watch 用来指令输出的动态变化
- Java使用POI解析复杂Excel思维模式
- 实验二:外部中断与定时器/计数器中断实验
- hrbust 2249 开锁魔法II【概率dp】
- iOS 格式化输出符号
- 小娜老师的讲义-搭建支持Web服务的镜像(Apache)
- iOS博客技术
- Move Zeroes
- SQL注入替换法
- Hbase shell 常用命令