java如何读取Excel简单模板

时间:2022-09-27 11:49:32

场景:对于经常需要导入excel模板或数据来解析后加以应用的,使用频率非常之高,做了一个比较稳定的版本,体现在这些地方

工具:org.apache.poi

使用前必须了解这些:

1、要解析,那肯定先判断是不是excel

2、xls后缀的excel,是03版及以前的用hssfworkbook类
      xlsx后缀的excel,是07版及以后的用xssfworkbook解析

3、getworkbook这个方法是我自己乱造各种excel数据不断测试搜索修正得出的结果,其他的像简单的判断后缀xls还是xlsx来决定用hssh还是xssf是不保险的,比如你可能没遇过org.apache.poi.openxml4j.exceptions.invalidformatexception这样的异常,当然这个异常仍然是因为excel类型导致获取workbook时出错,然而我查到的结果是,excel最底层是xml实现的,类型问题出在这儿,看异常的描述也可以稍微看出来openxml4j.exceptions

4 、可能出现空行,空的单元格,或者单元格值为空的情况,这些情况,在我的readexcel()方法里都考虑到了,为什么我不用迭代器,或者加强的for each循环?就是因为这些坑爹的空单元格或者空行啊,迭代器内部在取cell单元格对象时跳过这些空的对象,who knows why?我也不知道,反正我测试过,跳过去了,本来5个单元格,一个空的,结果就只得到4个数据,即使用cell.isempty()和cell!=null来判断,也没卵用,因为遍历的时候直接跳过去了,都没有判断的机会

5、取单元格数据,这个就比较简单了,判断单元格类型,根据类型做相应的处理取出来,但是我觉得我这个getcellvalue()的方法应该有漏洞,先这么用着

下面上代码,简单描述下关键部位

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import java.io.file;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.ioexception;
import java.io.inputstream;
import java.io.pushbackinputstream;
import java.util.arraylist;
import java.util.hashmap;
import java.util.map;
import java.util.list;
import org.apache.poi.poixmldocument;
import org.apache.poi.openxml4j.exceptions.invalidformatexception;
import org.apache.poi.openxml4j.opc.opcpackage;
import org.apache.poi.poifs.filesystem.poifsfilesystem;
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;
import org.apache.poi.hssf.usermodel.hssfcell;
import org.apache.poi.hssf.usermodel.hssfworkbook;
import org.apache.xmlbeans.impl.piccolo.io.fileformatexception;
/**
 *yanbiao 2016.10.25
 */
public class excelutil {
 
  private static final string extension_xls = "xls";
  private static final string extension_xlsx = "xlsx";
 
/**
* 文件检查
*/
private void prereadcheck(string filepath) throws filenotfoundexception, fileformatexception {
 
file file = new file(filepath);
if (!file.exists()) {
throw new filenotfoundexception("导入的文件不存在:" + filepath);
}
if (!(filepath.endswith(extension_xls) || filepath.endswith(extension_xlsx))) {
throw new fileformatexception("传入的文件不是excel");
}
}
 /**
   * 取得workbook对象
   * xls:hssfworkbook,03版
   * xlsx:xssfworkbook,07版
  */
 private workbook getworkbook(string filepath) throws ioexception, invalidformatexception {
    //直接判断后缀来返回相应的workbook对象多数情况没问题,但是这个更保险,第3条已经说明 
    workbook wb = null;
    inputstream is = new fileinputstream(filepath);
    if (!is.marksupported()) {
      is = new pushbackinputstream(is, 8);
    }
    if (poifsfilesystem.haspoifsheader(is)) {
       return new hssfworkbook(is);
    }
    if (poixmldocument.hasooxmlheader(is)) {
      return new xssfworkbook(opcpackage.open(is));
    }
    throw new illegalargumentexception("您的excel版本目前不支持poi解析");
  }
 
  /**
   * 读取excel文件内容
   */
  public map<integer, list<string>> readexcel(string filepath) throws filenotfoundexception, fileformatexception {
    // 检查和获取workbook对象
    this.prereadcheck(filepath);
    workbook wb = null;
    map<integer,list<string>> map = new hashmap<integer, list<string>>();
    try {
      wb = this.getworkbook(filepath);
      // 默认只读取第一个sheet
      sheet sheet = wb.getsheetat(0);
      int rowcount = sheet.getlastrownum();//逻辑行,包括空行
      int cellcount = sheet.getrow(0).getlastcellnum();//第一行(将来作为字段的行)有多少个单元格
      for (int i=0;i<rowcount;i++) {          //这里用最原始的for循环来保证每行都会被读取
         list<string> list = new arraylist<string>();
         row row = sheet.getrow(i);
         if(null!=row){
            for (int j=0;j<cellcount;j++) {
             list.add(getcellvalue(row.getcell(j)));  //这里也是用for循环,用cell c:row这样的遍历,空单元格就被抛弃了 
            }
            system.out.println("第"+(row.getrownum()+1)+"行数据:"+list.tostring());
            map.put(row.getrownum(), list);
          }else{
            for (int j=0;j<cellcount;j++) {
              list.add("无数据");  
            }
            system.out.println("第"+(i+1)+"行数据:"+list.tostring());
            map.put(i, list);
        }    
      }   
    } catch (exception e) {
        system.out.println("读取excel异常:"+e.getmessage());
        e.printstacktrace();
      } finally {
         if (wb != null) {
           try {
               wb.close();
            } catch (ioexception e) {
               e.printstacktrace();
             }
         }
       }
    return map;  
  }
  /**
   * 取单元格的值
   */
  private string getcellvalue(cell c) {
    if (c == null) {
      return "无数据";
    }
    string value = "";
    switch (c.getcelltype()){
    case hssfcell.cell_type_numeric://数字
       value = c.getnumericcellvalue()+"";
    break;
    case hssfcell.cell_type_string://字符串
      value = c.getstringcellvalue();
    break;
    case hssfcell.cell_type_boolean://boolean
      value = c.getbooleancellvalue()+"";
    break;
    case hssfcell.cell_type_formula://公式
      value = c.getcellformula()+"";
    break;
    case hssfcell.cell_type_blank://空值
      value= "无数据";
     break;
    case hssfcell.cell_type_error:
      value = "非法字符";
     break;
    default:
      value= "未知类型";
     break;   
    }
    return value;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/yb38156/p/9821804.html