SpringBoot利用java反射機制,實現靈活讀取Excel表格中的數據和導出數據至Excel表格

如果直接把固定Excel表格模板中的數據導入數據庫,直接將Excel中的數據讀取出來,再存入數據庫中即可,將數據導出至固定的Excel模板方法類似。但是,有時候,開發製作的模板與客戶需要的往往有些許差別(字段排版、字段數量等)。爲了實現導入導出的靈活性,將利用java的反射機制實現。

1.增加一個配置文件,文件內容包括(導出字段名稱,導出字段,導出字段類型)


####導入####
#社區版
useInfo.communityTitle=軟件名稱|版本類型|社區名|版本號|軟件分組|軟件類型|版本發佈時間|版本最後更新時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|專利說明|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|備註
useInfo.communityFiled=softwareName|versionType|community|versionNum|scene|softwareType|releaseTime|updateTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|patent|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|remark
useInfo.communityFiledType=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

#商業版
useInfo.businessTitle=軟件名稱|版本類型|發行廠商中文|發行廠商|版本號|軟件分組|軟件類型|版本發佈時間|版本最後更新時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|備註
useInfo.businessFiled=softwareName|versionType|distributorCN|distributorEN|versionNum|scene|softwareType|releaseTime|updateTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|remark
useInfo.businessFiledType=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

#二次開發版
useInfo.secondDevelopTitle=軟件名稱|錄入情況|版本類型|發行廠商中文|發行廠商|版本號|軟件分組|軟件類型|版本發佈時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|二次開發公司|備註
useInfo.secondDevelopFiled=softwareName|insertInfo|versionType|distributorCN|distributorEN|versionNum|scene|softwareType|releaseTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|secondDevelop|remark
useInfo.secondDevelopFiledType=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

####導出####
#社區版
useInfo.communityTitleExport=軟件名稱|版本類型|社區名|版本號|軟件分組|軟件類型|版本發佈時間|版本最後更新時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|專利說明|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|備註|告警級別
useInfo.communityFiledExport=softwareName|versionType|community|versionNum|scene|softwareType|releaseTime|updateTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|patent|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|remark|alarmLevel
useInfo.communityFiledTypeExport=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

#商業版
useInfo.businessTitleExport=軟件名稱|版本類型|發行廠商中文|發行廠商|版本號|軟件分組|軟件類型|版本發佈時間|版本最後更新時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|備註|告警級別
useInfo.businessFiledExport=softwareName|versionType|distributorCN|distributorEN|versionNum|scene|softwareType|releaseTime|updateTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|remark|alarmLevel
useInfo.businessFiledTypeExport=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

#二次開發版
useInfo.secondDevelopTitleExport=軟件名稱|錄入情況|版本類型|發行廠商中文|發行廠商|版本號|軟件分組|軟件類型|版本發佈時間|版本說明鏈接|版本說明附件|開源協議|版本測試報告|版本質量評測報告|安裝節點數|安裝套數|許可證類型|使用狀態|引用系統名稱|引用系統模板名稱|引用開始時間|引用結束時間|已安裝補丁記錄|局方負責人|局方負責人電話|廠商負責人|廠商負責人電話|所屬科室|二次開發公司|備註|告警級別
useInfo.secondDevelopFiledExport=softwareName|insertInfo|versionType|distributorCN|distributorEN|versionNum|scene|softwareType|releaseTime|versionLink|versionAttachment|opensourceProtocol|testReport|qualityEvaluateReport|installNode|installNum|licenseType|useStatus|systemName|systemTemplateName|useBeginTime|useEndTime|installedPatchRecord|principal|principalPhone|mfgrPrincipal|mfgrPrincipalPhone|department|secondDevelop|remark|alarmLevel
useInfo.secondDevelopFiledTypeExport=java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.Integer|java.lang.Integer|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.util.Date|java.util.Date|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String|java.lang.String

2.讀取配置文件(這裏指定了編碼格式爲UTF-8,因爲之前讀取中文的時候亂碼,各種百度,最終選擇了這種方式)

