ava 使用poi导入excel,结合xml文件进行数据验证的例子(增加了jar包)
假设现在要做一个通用的导入方法:
要求:
1.xml的只定义数据库表中的column字段,字段类型,是否非空等条件。
2.excel定义成模板,里面只填写了所需要的数据,有可能数据有问题。
3.在导入的时候就需要对每个excel单元格的数据进行验证。
4.验证完之后,若所有数据正确,那么批量保存。若有一点点错误,就不执行保存操作,并提示错误原因。
思路:
1.完美使用了Map的功能,先将xml中的数据存入map中,怎么存呢?
下面我根据xml文件来具体分析:(为图方便,我只做了字段的非空验证)
user.xml
<?xml version="1.0" encoding="UTF-8"?> <excel> <entity name="用户表" code="user" > <column name="状态" code="status" type="String"></column> <column name="端口号" code="port" type="int"> <rules> <rule name="nullable" message="端口号不允许为空"></rule> </rules> </column> <column name="IP地址" code="ip" type="String"> <rules> <rule name="nullable" message="IP地址不允许为空"></rule> </rules> </column> <column name="密码" code="password" type="String"> <rules> <rule name="nullable" message="密码不允许为空"></rule> </rules> </column> <column name="用户名" code="username" type="String"></column> <column name="员工号" code="no" type="String"> <rules> <rule name="nullable" message="员工号不允许为空"></rule> <rule name="checkUnique" message="员工号已经存在"></rule> </rules> </column> <column name="头像" code="userImage" type="BLOB"></column> </entity> </excel>
根据xml所做的准备:
准备4个Map:
(1),已知 <entity> 中的name="用户表" ,定义entityMap 来存放实体类的map对象
(2),已知 “用户表”和 某个字段名“员工号”,那么就可以存放每一列的map对象
(3),已知 “用户表”和 某个字段名“员工号”,可以找到该列下的所有验证规则存放到map中
(4),已知 “用户表” 和 “ 员工号”和验证规则name "nullable",那么可以找到每一列的某一个验证规则
2.读取excel数据时,需要一一对应xml map中的字段与验证规则。
下面是excel数据:标注红色 * 号的表示必填项。
接下来就要看具体的实现代码了:
东西很多,我只贴两个比较重要的java 类
1.ParseExcelUtil.java ,要试验代码,可以直接在工程里面单击右键--run as 运行这个类,不过前提是要导入这个测试项目,最后面我会上传。
package com.karen.test2; import java.beans.IntrospectionException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import com.karen.database.Dao; /** * 解析excel 工具类 * @author PCCW * */ @SuppressWarnings("rawtypes") public class ParseExcelUtil { public FileInputStream fis ; public HSSFWorkbook workBook; public HSSFSheet sheet; public ParseXMLUtil parseXmlUtil; public StringBuffer errorString; /**当前实体类的code**/ public String curEntityCode; /**表头map对象:key:entityCode, value:headMap(index,headTitle)**/ public Map curEntityHeadMap ; /**字段的必填:key:entityCode+headTitle, value:true(必填),false(不必填)**/ public Map curEntityColRequired; /**存放每一行的数据**/ public List listDatas ; public ParseExcelUtil(File excelFile,File xmlFile){ try { if(excelFile == null){ throw new FileNotFoundException(); } fis = new FileInputStream(excelFile); workBook = new HSSFWorkbook(fis); parseXmlUtil = new ParseXMLUtil(xmlFile); errorString = new StringBuffer(); readExcelData(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } } /**开始从excel读取数据**/ public void readExcelData(){ int sheetSize = workBook.getNumberOfSheets(); for(int i=0;i<sheetSize;i++){ sheet = workBook.getSheetAt(i); String entityName = workBook.getSheetName(i); readSheetData(sheet,entityName); } } /**读每个sheet页的数据**/ public void readSheetData(HSSFSheet sheet,String entityName){ int rowNumbers = sheet.getPhysicalNumberOfRows(); Map ent = (Map) parseXmlUtil.getEntityMap().get(entityName); this.setCurEntityCode((String) ent.get("code")); if(rowNumbers == 0){ System.out.println("================excel中数据为空!"); errorString.append(ParseConstans.ERROR_EXCEL_NULL); } List colList = (List) parseXmlUtil.getColumnListMap().get(entityName); int xmlRowNum = colList.size(); HSSFRow excelRow = sheet.getRow(0); int excelFirstRow = excelRow.getFirstCellNum(); int excelLastRow = excelRow.getLastCellNum(); if(xmlRowNum != (excelLastRow-excelFirstRow)){ System.out.println("==================xml列数与excel列数不相符,请检查"); errorString.append(ParseConstans.ERROR_EXCEL_COLUMN_NOT_EQUAL); } readSheetHeadData(sheet); readSheetColumnData(sheet,entityName); } /**读取sheet页中的表头信息**/ @SuppressWarnings({ "unchecked", "static-access"}) public void readSheetHeadData(HSSFSheet sheet){ Map headMap = new HashMap(); curEntityHeadMap = new HashMap(); curEntityColRequired = new HashMap(); HSSFRow excelheadRow = sheet.getRow(0); int excelLastRow = excelheadRow.getLastCellNum(); String headTitle = ""; for(int i=0;i<excelLastRow;i++){ HSSFCell cell = excelheadRow.getCell(i); headTitle = this.getStringCellValue(cell).trim(); if(headTitle.endsWith("*")){ curEntityColRequired.put(this.getCurEntityCode()+"_"+headTitle,true); }else{ curEntityColRequired.put(this.getCurEntityCode()+"_"+headTitle,false); } headMap.put(i, headTitle); } curEntityHeadMap.put(this.getCurEntityCode(), headMap); } /**读取sheet页里面的数据**/ @SuppressWarnings({ "unchecked", "static-access" }) public void readSheetColumnData(HSSFSheet sheet,String entityName){ HSSFRow excelheadRow = sheet.getRow(0); int excelLastcell = excelheadRow.getLastCellNum(); //excel总列数 int excelRowNum = sheet.getLastRowNum(); //excel总行数 Map headMap = (Map) this.getCurEntityHeadMap().get(this.getCurEntityCode()); Map colMap = parseXmlUtil.getColumnMap(); listDatas =new ArrayList(); for(int i=1;i<excelRowNum+1;i++){//行循环 HSSFRow columnRow = sheet.getRow(i); if(columnRow != null){ Map curRowCellMap = new HashMap(); for(int j =0; j<excelLastcell;j++){ //列循环 int cout = headMap.get(j).toString().indexOf("*"); String headTitle =""; if(cout == -1){ headTitle = headMap.get(j).toString(); }else{ headTitle = headMap.get(j).toString().substring(0, cout); } Map curColMap = (Map) colMap.get(entityName+"_"+headTitle); String curColCode = (String) curColMap.get("code"); String curColType = (String) curColMap.get("type"); HSSFCell colCell = columnRow.getCell(j); String value =this.getStringCellValue(colCell); if(value != null){ value = value.trim(); } String xmlColType = (String) curColMap.get("type"); if(xmlColType.equals("int")){ int intVal = Integer.valueOf(value); curRowCellMap.put(curColCode, intVal); //将这一行的数据以code-value的形式存入map }else{ curRowCellMap.put(curColCode, value); } /**验证cell数据**/ validateCellData(i+1,j+1,colCell,entityName,headTitle,curColType); } listDatas.add(curRowCellMap); } } if(this.getErrorString().length() ==0){//如果没有任何错误,就保存 saveExcelData(entityName); System.out.println("导入数据成功!"); }else{ //清理所有的缓存clearMap();现在暂时未清理 String[] strArr = errorString.toString().split("<br>"); for(String s: strArr){ System.out.println(s); } } } /**验证单元格数据**/ @SuppressWarnings("static-access") public void validateCellData(int curRow,int curCol,HSSFCell colCell,String entityName,String headName,String curColType){ List rulList = (List) parseXmlUtil.getColumnRulesMap().get(entityName+"_"+headName); if(rulList != null && rulList.size()>0){ for(int i=0 ; i<rulList.size() ; i++){ Map rulM = (Map) rulList.get(i); String rulName = (String) rulM.get("name"); String rulMsg = (String) rulM.get("message"); String cellValue = this.getStringCellValue(colCell).trim(); if(rulName.equals(ParseConstans.RULE_NAME_NULLABLE)){ if(cellValue.equals("")||cellValue == null){ errorString.append("第"+curRow+"行,第"+curCol+"列:"+rulMsg+"<br>"); } }else { //////这里写其他的验证规则。。。 } } } } /**保存excel里面的数据**/ @SuppressWarnings("unchecked") public void saveExcelData(String entityName){ List<User> users= new ArrayList(); for(int i = 0 ; i<this.getListDatas().size();i++){ Map excelCol = (Map) this.getListDatas().get(i); //得到第 i 行的数据 User user = new User(); try { User obj = (User) BeanToMapUtil.convertMap(user.getClass(), excelCol); users.add(obj); } catch (IntrospectionException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } /**批量保存数据**/ Dao dao = new Dao(); for(int i = 0;i<users.size();i++){ try{ dao.saveUser(users.get(i)); }catch(Exception e){ e.printStackTrace(); } } } /** * 获得单元格字符串 * @throws UnSupportedCellTypeException */ public static String getStringCellValue(HSSFCell cell) { if (cell == null){ return null; } String result = ""; switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_BOOLEAN: result = String.valueOf(cell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_NUMERIC: if (HSSFDateUtil.isCellDateFormatted(cell)) { java.text.SimpleDateFormat TIME_FORMATTER = new java.text.SimpleDateFormat( "yyyy-MM-dd"); result = TIME_FORMATTER.format(cell.getDateCellValue()); } else{ double doubleValue = cell.getNumericCellValue(); result = "" + doubleValue; } break; case HSSFCell.CELL_TYPE_STRING: if (cell.getRichStringCellValue() == null){ result = null; } else{ result = cell.getRichStringCellValue().getString(); } break; case HSSFCell.CELL_TYPE_BLANK: result = null; break; case HSSFCell.CELL_TYPE_FORMULA: try{ result = String.valueOf(cell.getNumericCellValue()); }catch(Exception e){ result = cell.getRichStringCellValue().getString(); } break; default: result = ""; } return result; } /**主方法**/ public static void main(String[] args) { File excelFile = new File("src/user.xls"); File xmlFile = new File("src/user.xml"); new ParseExcelUtil(excelFile,xmlFile); } public String getCurEntityCode() { return curEntityCode; } public void setCurEntityCode(String curEntityCode) { this.curEntityCode = curEntityCode; } public Map getCurEntityHeadMap() { return curEntityHeadMap; } public void setCurEntityHeadMap(Map curEntityHeadMap) { this.curEntityHeadMap = curEntityHeadMap; } public ParseXMLUtil getParseXmlUtil() { return parseXmlUtil; } public void setParseXmlUtil(ParseXMLUtil parseXmlUtil) { this.parseXmlUtil = parseXmlUtil; } public Map getCurEntityColRequired() { return curEntityColRequired; } public void setCurEntityColRequired(Map curEntityColRequired) { this.curEntityColRequired = curEntityColRequired; } public List getListDatas() { return listDatas; } public void setListDatas(List listDatas) { this.listDatas = listDatas; } public StringBuffer getErrorString() { return errorString; } public void setErrorString(StringBuffer errorString) { this.errorString = errorString; } }
2.ParseXMLUtil.java
这个类是用来解析xml的,测试方法同样可以右键 run as 运行。可以把下面的一段注释放开,查看打印结果。
package com.karen.test2; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * 解析xml工具类 * @author PCCW-80352891 * */ @SuppressWarnings("rawtypes") public class ParseXMLUtil { /**entity map对象,key:name ,value:entity的属性map集**/ public Map entityMap ; /**column map 对象,key:entityName_colName , value:column的属性map集 **/ public Map columnMap; /**rule map 对象,key:entityName_colName_ruleName, value: rule 的map集:找到一行rule**/ public Map ruleMap ; /**rules map 对象, key:entityName_colName, value: rules 的map集:找到该column下所有的rule**/ public Map columnRulesMap ; /**entity--column map: key:entityName, value: column list:根据实体类名得到所有的列**/ public Map columnListMap ; /**column list**/ public List columnList ; /**开始解析xml文件**/ public ParseXMLUtil(File xmlFilePath){ FileInputStream in = null; try { if(xmlFilePath == null){ throw new FileNotFoundException(); } SAXReader reader = new SAXReader(); in = new FileInputStream(xmlFilePath); Document doc = reader.read(in); Element root = doc.getRootElement(); Iterator itEntity = root.elements("entity").iterator(); while(itEntity.hasNext()){ Element entity = (Element) itEntity.next(); parseEntity(entity); } /**测试entityMap 是否正确**/ Map enMap = (Map) this.getEntityMap().get("用户表"); Set<?> set = enMap.keySet(); Iterator it = set.iterator(); while(it.hasNext()){ String uu = (String) it.next(); System.out.println("entity properties:"+uu+" = "+enMap.get(uu)); } /* *//**测试column list是否正确**//* List colList = (List) this.getColumnListMap().get("用户表"); System.out.println("column size:"+colList.size()); *//**测试columnMap是否正确**//* Map colMap = (Map) this.getColumnMap().get("用户表_员工号"); Set<?> coListSet = colMap.keySet(); Iterator coListIt = coListSet.iterator(); while(coListIt.hasNext()){ String coListKey = (String) coListIt.next(); System.out.println("column properties: "+coListKey+" = "+colMap.get(coListKey)); } *//**测试ruleMap是否正确**//* if(this.getColumnRulesMap() != null){ List rulesValidList = (List) this.getColumnRulesMap().get("用户表_员工号"); for(int i=0;i<rulesValidList.size(); i++){ Map colRuleMap = (Map) rulesValidList.get(i); String ruleName = (String) colRuleMap.get("name"); Map ruleMa = (Map) this.getRuleMap().get("用户表_员工号_"+ruleName); //eg: 用户表_用户名_nullable String mess = (String) ruleMa.get("message"); System.out.println("Validate Rules"+i+" : "+mess); } }*/ }catch(Exception e){ e.printStackTrace(); } } /**开始解析entity**/ @SuppressWarnings("unchecked") public void parseEntity(Element entity){ if(entity != null){ /**对数据进行初始化设置**/ columnListMap = new HashMap(); columnMap = new HashMap(); entityMap = new HashMap(); ruleMap = new HashMap(); columnRulesMap = new HashMap(); columnList = new ArrayList(); setEntityMap(entity); String entityName = entity.attributeValue("name"); Iterator itColumn = entity.elements("column").iterator(); while(itColumn.hasNext()){ Element column = (Element) itColumn.next(); setColumnMap(entityName,column); } columnListMap.put(entityName, columnList); } } /**将entity放入entityMap中**/ @SuppressWarnings("unchecked") public void setEntityMap(Element entity){ Map ent = new HashMap(); String name = entity.attributeValue("name"); String code = entity.attributeValue("code"); ent.put("name", name); ent.put("code", code); entityMap.put(name, ent); } /**将column放入columnMap中**/ @SuppressWarnings("unchecked") public void setColumnMap(String entityName,Element column){ if(column != null){ Map col = new HashMap(); String name = column.attributeValue("name"); String code = column.attributeValue("code"); String type = column.attributeValue("type"); col.put("name", name); col.put("code", code); col.put("type", type); String columnMapKey = entityName+"_"+name; //eg: 用户表_用户名 columnMap.put(columnMapKey, col); columnList.add(col); Iterator ruleIt = column.elements("rules").iterator(); //获得rules while(ruleIt.hasNext()){ Element rules = (Element)ruleIt.next(); Iterator rule = rules.elements("rule").iterator(); //获得 rule while(rule.hasNext()){ Element ruleValid = (Element) rule.next(); //获得每一行rule setRuleMap(entityName,name,ruleValid); } } } } /**将 rule 验证规则放入ruleMap中**/ @SuppressWarnings("unchecked") public void setRuleMap(String entityName,String columnName,Element ruleValid){ if(ruleValid != null){ String ruleName = ruleValid.attributeValue("name"); String ruleMsg = ruleValid.attributeValue("message"); Map ruleValidMap = new HashMap(); ruleValidMap.put("name", ruleName); ruleValidMap.put("message", ruleMsg); String ruleStrKey = entityName+"_"+columnName+"_"+ruleName; String colStrKey = entityName+"_"+columnName; if(this.getColumnRulesMap().containsKey(colStrKey)){ List valids = (List) this.getColumnRulesMap().get(colStrKey); valids.add(ruleValidMap); }else{ List valids = new ArrayList(); valids.add(ruleValidMap); this.columnRulesMap.put(colStrKey, valids); //将每个column下的所有rules存入该map中 } ruleMap.put(ruleStrKey, ruleValidMap); //将每个column下的一条rule存入该map中 } } /**主方法**/ public static void main(String[] args) { File file = new File("src/user.xml"); new ParseXMLUtil(file); } /**所有的get set 方法**/ public Map getEntityMap() { return entityMap; } public void setEntityMap(Map entityMap) { this.entityMap = entityMap; } public Map getColumnMap() { return columnMap; } public void setColumnMap(Map columnMap) { this.columnMap = columnMap; } public Map getRuleMap() { return ruleMap; } public void setRuleMap(Map ruleMap) { this.ruleMap = ruleMap; } public Map getColumnRulesMap() { return columnRulesMap; } public void setColumnRulesMap(Map columnRulesMap) { this.columnRulesMap = columnRulesMap; } public Map getColumnListMap() { return columnListMap; } public void setColumnListMap(Map columnListMap) { this.columnListMap = columnListMap; } }
3.既然做导入,当然需要连接数据库啦。只需要在mysql数据库中,建立一个 名为 chat 的数据库,然后导入下面的sql.来创建一张user表
CREATE TABLE `user` ( `status` varchar(20) default NULL, `port` int(10) NOT NULL, `ip` varchar(40) NOT NULL, `password` varchar(10) NOT NULL, `username` varchar(100) NOT NULL, `no` varchar(10) default NULL, `userImage` blob, PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4.例子肯定需要很多jar包,比如poi啊,各种包。我就不在这里写出来了。
需要例子源码 请到这里下载:
http://download.csdn.net/detail/chenxuejiakaren/4439307
5.运行方法: 将例子导入到eclipse之中,然后可能会因为jdk版本不一样会有红色感叹号,没关系,改一下。单击项目右键--properties--java build path--libraries--找jdk啊。这个搞java的都会吧。
然后,单击右键 run as 运行ParseExcelUtil.java 就可以啦。
关于例子导入后会提示缺少包的问题:
我引入的相关jar包是在eclipse里面直接引入的,没有相对于的lib目录。主要是缺少了2个jar
poi-3.8-20120326.jar 下载地址: http://download.csdn.net/detail/chenxuejiakaren/4440128
mysql-connector-java-5.0.8-bin.jar 下载地址: http://download.csdn.net/detail/chenxuejiakaren/4440132
必须要在eclipse里引入他们。