如果直接把固定Excel表格模板中的数据导入数据库,直接将Excel中的数据读取出来,再存入数据库中即可,将数据导出至固定的Excel模板方法类似。但是,有时候,开发制作的模板与客户需要的往往有些许差别(字段排版、字段数量等)。为了实现导入导出的灵活性,将利用java的反射机制实现。
1.增加一个配置文件,文件内容包括(导出字段名称,导出字段,导出字段类型)
####导入####
#社区版
communityTitle=软件名称|版本类型|社区名|版本号|软件分组|软件类型|版本发布时间|版本最后更新时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|专利说明|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|备注
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
#商业版
businessTitle=软件名称|版本类型|发行厂商中文|发行厂商|版本号|软件分组|软件类型|版本发布时间|版本最后更新时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|备注
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
#二次开发版
secondDevelopTitle=软件名称|录入情况|版本类型|发行厂商中文|发行厂商|版本号|软件分组|软件类型|版本发布时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|二次开发公司|备注
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
####导出####
#社区版
communityTitleExport=软件名称|版本类型|社区名|版本号|软件分组|软件类型|版本发布时间|版本最后更新时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|专利说明|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|备注|告警级别
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
#商业版
businessTitleExport=软件名称|版本类型|发行厂商中文|发行厂商|版本号|软件分组|软件类型|版本发布时间|版本最后更新时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|备注|告警级别
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
#二次开发版
secondDevelopTitleExport=软件名称|录入情况|版本类型|发行厂商中文|发行厂商|版本号|软件分组|软件类型|版本发布时间|版本说明链接|版本说明附件|开源协议|版本测试报告|版本质量评测报告|安装节点数|安装套数|许可证类型|使用状态|引用系统名称|引用系统模板名称|引用开始时间|引用结束时间|已安装补丁记录|局方负责人|局方负责人电话|厂商负责人|厂商负责人电话|所属科室|二次开发公司|备注|告警级别
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
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 = "")
@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 importUseInfo(final Workbook workBook, final String sheetName) {
//有一个不通过就不通过
boolean flag = true;
final List 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 getDataList (final List useInfoList, final String versionType) {
final List 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;
}
/**
* 获取当前对象【fieldName】属性的值
* @param obj 对象
* @param fieldName 属性名
* @return
* @throws Exception
*/
public Object getValue(final Object obj, final String fieldName) {
logger.info("获取对象属性[" + fieldName + "]的值");
if (obj == null || StringUtils.isEmpty(fieldName)) {
return null;
}
// 返回此属性的值
Object val = null;
try {
// 获取对象的属性
final Field field = obj.getClass().getDeclaredField(fieldName);
// 对象的属性的访问权限设置为可访问
field.setAccessible(true);
val = field.get(obj);
logger.info("对象属性[" + fieldName + "]的值为:" + val);
} catch (Exception e) {
logger.error("更具字段名通过反射机制获取字段值失败", e);
}
return val;
}
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);
}
}