Java - Read Excel to Compose JavaBean by Java Reflection

之前曾經發過一篇關於觀察者模式的範例,裡面所讀取的檔案為txt檔,所定義的資料格式

雖然簡單,但是編輯方式並不方便。因此在這邊將以讀取Excel檔的方式,並且自動組成

JavaBean,透過Excel檔內的第一列設定JavaBean的成員變數名稱,並且搭配程式產生的

HashMap,為成員變數對應它的setter method,如此一來再透過Java Reflection就可以自動組

出相關的JavaBean Object。

txt檔資料格式如下:

資工系,男,21,小彬
經濟系,女,19,小花
建築系,男,23,小勇
國貿系,男,21,小金
中文系,女,20,小琪
歷史系,男,18,小強
財金系,女,24,小雯
畜產系,男,23,小維
哲學系,男,25,小茂
外文系,女,20,小琳

xls檔資料格式如下:

承該篇文章,主要多定義了

public List<Participant> LoadParticipantListByXls(File f)

public Map<String, String> getSetterMethod(Class<?> c)

先來說說getSetterMethod的目的,主要是組出JavaBean下成員變數對應setter method的資料

格式,相關程式如下:

  1. public Map<String, String> getSetterMethod(Class<?> c){
  2. Map<String, String> col2method = new HashMap<String, String>();
  3. Method[] methods = c.getDeclaredMethods();
  4. List<String> fields = new ArrayList<String>();
  5. List<String> fieldsLower = new ArrayList<String>();
  6. for(Field n : c.getDeclaredFields()){
  7. fields.add(n.getName());
  8. fieldsLower.add(n.getName().toLowerCase());
  9. }
  10. String colname = "";
  11. for (Method method : methods){
  12. if (Modifier.isPublic(method.getModifiers())
  13. && method.getParameterTypes().length == 1) {
  14. if (method.getName().matches("^set[A-Z].*")
  15. && method.getReturnType().equals(void.class)){
  16. colname = method.getName().toLowerCase().substring(3,
  17. method.getName().length());
  18. for(int i = 0 ; i < fieldsLower.size() ; i++){
  19. if(fieldsLower.get(i).equals(colname)){
  20. col2method.put(fields.get(i), method.getName());
  21. }
  22. }
  23. }
  24. }
  25. }
  26. return col2method;
  27. }
因為我們只針對setter method,因此主要是先判斷是否為public宣告的及set開頭的,同時

為void,如此一來截取出set後的字串,並且與現有的成員變數比對,如果吻合的話,則

put進col2method map內。

再來是LoadParticipantListByXls,跟原先的LoadParticipantList一樣,會回傳一list

相關程式碼如下:
  1. public List<Participant> LoadParticipantListByXls(File f){
  2. List<Participant> plist = new ArrayList<Participant>();
  3. Map<String, String> col2method = new HashMap<String, String>();
  4. Map<Integer, String> col2field = new HashMap<Integer, String>();
  5. Workbook xlsBook = null;
  6. Participant bean = null;
  7. Method m = null;
  8. try{
  9. col2method = this.getSetterMethod(Participant.class);
  10. xlsBook = Workbook.getWorkbook(f);
  11. Sheet sheet = xlsBook.getSheet(0);
  12. for(int i = 0 ; i < sheet.getRows() ; i++){
  13. if(i > 0)bean = new Participant();
  14. for(int j = 0 ; j < sheet.getColumns() ; j++){
  15. if(i == 0)
  16. col2field.put(j, sheet.getCell(j, i).
  17. getContents().toLowerCase());
  18. else{
  19. String val = sheet.getCell(j, i).getContents();
  20. if(NumberUtils.isNumber(val)){
  21. m = Participant.class.getDeclaredMethod(
  22. col2method.get(col2field.get(j)), int.class);
  23. m.invoke(bean, Integer.parseInt(val));
  24. }else{
  25. m = Participant.class.getDeclaredMethod(
  26. col2method.get(col2field.get(j)), String.class);
  27. m.invoke(bean, val);
  28. }
  29. }
  30. }
  31. if(i > 0){
  32. plist.add(bean);
  33. //System.out.println(bean);
  34. }
  35. }
  36. } catch(Exception e){
  37. e.printStackTrace();
  38. } finally{
  39. xlsBook.close();
  40. }
  41. return plist;
  42. }

在此使用jxl library來讀取Excel檔的資料,除了col2method以外,也定義了col2field來得知

目前的column index為哪個field,如此一來才能夠知道該column的欄位值要做哪個setter。

最後,原程式範例要改寫的地方為

public List<Participant> LoadParticipantList(File f){
List<Participant> plist = new ArrayList<Participant>();

if(f.getName().lastIndexOf(".xls") > 0){
return LoadParticipantListByXls(f);
}
......

}

主要是多加上了這一段,如此一來如果load的檔案為.xls格式的資料,則呼叫

LoadParticipantListByXls來組list。

留言