實現工具類
利用注解實現簡單的excel數據讀取,利用注解對類的屬性和excel中的表頭映射,使用Apache的poi就不用在業務代碼中涉及row,rows這些屬性了。
定義注解:
1
2
3
4
5
6
7
|
@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.FIELD) public @interface Excel { String name(); } |
由于本例中只涉及根據Excel表頭部分對Excel進行解析,只定義了一個name作為和Excel表頭的隱射。
工具類完整代碼如下:
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
|
public class ExcelUtil<T> { Class<T> clazz; public ExcelUtil(Class<T> clazz) { this .clazz = clazz; } public List<T> importExcel(String sheetName, InputStream input) { int maxCol = 0 ; List<T> list = new ArrayList<T>(); try { Workbook workbook = WorkbookFactory.create(input); Sheet sheet = workbook.getSheet(sheetName); // 如果指定sheet名,則取指定sheet中的內容. if (!sheetName.trim().equals( "" )) { sheet = workbook.getSheet(sheetName); } // 如果傳入的sheet名不存在則默認指向第1個sheet. if (sheet == null ) { sheet = workbook.getSheetAt( 0 ); } int rows = sheet.getPhysicalNumberOfRows(); // 有數據時才處理 if (rows > 0 ) { List<Field> allFields = getMappedFiled(clazz, null ); // 定義一個map用于存放列的序號和field. Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>(); // 第一行為表頭 Row rowHead = sheet.getRow( 0 ); Map<String, Integer> cellMap = new HashMap<>(); int cellNum = rowHead.getPhysicalNumberOfCells(); for ( int i = 0 ; i < cellNum; i++){ cellMap.put(rowHead.getCell(i).getStringCellValue().toLowerCase(), i); } for (Field field : allFields) { // 將有注解的field存放到map中. if (field.isAnnotationPresent(Excel. class )) { Excel attr = field.getAnnotation(Excel. class ); // 根據Name來獲取相應的failed int col = cellMap.get(attr.name().toLowerCase()); field.setAccessible( true ); fieldsMap.put(col, field); } } // 從第2行開始取數據 for ( int i = 1 ; i < rows; i++) { Row row = sheet.getRow(i); T entity = null ; for ( int j = 0 ; j < cellNum; j++) { Cell cell = row.getCell(j); if (cell == null ) { continue ; } int cellType = cell.getCellType(); String c = "" ; if (cellType == HSSFCell.CELL_TYPE_NUMERIC) { DecimalFormat df = new DecimalFormat( "0" ); c = df.format(cell.getNumericCellValue()); } else if (cellType == HSSFCell.CELL_TYPE_BOOLEAN) { c = String.valueOf(cell.getBooleanCellValue()); } else { c = cell.getStringCellValue(); } if (c == null || c.equals( "" )) { continue ; } entity = (entity == null ? clazz.newInstance() : entity); // 從map中得到對應列的field. Field field = fieldsMap.get(j); if (field == null ) { continue ; } // 取得類型,并根據對象類型設置值. Class<?> fieldType = field.getType(); if (String. class == fieldType) { field.set(entity, String.valueOf(c)); } else if ((Integer.TYPE == fieldType) || (Integer. class == fieldType)) { field.set(entity, Integer.valueOf(c)); } else if ((Long.TYPE == fieldType) || (Long. class == fieldType)) { field.set(entity, Long.valueOf(c)); } else if ((Float.TYPE == fieldType) || (Float. class == fieldType)) { field.set(entity, Float.valueOf(c)); } else if ((Short.TYPE == fieldType) || (Short. class == fieldType)) { field.set(entity, Short.valueOf(c)); } else if ((Double.TYPE == fieldType) || (Double. class == fieldType)) { field.set(entity, Double.valueOf(c)); } else if (Character.TYPE == fieldType) { if (c.length() > 0 ) { field.set(entity, c.charAt( 0 )); } } } if (entity != null ) { list.add(entity); } } } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 得到實體類所有通過注解映射了數據表的字段 * * @param clazz * @param fields * @return */ private List<Field> getMappedFiled(Class clazz, List<Field> fields) { if (fields == null ) { fields = new ArrayList<Field>(); } // 得到所有定義字段 Field[] allFields = clazz.getDeclaredFields(); // 得到所有field并存放到一個list中. for (Field field : allFields) { if (field.isAnnotationPresent(Excel. class )) { fields.add(field); } } if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object. class )) { getMappedFiled(clazz.getSuperclass(), fields); } return fields; } } |
代碼很簡單,獲取sheet,解析第一行,并和實體類標有注解的字段一一對應,用hashMap記錄下來,然后循環取得Excel中剩下所有的數據,根據map的對應關系將值set到對應字段。
基本使用
待解析表格如下:
定義實體類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class User { @Excel (name = "filed1" ) private String name; @Excel (name = "filed2" ) private String nameEn; @Excel (name = "filed3" ) private Integer age; @Excel (name = "filed4" ) private String six; @Excel (name = "filed5" ) private String weight; // ...getter setter } |
使用工具類:
1
2
3
4
5
6
7
8
9
10
11
|
public static void main (String[] args) { FileInputStream fileInputStream = null ; try { fileInputStream = new FileInputStream( "D://data.xlsx" ); } catch (FileNotFoundException e) { e.printStackTrace(); } ExcelUtil<User> util = new ExcelUtil<>(User. class ); List<User> jalanHotelList = util.importExcel( "user" , fileInputStream); // do something } |
利用這個思路可以擴展出導出excel功能,利用注解指定導出的excel表頭,甚至可以輕松控制excel表頭的顏色,合并屬性等等,在xdemo中有詳細復雜的示例,可以研究下。由于我的需求很簡單,就不整那么復雜啦。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。