1. 程式人生 > >匯入Excel時,根據註解生成實體類

匯入Excel時,根據註解生成實體類

  • 一、環境說明:win10專業版、jdk1.8.0_171、eclipse4.7.3a、Junit5
  • 二、建立maven工程,引入pom依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.szcatic</groupId>
  <artifactId>import</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  	<!-- HSSFWorkbook所需jar包 -->
	<dependency>
	    <groupId>org.apache.poi</groupId>
	    <artifactId>poi</artifactId>
	    <version>4.0.0</version>
	</dependency>
	<!-- XSSFWorkbook所需jar包 -->
	<dependency>
	    <groupId>org.apache.poi</groupId>
	    <artifactId>poi-ooxml</artifactId>
	    <version>4.0.0</version>
	</dependency>
	<!-- log4j2所需jar包 -->
	<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-api</artifactId>
	    <version>2.11.0</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-core</artifactId>
	    <version>2.11.0</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-slf4j-impl</artifactId>
	    <version>2.11.0</version>
	</dependency>
	<dependency>
	    <groupId>org.slf4j</groupId>
	    <artifactId>slf4j-api</artifactId>
	    <version>1.7.25</version>
	</dependency>
	<!-- junit5執行所需jar包 -->
	<dependency>
	    <groupId>org.junit.jupiter</groupId>
	    <artifactId>junit-jupiter-engine</artifactId>
	    <version>5.2.0</version>
	    <scope>test</scope>
	</dependency>
	<dependency>
	    <groupId>org.junit.platform</groupId>
	    <artifactId>junit-platform-runner</artifactId>
	    <version>1.2.0</version>
	    <scope>test</scope>
	</dependency>
  </dependencies>
