日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java开发小技巧(六):使用Apache POI读取Excel

發布時間:2025/3/20 java 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java开发小技巧(六):使用Apache POI读取Excel 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在數據倉庫中,ETL最基礎的步驟就是從數據源抽取所需的數據,這里所說的數據源并非僅僅是指數據庫,還包括excel、csv、xml等各種類型的數據接口文件,而這些文件中的數據不一定是結構化存儲的,比如各種各樣的報表文件,往往是一些復雜的表格結構,其中不僅有我們需要的數據,還有一些冗余的、無價值的數據,這時我們就無法直接用一般數據加載工具直接讀取入庫了。也許你會想,數據源導出文件前先處理好數據就行了。然而,實際開發中數據源往往是多個的,而且涉及到不同的部門甚至公司,這其間難免會出現各種麻煩,甚至有些數據文件還是純手工處理的,不一定能給到你滿意的數據格式。所以我們不討論誰該負責轉換的問題,這里主要介紹如何使用Apache POI來從Excel數據文件中讀取我們想要的數據,以及用Bean Validation對數據內容按照預定的規則進行校驗。

文章要點:

  • Apache POI是什么
  • 如何使用Apache POI讀取Excel文件
  • 使用Bean Validation進行數據校驗
  • Excel讀取工具類
  • 使用實例

Apache POI是什么

Apache POI是用Java編寫的免費開源的跨平臺的Java API,提供API給Java程式對Microsoft Office格式檔案進行讀和寫的操作。


如何使用Apache POI處理Excel文件

1、導入Maven依賴

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version> </dependency> <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version> </dependency> <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.17</version> </dependency> <dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.17</version> </dependency>

2、創建Workbook實例

這里需要注意的是Excel文檔的版本問題,Excel2003及以前版本的文檔使用HSSFWorkbook對象,Excel2007及之后版本使用HSSFWorkbook對象

// Excel2003及以前版本 Workbook workbook = new XSSFWorkbook(new FileInputStream(path)); // Excel2007及之后版本 Workbook workbook = new HSSFWorkbook(new FileInputStream(path));

3、獲取Sheet表格頁對象

Sheet是Excel文檔中的工作簿即表格頁面,讀取前要先找到數據所在頁面,可以通過標簽名或者索引的方式獲取指定Sheet對象

// 按索引獲取 Sheet sheet = workbook.getSheetAt(index); // 按標簽名獲取 Sheet sheet = workbook.getSheet(label);

4、獲取Cell單元格對象

// 行索引row和列索引col都是以 0 起始 Cell cell = sheet.getRow(row).getCell(col);

5、獲取單元格內容