@Component
@ConfigurationProperties(prefix = "useInfo")
@PropertySource(value={"classpath:useInfoTable.properties"},ignoreResourceNotFound = true,encoding = "utf-8")
public class UseInfoTableProperty {
	
	/**
	 * 社區版導入表頭
	 */
	private String communityTitle;
	/**
	 * 社區版導出表頭
	 */
	private String communityTitleExport;
	
	/**
	 * 社區版導入使用的字段
	 */
	private String communityFiled;
	/**
	 * 社區版導出使用的字段
	 */
	private String communityFiledExport;
	
	/**
	 * 社區版導入字段類型
	 */
	private String communityFiledType;
	/**
	 * 社區版導出字段類型
	 */
	private String communityFiledTypeExport;

	/**
	 * 商業版導入表頭
	 */
	private String businessTitle;
	/**
	 * 商業版導出表頭
	 */
	private String businessTitleExport;
	
	/**
	 * 商業版導入使用的字段
	 */
	private String businessFiled;
	/**
	 * 商業版導出使用的字段
	 */
	private String businessFiledExport;
	
	/**
	 * 商業版導入字段類型
	 */
	private String businessFiledType;
	/**
	 * 商業版導出字段類型
	 */
	private String businessFiledTypeExport;
	
	/**
	 * 二次開發版導入表頭
	 */
	private String secondDevelopTitle;
	
	/**
	 * 二次開發版導出表頭
	 */
	private String secondDevelopTitleExport;
	
	/**
	 * 二次開發版導入使用的字段
	 */
	private String secondDevelopFiled;
	/**
	 * 二次開發版導出使用的字段
	 */
	private String secondDevelopFiledExport;
	
	/**
	 * 二次開發版導入字段類型
	 */
	private String secondDevelopFiledType;
	/**
	 * 二次開發版導出字段類型
	 */
	private String secondDevelopFiledTypeExport;

	
	getter、setter方法略...
	
}

3.導入Excel

