在java poi導(dǎo)入Excel通用工具類示例詳解
前言
本文主要給大家介紹了關(guān)于java poi導(dǎo)入Excel通用工具類的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
問題引入和分析
提示:如果不想看羅嗦的文章,可以直接到最后點擊源碼下載運(yùn)行即可
最近在做一個導(dǎo)入Excel的功能,在做之前在百度上面查找“java通用導(dǎo)入Excel工具類”,沒有查到,大多數(shù)都是java通用導(dǎo)出Excel。后來仔細(xì)想想,導(dǎo)出可以利用java的反射,做成通用的,放進(jìn)相應(yīng)的實體成員變量中,導(dǎo)入為什么不可以呢?也是可以的,不過在做之前我們要解決如下兩個問題:
1.表格中的列數(shù)和順序要和實體類中的成員變量個數(shù)和順序一致。
2.表格中的列的類型要和成員變量的類型一致。
第一個問題:
列數(shù)一致可以做到,但是我們最后都是要插入數(shù)據(jù)庫的。那么id是必不可少的,或者良好的習(xí)慣可能還有創(chuàng)建時間,創(chuàng)建人等信息。
所以我想到了兩個辦法:
1.封裝一個Vo,只將需要的字段封裝進(jìn)去,并且字段順序和表格列的順序一致,再將vo與實體類po轉(zhuǎn)化(用PropertyUtil.copy
方法);
2.在需要的成員變量上注入自定義注解,并且加入注解的這些字段順序和表格列的順序一致,利用反射得到這些字段。
這里主要利用第二個方法,因為擴(kuò)展性更好
第二個問題:
獲取表格數(shù)據(jù)的時候,我們要判斷類型,并取得相應(yīng)值,全部轉(zhuǎn)化為String類型,當(dāng)我們給實體類賦值的時候,利用反射獲取需要的成員變量的類型,并賦值。
需求
假設(shè)我們需求的excel如下:
我們可以看做兩部分:
第一部分:
第二行到第11行,為一個列表數(shù)據(jù),共有字段5個,分別為:學(xué)號,姓名,身份證號碼,性別,分?jǐn)?shù)
第二部分:
第12行第五列,第12行第六列,共有字段2個,分別為:總計,平均
項目
需要導(dǎo)入的jar包
1.poi的相關(guān)jar包,主要用來處理excel
2.beanutils 利用反射為成員變量賦值
3.commons-lang String判斷非空的方法,可以不用自己判斷
如若maven項目導(dǎo)入下面的jar包
<!-- poi操作excel --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.8</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.8</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.8</version> </dependency> <!-- beanutils --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.8.3</version> </dependency> <!-- commons-lang--> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency>
非maven項目導(dǎo)入下面的jar(下面例子當(dāng)中用到的jar,有些沒用到,可自行處理)
commons-beanutils-1.8.3.jar commons-lang-2.6.jar commons-logging-1.1.jar dom4j-1.6.1.jar log4j-1.2.13.jar poi-3.8-20120326.jar poi-excelant-3.8-20120326.jar poi-ooxml-3.8-20120326.jar poi-ooxml-schemas-3.8-20120326.jar poi-scratchpad-3.8-20120326.jar stax-api-1.0.1.jar xmlbeans-2.3.0.jar
項目結(jié)構(gòu)
工具類
package com.dao.chu.excel; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang.StringUtils; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFWorkbook; 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; /** * * excel讀取工具類 * * @author daochuwenziyao * @see [相關(guān)類/方法] * @since [產(chǎn)品/模塊版本] */ public class ImportExeclUtil { private static int totalRows = 0;// 總行數(shù) private static int totalCells = 0;// 總列數(shù) private static String errorInfo;// 錯誤信息 /** 無參構(gòu)造方法 */ public ImportExeclUtil() { } public static int getTotalRows() { return totalRows; } public static int getTotalCells() { return totalCells; } public static String getErrorInfo() { return errorInfo; } /** * * 根據(jù)流讀取Excel文件 * * * @param inputStream * @param isExcel2003 * @return * @see [類、類#方法、類#成員] */ public List<List<String>> read(InputStream inputStream, boolean isExcel2003) throws IOException { List<List<String>> dataLst = null; /** 根據(jù)版本選擇創(chuàng)建Workbook的方式 */ Workbook wb = null; if (isExcel2003) { wb = new HSSFWorkbook(inputStream); } else { wb = new XSSFWorkbook(inputStream); } dataLst = readDate(wb); return dataLst; } /** * * 讀取數(shù)據(jù) * * @param wb * @return * @see [類、類#方法、類#成員] */ private List<List<String>> readDate(Workbook wb) { List<List<String>> dataLst = new ArrayList<List<String>>(); /** 得到第一個shell */ Sheet sheet = wb.getSheetAt(0); /** 得到Excel的行數(shù) */ totalRows = sheet.getPhysicalNumberOfRows(); /** 得到Excel的列數(shù) */ if (totalRows >= 1 && sheet.getRow(0) != null) { totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } /** 循環(huán)Excel的行 */ for (int r = 0; r < totalRows; r++) { Row row = sheet.getRow(r); if (row == null) { continue; } List<String> rowLst = new ArrayList<String>(); /** 循環(huán)Excel的列 */ for (int c = 0; c < getTotalCells(); c++) { Cell cell = row.getCell(c); String cellValue = ""; if (null != cell) { // 以下是判斷數(shù)據(jù)的類型 switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 數(shù)字 cellValue = cell.getNumericCellValue() + ""; break; case HSSFCell.CELL_TYPE_STRING: // 字符串 cellValue = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean cellValue = cell.getBooleanCellValue() + ""; break; case HSSFCell.CELL_TYPE_FORMULA: // 公式 cellValue = cell.getCellFormula() + ""; break; case HSSFCell.CELL_TYPE_BLANK: // 空值 cellValue = ""; break; case HSSFCell.CELL_TYPE_ERROR: // 故障 cellValue = "非法字符"; break; default: cellValue = "未知類型"; break; } } rowLst.add(cellValue); } /** 保存第r行的第c列 */ dataLst.add(rowLst); } return dataLst; } /** * * 按指定坐標(biāo)讀取實體數(shù)據(jù) * <按順序放入帶有注解的實體成員變量中> * * @param wb 工作簿 * @param t 實體 * @param in 輸入流 * @param integers 指定需要解析的坐標(biāo) * @return T 相應(yīng)實體 * @throws IOException * @throws Exception * @see [類、類#方法、類#成員] */ @SuppressWarnings("unused") public static <T> T readDateT(Workbook wb, T t, InputStream in, Integer[]... integers) throws IOException, Exception { // 獲取該工作表中的第一個工作表 Sheet sheet = wb.getSheetAt(0); // 成員變量的值 Object entityMemberValue = ""; // 所有成員變量 Field[] fields = t.getClass().getDeclaredFields(); // 列開始下標(biāo) int startCell = 0; /** 循環(huán)出需要的成員 */ for (int f = 0; f < fields.length; f++) { fields[f].setAccessible(true); String fieldName = fields[f].getName(); boolean fieldHasAnno = fields[f].isAnnotationPresent(IsNeeded.class); // 有注解 if (fieldHasAnno) { IsNeeded annotation = fields[f].getAnnotation(IsNeeded.class); boolean isNeeded = annotation.isNeeded(); // Excel需要賦值的列 if (isNeeded) { // 獲取行和列 int x = integers[startCell][0] - 1; int y = integers[startCell][1] - 1; Row row = sheet.getRow(x); Cell cell = row.getCell(y); if (row == null) { continue; } // Excel中解析的值 String cellValue = getCellValue(cell); // 需要賦給成員變量的值 entityMemberValue = getEntityMemberValue(entityMemberValue, fields, f, cellValue); // 賦值 PropertyUtils.setProperty(t, fieldName, entityMemberValue); // 列的下標(biāo)加1 startCell++; } } } return t; } /** * * 讀取列表數(shù)據(jù) * <按順序放入帶有注解的實體成員變量中> * * @param wb 工作簿 * @param t 實體 * @param beginLine 開始行數(shù) * @param totalcut 結(jié)束行數(shù)減去相應(yīng)行數(shù) * @return List<T> 實體列表 * @throws Exception * @see [類、類#方法、類#成員] */ @SuppressWarnings("unchecked") public static <T> List<T> readDateListT(Workbook wb, T t, int beginLine, int totalcut) throws Exception { List<T> listt = new ArrayList<T>(); /** 得到第一個shell */ Sheet sheet = wb.getSheetAt(0); /** 得到Excel的行數(shù) */ totalRows = sheet.getPhysicalNumberOfRows(); /** 得到Excel的列數(shù) */ if (totalRows >= 1 && sheet.getRow(0) != null) { totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } /** 循環(huán)Excel的行 */ for (int r = beginLine - 1; r < totalRows - totalcut; r++) { Object newInstance = t.getClass().newInstance(); Row row = sheet.getRow(r); if (row == null) { continue; } // 成員變量的值 Object entityMemberValue = ""; // 所有成員變量 Field[] fields = t.getClass().getDeclaredFields(); // 列開始下標(biāo) int startCell = 0; for (int f = 0; f < fields.length; f++) { fields[f].setAccessible(true); String fieldName = fields[f].getName(); boolean fieldHasAnno = fields[f].isAnnotationPresent(IsNeeded.class); // 有注解 if (fieldHasAnno) { IsNeeded annotation = fields[f].getAnnotation(IsNeeded.class); boolean isNeeded = annotation.isNeeded(); // Excel需要賦值的列 if (isNeeded) { Cell cell = row.getCell(startCell); String cellValue = getCellValue(cell); entityMemberValue = getEntityMemberValue(entityMemberValue, fields, f, cellValue); // 賦值 PropertyUtils.setProperty(newInstance, fieldName, entityMemberValue); // 列的下標(biāo)加1 startCell++; } } } listt.add((T)newInstance); } return listt; } /** * * 根據(jù)Excel表格中的數(shù)據(jù)判斷類型得到值 * * @param cell * @return * @see [類、類#方法、類#成員] */ private static String getCellValue(Cell cell) { String cellValue = ""; if (null != cell) { // 以下是判斷數(shù)據(jù)的類型 switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 數(shù)字 if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) { Date theDate = cell.getDateCellValue(); SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd"); cellValue = dff.format(theDate); } else { DecimalFormat df = new DecimalFormat("0"); cellValue = df.format(cell.getNumericCellValue()); } break; case HSSFCell.CELL_TYPE_STRING: // 字符串 cellValue = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean cellValue = cell.getBooleanCellValue() + ""; break; case HSSFCell.CELL_TYPE_FORMULA: // 公式 cellValue = cell.getCellFormula() + ""; break; case HSSFCell.CELL_TYPE_BLANK: // 空值 cellValue = ""; break; case HSSFCell.CELL_TYPE_ERROR: // 故障 cellValue = "非法字符"; break; default: cellValue = "未知類型"; break; } } return cellValue; } /** * * 根據(jù)實體成員變量的類型得到成員變量的值 * * @param realValue * @param fields * @param f * @param cellValue * @return * @see [類、類#方法、類#成員] */ private static Object getEntityMemberValue(Object realValue, Field[] fields, int f, String cellValue) { String type = fields[f].getType().getName(); switch (type) { case "char": case "java.lang.Character": case "java.lang.String": realValue = cellValue; break; case "java.util.Date": realValue = StringUtils.isBlank(cellValue) ? null : DateUtil.strToDate(cellValue, DateUtil.YYYY_MM_DD); break; case "java.lang.Integer": realValue = StringUtils.isBlank(cellValue) ? null : Integer.valueOf(cellValue); break; case "int": case "float": case "double": case "java.lang.Double": case "java.lang.Float": case "java.lang.Long": case "java.lang.Short": case "java.math.BigDecimal": realValue = StringUtils.isBlank(cellValue) ? null : new BigDecimal(cellValue); break; default: break; } return realValue; } /** * * 根據(jù)路徑或文件名選擇Excel版本 * * * @param filePathOrName * @param in * @return * @throws IOException * @see [類、類#方法、類#成員] */ public static Workbook chooseWorkbook(String filePathOrName, InputStream in) throws IOException { /** 根據(jù)版本選擇創(chuàng)建Workbook的方式 */ Workbook wb = null; boolean isExcel2003 = ExcelVersionUtil.isExcel2003(filePathOrName); if (isExcel2003) { wb = new HSSFWorkbook(in); } else { wb = new XSSFWorkbook(in); } return wb; } static class ExcelVersionUtil { /** * * 是否是2003的excel,返回true是2003 * * * @param filePath * @return * @see [類、類#方法、類#成員] */ public static boolean isExcel2003(String filePath) { return filePath.matches("^.+\\.(?i)(xls)$"); } /** * * 是否是2007的excel,返回true是2007 * * * @param filePath * @return * @see [類、類#方法、類#成員] */ public static boolean isExcel2007(String filePath) { return filePath.matches("^.+\\.(?i)(xlsx)$"); } } public static class DateUtil { // ======================日期格式化常量=====================// public static final String YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss"; public static final String YYYY_MM_DD = "yyyy-MM-dd"; public static final String YYYY_MM = "yyyy-MM"; public static final String YYYY = "yyyy"; public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; public static final String YYYYMMDD = "yyyyMMdd"; public static final String YYYYMM = "yyyyMM"; public static final String YYYYMMDDHHMMSS_1 = "yyyy/MM/dd HH:mm:ss"; public static final String YYYY_MM_DD_1 = "yyyy/MM/dd"; public static final String YYYY_MM_1 = "yyyy/MM"; /** * * 自定義取值,Date類型轉(zhuǎn)為String類型 * * @param date 日期 * @param pattern 格式化常量 * @return * @see [類、類#方法、類#成員] */ public static String dateToStr(Date date, String pattern) { SimpleDateFormat format = null; if (null == date) return null; format = new SimpleDateFormat(pattern, Locale.getDefault()); return format.format(date); } /** * 將字符串轉(zhuǎn)換成Date類型的時間 * <hr> * * @param s 日期類型的字符串<br> * datePattern :YYYY_MM_DD<br> * @return java.util.Date */ public static Date strToDate(String s, String pattern) { if (s == null) { return null; } Date date = null; SimpleDateFormat sdf = new SimpleDateFormat(pattern); try { date = sdf.parse(s); } catch (ParseException e) { e.printStackTrace(); } return date; } } }
自定義注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * 是否需要從解析excel賦值 * @author daochuwenziyao * @see [相關(guān)類/方法] * @since [產(chǎn)品/模塊版本] */ @Retention(value = RetentionPolicy.RUNTIME) @Target(value = {ElementType.FIELD}) public @interface IsNeeded { /** * 是否需要從解析excel賦值 * @return * true:需要 false:不需要 * @see [類、類#方法、類#成員] */ boolean isNeeded() default true; }
學(xué)生基本信息
import java.math.BigDecimal; /** * * 學(xué)生基本信息 * @author daochuwenziyao * @see [相關(guān)類/方法] * @since [產(chǎn)品/模塊版本] */ public class StudentBaseInfo { private Integer id; @IsNeeded private String no; @IsNeeded private String name; @IsNeeded private String idnum; @IsNeeded private String sex; @IsNeeded private BigDecimal grade; @Override public String toString() { return "StudentBaseInfo [id=" + id + ", no=" + no + ", name=" + name + ", idnum=" + idnum + ", sex=" + sex + ", grade=" + grade + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getIdnum() { return idnum; } public void setIdnum(String idnum) { this.idnum = idnum; } public BigDecimal getGrade() { return grade; } public void setGrade(BigDecimal grade) { this.grade = grade; } }
學(xué)生統(tǒng)計信息
/** * * 學(xué)生統(tǒng)計信息 * @author daochuwenziyao * @see [相關(guān)類/方法] * @since [產(chǎn)品/模塊版本] */ public class StudentStatistics { private Integer id; @IsNeeded private BigDecimal totalGrade; @IsNeeded private BigDecimal avgGrade; @Override public String toString() { return "StudentStatistics [id=" + id + ", totalGrade=" + totalGrade + ", avgGrade=" + avgGrade + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public BigDecimal getTotalGrade() { return totalGrade; } public void setTotalGrade(BigDecimal totalGrade) { this.totalGrade = totalGrade; } public BigDecimal getAvgGrade() { return avgGrade; } public void setAvgGrade(BigDecimal avgGrade) { this.avgGrade = avgGrade; } }
測試類
package com.dao.chu.excel; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.poi.ss.usermodel.Workbook; public class TestImportExcel { public static void main(String[] args) throws IOException, Exception { String fileName="student.xlsx"; InputStream in = new FileInputStream(new File("excelfile\\student.xlsx")); Workbook wb = ImportExeclUtil.chooseWorkbook(fileName, in); StudentStatistics studentStatistics = new StudentStatistics(); //讀取一個對象的信息 StudentStatistics readDateT = ImportExeclUtil.readDateT(wb, studentStatistics, in, new Integer[] {12, 5}, new Integer[] {13, 5}); System.out.println(readDateT); //讀取對象列表的信息 StudentBaseInfo studentBaseInfo = new StudentBaseInfo(); //第二行開始,到倒數(shù)第三行結(jié)束(總數(shù)減去兩行) List<StudentBaseInfo> readDateListT = ImportExeclUtil.readDateListT(wb, studentBaseInfo, 2, 2); System.out.println(readDateListT); } }
輸出結(jié)果
StudentStatistics [id=null, totalGrade=845, avgGrade=84] [StudentBaseInfo [id=null, no=2012240001, name=張三1, idnum=233314199009062304, sex=男, grade=80], StudentBaseInfo [id=null, no=2012240002, name=張三2, idnum=233314199009062304, sex=男, grade=81], StudentBaseInfo [id=null, no=2012240003, name=張三3, idnum=233314199009062304, sex=男, grade=82], StudentBaseInfo [id=null, no=2012240004, name=張三4, idnum=233314199009062304, sex=男, grade=83], StudentBaseInfo [id=null, no=2012240005, name=張三5, idnum=233314199009062304, sex=男, grade=84], StudentBaseInfo [id=null, no=2012240006, name=張三6, idnum=233314199009062304, sex=男, grade=85], StudentBaseInfo [id=null, no=2012240007, name=張三7, idnum=233314199009062304, sex=男, grade=86], StudentBaseInfo [id=null, no=2012240008, name=張三8, idnum=233314199009062304, sex=男, grade=87], StudentBaseInfo [id=null, no=2012240009, name=張三9, idnum=233314199009062304, sex=男, grade=88], StudentBaseInfo [id=null, no=2012240010, name=張三10, idnum=233314199009062304, sex=男, grade=89]]
源碼下載
源碼分享給大家,上面提到的都在這里,由于很多的數(shù)據(jù)類型沒有試驗到,可能會有些類型有問題,所以希望大家如果遇到問題回復(fù)我,我會將其完善。
源碼下載:http://xiazai.jb51.net/201709/yuanma/ImportExcelUtil(jb51.net).rar
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- JAVA使用POI獲取Excel的列數(shù)與行數(shù)
- java使用poi讀取ppt文件和poi讀取excel、word示例
- java使用poi讀取excel內(nèi)容方法實例
- Java利用POI讀取、寫入Excel的方法指南
- Java利用POI實現(xiàn)導(dǎo)入導(dǎo)出Excel表格示例代碼
- Java 使用poi把數(shù)據(jù)庫中數(shù)據(jù)導(dǎo)入Excel的解決方法
- java poi讀取excel操作示例(2個代碼)
- java的poi技術(shù)讀取和導(dǎo)入Excel實例
- Java 使用POI生成帶聯(lián)動下拉框的excel表格實例代碼
- Java中利用POI優(yōu)雅的導(dǎo)出Excel文件詳解
相關(guān)文章
基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實例
HTML5 WebSocket實現(xiàn)了服務(wù)器與瀏覽器的雙向通訊,本篇文章主要介紹了基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實例,具有一定的參考價值,有興趣的可以了解一下。2016-12-12SpringBoot如何實現(xiàn)Tomcat自動配置
這篇文章主要介紹了SpringBoot如何實現(xiàn)Tomcat自動配置,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot框架,感興趣的朋友可以了解下2021-03-03SpringBoot2實現(xiàn)MessageQueue消息隊列
本文主要介紹了 SpringBoot2實現(xiàn)MessageQueue消息隊列,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04