獲取單元格的值之前首先要獲知單元格內容的類型,在Excel中單元格有6種類型:

  • CELL_TYPE_BLANK :空值
  • CELL_TYPE_BOOLEAN :布爾型
  • CELL_TYPE_ERROR : 錯誤
  • CELL_TYPE_FORMULA :公式型
  • CELL_TYPE_STRING:字符串型
  • CELL_TYPE_NUMERIC:數值型
  • 各種類型的內容還需要進一步判斷其數據格式,例如單元格的Type為CELL_TYPE_NUMERIC時,它有可能是Date類型,在Excel中的Date類型是以Double類型的數字存儲的,不同類型的值要調用cell對象相應的方法去獲取,具體情況具體分析

    public Object getCellValue(Cell cell) {if(cell == null) {return null;}switch (cell.getCellType()) {case Cell.CELL_TYPE_STRING:return cell.getRichStringCellValue().getString();case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {return cell.getDateCellValue();} else {return cell.getNumericCellValue();}case Cell.CELL_TYPE_BOOLEAN:return cell.getBooleanCellValue();case Cell.CELL_TYPE_FORMULA:return formula.evaluate(cell).getNumberValue();default:return null;} }

    6、關閉Workbook對象

    workbook.close();

    使用Bean Validation進行數據校驗

    當你要處理一個業務邏輯時,數據校驗是你不得不考慮和面對的事情,程序必須通過某種手段來確保輸入進來的數據從語義上來講是正確的或者符合預定義的格式,一個Java程序一般是分層設計的,而不同的層可能是不同的開發人員來完成,這樣就很容易出現不同的層重復進行數據驗證邏輯,導致代碼冗余等問題。為了避免這樣的情況發生,最好是將驗證邏輯與相應的模型進行綁定。

    Bean Validation 規范的目標就是避免多層驗證的重復性,它提供了對 Java EE 和 Java SE 中的 Java Bean 進行驗證的方式。該規范主要使用注解的方式來實現對 Java Bean 的驗證功能,從而使驗證邏輯從業務代碼中分離出來。

    Hibernate Validator 是 Bean Validation 規范的參考實現,我們可以用它來實現數據驗證邏輯,其Maven依賴如下:

    <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.1.3.Final</version> </dependency> <dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version> </dependency>

    關于Bean Validation的詳細介紹可參考以下文章:
    JSR 303 - Bean Validation 介紹及最佳實踐
    Bean Validation 技術規范特性概述


    Excel讀取工具類

    我們要達到的效果是,模擬游標的方式構建一個Excel讀取工具類ExcelReadHelper,然后加載Excel文件流來創建工具類實例,通過這個實例我們可以像游標一樣設置當前的行和列,定好位置之后讀取出單元格的值并進行校驗,完成對Excel文件的讀取校驗操作。既然是讀取還有校驗數據,異常處理和提示當然是至關重要的,所以還要有人性化的異常處理方式,方便程序使用者發現Excel中格式或內容有誤的地方,具體到哪一行哪一項,出現的問題是什么。

    ExcelReadHelper工具類主體

    public class ExcelReadHelper {private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();//文件絕對路徑private String excelUrl;private Workbook workbook;private Sheet sheet;//Sheet總數private int sheetCount;//當前行private Row row;private Validator validator;public ExcelReadHelper(File excelFile) throws ExcelException {validator = factory.getValidator();excelUrl = excelFile.getAbsolutePath();//判斷工作簿版本String fileName = excelFile.getName();String suffix = fileName.substring(fileName.lastIndexOf("."));try {if(suffix.equals(".xlsx")) {workbook = new XSSFWorkbook(new FileInputStream(excelFile));} else if(suffix.equals(".xls")) {workbook = new HSSFWorkbook(new FileInputStream(excelFile));} else {throw new ExcelException("Malformed excel file");}} catch(Exception e) {throw new ExcelException(excelUrl, e);}sheetCount = workbook.getNumberOfSheets();}/*** 關閉工作簿* @throws ExcelException * @throws IOException*/public void close() throws ExcelException {if (workbook != null) {try {workbook.close();} catch (IOException e) {throw new ExcelException(excelUrl, e);}}}/*** 獲取單元格真實位置* @param row 行索引* @param col 列索引* @return [行,列]*/public String getCellLoc(Integer row, Integer col) {return String.format("[%s,%s]", row + 1, CellReference.convertNumToColString(col)); }/*** 根據標簽設置Sheet* @param labels* @throws ExcelException*/public void setSheetByLabel(String... labels) throws ExcelException {Sheet sheet = null;for(String label : labels) {sheet = workbook.getSheet(label);if(sheet != null) {break;}}if(sheet == null) {StringBuilder sheetStr = new StringBuilder();for (String label : labels) {sheetStr.append(label).append(",");}sheetStr.deleteCharAt(sheetStr.lastIndexOf(","));throw new ExcelException(excelUrl, sheetStr.toString(), "Sheet does not exist");}this.sheet = sheet;}/*** 根據索引設置Sheet* @param index* @throws ExcelException */public void setSheetAt(Integer index) throws ExcelException {Sheet sheet = workbook.getSheetAt(index);if(sheet == null) {throw new ExcelException(excelUrl, index + "", "Sheet does not exist");}this.sheet = sheet;}/*** 獲取單元格內容并轉為String類型* @param row 行索引* @param col 列索引* @return*/@SuppressWarnings("deprecation")public String getValueAt(Integer row, Integer col) {Cell cell = sheet.getRow(row).getCell(col);String value = null;if (cell != null) {switch (cell.getCellType()) {case Cell.CELL_TYPE_STRING:value = cell.getStringCellValue() + "";break;case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {value = cell.getDateCellValue().getTime() + "";} else {double num = cell.getNumericCellValue();if(num % 1 == 0) {value = Double.valueOf(num).intValue() + "";} else {value = num + "";}}break;case Cell.CELL_TYPE_FORMULA:value = cell.getNumericCellValue() + "";break;case Cell.CELL_TYPE_BOOLEAN:value = String.valueOf(cell.getBooleanCellValue()) + "";break;}}return (value == null || value.isEmpty()) ? null : value.trim();}/*** 獲取當前行指定列內容* @param col 列索引* @return*/public String getValue(Integer col) {return getValueAt(row.getRowNum(), col);}/*** 獲取Sheet名稱* @return*/public String getSheetLabel() {String label = null;if(sheet != null) {label = sheet.getSheetName();}return label;}/*** 行偏移* @param offset 偏移量* @return*/public Boolean offsetRow(Integer offset) {Boolean state = true;if(row == null) {row = sheet.getRow(offset-1);} else {row = sheet.getRow(row.getRowNum() + offset);if(row == null) {state = false;}}return state;}/*** 設置行* @param index 索引* @return*/public Boolean setRow(Integer index) {row = sheet.getRow(index);return row != null;}/*** 偏移一行* @return*/public Boolean nextRow() {return offsetRow(1);}/*** 偏移到下一個Sheet* @return*/public Boolean nextSheet() {Boolean state = true;if(sheet == null) {sheet = workbook.getSheetAt(0);} else {int index = workbook.getSheetIndex(sheet) + 1;if(index >= sheetCount) {sheet = null;} else {sheet = workbook.getSheetAt(index);}if(sheet == null) {state = false;}}row = null;return state;}/*** 數據校驗* @param obj 校驗對象* @throws ExcelException*/public <T> void validate(T obj) throws ExcelException {Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj);if(constraintViolations.size() > 0) {Iterator<ConstraintViolation<T>> iterable = constraintViolations.iterator();ConstraintViolation<T> cv = iterable.next();throw new ExcelException(excelUrl, sheet.getSheetName(), row.getRowNum() + 1 + "", String.format("%s=%s:%s", cv.getPropertyPath(), cv.getInvalidValue(), cv.getMessage()));}}/*** 拋出當前Sheet指定行異常* @param row 異常發生行索引* @param message 異常信息* @return*/public ExcelException excelRowException(Integer row, String message) {return new ExcelException(excelUrl, sheet.getSheetName(), row + 1 + "", message);}/*** 拋出當前行異常* @param message 異常信息* @return*/public ExcelException excelCurRowException(String message) {return new ExcelException(excelUrl, sheet.getSheetName(), row.getRowNum() + 1 + "", message);}/*** 拋出自定義異常* @param message 異常信息* @return*/public ExcelException excelException(String message) {return new ExcelException(excelUrl, message);} }

    ExcelException異常類

    public class ExcelException extends Exception {public ExcelException() {super();}public ExcelException(String message) {super(message);}public ExcelException(String url, String message) {super(String.format("EXCEL[%s]:%s", url, message));}public ExcelException(String url, String sheet, String message) {super(String.format("EXCEL[%s],SHEET[%s]:%s", url, sheet, message));}public ExcelException(String url, String sheet, String row, String message) {super(String.format("EXCEL[%s],SHEET[%s],ROW[%s]:%s", url, sheet, row, message));}public ExcelException(String url, Throwable cause) {super(String.format("EXCEL[%s]", url), cause);}}

    使用實例

    // 使用Excel文件對象初始化ExcelReadHelper ExcelReadHelper excel = new ExcelReadHelper(file);// 第一頁 excel.setSheetAt(0);// “Sheet1”頁 excel.setSheetByLabel("Sheet1");// 下一頁 excel.nextSheet();// 第一行(以 0 起始) excel.setRow(0);// 下一行 excel.nextRow();// 偏移兩行 excel.offsetRow(2);// 當前行第一列的值 String value1 = excel.getValue(0);// 第一行第一列的值 String value2 = excel.getValueAt(0,0);// 獲取單元格真實位置(如索引都為0時結果為[1,A]) String location = excel.getCellLoc(0,0);// 當前頁標題(如“Sheet1”) String label = excel.getSheetLabel();// 校驗讀取的數據 try {excel.validate(obj); } catch (ExcelException e) {// 錯誤信息中包含具體錯誤位置以及原因e.printStackTrace(); }//拋出異常,結果自動包含出現異常的Excel路徑 throw excel.excelException(message);//拋出指定行異常,結果自動包含出現錯誤的Excel路徑、當前頁位置 throw excel.excelRowException(0, message);//拋出當前行異常,結果自動包含出現錯誤的Excel路徑、當前頁、當前行位置 throw excel.excelCurRowException(message);//關閉工作簿Workbook對象 excel.close();

    本文為作者kMacro原創,轉載請注明來源:https://zkhdev.github.io/2018/10/14/java-dev6/

    轉載于:https://www.cnblogs.com/zkh101/p/9786974.html

    總結

    以上是生活随笔為你收集整理的Java开发小技巧(六):使用Apache POI读取Excel的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 天堂av中文 | 看了让人下面流水的视频 | 最近最新mv字幕观看 | 午夜亚洲视频 | 亚洲综合伊人 | 小俊大肉大捧一进一出好爽 | 亚洲欧美日韩国产综合 | 亚洲av无码乱码在线观看富二代 | 看国产毛片 | 污站在线观看 | 超碰成人97 | 黄色特一级 | 亚洲色图 校园春色 | 韩国日本欧美一区 | 丝袜国产在线 | 日韩欧美高清片 | 日韩美女国产精品 | 九色视频网站 | 日本香蕉视频 | 亚洲乱码国产乱码精品精大量 | 福利网址在线观看 | 中文字幕乱码人妻无码久久95 | 在线观看黄色av网站 | 人妖被c到高潮欧美gay | 热热久| 国产精品女优 | 男人插入女人阴道视频 | 少妇无内裤下蹲露大唇视频 | 亚洲成年人av | 成人网站免费观看入口 | 91在线无精精品白丝 | 亚洲色图国产 | 性欢交69精品久久久 | 樱桃av| 91在线色| 卡通动漫av| 少妇太紧太爽又黄又硬又爽 | 龚玥菲一级淫片 | 黑人玩弄人妻一区二区三区影院 | 日本欧美韩国国产精品 | 成人性生活免费视频 | 欧美精品久久久久久久久久 | 久久精品午夜 | 毛片在线免费 | 国产在线h | 日本少妇电影 | 欧美性做爰猛烈叫床潮 | 日本成人午夜 | 九热精品| 亚洲国内自拍 | 久久久久久久久国产精品一区 | 先锋资源av | 国产粉嫩一区二区三区 | 日韩高清免费av | 五月天婷婷在线视频 | 日日夜夜综合网 | 好男人.www | 日韩欧美在线观看免费 | 久久久免费观看 | 熟女精品一区二区三区 | 久久国产精品毛片 | 欧美丝袜视频 | 国产电影一区二区三区爱妃记 | 激情午夜影院 | 丝袜一级片 | 激情图片在线视频 | a级片一级片 | 久久久免费在线观看 | 日本特黄一级大片 | 亚洲永久无码精品 | 国产精品视频免费播放 | 国产成人精品视频ⅴa片软件竹菊 | 欧美一级成人 | 亚洲无码精品在线播放 | 小泽玛利亚一区二区三区 | 久久国产传媒 | 精品欧美一区二区三区在线观看 | 51成人| 91视频99| 米奇影视第四色 | 高清一级片| 亚洲视频大全 | 欧美三日本三级少妇99 | 成人亚洲一区二区 | 久久成人综合 | 国语毛片 | 成人羞羞国产免费游戏 | 性生活网址| 久草精品视频 | 偷偷操网站 | 亚洲欧洲视频在线观看 | 免费古装一级淫片潘金莲 | 亚洲一区二区三区网站 | 在线免费观看毛片 | 日本色悠悠 | 免费精品无码AV片在线观看黄 | 九色视频在线观看 | 国产毛茸茸 | 亚洲欧美激情图片 |