</project>
  • 三、詳細程式碼:
  1. 註解介面
    package com.szcatic.service;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * Excel註解定義
     * @author zsx
     * @version 2018-09-27
     */
    @Target({ ElementType.METHOD, ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExcelField {
    	
    	// 列名
    	String name() default "";
    
    }
  2. 實體類
    package com.szcatic.entity;
     
    import java.io.Serializable;
    import java.math.BigDecimal;
    import java.util.Date;
    
    import com.szcatic.service.ExcelField;
     
    /**
     * 使用者實體類
     * @author zsx
     * @version 2018-09-27
     */
    public class User implements Serializable {
     
    	private static final long serialVersionUID = 1L;
    	
    	@ExcelField(name="使用者名稱")
    	private String userName; // 使用者名稱
    	
    	@ExcelField(name="密碼")
    	private String password; // 密碼
    	
    	@ExcelField(name="年齡")
    	private Integer age; // 年齡
    	
    	@ExcelField(name="性別")
    	private String gender; // 性別
    	
    	@ExcelField(name="郵箱")
    	private String email; // 郵箱
    	
    	@ExcelField(name="時間")
    	private Date date; // 時間
    	
    	@ExcelField(name="花費")
    	private BigDecimal cost; // 花費
    	
    	
    	public String getUserName() {
    		return userName;
    	}
     
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    	
    	public String getPassword() {
    		return password;
    	}
     
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	
    	
    	public Integer getAge() {
    		return age;
    	}
     
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    	
    	public String getGender() {
    		return gender;
    	}
    	
    	public void setGender(String gender) {
    		this.gender = gender;
    	}
     
    	public String getEmail() {
    		return email;
    	}
    	
    	public void setEmail(String email) {
    		this.email = email;
    	}
     
    	public Date getDate() {
    		return date;
    	}
    
    	public void setDate(Date date) {
    		this.date = date;
    	}
    	
    	public BigDecimal getCost() {
    		return cost;
    	}
    
    	public void setCost(BigDecimal cost) {
    		this.cost = cost;
    	}
    
    	@Override
    	public String toString() {
    		return "User [userName=" + userName + ", password=" + password + ", age=" + age + ", gender=" + gender
    				+ ", email=" + email + ", date=" + date + ", cost=" + cost + "]";
    	}
     
     
    }
     
    
  3. 工具類
    package com.szcatic.util;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.math.BigDecimal;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.commons.compress.utils.Lists;
    import org.apache.poi.hssf.usermodel.HSSFDateUtil;
    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;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.szcatic.service.ExcelField;
    
    /**
     * 匯入工具類
     * @author zsx
     * @version 2018-09-27
     */
    public class ExcelImportUtils {
    	
    	private static Logger logger = LoggerFactory.getLogger(ExcelImportUtils.class);
    	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	
    	public static <E> List<E> readFile(File file, Class<E> clzz) {
    		return readFile(file, clzz, ExcelField.class, "name");
    	}
    	
    	 /**
         * 從檔案讀取資料
         * @param file:Excel檔案,第一行為列標題
         * @param clzz:對映生成的實體類
         * @param annotationClass:註解類
         * @param methodName:註解類中對列應名的方法
         * @return List
         */
        public static <E, T extends Annotation> List<E> readFile(File file, Class<E> clzz, 
        		Class<T> annotationClass, String methodName) {
        	Workbook wb = null;
    		try {
    			if (file == null || !validateExcel(file.getName())) {
    				logger.error("檔案為空或者不是Excel型別的檔案");
    				return Lists.newArrayList();
    			}
    			InputStream is;
    			is = new FileInputStream(file);
    			//建立工作表
    			if (isExcel2003(file.getName())) {
    				wb = new HSSFWorkbook(is);
    			}else {
    				wb = new XSSFWorkbook(is);
    			}
    			return readExcel(clzz, wb, annotationClass, methodName);
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    			return Lists.newArrayList();
    		} catch (IOException e) {
    			e.printStackTrace();
    			return Lists.newArrayList();
    		}finally {
    			if (wb != null) {
    				try {
    					wb.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
        }
        
        /**
         * 讀取Excel內容,預設第一行為標題行
         * @param wb
         * @param file
         * @param map
         * @return
         */
        private static <E, T extends Annotation> List<E> readExcel(Class<E> clzz, Workbook wb, 
        		Class<T> annotationClass, String methodName) {
        	//獲取實體類的所有屬性
            Field[] fields = clzz.getDeclaredFields();
        	Map<String, String> map = getFieldMap(fields, annotationClass, methodName);
            Sheet sheet = wb.getSheetAt(0);
            Row title = sheet.getRow(0);
            int totalColumns = title.getPhysicalNumberOfCells();
            int totalRows = sheet.getPhysicalNumberOfRows();
            //獲取Excel所有的列標題
            String[] titles = getColumnTitle(title, totalColumns);
            List<E> list = new ArrayList<>();
            Cell cell;
            Row row;
            E e;
            //從第二行開始讀取資料
            for (int i = 1; i < totalRows; i++) {
            	row = sheet.getRow(i);
            	e = getNewInstance(clzz);
                for (int j = 0; j < totalColumns; j++) {
                    cell = row.getCell(j);
                    readCellContent(map.get(titles[j]), fields, cell, e);
                }
                list.add(e);
            }
            return list;
    
        }
        
        /**
         * 讀取單元格內容,並將內容新增到實體類E中
         * @param fieldName 當前單元格對應的Bean欄位
         * @param fields 屬性陣列
         * @param cell 單元格
         * @param e 實體類
         */
        private static <E> void readCellContent(String fieldName, Field[] fields, Cell cell, E e) {
    		Object obj = getCellValue(cell);
    		if (obj == null) {
    			return;
    		}
    		mappingValueToBean(fieldName, fields, obj, e);
    	}
        
        /**
         * 對映值到實體類
         * @param fieldName
         * @param fields
         * @param obj
         * @param e
         */
        private static <E> void mappingValueToBean(String fieldName, Field[] fields, Object obj, E e) {
    		try {
    			for (Field field : fields) {
    				if(!fieldName.equals(field.getName())) {
    					continue;
    				}
    			//設定私有屬性可以訪問
    			field.setAccessible(true);
    			field.set(e, getValue(field, obj));
    			break;
    			}
    		}catch (IllegalArgumentException e1) {
    			e1.printStackTrace();
    		}catch (IllegalAccessException e1) {
    			e1.printStackTrace();
    		}
        }
        
        /**
         * 將obj的值轉化為該屬性型別的值
         * @param field
         * @param obj
         * @return
         */
        private static Object getValue(Field field, Object obj) {
        	if(field.getType().equals(obj.getClass())) {
        		return obj;
    		}
        	Object obj2 = null;
        		try {
    	    		if(Date.class.equals(field.getType())) {
    	    			obj2 = sdf.parse(obj.toString());
    				}else if (String.class.equals(field.getType())) {
    					obj2 = String.valueOf(obj);
    				}else if (Long.class.equals(field.getType())) {
    					obj2 = Long.valueOf(obj.toString());
    				}else if (Integer.class.equals(field.getType())) {
    					obj2 = Integer.valueOf(obj.toString());
    				}else if (BigDecimal.class.equals(field.getType())) {
    					obj2 = new BigDecimal(obj.toString());
    				}else if (Boolean.class.equals(field.getType())) {
    					obj2 = Boolean.valueOf(obj.toString());
    				}else if (Float.class.equals(field.getType())) {
    					obj2 = Float.valueOf(obj.toString());
    				}else if (Double.class.equals(field.getType())) {
    					obj2 = Double.valueOf(obj.toString());
    				}
    			} catch (ParseException e) {
    				e.printStackTrace();
    			}
        	return obj2;
        }
        
        /**
    	 * 獲取單元格的值
    	 * @param cell
    	 * @return Object
    	 */
        private static Object getCellValue(Cell cell) {
    		Object obj;
    		// 以下是判斷資料的型別
            switch (cell.getCellType()) {
            case NUMERIC : // 數字
                obj = cell.getNumericCellValue();
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                	obj = HSSFDateUtil.getJavaDate((double) obj);
    			}
                break;
            case STRING : // 字串
                obj = cell.getStringCellValue();
                break;
            case BOOLEAN : // Boolean
                obj = cell.getBooleanCellValue();
                break;
            case FORMULA : // 公式
                obj = cell.getCellFormula();
                break;
            case BLANK : // 空值
                obj = null;
                break;
            case ERROR : // 故障
                obj = "非法字元";
                break;
            default:
                obj = "未知型別";
                break;
            }
            return obj;
    	}
        
        /**
         * 通過反射獲取T類的新例項
         * @param clzz
         * @return T
         */
        private static <T> T getNewInstance(Class<T> clzz) {
        	T t = null;
        	try {
    			t = clzz.newInstance();
    		} catch (InstantiationException e) {
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			e.printStackTrace();
    		}
        	return t;
        }
    
    	/**
         * 獲取列標題
         * @param title 列標題所在行
         * @param totalColumns 總列數
         * @return String[]
         */
        private static String[] getColumnTitle(Row title, int totalColumns) {
        	String[] titles = new String[totalColumns];
            for (int j = 0; j < totalColumns; j++) {
                titles[j] = title.getCell(j).getStringCellValue();
            }
            return titles;
        }
        
        /**
         * 獲取屬性和註解對應的集合
         * @param clzz
         * @param annotationClass
         * @param methodName
         * @return Map : key為屬性上的註解值,value為屬性名
         */
    	private static <T extends Annotation> Map<String, String> getFieldMap(Field[] fields, Class<T> annotationClass,
    			String methodName) {
            Map<String, String> map = new HashMap<>();
            T t;
            for (Field field : fields) {
            	//獲取屬性上T型別的註解
            	if(field.isAnnotationPresent(annotationClass)) {
            		t = field.getAnnotation(annotationClass);
                	map.put(String.valueOf(getMethodReturnValue(t, methodName)), field.getName());
    			}
            }
    		return map;
    	}
        
        /**
         * 獲取方法的返回值
         * @param T 實體類 
         * @param methodName 方法名
         * @return Object
         */
    	private static <T> Object getMethodReturnValue(T t, String methodName) {
        	Object obj = null;
        	try {
    			obj = t.getClass().getMethod(methodName).invoke(t);
    		}catch (NoSuchMethodException e) {
    			e.printStackTrace();
    	    }catch (SecurityException e) {
    	    	e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			e.printStackTrace();
    		} catch (IllegalArgumentException e) {
    			e.printStackTrace();
    		} catch (InvocationTargetException e) {
    			e.printStackTrace();
    		}
        	return obj;
        }
    	
    	/**
    	 * 驗證是否是Excel格式的檔案
    	 * @param fileName:檔名
    	 * @return boolean : true表示是Excel格式的檔案,false表示不是
    	 */
    	private static boolean validateExcel(String fileName) {
    		if (fileName == null || !(isExcel2003(fileName) || isExcel2007(fileName))) {
    			return false;
    		}
    		return true;
    	}
    	
    	/**
    	 * 判斷是不是2003格式的Excel
    	 * @param fileName
    	 * @return boolean : true表示是2003格式的Excel,false表示不是
    	 */
    	private static boolean isExcel2003(String fileName) {
    		return fileName.matches("^.+\\.(?i)(xls)$");
    	}
    	
    	/**
    	 * 判斷是不是2007格式的Excel
    	 * @param fileName
    	 * @return boolean : true表示是2007格式的Excel,false表示不是
    	 */
    	private static boolean isExcel2007(String fileName) {
    		return fileName.matches("^.+\\.(?i)(xlsx)$");
    	}
    	
    }
    
  4. l測試類

    package com.szcatic.test;
    
    import java.io.File;
    import java.util.List;
    
    import org.junit.jupiter.api.Test;
    
    import com.szcatic.entity.User;
    import com.szcatic.util.ExcelImportUtils;
    
    /**
     * 匯入Excel工具類測試類
     * @author zsx
     * @version 2018-09-27
     */
    public class ExcelImportUtilsTest {
    	
    	@Test
    	void testReadFile() {
    		File file = new File("D:/newProject/export.xls");
    		List<User> list = ExcelImportUtils.readFile(file, User.class);
    		System.out.println(list);
    		File file2 = new File("D:/newProject/export.xls");
    		List<User> list2 = ExcelImportUtils.readFile(file2, User.class);
    		System.out.println(list2);
    	}
    }
  5. 執行結果:

    [User [userName=zhangsan, password=1234, age=20, gender=男, [email protected], date=Thu Sep 27 00:00:00 CST 2018, cost=8555.55], User [userName=lisi, password=1234, age=25, gender=男, [email protected], date=Thu Sep 27 00:00:00 CST 2018, cost=6666.66]]
    [User [userName=zhangsan, password=1234, age=20, gender=男, [email protected], date=Thu Sep 27 00:00:00 CST 2018, cost=8555.55], User [userName=lisi, password=1234, age=25, gender=男, [email protected], date=Thu Sep 27 00:00:00 CST 2018, cost=6666.66]]
    
  • 補充說明:

專案結構

Excel表格內容

相關推薦

匯入Excel根據註解生成實體

一、環境說明:win10專業版、jdk1.8.0_171、eclipse4.7.3a、Junit5 二、建立maven工程,引入pom依賴 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht

使用PHPExcel匯入excel日期出現錯誤。

PHPExcel讀取excel中的時間的時候都會轉換為類似 41890.6101這樣的格式,解決方式如下: PHPExcel_Shared_Date::ExcelToPHP("要轉換的時間") 使用

idea如何根據資料庫生成實體(這裡演示oracle的操作方法其他類似)

教程:點選idea右側Database——>點選+號——>點選Data Source——>選擇資料庫——>配置如下 ——>點選OK——>右鍵點選你要生成的entity表,然後選擇Spripted Extensions——>然後選擇POJO.clj

解決POI匯入Excel數字精確到小數後一位的問題

今天在做匯入Excel的功能,遇到一個操蛋的問題,那就是如果excel某列為數字,例如123, POI 讀取會變成 123.0  如果遇到一些數字密碼或者手機號之類的需求,那可怎麼辦? 網上搜了一些辦法,使用後還是或多或少有點問題,於是想了一個不是方法的方法,如下程式碼片

spring-cloud匯入eclipse@slf4j註解為什麼找不到log變數

原因是缺少外掛Lomboz。Lomboz是一個基於LGPL的開源J2EE綜合開發環境的Eclipse外掛,對編碼,釋出,測試,以及debug等各個軟體開發的生命週期提供支援,支援JSP,EJB等。Lomboz是Eclipse的一個J2EE的外掛,它將很多Java應用伺服器、J

根據生成實體的工具

package com.zsf.shenzhou.customer.po; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; imp

T4系列文章之四:根據SqlServer生成實體

學習了前面三章的內容現在我們可以利用T4模板做一些小工具了,今天這裡要講的就是利用T4模板生成實體類。在寫這一部分的時候,我發現統一編碼格式是一件麻煩事,因為T4程式碼裡邊有“<##>”這樣的東西,試驗了幾種方法之後,我找到了一種稍微好點的,那就是把

Oracle 觸發器的編寫-----》假設需求要在插入資料觸發觸發器生成附件ID (假如Excel動態匯入資料列表欄再上傳附件因此要插入資料生成附件ID)

  /********************************************************************   功能名稱:  GET_BAIHOO_ID_BY_NAME   功能描述:  觸發觸發器生成附件ID &

動軟代碼生成器生成實體修改模板簡化實體的封裝

rem table rip return tex info ber 如果 ret 首先點擊代碼模板右鍵新建一個模板 <#@ template language="c#" HostSpecific="True" #> <#@ output exten

mybatis根據數據庫表結構自動生成實體daomapper

nts cat mybatis pack edt enc ren val 執行 首先, pom需要引入 <!-- mysql --> <dependency> <groupId>mysql</groupI

C#匯出 Excel 生成 CheckBox 控制元件

在使用 Microsoft.Office.Interop.Excel 元件匯出Excel 表格時,要把匯出前的  CheckBox 控制元件一同匯出到 excel 表格中,對於這個功能 看似很簡單,但 Microsoft.Office.Interop

java poi 匯入excel 讀取單元格內容的方法 其中包含excel中有函式的讀法

public static String getExcelCellValue(Cell cell) { String ret = ""; try { if (cell == null) { ret = ""; } else if (cell.get

java生成Excel為某列(單元格)建立下拉框

在做專案時,有時需要批量匯入的功能,通過Excel來進行批量匯入.... 遇到個小問題,希望在Java生成Excel中,有個模板,對於某些單元格,如性別等列,可以通過下拉框的方式來進行為使用者提示。 這樣既讓使用者覺得方便了,而且Excel會自動進行檢查,一旦不是下拉框中的

MyEclipse通過Oracle資料庫表反轉生成實體(包括註解)hibernate反向生成

在開發專案的階段,當專案的資料庫表設計完畢之後,一般都是存在很多資料庫表,這時候我們會想起使用MyEclipse的反轉功能,站在巨人的肩膀上會減少我們的開發的時間; 反轉生成實體類大致分為3步。 第一步:通過Myeclipse連線資料庫

反射+列舉+freemarker自動生成實體自動建表建索引(二)之建表建索引註解和DatabaseMetaData 獲取資訊

package com.test.common; import static com.test.common.EntityConfigData.DEFAULTS; import static com.test.common.EntityConfigData.INDEX; import static com.

使用Microsoft.Office.Interop.Excel64位問題

microsoft pop 都是 遷移 自己 方案 button 解決方案 安全 前不久,碰到一個問題。曾經用的好好的Microsoft.Office.Interop.Excel實現的導出Excel,遷移至64位server後,就出現:檢索 COM 類工廠中 CLSID

導出excel跳轉新空白頁不要跳轉怎麽改

頁面 iframe open() color one bsp pan nbsp 需要 導出excel的時候,偶爾會出現跳轉到一個新頁面再導出exceljs中用window.open()做跳轉 不想讓它跳轉到新頁面,需要加一個隱藏的iframe <iframe nam

AutomaticallyProfile 自動化引擎 MyBatis和DB溝通的引擎 (根據數據庫信息自動給生成實體那些...)

... 數據庫名 ica cmd 信息 images 類名 sources 生成 1.首先建立一個文件夾AutomaticallyProfile 文件夾內有四個jar包 :mysql.jar mybat

通過數據庫中的表使用 MyEclipse2017的反向生成工具-->hibernate反轉引擎引擎(MyEclipse2017自帶的插件) 來反轉生成實體和對應的映射文件

需要 ria sdn http rap div aci radi 工具 Java視圖 1、在MyEclipse中,Java視圖下,新建一個普通的java project,新建該項目的目的是:用來接收反轉引擎生成的實體類和對應的映射文件。 2、在項目上右鍵 -->

處理物件陣列根據某個屬性名相同求某一項的和。

當我們從後臺得到資料格式如下,我們需要求每個使用者money的和,就可以這樣做。 var arry = [ {user_id:1,money:100}, {user_id:2,money:33}, {user_