java反射机制-excel导入-表头名字和顺序允许互换

发布时间:2020-04-04 21:51:31 作者:zhao_anan
来源:网络 阅读:414

如下excel表格,按照表头名字读取数据,允许表头增加无意义空格,允许表头顺序交换。


序号隧道左公里标隧道右公里标是否隧道
1DK2291.416DK0
2DK7389.65DK2291.416
3ZK2277ZK0
4ZK5235.68ZK2277
实现方法如下,充分利用java反射机制,巧妙运用正则表达式进行表头名字匹配,提取配置表格文件顺序,模糊动态匹配表头名字和顺序。
/**
	 * 
	 * 读取指定sheet 页指定行<T>数据
	 * 
	 * @param sheetIx 指定 sheet 页,从 0 开始
	 * @param start   指定开始行,从 0 开始
	 * @param end     指定结束行,从 0 开始
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<List<T>> readGeneric(int sheetIx, int start, int end, T t) throws Exception {
		Sheet sheet = workbook.getSheetAt(sheetIx);
		List<List<T>> list = new ArrayList<List<T>>();

		if (end > getRowCount(sheetIx)) {
			end = getRowCount(sheetIx);
		}
		List<Integer> colNums = new ArrayList<Integer>();
		for (int i = start; i <= end; i++) {
			List<T> rowList = new ArrayList<T>();
			Row row = sheet.getRow(i);
			List rowdata = getRowdata(row);
			Class clazz = t.getClass();
			Object fa= clazz.newInstance();
			Method method = t.getClass().getMethod("getLdcode", new Class[]{});
			String[] ldcode = (String[])method.invoke(fa, new Object[]{});
			

			//处理从0行开始取得请求
			if(0 == start)
			{
				//处理请求的第0行,即表头
				if(i == 0)
				{
					//通过反射获取模板类的实例
					try {
						String simpleName = t.getClass().getSimpleName();
						String StrEnumClass = simpleName.substring(0, simpleName.length()-5) + "Enum";
						Class EnumClass = Class.forName("com.crscd.config.service.cbtc2.atp.excel.enums."+StrEnumClass);
						//Object enumInstance = EnumClass.newInstance();
						
						for(int j = 0; j < rowdata.size(); j++)
						{
							//去除表头上空格、回车、换行符、制表符
							if(null != rowdata.get(j) && !"".equals(rowdata.get(j))) {
								Pattern p = Pattern.compile("\\s*|\t|\r|\n");
								String str = (String)rowdata.get(j);
					            Matcher m = p.matcher(str);
					            String excelData =  m.replaceAll("");
					            //获取表头对应的工具类中ldcode位置
					            Method met = EnumClass.getMethod("getStatus", String.class);
					            int col = (int) met.invoke(Object.class, excelData);
								colNums.add(col);
							}else
							{
								colNums.add(-1);
							}
						}
					}catch(ClassNotFoundException e) {
						//e.printStackTrace();
					}
					
				}
			}
				
			for(int j = 0; j < colNums.size(); j++) {
				int k = j;
				//如果映射表头列和数据列不匹配,当数据列小于映射表头列时,说明excel有无效列,则不足的列用空串补足
				if (colNums.size() > rowdata.size() ) {
					rowdata.add("");
				}
				if(0 == start && !colNums.isEmpty())
				{
					k = colNums.get(j);
				}
				if(k == -1) {
					continue;
				}else {
					try {
						method = t.getClass().getMethod("set"+ldcode[k], String.class);
						method.invoke(fa, rowdata.get(j));
					//如果映射表头列和数据列不匹配,是excel多余无效行列,则越界,仍保留未越界之前的全部数据。
					}catch(IndexOutOfBoundsException e) {
						continue;
					}
				}
			}
			rowList.add((T) fa);
			list.add(rowList);
		}

		return list;
	}


package com.crscd.config.service.cbtc2.atp.excel;

public class TunnelUtils<T> implements Comparable<TunnelUtils<T>>,Cloneable{

	private String[] ldcode = {
			"Id", "TunnelLeftKilo", "TunnelRightKilo", "IsTunnel"
	};
	
	private String id;
	private String tunnelLeftKilo;
	private String tunnelRightKilo;
	private String isTunnel;
	
	public String[] getLdcode() {
		return ldcode;
	}
	public void setLdcode(String[] ldcode) {
		this.ldcode = ldcode;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getTunnelLeftKilo() {
		return tunnelLeftKilo;
	}
	public void setTunnelLeftKilo(String tunnelLeftKilo) {
		this.tunnelLeftKilo = tunnelLeftKilo;
	}
	public String getTunnelRightKilo() {
		return tunnelRightKilo;
	}
	public void setTunnelRightKilo(String tunnelRightKilo) {
		this.tunnelRightKilo = tunnelRightKilo;
	}
	public String getIsTunnel() {
		return isTunnel;
	}
	public void setIsTunnel(String isTunnel) {
		this.isTunnel = isTunnel;
	}
	
	@Override
	public int compareTo(TunnelUtils<T> o) {
		if(Double.parseDouble(stringGetNum(tunnelLeftKilo))<Double.parseDouble(stringGetNum(o.getTunnelLeftKilo()))) {
			return -1;
		}
		if(Double.parseDouble(stringGetNum(tunnelLeftKilo))>Double.parseDouble(stringGetNum(o.getTunnelLeftKilo()))) {
			return 1;
		}
		return 0;
	}
	//字符串取数
		public String stringGetNum(String str) {
			String str2 = "";
			if(str != null && !"".equals(str)){
				for(int i=0;i<str.length();i++){
					if((str.charAt(i)>=48 && str.charAt(i)<=57) || str.charAt(i)==46){
						str2+=str.charAt(i);
					}
				}
				return str2;
			}
			return str;
		}
		@Override  
	    public Object clone() {  
			TunnelUtils<T> stu = null;  
	        try{  
	            stu = (TunnelUtils<T>)super.clone();  
	        }catch(CloneNotSupportedException e) {  
	            e.printStackTrace();  
	        }  
	        return stu;  
	    }  
}
package com.crscd.config.service.cbtc2.atp.excel.enums;

import java.util.regex.Pattern;

public enum TunnelEnum {
	id("序号",0),
	tunnelLeftKilo("隧道左公里标",1),
	tunnelRightKilo("隧道右公里标",2),
	isTunnel("是否隧道",3);
	
	private final String msg;
    private final int status;
	
	TunnelEnum(String msg,int status)
	{
		this.msg = msg;
        this.status = status;
	}	
	//动态匹配表头名字,允许加空,加无意义字符
	public static int getStatus(String str)
	{
		str = str.replaceAll("\\(", "\\\\(");
		str = str.replaceAll("\\)", "\\\\)");
		String pattern = "^"+str+".*";
		for(TunnelEnum e : TunnelEnum.values())
		{
			if(Pattern.matches(pattern, e.msg))
			{
				return e.status;
			}
		}
		return -1;
	}

}

excel的数据如下:

序号隧道左公里标隧道右公里标是否隧道
1DK2291.416DK0
2DK7389.65DK2291.416
3ZK2277ZK0
4ZK5235.68ZK2277


推荐阅读:
  1. Go中的其他匿名字段和同名字段
  2. 前端实现Excel导入和导出功能的方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

反射 动态表格表头 动态顺序

上一篇:Mysql与Oracle的分页查询比较

下一篇:Nginx 配置二级虚拟目录访问 Laravel 后台重写

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》