SpringBoot利用java反射機制,實現靈活讀取Excel表格中的資料和匯出資料至Excel表格
阿新 • • 發佈:2018-12-15
如果直接把固定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;
}