excel匯入,用反射匹配欄位名
阿新 • • 發佈:2019-01-08
最近在開發的系統,涉及到很多xls匯入, 開發太忙,沒時間做比較通用的模組,我反正閒著, 就試著幫他們寫了個比較通用的xls匯入模組,自我感覺良好, 就寫個文章記錄下
(demo程式碼,輕噴)
首先縮小需求:
1. 按行匯入,不支援合併行,和並列,合併的單元格處理太累
2. 第一行是表頭, 匯入xls需要通過表頭的字串來匹配列
這樣相對就簡單了, 首先是建立表頭和列索引的關係, 通過類反射建立索引關係
類反射定義
```java
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interfaceFieldDescInject { String value() default ""; }
類反射的使用
public class Order extends XlsObject { @FieldDescInject("訂單號") String thirdOrderId; @FieldDescInject("收件人") String receiveName; @FieldDescInject("省") String province; @FieldDescInject("市") String city; @FieldDescInject}("區") String zone; @FieldDescInject("地址") String detailAddress; @FieldDescInject("電話") String mobile;
把類成員變數和xls對應列關聯起來
XlsObject定義
package com.digitcore.readxls; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /*** Created by pan on 2016/12/1. */ public abstract class XlsObject { //for example // @FieldDescInject("價格") // public int price; public void setFieldValue(String desc, String value){ String fieldStr = fieldDescMap.get(desc); if(fieldStr == null){ setFieldValueNotFound(desc, value); return; } try { Field field = this.getClass().getDeclaredField(fieldStr); field.setAccessible(true); Class clzz = field.getType(); if(clzz == String.class){ field.set(this, value); } else if(clzz == int.class || clzz == Integer.class){ field.setInt(this, Integer.parseInt(value)); } else if(clzz == float.class || clzz == Float.class){ field.setFloat(this, Float.parseFloat(value)); } else { throw new IllegalArgumentException("聯絡程式設計師補充型別支援!"); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } public void setFieldValueNotFound(String field, String value){ } public XlsObject() { inject(); } private HashMap<String, String> fieldDescMap = new HashMap<String, String>(); public List<String> getDescList(){ return new ArrayList<String>(fieldDescMap.keySet()); } public void inject(){ Field[] fields = this.getClass().getDeclaredFields(); if (fields != null && fields.length > 0) { for (Field field : fields) { // Class<?> fieldType = field.getType(); FieldDescInject ed = field.getAnnotation(FieldDescInject.class); if (ed != null) { // field.setAccessible(true); fieldDescMap.put(ed.value(), field.getName()); } } } } }
再增加一個匯入的輔助工具類
package com.digitcore.readxls; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import static android.R.attr.order; /** * Created by pan on 2016/11/29. * 匯入xls表, 通過變數描述對應表字段, 或者手動選擇(外部介面配合)列和物件變數對應 */ public class ImportXls { private String mFile; private int mStartRow = 0;//head開始行, 預設從0開始 private Class<? extends XlsObject> mClazz; private HashMap<String, Integer> mIndexMap; public ImportXls(String file, int startRow, Class<? extends XlsObject> clazz){ mFile = file; mStartRow = startRow; mClazz = clazz; } /** * 獲取xls表頭的head列表 * @return */ public List<String> getXlsHead(){ List<String> heads = new ArrayList<String>(); InputStream is = null; Workbook book = null; try { is = new FileInputStream(mFile); book = Workbook.getWorkbook(is); // int num = book.getNumberOfSheets(); // txt.setText("the num of sheets is " + num+ "\n"); // // 獲得第一個工作表物件 Sheet sheet = book.getSheet(0); int Rows = sheet.getRows(); int Cols = sheet.getColumns(); if(Rows >= mStartRow && Cols > 0){ for(int i = 0; i < Cols; i++){ heads.add(sheet.getCell(i, mStartRow).getContents()); } } } catch (Exception e) { System.out.println(e); } finally { if(book != null){ book.close(); } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return heads; } public void setIndexMap(HashMap<String, Integer> indexMap){ mIndexMap = indexMap; } /** * 自動生成xls檔案中欄位索引表, xlsObject物件中註解的描述要和xls頭對應 * @param importHead xlsObject中註解的描述 */ public void generateIndexMap(List<String> importHead){ List<String> xlsHead = getXlsHead(); mIndexMap = new HashMap<String, Integer>(); for(String head : importHead){ int index = xlsHead.lastIndexOf(head); if(index >= 0) { mIndexMap.put(head, Integer.valueOf(index)); } } } public List<XlsObject> importXls(){ ArrayList<XlsObject> list = new ArrayList<XlsObject>(); InputStream is = null; Workbook book = null; try { is = new FileInputStream(mFile); book = Workbook.getWorkbook(is); Sheet sheet = book.getSheet(0); int Rows = sheet.getRows(); // int Cols = sheet.getColumns(); for (int i = 1; i < Rows; ++i) { XlsObject o = mClazz.newInstance(); Iterator iter = mIndexMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); Integer val = (Integer) entry.getValue(); o.setFieldValue(key, sheet.getCell(val, i).getContents()); } list.add(o); } } catch (Exception e) { System.out.println(e); } finally { if(book != null){ book.close(); } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return list; } }
使用示例:
ImportXls importXls = new ImportXls("/buhebing.xls", 0, Order.class);
Order order = new Order();List<String> imprtHead = order.getDescList();
importXls.generateIndexMap(imprtHead); importXls.importXls();
優化:
generateIndexMap這個函式後面可以優化, 實際上不需要傳參, 寫的時候沒注意, 後面懶得調整了