最近在开发的系统,涉及到很多xls导入, 开发太忙,没时间做比较通用的模块,我反正闲着, 就试着帮他们写了个比较通用的xls导入模块,自我感觉良好, 就写个文章记录下

(demo代码,轻喷)

首先缩小需求:

1. 按行导入,不支持合并行,和并列,合并的单元格处理太累

2. 第一行是表头, 导入xls需要通过表头的字符串来匹配列

这样相对就简单了, 首先是建立表头和列索引的关系, 通过类反射建立索引关系

类反射定义

```java

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldDescInject {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这个函数后面可以优化, 实际上不需要传参, 写的时候没注意, 后面懒得调整了

excel导入,用反射匹配字段名相关推荐

  1. 通过PropertyDescriptor反射进行字段名值的获取及设置

    /**  * 根据属性名获取对应的value  * @param fieldName  * @param obj  * @return  * @throws Exception  */ private ...

  2. c#中高效的excel导入oracle的方法(转)

    如何高效的将excel导入到oracle?和前两天的SqlBulkCopy 导入到sqlserver对应,oracle也有自身的方法,只是稍微复杂些. 那就是使用oracle的sql*loader功能 ...

  3. c#中高效的excel导入oracle的方法

    c#中高效的excel导入oracle的方法 2009年04月21日 星期二 下午 07:57 如何高效的将excel导入到oracle?和前两天的SqlBulkCopy 导入到sqlserver对应 ...

  4. ASP实现Excel导入Access数据库

    导入方式有很多,思路有两种: 1.用户直接打开本地Excel文件,通过程序直接导入Access数据库; 2.用户打开本地Excel文件,通过程序上传至固定文件夹,然后通过程序将数据导入Access数据 ...

  5. jpa在自己创建表的是字段名不一致_用 数据透视表 完成 Excel多表合并

    一般情况下,数据透视表只能汇总一个表格中的数据.即使使用多区域汇总,也只能对多表的单列内容进行数据汇总,而多列却无法实现.前段时间也推送过Power Query的方法,但它有版本限制.而今天宏兴会计培 ...

  6. mysql自动匹配数据,excel自动从数据库匹配相应的数据:excel导入表格

    如何在excel表格中链接另一个excel表中的数据库 这个具体要看链接的具体要求 如果单纯链接,可以考虑使用超级链接 其他的可以考虑公式,如vlookup进行匹配 或者使用vba事件实现的 Exce ...

  7. 注解+反射优雅的实现Excel导入导出(通用版)

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/youzi1394046585/ article/details/86670203 日常在做后 ...

  8. 当excel 导入数据库的字段大于255时,把第一行的字段加长超过255.

    当excel 导入数据库的字段大于255时,把第一行的字段加长超过255. 因为Excel驱动程序在进行导入操作时会预先采样部分数据判断字段的数据类型,所以对采样数据结果作的判断同全部数据的数据类型有 ...

  9. java反射之Field用法(获取对象的字段名和属性值)

    一.概述 Field是一个类,位于java.lang.reflect包下.在Java反射中Field类描述的是类的属性信息,功能包括: 获取当前对象的成员变量的类型 对成员变量重新设值 二.如何获取F ...

  10. excel 宏命令 VB 选择字段名相同的多行数据,复制到另一sheet

    Sub 选择字段名相同的数据复制()Dim d As ObjectSet d = CreateObject("scripting.dictionary")With Sheets(& ...

最新文章

  1. Yoshua:深度学习AI迈向人类水平的挑战(附PPT下载)
  2. 基于Kubernetes构建Docker集群管理详解
  3. 关于代码评审的微博讨论汇集
  4. Asp.Net分页控件
  5. python123查找指定字符输入m_大数据应用人才培养系列教材 Python语言 刘 鹏 张 燕 总主编 李肖俊 主编 刘 河 钟 涛 副主编....
  6. 面试官:你知道怎么求素数吗?
  7. Ubuntu 16.zabbixserver服务报错: Assuming that agent dropped connection because of access permissions.
  8. 关于抽象和多态的总结
  9. 官方开源的安卓客户端
  10. 基于STM32的超声波避障小车
  11. JS根据城市名称获取所在省份
  12. 如何面试软件工程师 看这篇就够了
  13. PostgreSQL 视图
  14. 软件测试整理:测试设计
  15. c语言筛法求一个范围内的素数,运用埃拉托色尼筛法求解一定范围内的素数.docx...
  16. gms认证流程_谷歌GMS测试认证具体流程
  17. clickhouse-MergeTree原理解析
  18. 前端和后端是如何实现交互的
  19. 电脑鼠标如何进行维护
  20. php等比例剪切缩放图片

热门文章

  1. 用pcdet跑deecamp20_liadr3-1
  2. crfclust.bdb文件过大处理
  3. Mysql用户与权限操作
  4. office图标空白异常解决方法
  5. 差分 线宽 线距_做设计时线宽、线距规则设置多大比较好?
  6. CSS设置background背景透明
  7. 【C语言】输出杨辉三角形 - 杨辉直角三角形(杨辉三角最佳算法) 输出杨辉三角前十行
  8. vscode美化:主题切换+背景图片设置
  9. 【学习笔记】认识张量
  10. 使用代理爬去微信公众号_使用代理爬取微信公众号文章的方法