a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁(yè) > 編程 > Java > 正文

Java使用Apache poi 導(dǎo)入Excel文件

2019-11-11 07:46:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

java使用Apache poi 操作Excel-基本概念與使用中介紹了poi與excel相關(guān)的基本概念,接下來(lái)通過(guò)poi來(lái)導(dǎo)入excel。

本文將使用如下版本的 POI來(lái)完成導(dǎo)入數(shù)據(jù)的演示。

<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency>

1 讀取Excel并打印結(jié)果

由上篇文章可知Excel的基本結(jié)構(gòu),因此導(dǎo)入Excel就是要將Excel某個(gè)電子表單中的所有行讀入到程序中。

public static <T> List<T> importExcel(File excelFile) throws InvalidFormatException, IOException, InstantiationException, IllegalaccessException { XSSFWorkbook workBook = new XSSFWorkbook(excelFile); XSSFSheet sheet = workBook.getSheetAt(0); for(int ri = sheet.getFirstRowNum() + 1 ; ri <= sheet.getLastRowNum(); ri++) { Row row = sheet.getRow(ri); for(int ci = row.getFirstCellNum(); ci < row.getLastCellNum(); ci++) { Cell cell = row.getCell(ci); Object value = getCellValue(cell,fields[ci]); System.out.如上代碼是將excelFile讀入,然后讀取workBook.getSheetAt(0);表單,接著遍歷各個(gè)行,并獲取各個(gè)行的數(shù)據(jù)并輸出。

由于Excel單元格的數(shù)據(jù)由不同的類(lèi)型組成,因此獲取數(shù)據(jù)時(shí)要判斷單元格類(lèi)型,并調(diào)對(duì)應(yīng)的方法獲取數(shù)據(jù)。

2 將讀取的數(shù)據(jù)存入Java對(duì)象中

接下來(lái)將1中讀取的數(shù)據(jù)保存在Java對(duì)象中。這里以Person對(duì)象為例。Person對(duì)象省略了Getter,Setter,及toString方法。

public class Person { private String name; private String sex; private Integer age; private Double height; }

使用的Excel數(shù)據(jù)如下所示。首行是標(biāo)題列,首行之后是數(shù)據(jù)列。

姓名 性別 年齡 身高(M)洛克 男 18 1.83 羅琳 女 18 1.76

為了將Excel中讀取的數(shù)據(jù)存儲(chǔ)在Java對(duì)象中,將1中的方法簽名修改為,其中type是最終的類(lèi)型,本文中為Person。

public static <T> List<T> importExcel(File excelFile,Class<T> type)

修改后的importExcel方法如下。

public static <T> List<T> importExcel(File excelFile,Class<T> type) throws InvalidFormatException, IOException, InstantiationException, IllegalAccessException { XSSFWorkbook workBook = new XSSFWorkbook(excelFile); List<T> result = new ArrayList<T>(); XSSFSheet sheet = workBook.getSheetAt(0); for(int ri = sheet.getFirstRowNum() + 1 ; ri <= sheet.getLastRowNum(); ri++) { Row row = sheet.getRow(ri); T object = type.newInstance(); Field[] fields = object.getClass().getDeclaredFields(); Field.setAccessible(fields, true); for(int ci = row.getFirstCellNum(); ci < row.getLastCellNum(); ci++) { Cell cell = row.getCell(ci); Object value = getCellValue(cell,fields[ci]); fields[ci].set(object, value); } result.add(object); Field.setAccessible(fields, false); } return result; }

上述代碼忽略Excel標(biāo)題行,因此是從首行+1行開(kāi)始進(jìn)行遍歷。

代碼中首先根據(jù)type來(lái)創(chuàng)建一個(gè)實(shí)例。 T object = type.newInstance(); 注意事項(xiàng):這里需要注意的是對(duì)象的各個(gè)成員的類(lèi)型要與Excel各列所保持一致,這樣免去尋找對(duì)象成員與Excel列單元的對(duì)應(yīng)關(guān)系的麻煩,并簡(jiǎn)化示例。

創(chuàng)建完實(shí)例后,獲取對(duì)象中的各個(gè)字段,并修改訪問(wèn)權(quán)限,以便隨后賦值。

Field[] fields = object.getClass().getDeclaredFields();Field.setAccessible(fields, true);

接著遍歷各個(gè)列,由于對(duì)象中字段的順序與Excel列順序保持一致,因此使用同樣的列索引即可獲取Excel列單元與對(duì)象成員。

Person成員的類(lèi)型由String,int,double,而在Excel中單元格數(shù)值的類(lèi)型統(tǒng)一被描述為Cell.CELL_TYPE_NUMERIC類(lèi)型,因此在導(dǎo)入并轉(zhuǎn)換為Java對(duì)象就需要格外注意類(lèi)型處理,以避免出錯(cuò)。以本文中Excel中年齡為例,獲取后單元格數(shù)值使用的是cell.getNumericCellValue()方法,該方法返回類(lèi)型為Double,而Java對(duì)象中使用的是Integer。此外使用中也可能將年齡寫(xiě)成字符串。因此需要對(duì)每種數(shù)據(jù)類(lèi)型判斷并合理轉(zhuǎn)換,或給出相應(yīng)錯(cuò)誤提示。

通過(guò)定義接口TypeHandler 來(lái)處理各種類(lèi)型轉(zhuǎn)換的問(wèn)題。

public interface TypeHandler { public Object handle(Cell cell,Field field);}

以Integer類(lèi)型為例,接著定義Integer處理器。

public class IntegerHandler implements TypeHandler{ @Override public Object handle(Cell cell, Field field) { int type = cell.getCellType(); if(type == Cell.CELL_TYPE_NUMERIC) { return (int)cell.getNumericCellValue(); } else if(type == Cell.CELL_TYPE_STRING) { try { return Integer.valueOf(cell.getStringCellValue()); }catch(NumberFormatException e) { return null; } } else { return null; } }}

當(dāng)單元格類(lèi)型返回double(Cell.CELL_TYPE_NUMERIC),則執(zhí)行類(lèi)型轉(zhuǎn)換。如果是字符串類(lèi)型,則嘗試轉(zhuǎn)換為整型。如果無(wú)法轉(zhuǎn)換則返回null。對(duì)于無(wú)法轉(zhuǎn)換的類(lèi)型直接返回null。

其它類(lèi)型如String,Double以處理方法與此一致。

最后修改getCellValue,代碼如下。

private final static Map<Class<?>,TypeHandler> typeHandlerMap = new HashMap<>(); static { typeHandlerMap.put(Integer.class, new IntegerHandler()); typeHandlerMap.put(Double.class, new DoubleHandler()); typeHandlerMap.put(String.class, new StringHandler()); } private static Object getCellValue(Cell cell,Field field) { TypeHandler handler = typeHandlerMap.get(field.getType()); if(handler == null) { return null; } return handler.handle(cell, field); }

3 使用注解添加輔助功能

1,2中講述了基本的導(dǎo)入功能實(shí)現(xiàn)。而對(duì)字段排序,驗(yàn)證等還可以結(jié)合自定義注解來(lái)完成,也就是在獲取對(duì)象Field時(shí),拿到注解并獲取相關(guān)參數(shù),最后完成校驗(yàn)排序等功能。

4 完整代碼

private final static Map<Class<?>,TypeHandler> typeHandlerMap = new HashMap<>(); static { typeHandlerMap.put(Integer.class, new IntegerHandler()); typeHandlerMap.put(Double.class, new DoubleHandler()); typeHandlerMap.put(String.class, new StringHandler()); } public static <T> List<T> importExcel(File excelFile,Class<T> type) throws InvalidFormatException, IOException, InstantiationException, IllegalAccessException { XSSFWorkbook workBook = new XSSFWorkbook(excelFile); List<T> result = new ArrayList<T>(); XSSFSheet sheet = workBook.getSheetAt(0); for(int ri = sheet.getFirstRowNum() + 1 ; ri <= sheet.getLastRowNum(); ri++) { Row row = sheet.getRow(ri); T object = type.newInstance(); Field[] fields = object.getClass().getDeclaredFields(); Field.setAccessible(fields, true); for(int ci = row.getFirstCellNum(); ci < row.getLastCellNum(); ci++) { Cell cell = row.getCell(ci); Object value = getCellValue(cell,fields[ci]); fields[ci].set(object, value); } result.add(object); Field.setAccessible(fields, false); } return result; } private static Object getCellValue(Cell cell,Field field) { TypeHandler handler = typeHandlerMap.get(field.getType()); if(handler == null) { return null; } return handler.handle(cell, field); }public interface TypeHandler { public Object handle(Cell cell,Field field);}public class IntegerHandler implements TypeHandler{ @Override public Object handle(Cell cell, Field field) { int type = cell.getCellType(); if(type == Cell.CELL_TYPE_NUMERIC) { return (int)cell.getNumericCellValue(); } else if(type == Cell.CELL_TYPE_STRING) { try { return Integer.valueOf(cell.getStringCellValue()); }catch(NumberFormatException e) { return null; } } else { return null; } }}public class DoubleHandler implements TypeHandler{ @Override public Object handle(Cell cell, Field field) { int type = cell.getCellType(); if(type == Cell.CELL_TYPE_NUMERIC) { return cell.getNumericCellValue(); } else if(type == Cell.CELL_TYPE_STRING) { try { return Double.valueOf(cell.getNumericCellValue()); }catch(NumberFormatException e) { return null; } } else { return null; } }}public class StringHandler implements TypeHandler{ @Override public Object handle(Cell cell, Field field) { int type = cell.getCellType(); if(type != Cell.CELL_TYPE_STRING) { return ""; } else { return cell.getStringCellValue(); } }}

使用時(shí)要根據(jù)實(shí)際情況調(diào)整或新增handler即可。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 成人免费毛片高清视频 | 午夜高清视频 | 国产精品一区免费观看 | 三级性视频 | 成人久久久精品乱码一区二区三区 | 久久精品久久久久久 | 一级二级在线观看 | 亚洲欧美综合精品久久成人 | av一区二区在线观看 | 欧美一级欧美三级在线观看 | 看亚洲a级一级毛片 | 激情综合色综合久久综合 | 在线观看一区 | 精品影视一区二区 | 国产精品久久国产精品 | 午夜精品久久久久久久久久久久 | 午夜精品福利一区二区三区蜜桃 | 少妇一区二区三区 | 成人精品视频99在线观看免费 | 成人国产精品一区二区毛片在线 | 2022中文字幕 | 日韩av视屏 | 成人精品在线视频 | 一区二区精品 | 国产99久久 | 少妇裸体淫交免费视频 | 欧美国产精品一区 | 国产二区三区 | 欧美精品网站 | 免费一区二区三区 | 亚洲一区| 日韩欧美一级在线 | 艹逼网 | 在线碰| 日本天堂一区二区 | www.啪啪 | 国产一区久久 | 国产成人精品网站 | 中文字幕成人在线视频 | 视色视频在线观看 | 欧美成人精精品一区二区频 |