public List<UseInfo> importUseInfo(final Workbook workBook, final String sheetName) {
    	//有一個不通過就不通過
    	boolean flag = true;
    	final List<UseInfo> list = new ArrayList<>();
    	
    	// 獲取該對象的class對象
		Class objClass = UseInfo.class;
//		// 獲得該類的所有屬性
//		Field[] fields = objClass.getDeclaredFields();
		// 讀取excel數據,獲得指定的excel表
		Sheet sheet = workBook.getSheet(sheetName);
		// 讀取表頭信息,確定需要用的方法名---set方法
		// 用於存儲方法名
		String[] methodNames;
		// 用於存儲屬性類型
		String[] fieldTypes ;
		
		if (UseInfoConstant.VERSIONTYPE_COMMUNITY.equals(sheetName)) {
			methodNames = useInfoTableProperty.getCommunityFiled().split("\\|");
			fieldTypes = useInfoTableProperty.getCommunityFiledType().split("\\|");
		} else if (UseInfoConstant.VERSIONTYPE_BUSINESS.equals(sheetName)) {
			methodNames = useInfoTableProperty.getBusinessFiled().split("\\|");
			fieldTypes = useInfoTableProperty.getBusinessFiledType().split("\\|");
		} else if (UseInfoConstant.VERSIONTYPE_SECONDDEVELOP.equals(sheetName)) {
			methodNames = useInfoTableProperty.getSecondDevelopFiled().split("\\|");
			fieldTypes = useInfoTableProperty.getSecondDevelopFiledType().split("\\|");
		} else {
			return list;
		}
		for (int i = 0; i < methodNames.length; i++) {
			//獲取字段對應的方法名稱
			methodNames[i] = "set" + Character.toUpperCase(methodNames[i].charAt(0)) + methodNames[i].substring(1);
		}
		final SimpleDateFormat format1 = new SimpleDateFormat("dd/MM/yyyy");
    	final SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd日");
		// 逐行讀取數據 從1開始 忽略表頭
		for (int i = 1; i < sheet.getRows(); i++) {
			//實例化該泛型類的對象一個對象
			Object obj;
			try {
				obj = objClass.newInstance();
			} catch (Exception e) {
				LOGGER.error("實例化對象失敗");
				return list;
			}
			// 獲得本行中各單元格中的數據
			String temp = "";
			for (int j = 0; j < methodNames.length; j++) {
				try {
					String data = sheet.getCell(j, i).getContents();
					// 獲取要調用方法的方法名
					Method method = null;
					if ("java.lang.String".equals(fieldTypes[j])) {
						// 設置要執行的方法--set方法參數爲String
						LOGGER.info("methodName=" + methodNames[j]);
						method = objClass.getDeclaredMethod(methodNames[j], String.class);
						method.invoke(obj, data); // 執行該方法
					} else if ("java.lang.Integer".equals(fieldTypes[j])) {
						// 設置要執行的方法--set方法參數爲String
						LOGGER.info("methodName=" + methodNames[j]);
						method = objClass.getDeclaredMethod(methodNames[j], Integer.class);
						if (!StringUtils.isEmpty(data)) {
							try {
								method.invoke(obj, Integer.valueOf(data)); // 執行該方法
							} catch (Exception e) {
								temp += "安裝節點數是整數,";
							}
						}
					} else if ("java.util.Date".equals(fieldTypes[j])) {
						// 設置要執行的方法--set方法參數爲String
						LOGGER.info("methodName=" + methodNames[j]);
						method = objClass.getDeclaredMethod(methodNames[j], Date.class);
						if (!StringUtils.isEmpty(data)) {
							try {
								method.invoke(obj, format1.parse(data));
							} catch (Exception e) {
								try {
									method.invoke(obj, format2.parse(data));
								} catch (ParseException e1) {
									temp += "時間格式爲(2018/10/10),";
								}
							}
						}
					}
				} catch (Exception e2) {
					LOGGER.error("設置屬性值失敗", e2);
				}
			}
		return list;
    }

4.獲取需要導出的字段值

public List<String[]> getDataList (final List<UseInfo> useInfoList, final String versionType) {
		final List<String[]> dataList = new ArrayList<>();
		final SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");

		//用於存儲字段名
		String[] fieldNames = null;
		String[] fieldTypes = null;
		
		if (UseInfoConstant.VERSIONTYPE_COMMUNITY.equals(versionType)) {
			fieldNames = useInfoTableProperty.getCommunityFiledExport().split("\\|");
			fieldTypes = useInfoTableProperty.getCommunityFiledTypeExport().split("\\|");
		} else if (UseInfoConstant.VERSIONTYPE_BUSINESS.equals(versionType)) {
			fieldNames = useInfoTableProperty.getBusinessFiledExport().split("\\|");
			fieldTypes = useInfoTableProperty.getBusinessFiledTypeExport().split("\\|");
		} else if (UseInfoConstant.VERSIONTYPE_SECONDDEVELOP.equals(versionType)) {
			fieldNames = useInfoTableProperty.getSecondDevelopFiledExport().split("\\|");
			fieldTypes = useInfoTableProperty.getSecondDevelopFiledTypeExport().split("\\|");
		}
		for (final UseInfo useInfo : useInfoList) {
			if (fieldNames != null) {
				String[] data = new String[fieldNames.length];
				for (int i = 0; i < fieldNames.length; i++) {
					final Object val = getValue(useInfo, fieldNames[i]);
					if ("java.lang.String".equals(fieldTypes[i])) {
						data[i] = (String)val;
					} else if ("java.lang.Integer".equals(fieldTypes[i])) {
						data[i] = String.valueOf(((Integer)val));
					} else if ("java.util.Date".equals(fieldTypes[i])) {
						data[i] = val== null ? null : format.format(((Date)val));
					}
				}
				dataList.add(data);
			}
		}
		return dataList;
	}
 private class MyDateEditor extends PropertyEditorSupport {
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = null;
            try {
                date = format.parse(text);
            } catch (ParseException e) {
                e.printStackTrace();
            }

            setValue(date);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章