/**
 * 批量导入数据
 */
package weaver.formmode.excel;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import com.engine.cube.biz.CodeBuilder;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import com.weaver.formmodel.util.DateHelper;
import com.weaver.formmodel.util.StringHelper;

import jxl.WorkbookSettings;
import jxl.read.biff.BiffException;
import weaver.common.StringUtil;
import weaver.conn.RecordSet;
import weaver.dateformat.TimeZoneVar;
import weaver.file.ExcelParse;
import weaver.file.ExcelParseForJXL;
import weaver.file.ExcelParseForPOI;
import weaver.file.FileUploadToPath;
import weaver.formmode.FormModeConfig;
import weaver.formmode.cache.StringCacheMap;
import weaver.formmode.data.FieldInfo;
import weaver.formmode.data.ModeDataManager;
import weaver.formmode.exttools.impexp.common.FileUtils;
import weaver.formmode.exttools.impexp.common.StringUtils;
import weaver.formmode.interfaces.ImportFieldTransAction;
import weaver.formmode.interfaces.ImportFieldTransActionPOI;
import weaver.formmode.interfaces.ImportPreInterfaceAction;
import weaver.formmode.interfaces.ImportPreInterfaceForJXLAction;
import weaver.formmode.interfaces.ImportPreInterfaceForPOIAction;
import weaver.formmode.log.FormmodeLog;
import weaver.formmode.search.batchoperate.DeleteData;
import weaver.formmode.service.CommonConstant;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.systeminfo.SystemEnv;

/**
 * -2000:id;-2001:mainid;-1000:dataid;-1001:modedatacreater;-1002:modedatacreatedate
 */
public class ImpExcelServer extends FormmodeLog {

	private String clientaddress = "";//clint IP
	private String key = "";
	private boolean isprintlog = false;
	/**
	 * 默认共享是否与明细表字段有关,如果有关,则权限重构需等到明细表插入完成才重构,否则可以主表插入一条就重构一条
	 */
	private boolean isdetailright = false;
	private User user ;//操作用户

	private ArrayList errorRow = new ArrayList();//错误的数据行
	private ArrayList errorTable = new ArrayList();//错误的表名称

	private ImportPreInterfaceAction object;
	private Map<String,String> checkMap = new HashMap<String, String>();

	public static Map<String,String> progressMap  = new HashMap<String,String>();

	private static final String CANIMPORT = "canImport";//是否可以继续导入
	private static final String CANIMPORTMSG = "canImportmsg";//
	private static final String STATUS = "status";//状态
	private static final String STEP = "step";//进度步骤，一共6步
	private static final String STARTTIME = "starttime";//开始时间
	private static final String ERRMSG = "errmsg";//错误消息
	private static final String TIME = "time";//耗时
	private static final String ENDTIME = "endtime";//结束时间
	private static final String MSG = "msg";//进度消息
	private static final String IMPADDR = "impaddr";//导入服务器的地址

	private static final String MODEIMP = "modeimp";//大KEY
	private static final String SEARCHID = "searchid";//返回的页面搜索的id
	private static final String ERRORFLAG = "errorflag";//是否展示页面
	private String backupremark="";//日志备注
	private static final String suffix="_bak";//覆盖删除备份表的后缀
	private int backindex=0;
	public ArrayList getErrorRow() {
		return errorRow;
	}

	public void setErrorRow(ArrayList errorRow) {
		this.errorRow = errorRow;
	}


	/**
	 * 获得是否允许创建节点导入明细
	 * @param workflowid
	 * @param nodeid
	 * @param isremark
	 * @return
	 */
	public boolean getAllowesImport(int requestid, int workflowid, int nodeid,
									int isremark, User user) {
		boolean isimport = false;
		if (isremark == 0) {
			RecordSet rs = new RecordSet();
			// 看到当前节点是否是创建节点
			rs.execute("select id from workflow_nodebase where isstart='1' and id="+ nodeid);
			if (rs.next()) {
				// 看是否设置 这个流程可以导入明细表
				rs.execute("select formid,isbill from workflow_base where isImportDetail='1' and id="+ workflowid);
				if (rs.next()) {
					int formid = rs.getInt("formid");
					int isbill = rs.getInt("isbill");
					String ismode = "";
					int showdes = 0;
					int modeid = 0;
					// ismode “1”:模板模式 “0”:普通模式
					// showdes “1”:没有显示模板 “0”:有显示模板
					// printdes “1”:没有打印模板 “0”:有打印模板
					// toexcel “1”:导出excel
					rs.execute("select ismode,showdes,printdes,toexcel from workflow_flownode where workflowid="+ workflowid + " and nodeid=" + nodeid);
					if (rs.next()) {
						ismode = Util.null2String(rs.getString("ismode"));
						showdes = Util.getIntValue(Util.null2String(rs.getString("showdes")), 0);
					}
					// 是模板模式,并且有显示模板
					if (ismode.equals("1") && showdes != 1) {
						// 得到可以打印的该节点的id??mode是什么??
						rs.execute("select id from workflow_nodemode where isprint='0' and workflowid="+ workflowid + " and nodeid=" + nodeid);
						if (rs.next()) {
							modeid = rs.getInt("id");
						} else {
							rs.execute("select id from workflow_formmode where isprint='0' and formid=" + formid+ " and isbill='" + isbill + "'");
							if (rs.next()) {
								modeid = rs.getInt("id");
							}
						}
					}
					String tablename = "workflow_nodeform";
					if (ismode.equals("1") && modeid > 0) {
						tablename = "workflow_modeview";
					}
					// isbill:1 单据 0:表单!
					if (isbill == 1) {
						rs.execute("select b.fieldid from workflow_billfield a,"+ tablename+ " b where a.id=b.fieldid and a.viewtype=1 and b.isedit='1'");
					} else {
						rs.execute("select b.fieldid from workflow_formdictdetail a,"+ tablename + " b where a.id=b.fieldid and b.isedit='1'");
					}
					if (rs.next()) {
						isimport = true;
					}
				}
			}
		}
		return isimport;
	}

	/**
	 * 获得是否有导入明细权限
	 *
	 * @param requestid
	 * @param nodeid
	 * @param userid
	 * @return
	 */
	public boolean getImportRight(int requestid, int nodeid, int userid) {
		boolean hasright = false;
		RecordSet rs = new RecordSet();
		rs.execute("select requestid from workflow_currentoperator where isremark='0' and requestid="+ requestid
				+ " and userid="+ userid + " and nodeid="+ nodeid
				+ " and exists(select 1 from workflow_nodebase where isstart='1' and id="+ nodeid + ")");
		if (rs.next()) {
			hasright = true;
		}
		return hasright;
	}

	// 得到明细表字段的属性描述
	private String getFdName(String fid, int isbill, int formid) {
		RecordSet rs = new RecordSet();
		String sql;
		if (isbill > 0) {
			sql = "select fieldname from workflow_billfield where id = " + fid;
		} else {
			sql = "SELECT  a.fieldname FROM workflow_formfield wf , ( SELECT DISTINCT id , fielddbtype , fieldname ,description FROM workflow_formdictdetail ) a WHERE wf.formid = "
					+ formid + " AND wf.isdetail = '1' " + "AND wf.fieldid = a.id AND a.id =  " + fid;
		}
		rs.execute(sql);
		if (rs.next()) {
			return rs.getString("fieldname");
		}
		return null;
	}

	private String getDtName(String id, int isbill, int formid) {
		RecordSet rs = new RecordSet();
		String sql;
		if (isbill > 0) {
			sql = "select detailtable from workflow_billfield where id = " + id;
			// 查询明细表列名
			rs.execute(sql);
			if (rs.next()) {
				return rs.getString("detailtable");
			}
		} else
			return "workflow_formdetail";
		return null;
	}

	private String getDtValue(String dtName, String dtFieldId, String id) {
		RecordSet rs = new RecordSet();
		String sql = "select dtFieldId from mainKey where id = " + id;
		// 查询明细表列名
		rs.execute(sql);
		if (rs.next()) {
			return rs.getString("detailtable");
		}
		return null;
	}

	// 计算一个明细表的行列表达式.
	private void colCal(String rowcalstr, int isbill, int formid, Map map,
						int mainid, int billid) {
		String sql = "";
		Set fdName = new HashSet();
		RecordSet rs2 = new RecordSet();
		RecordSet rs = new RecordSet();
		String firstFid = "";
		String firstFname = "";
		Pattern pattern = Pattern.compile("detailfield[_](\\d+)");
		Matcher matcher = null;
		matcher = pattern.matcher(rowcalstr);
		while (matcher.find()) {
			if ("".equals(firstFid)) {
				firstFid = matcher.group(1);
			} else {
				fdName.add(matcher.group(1));
			}
		}
		// 得到等于号左边的对应的fdname.
		firstFname = getFdName(firstFid, isbill, formid);
		// 得到明细表名
		String detailTableName = getDtName(firstFid, isbill, formid);

		List l = new ArrayList();
		l.addAll(fdName);
		Iterator it = l.iterator();
		String allV = "";
		Map mmm = new HashMap();
		int count = 0;
		while (it.hasNext()) {
			String fidid = (String) it.next();
			String fdname = getFdName(fidid + "", isbill, formid);
			allV += fdname + ",";
			mmm.put(fdname, fidid);
			count++;
		}
		if (allV.length() > 0) {
			allV = allV.substring(0, allV.length() - 1);
			String mainKey = (String) map.get(detailTableName);
			if (isbill > 0)
				sql = "select " + allV + ",id from " + detailTableName + " where " + mainKey + " = " + mainid;
			rs.execute(sql);
			while (rs.next()) {
				FelEngine fel = new FelEngineImpl();
				FelContext ctx = fel.getContext();
				Iterator iterator = mmm.keySet().iterator();
				while (iterator.hasNext()) {
					String eee = (String) iterator.next();
					int index = 1 + l.indexOf(mmm.get(eee));
					String string = rs.getString(index);
					// 如果没有这个明细值,就设置为0
					if (string == null || "".equals(string)) {
						ctx.set("detailfield_" + mmm.get(eee), new Double(0.0));
					} else {
						if(string.indexOf(",")!=-1){
							string = string.replace(",", "");
						}
						double d = Util.getDoubleValue(string,0);
						ctx.set("detailfield_" + mmm.get(eee), d);
					}
				}
				String idString = rs.getString(l.size() + 1);
				Object result = fel.eval(rowcalstr.substring(rowcalstr
						.indexOf("=") + 1, rowcalstr.length()));

				if(!result.equals("")){
					String sql2 = "select fieldhtmltype,type,fielddbtype,qfws from workflow_billfield where id="+firstFid;
					rs2.execute(sql2);
					if(rs2.next()){
						String fieldhtmltype = rs2.getString("fieldhtmltype");
						String type = rs2.getString("type");
						String qfws = rs2.getString("qfws");
						String fielddbtype = Util.null2String(rs2.getString("fielddbtype"));
						if(fieldhtmltype.equals("1")&&type.equals("2")){
							BigDecimal b = new BigDecimal(result+"");
							int f1 = b.setScale(0,BigDecimal.ROUND_HALF_UP).intValue();
							result = Util.toDecimalDigits(f1+"",0);
						}else if(fieldhtmltype.equals("1")&&type.equals("4")){
							BigDecimal b = new BigDecimal(result+"");
							double f1 = b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
							result = Util.toDecimalDigits(f1+"",2);
						}else if(fieldhtmltype.equals("1")&&type.equals("5")){
							BigDecimal b = new BigDecimal(result+"");
							double f1 = b.setScale(Util.getIntValue(qfws,2),BigDecimal.ROUND_HALF_UP).doubleValue();
							result = Util.toDecimalDigits(f1+"",Util.getIntValue(qfws,2));
							result = Util.milfloatFormat(result+"");
						}else if(type.equals("3")&&fieldhtmltype.equals("1")){
							int digitsIndex = fielddbtype.indexOf(",");
							int decimaldigits_t=0;
							if(digitsIndex > -1){
								decimaldigits_t = Util.getIntValue(fielddbtype.substring(digitsIndex+1, fielddbtype.length()-1), 2);
							}else{
								decimaldigits_t = 2;
							}
							BigDecimal b = new BigDecimal(result+"");
							double f1 = b.setScale(decimaldigits_t,BigDecimal.ROUND_HALF_UP).doubleValue();
							result = Util.toDecimalDigits(f1+"",decimaldigits_t);
						}
					}
				}

				sql = "update " + detailTableName + " set " + firstFname + " = '" + result + "' where id = " + idString;
				rs2.execute(sql);
			}
		}
	}

	// 计算列转换的值.
	public void getColCalStr(int formid, int billid, String mainTableName,
							 Map map, int mainid, int isbill, String dtname) {
		RecordSet rs = new RecordSet();
		RecordSet rs2 = new RecordSet();
		String colcalstr = "";
		String maincalstr = "";
		String rowcalstr = "";
		String sql = "select * from workflow_formdetailinfo where formid =" + formid;
		if (formid != 0)
			rs.execute(sql);
		if (rs.next()) {
			colcalstr = rs.getString("colcalstr");
			maincalstr = rs.getString("maincalstr");
			rowcalstr = rs.getString("rowcalstr");
		}
		// 计算多个明细表的行列规则
		if (rowcalstr != null && !"".equals(rowcalstr.trim())) {
			String[] rowcalstrs = rowcalstr.split(";");
			for (int ii = 0; ii < rowcalstrs.length; ii++) {
				colCal(rowcalstrs[ii], isbill, formid, map, mainid, billid);
			}
		}

		// 下面计算总和
		if (maincalstr != null && !"".equals(maincalstr.trim())) {
			String[] m = maincalstr.split(";");
			for (int i = 0; i < m.length; i++) {
				String detailTableName = "";
				String dfname = "";
				String mfname = "";
				String[] temp = m[i].split("=");
				String mf = temp[0].replace("mainfield_", "");
				String qfws = "";
				String df = temp[1].replace("detailfield_", "");
				if (isbill > 0) {
					sql = "select fieldname,qfws from workflow_billfield where id = " + mf;
				} else {
					sql = "select fieldname from workflow_formdict where id = " + mf;
				}
				rs2.execute(sql);
				if (rs2.next()) {
					mfname = rs2.getString("fieldname");
					qfws = rs2.getString("qfws");
				}

				// 得到等于号左边的对应的fdname.
				dfname = getFdName(df, isbill, formid);
				// 得到明细表名
				detailTableName = getDtName(df, isbill, formid);

				String mainKey = (String) map.get(detailTableName);
				if (mainKey == null || "".equals(mainKey.trim())) {
					mainKey = "requestid";
				}
				sql = "select " + dfname + " dd from " + detailTableName + " where " + mainKey + " = " + mainid;
				rs2.execute(sql);
				double ddvaluesum=0;
				while (rs2.next()) {
					String ddvalue = Util.null2String(rs2.getString("dd"));
					ddvaluesum += Util.getDoubleValue(ddvalue.replace(",", ""),0);
				}
				String dstr="";
				String sql2 = "select fieldhtmltype,type,fielddbtype,qfws from workflow_billfield where id="+df;
				rs2.execute(sql2);
				if(rs2.next()){
					String fieldhtmltype = rs2.getString("fieldhtmltype");
					String type = rs2.getString("type");
					String fielddbtype = Util.null2String(rs2.getString("fielddbtype"));
					if(fieldhtmltype.equals("1")&&type.equals("2")){
						BigDecimal b = new BigDecimal(ddvaluesum);
						int f1 = b.setScale(0,BigDecimal.ROUND_HALF_UP).intValue();
						dstr = Util.toDecimalDigits(f1+"",0);
					}else if(fieldhtmltype.equals("1")&&type.equals("4")){
						BigDecimal b = new BigDecimal(ddvaluesum+"");
						double f1 = b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
						dstr = Util.toDecimalDigits(f1+"",2);
					}else if(fieldhtmltype.equals("1")&&type.equals("5")){
						BigDecimal b = new BigDecimal(ddvaluesum+"");
						double f1 = b.setScale(Util.getIntValue(qfws,2),BigDecimal.ROUND_HALF_UP).doubleValue();
						dstr = Util.toDecimalDigits(f1+"", Util.getIntValue(qfws,2));
						dstr = Util.milfloatFormat(dstr+"");
					}else if(type.equals(""+3)&&fieldhtmltype.equals("1")){
						int digitsIndex = fielddbtype.indexOf(",");
						int decimaldigits_t=0;
						if(digitsIndex > -1){
							decimaldigits_t = Util.getIntValue(fielddbtype.substring(digitsIndex+1, fielddbtype.length()-1), 2);
						}else{
							decimaldigits_t = 2;
						}
						BigDecimal b = new BigDecimal(ddvaluesum+"");
						double f1 = b.setScale(decimaldigits_t,BigDecimal.ROUND_HALF_UP).doubleValue();
						dstr = Util.toDecimalDigits(f1+"",decimaldigits_t);
					}else{
						dstr = ddvaluesum+"";
					}
				}
				// 更新新表单
				if (isbill > 0  && formid < 0)
					sql = " update  " + mainTableName + " set " + mfname + " = '" + dstr + "' where id = " + mainid;
				rs.execute(sql);
			}
		}
	}




	@Override
	public void writeLog(Object obj) {
		if(this.isprintlog) {
			super.writeLog(obj);
		}
	}

	@Override
	public void writeLog(String classname, Object obj) {
		if(this.isprintlog) {
			super.writeLog(classname, obj);
		}
	}

	/**
	 * 批量导入，E9已经不走此接口，废弃
	 * @param fu
	 * @return
	 */
	@Deprecated
	public String ImportData(FileUploadToPath fu, User user,HttpServletRequest req) {
		Map<String, Object> params = new HashMap<String,Object>();

		int modeid = Util.getIntValue(fu.getParameter("modeid"),0);
		int importtype = Util.getIntValue(fu.getParameter("importtype"),0);//1 追加，2覆盖,3更新
		int updateadddata = Util.getIntValue(fu.getParameter("updateadddata"),0); //importtype==3的时候
		String keyfield=Util.null2String(fu.getParameter("keyField")).toLowerCase();//重复验证字段

		int sourcetype = Util.getIntValue(fu.getParameter("sourcetype"));//为1的时候，表示是后台设置界面

		int importorder = Util.getIntValue(fu.getParameter("importorder"));//为后台设置界面时，无需保存，导入顺序即可生效
		String tempkey = Util.null2String(fu.getParameter("tempkey"));
		int formid = Util.getIntValue(fu.getParameter("formid"));
		int pageexpandid = Util.getIntValue(fu.getParameter("pageexpandid"));
		int isprintlog = Util.getIntValue(fu.getParameter("isprintlog"));
		String isImportedWithIgnoringError = Util.null2String(fu.getParameter("isImportedWithIgnoringError"));

		String tempkeyStr = Util.null2String(params.get("tempkey"));
		String key = user.getUID()+"_"+modeid+"_"+tempkeyStr;
		this.key = key;
		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

		params.put("modeid", modeid);
		params.put("importtype", importtype);
		params.put("updateadddata", updateadddata);
		params.put("keyfield", keyfield);
		params.put("sourcetype", sourcetype);

		params.put("importorder", importorder);
		params.put("tempkey", tempkey);

		params.put("isprintlog", isprintlog);
		params.put("isImportedWithIgnoringError", isImportedWithIgnoringError);

		//-----------------单独处理------------------
		RecordSet rs = new RecordSet();
		if(pageexpandid<1){
			String sql = "SELECT id FROM mode_pageexpand WHERE  modeid="+modeid+" AND issystemflag=103  ";
			rs.execute(sql);
			if(rs.next()){
				pageexpandid = rs.getInt("id");
			}
		}
		if(formid<0){
			String sql = "SELECT formid FROM modeinfo WHERE  id="+modeid;
			rs.execute(sql);
			if(rs.next()){
				formid = rs.getInt("formid");
			}
		}
		params.put("formid", formid);
		params.put("pageexpandid", pageexpandid);
		String filename = fu.uploadFiles("excelfile");
		HttpSession session = req.getSession(true);
		params.put("session", session);
		params.put("fu", fu);
		params.put("filename", filename);
		return this.ImportDataNew(params, user);
	}

	/**
	 * 批量导入
	 * @param params
	 * @param user
	 * @return
	 */
	public String ImportDataNew(Map<String, Object> params, User user) {
		String filename = Util.null2String(params.get("filename"));
		String startStr = DateHelper.getCurDateTime();
		//导入前先加载下缓存
		int modeid = Util.getIntValue(Util.null2String(params.get("modeid")));
		this.isdetailright=getIsDetailRight(modeid);
		String tempkeyStr = Util.null2String(params.get("tempkey"));
		String key = user.getUID()+"_"+modeid+"_"+tempkeyStr;
		this.key = key;
		//校验文件大小
		File file = new File(filename);
		FormModeConfig config=new FormModeConfig();
		int batchimportSize = config.getBatchimportSize();
		if (file.exists()&&file.length()>(batchimportSize*1024*1024)) {
			String msg=MessageFormat.format(SystemEnv.getHtmlLabelName(523743, user.getLanguage()), batchimportSize);
			writeProgressMsg(key,msg, "-1");
			ExpExcelUtil.removeImpUserState(user.getUID(),modeid+"");
			return msg;
		}
		//30s内禁止同一个用户的多次请求
		String stateStr=Util.null2String(ExpExcelUtil.getObject("modeImp30s_"+user.getUID()));
		if(stateStr!=null&&!"".equals(stateStr)){
			String currentTime = DateHelper.getCurDateTime();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String lastTime = Util.splitString(stateStr,"##")[0];
			try {
				Date dt1 = sdf.parse(lastTime);//上次的时间
				Date dt2 = sdf.parse(currentTime);
				double t = (dt2.getTime() - dt1.getTime()) / (1000.0);//当前时间-上次的时间的秒数
				if(t<10){
					writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(512688, user.getLanguage()), "10"), "-1");
					writeLog("imp:10s内禁止同一个用户的多次请求",lastTime+"_"+currentTime);
					ExpExcelUtil.removeImpUserState(user.getUID(),modeid+"");
					return SystemEnv.getHtmlLabelName(508071, user.getLanguage());
				}
			} catch (ParseException e) {
				e.printStackTrace();
				writeLog("imp:10s内禁止同一个用户的多次请求:日期转换异常",lastTime+"_"+currentTime);
			}
		}
		ExpExcelUtil.putObject("modeImp30s_"+user.getUID(), startStr, true);
		//30s内禁止同一个用户的多次请求




		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

		Date starttime = new Date();
		String Errmsg = "";


		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

		ModeCacheManager.getInstance().loadCacheNow(modeid+"", "", "");
		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
		int sourcetype = Util.getIntValue(Util.null2String(params.get("sourcetype")));//为1的时候，表示是后台设置界面
		int importorderReq = Util.getIntValue(Util.null2String(params.get("importorder")));//为后台设置界面时，无需保存，导入顺序即可生效
		int importtype = Util.getIntValue(Util.null2String(params.get("importtype")));//1 追加，2覆盖,3更新
		int formid = Util.getIntValue(Util.null2String(params.get("formid")));
		this.isprintlog = (1 == Util.getIntValue(Util.null2String(params.get("isprintlog"))));
		String importhref = StringUtil.getURLDecode(Util.null2String(params.get("href"))); //导入地址
		String impAddr = ExcelCacheUtil.getHostaddr();
		setProgressCanImport(key, true);
		putMessage(STARTTIME,key, starttime.getTime()+"");
		putMessage(IMPADDR,key, impAddr);
		writeProgressMsg(key,SystemEnv.getHtmlLabelName(132262, user.getLanguage()), "0");
		List rowNumList  = new Vector();//仅记录当前进度，不管是否成功
		List billList  = new Vector();//记录成功导入的id
		List rightList  = new Vector();
		List detailList  = new Vector();
		List<String> addBillIdList  = new Vector<String>();//增加
		List<String> updateList  = new Vector<String>();//更新
		List<Integer> errorRowList  = new Vector<Integer>();//出错行
		Hashtable<String,Vector<Integer>> errorDetailMap = new Hashtable<String,Vector<Integer>>();
		int mainrows = 0;
		int mainrowsALL = 0;
		int delmainRow = 0;
		int deldetailRow = 0;
		String ErrmsgRow = "";
		boolean hasDetail=false;
		Sheet[] allSheets = null;
		String sheetEmptyRowMsg = "";
		boolean isExcel2007=true;
		try {
			String sql = "";
			RecordSet rs = new RecordSet();
			RecordSet rs2 = new RecordSet();

			String interfacePath = "";
			String fieldtranspath = "";
			String isuse = ""; //1启用
			int billid = -1;
			int modetype = -1;

			sql = "select modename,modedesc,formid,modetype from modeinfo where id = " + modeid;
			rs.execute(sql);
			while(rs.next()){
				formid = Util.getIntValue(rs.getString("formid"));
				modetype = Util.getIntValue(rs.getString("modetype"));
			}
			boolean hetong = false;//如果是合同数据
			String modetypeids = getPropValue("modedatabatchimport", "modetype");
			modetypeids = ","+modetypeids+",";
			if(modetypeids.indexOf(","+modetype+",")>-1){//如果是合同数据
				String needrightmodeids =","+ getPropValue("modedatabatchimport", "modeneedrightids")+",";
				if (needrightmodeids.indexOf(","+modeid+",")<0) {
					hetong = true;
				}
			}

			sql = "select * from mode_DataBatchImport where modeid="+modeid;
			rs.execute(sql);
			if (rs.next()) {
				interfacePath = rs.getString("interfacepath");
				fieldtranspath=Util.null2String(rs.getString("fieldtranspath"));
				isuse = rs.getString("isuse");
			}
			Object  fieldTransObject=null;
			List<String> fieldtranslist = new ArrayList<String>();
			if (!"".equals(fieldtranspath)) {
				sql = "select fieldid from mode_import_fieldtrans where modeid=? and formid=?";
				rs.executeQuery(sql, modeid,formid);
				while (rs.next()) {
					String fieldid = Util.null2String(rs.getString("fieldid"));
					fieldtranslist.add(fieldid);
				}
				try {
					fieldtranspath=fieldtranspath.replaceAll(".java$", "").replaceAll(".class$", "");
					fieldTransObject = Class.forName(fieldtranspath).newInstance();
				} catch (Exception e) {
					writeLog(e);
				}
			}
			params.put("fieldTransObject", fieldTransObject);
			params.put("fieldtranslist", fieldtranslist);
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132263, user.getLanguage()), "0",1);
			//init excel object
//			String filename = fu.uploadFiles("excelfile");
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132264, user.getLanguage()), "0");
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			//创建输入流
			InputStream stream = new FileInputStream(filename);
			//获取Excel文件对象
			Workbook  rwb = WorkbookFactory.create(stream);
			if (rwb instanceof HSSFWorkbook) {
				isExcel2007=false;
			}
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132265, user.getLanguage()), "0",1);
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			//---------------验证表头--------------------------
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132266, user.getLanguage()), "0",2);
			int totalsheet=rwb.getNumberOfSheets();
			allSheets=new Sheet[totalsheet];
			for (int i = 0; i < totalsheet; i++) {
				allSheets[i]=rwb.getSheetAt(i);
			}
			//#不需要添加共享数据模块类型，不是模块id，该类型下面的所有数据都不进行权限处理，也不能导入明细数据，只能导入主数据，
			//modetype=17
			if(hetong&&allSheets.length>1){
				Sheet mainSheet = allSheets[0];
				allSheets = new Sheet[]{mainSheet};
			}
			Sheet sheet = rwb.getSheetAt(0);
			int realRows = getSheetRealRows(sheet);
			try{
				if(importtype==2&&realRows<=1){//是覆盖操作
					if(realRows==POIUtil.getLastRowNum(sheet)){
						Errmsg = SystemEnv.getHtmlLabelName(519671, user.getLanguage());//"删除全部数据后导入本次数据操作，不允许导入空的excel"
						throw new Exception(Errmsg);
					}else if(realRows<POIUtil.getLastRowNum(sheet)) {
						Errmsg = SystemEnv.getHtmlLabelName(30769, user.getLanguage());//"数据之间不能有空行。"
						throw new Exception(Errmsg);
					}
				}
			}catch (Exception e){
				Errmsg = e.getMessage();
				throw new Exception(Errmsg);
			}
			if(realRows<POIUtil.getLastRowNum(sheet) && isTipMessage(realRows,sheet)){
				sheetEmptyRowMsg = ",1";
				ErrmsgRow = MessageFormat.format(SystemEnv.getHtmlLabelName(132267, user.getLanguage()),realRows+1);
			}
			int rowNum = realRows;
			mainrowsALL = POIUtil.getLastRowNum(sheet)-1;
			mainrows = realRows-1;
			int isHaveTemplate = 0;
			String templateSql = "select 1 from mode_import_template a where modeid="+modeid+" and formid="+formid+" and (exists(select 1 from workflow_billfield b where b.billid="+formid+" and b.id=a.fieldid) or  a.fieldid in(-1000,-1001,-1002)) ";
			rs.execute(templateSql);
			if(rs.getCounts()>0){
				isHaveTemplate = 1;
			}
			FieldInfo FieldInfo = new FieldInfo();
			FieldInfo.setUser(user);
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132271, user.getLanguage()), "0");
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			List<List<String>> impFieldIds = new ArrayList<>();//记录excel中字段顺序
			try{
				String keyfield = Util.null2String(params.get("keyfield"));
				String conditionfield = Util.null2String(params.get("conditionfield"));
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				//验证主表表头
				if(isHaveTemplate==1){
					FieldInfo.GetManTableFieldToExcelTemplate(formid, 1, user.getLanguage(),modeid);//根据模块导入模板获得主字段
				}else{
					FieldInfo.GetManTableFieldToExcel(formid, 1, user.getLanguage());//获得主字段
				}
				verifyExcelMainHeader(key, sheet,keyfield,conditionfield,modeid,user,FieldInfo,impFieldIds);

				//验证明细表表头
				writeProgressMsg(key,SystemEnv.getHtmlLabelName(132271, user.getLanguage()), "0");
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				if(isHaveTemplate==1){
					FieldInfo.GetDetailTableFieldToExcelTemplate(formid, 1, user.getLanguage(),modeid);//根据模块导入模板获得明细字段
				}else{
					FieldInfo.GetDetailTableFieldToExcel(formid, 1, user.getLanguage());//获得明细字段
				}
				verifyExcelDetailHeader(key,allSheets,modeid,user,FieldInfo,impFieldIds);
			}catch (Exception e){
				Errmsg = e.getMessage();
				throw new Exception(Errmsg);
			}
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			//---------------验证表头end--------------------------

			try {
				if (!StringHelper.isEmpty(interfacePath) && "1".equals(isuse)) {
					writeProgressMsg(key,SystemEnv.getHtmlLabelName(132276, user.getLanguage()), "0");
					Object interfaceObject = Class.forName(interfacePath).newInstance();

					if(interfaceObject instanceof ImportPreInterfaceAction) { //老的POI 方式
						ExcelParse ExcelParse = new ExcelParse();
						ExcelParse.init(filename);
						ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
						if (ExcelParse.getWb()==null) {
							Errmsg=MessageFormat.format(SystemEnv.getHtmlLabelName(513664, user.getLanguage()), SystemEnv.getHtmlLabelName(388652, user.getLanguage()));
							throw new Exception();
						}
						//---------------------验证待处理--------------------------------
						FileUploadToPath fu = (FileUploadToPath) params.get("fu");
						Errmsg = ((ImportPreInterfaceAction)interfaceObject).checkImportData(fu, user, formid, ExcelParse, modeid);
					}else if(interfaceObject instanceof ImportPreInterfaceForJXLAction) {  // JXL 方式
						//获取Excel文件对象
						WorkbookSettings settings=new WorkbookSettings();
						settings.setEncoding("iso-8859-1");
						jxl.Workbook workbook=null;
						try {
							stream = new FileInputStream(filename);
							workbook = jxl.Workbook.getWorkbook(stream,settings);
						} catch (BiffException e) {
							Errmsg=MessageFormat.format(SystemEnv.getHtmlLabelName(513664, user.getLanguage()), SystemEnv.getHtmlLabelName(388652, user.getLanguage()));
							throw new Exception();
						}
						ExcelParseForJXL excelParseForJXL = new ExcelParseForJXL(workbook );
						ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
						//---------------------验证待处理--------------------------------
						Map<String,Object> paramsForJXL = new HashMap<String,Object>();
						paramsForJXL.put("modeid",params.get("modeid"));
						paramsForJXL.put("formid",params.get("formid"));
						Errmsg = ((ImportPreInterfaceForJXLAction)interfaceObject).checkImportData(paramsForJXL, user, excelParseForJXL );
					}else if(interfaceObject instanceof ImportPreInterfaceForPOIAction) {  //新版poi方式,支持excel2007导入
						//获取Excel文件对象
						ExcelParseForPOI excelParse = new ExcelParseForPOI();
						excelParse.init(filename);
						ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
						//---------------------验证待处理--------------------------------
						Map<String,Object> paramsForPOI = new HashMap<String,Object>();
						paramsForPOI.put("modeid",params.get("modeid"));
						paramsForPOI.put("formid",params.get("formid"));
						Errmsg = ((ImportPreInterfaceForPOIAction)interfaceObject).checkImportData(paramsForPOI, user, excelParse );
					}

					if (!StringHelper.isEmpty(Errmsg)) {
						writeLog("Errmsg:"+Errmsg);
						throw new Exception(Errmsg);
					}
				}
			} catch(Exception e) {
				if ("".equals(Errmsg)) {
					Errmsg = SystemEnv.getHtmlLabelName(132277, user.getLanguage())+":"+e.getMessage();
				}
				throw e;
			}
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132278, user.getLanguage()), "0");
			this.closeStream(stream);
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132279, user.getLanguage()), "0");
			//获得后台配置的待验证的字段的id以及验证的条件
			Map<String,List<String>> validateMap = new HashMap<String,List<String>>();
			sql = "select b.* from mode_DataBatchImport a,mode_excelFieldDetail b where b.mainid=a.validateid and a.modeid="+modeid;
			rs.execute(sql);
			while(rs.next()){
				String fieldids = Util.null2String(rs.getString("fieldid"));
				String selectid = Util.null2String(rs.getString("selectids"));
				String selectvalue = Util.null2String(rs.getString("selectvalue"));
				String selectname = Util.null2String(rs.getString("selectname"));
				if(!selectid.equals("") && !selectvalue.equals("")){
					sql = "select * from workflow_SelectItem where fieldid="+selectid+" and selectvalue='"+selectvalue+"'";
					rs2.execute(sql);
					if(rs2.next()){
						selectname =Util.formatMultiLang( rs2.getString("selectname"), user.getLanguage()+"");
					}
				}
				if(!fieldids.equals("")){
					String[] ids = fieldids.split(",");
					for(int i=0;i<ids.length;i++){
						if(validateMap.containsKey(ids[i])){
							List<String> temp = validateMap.get(ids[i]);
							if(selectid.equals("")){
								temp.clear();
							}else{
								if(temp.size() == 0){
									temp.clear();
								}else{
									temp.add(selectid+":"+selectname);
								}
							}
							validateMap.put(ids[i], temp);
						}else{
							List<String> list = new ArrayList<String>();
							if(!selectid.equals("") && !selectvalue.equals("")){
								list.add(selectid+":"+selectname);
							}
							validateMap.put(ids[i], list);
						}
					}
				}

			}
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132280, user.getLanguage()), "0");
			//
			rs.execute("select fieldid,checkexpression from ModeFormFieldExtend where formId='"+formid+"' and (checkexpression is not null or checkexpression!='')");
			while(rs.next()){
				checkMap.put(rs.getString("fieldid"), rs.getString("checkexpression"));
			}
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132281, user.getLanguage()), "0",2);
			//import maintable
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132246, user.getLanguage()), "0",3);
			int cpuNum = 2;
			boolean useSingleThread = true;//默认为顺序导入
			if(sourcetype==1){//为后台设置界面时，按照后台设置界面导入顺序的选择，无需保存即可生效
				if(importorderReq==0){
					useSingleThread = false;
				}
			}else{
				//顺序导入仍然使用单线程导入
				sql = "select importorder from mode_DataBatchImport where modeid="+modeid;
				rs.execute(sql);
				if(rs.next()){
					int importorder = rs.getInt("importorder");
					if(importorder==0){
						useSingleThread = false;
					}
				}
			}
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			if(importtype==2){//是否需要删除历史数据
				writeProgressMsg(key,SystemEnv.getHtmlLabelName(132282, user.getLanguage()), "0");
				RecordSet rs1 = new RecordSet();
				String tablename = "";
				String detailkeyfield = "";
				sql = "select tablename,detailkeyfield from workflow_bill where id = " + formid;//删除数据
				rs.execute(sql);
				if(rs.next()){
					tablename = rs.getString("tablename");
					detailkeyfield = rs.getString("detailkeyfield");
				}
				//-------------删除数据前记录覆盖删除日志-------------
				sql ="select id from " + tablename + " where formmodeid = "+modeid ;
				rs.execute(sql);
				delmainRow = rs.getCounts();
				writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132284,user.getLanguage()),tablename), "0");
				String operatedesc = SystemEnv.getHtmlLabelName(125685, user.getLanguage());//删除（导入被覆盖）
				String operatetype = "3";//操作的类型： 1：新建 2：修改 3：删除 4：查看

				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
//				ImpExcelReader impExcelReader = new ImpExcelReader();
//				impExcelReader.setUser(user);
				DeleteData delData = new DeleteData();
				delData.setUser(user);
				delData.setClientaddress(clientaddress);
				delData.setExcel(true);
				int index = 0;
				while(rs.next()){
					index++;
					writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132284,user.getLanguage()),tablename)+index+"/"+rs.getCounts(), "0");
					int relatedid = rs.getInt("id");
					delData.insertDeleteData(tablename, relatedid+"", modeid+"", formid+"");
//					impExcelReader.writeBeatchLog(modeid,operatedesc, operatetype, relatedid,null,null,null);
				}
				//-------------删除数据前记录覆盖删除日志-------------
				sql = "select tablename from Workflow_billdetailtable where billid = " + formid;
				rs.execute(sql);//查询单据明细表的信息
				int backindex = this.getAndUpdateBackIndex(modeid);
				this.backindex=backindex;
				String detailremark="";
				while(rs.next()){
					String deltablename = rs.getString("tablename");
					sql = "select 1 from "+deltablename+" where "+detailkeyfield+" in (select id from "+tablename+" where formmodeid = "+modeid+" )";
					rs1.execute(sql);//删除明细
					deldetailRow += rs1.getCounts();
					writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132283,user.getLanguage()),deltablename,rs1.getCounts()), "0");
					//修正逻辑,批量导入覆盖删除数据时不删除文档
//					if (isdelfile) {
//						sql="select id from "+tablename+" where formmodeid = "+modeid;
//						rs.executeQuery(sql);
//						while (rs.next()) {
//							String mainid=Util.null2String(rs.getString("id"));
//							del.deleteDocFile(tablename, mainid, formid, false, null, null);//删除主表的附件
//							del.deleteDocFile(deltablename, mainid, formid, true, null, detailkeyfield);//再删除明细表的附件
//						}
//					}
					//备份明细表数据
					String sqlwhere=" where "+detailkeyfield+" in (select id from "+tablename+" where formmodeid = "+modeid+" )";
					// this.BackUpTable(deltablename, modeid, false, backindex, sqlwhere);
					if (rs1.getCounts()>0) {//明细表有数据则备份
						detailremark+=","+MessageFormat.format(SystemEnv.getHtmlLabelName(514955, user.getLanguage()), rs1.getCounts(),deltablename+this.suffix+backindex);
					}
					//{0}条明细数据已备份至{1}
					sql = "delete from "+deltablename+sqlwhere;
					rs1.execute(sql);//删除明细
				}
				writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132285,user.getLanguage()),tablename,rs.getCounts()), "0");
				String sqlwhere=" where formmodeid = "+modeid + " and id not in ("+billid+") ";
				if (delmainRow>0) {
					// this.BackUpTable(tablename, modeid, true, backindex, sqlwhere);
					this.backupremark+=MessageFormat.format(SystemEnv.getHtmlLabelName(514954, user.getLanguage()),tablename+this.suffix+backindex);
				}
				if (!"".equals(detailremark)) {
					this.backupremark+=detailremark;
				}
				sql = "delete from " + tablename + sqlwhere;
				rs.execute(sql);
			}

			Map IdMap = new HashMap();
			ExecutorService executorService = ExpExcelUtil.getInstance().getImppool();//固定线程池
			ExecutorService asynService = ExpExcelUtil.getInstance().getAsynimpPool();//异步任务线程池
			Map<String,Object> modeLogMap = new ConcurrentHashMap<String,Object>();//记录主表id及对应的viewlogid
			int currentIndex = 0;
			CountDownLatch doneSignal = null;
			HashMap creatoridMap = new HashMap();
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			rowNumList.clear();//清除计数器
			params.put("sheetindex", 1);
			jxl.Sheet[] allSheetsJXL = null;
			if (fieldTransObject!=null) {//设置了导入转换接口,初始化所需参数
				this.closeStream(stream);
				stream = new FileInputStream(filename);
				if (fieldTransObject instanceof ImportFieldTransAction) {//JXL
					WorkbookSettings settings=new WorkbookSettings();
					settings.setEncoding("iso-8859-1");
					try {
						jxl.Workbook workbook = jxl.Workbook.getWorkbook(stream,settings);
						allSheetsJXL = workbook.getSheets();
						params.put("sheetJXL", allSheetsJXL[0]);
					} catch (BiffException e) {
						Errmsg=MessageFormat.format(SystemEnv.getHtmlLabelName(513664, user.getLanguage()), SystemEnv.getHtmlLabelName(504236, user.getLanguage()));
						throw new Exception();
					}
				}else if (fieldTransObject instanceof ImportFieldTransActionPOI) {//poi
					ExcelParseForPOI excelParse = new ExcelParseForPOI();
					excelParse.init(stream);
					params.put("excelParse", excelParse);
				}
			}
			if((rowNum-1)<100||useSingleThread){
				doneSignal = new CountDownLatch(1);//使用计数栅栏
				executorService.submit(new ImpExcelReader("importMainData",doneSignal, 0, rowNum,currentIndex
						,key,sheet,params,user,formid
						,modeid,validateMap,IdMap,checkMap,errorRow,clientaddress,SystemEnv.getHtmlLabelName(524507,user.getLanguage())//导入ALL线程
						,FieldInfo,new HashMap(),"",Errmsg,1,billList
						,creatoridMap,addBillIdList,detailList,updateList,errorRowList,errorDetailMap,mainrows,rowNumList,modeLogMap,
						errorTable,TimeZoneVar.getTimeZone(),isdetailright,impFieldIds));
			}else{
				doneSignal = new CountDownLatch(cpuNum);//使用计数栅栏
				int d = (rowNum-rowNum%cpuNum)/cpuNum;
				for(int i=0;i<cpuNum;i++){
					int start = i*d;
					int end  = (i+1)*d;
					if(i==cpuNum-1){
						end = rowNum;
					}
					executorService.submit(new ImpExcelReader("importMainData",doneSignal, start, end,currentIndex
							,key,sheet,params,user,formid
							,modeid,validateMap,IdMap,checkMap,errorRow,clientaddress,MessageFormat.format(SystemEnv.getHtmlLabelName(524513,user.getLanguage()),i)//导出i线程

							,FieldInfo,new HashMap(),"",Errmsg,1,billList,creatoridMap,addBillIdList,detailList,updateList,errorRowList,errorDetailMap,mainrows,rowNumList,modeLogMap,errorTable
							,TimeZoneVar.getTimeZone(),isdetailright,impFieldIds
					));
				}
			}
			/**
			 * 使用CountDownLatch的await方法，等待所有线程完成sheet操作
			 */
			doneSignal.await();
//			executorService.shutdown();//固定线程池不能shutdown
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132286, user.getLanguage()), "0");
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			String maintable = "";
			sql = "select tablename from workflow_bill where id=" + formid;
			rs.execute(sql);
			if (rs.next()) {
				maintable = Util.null2String(rs.getString("tablename"));
			}
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132286, user.getLanguage()), "0",3);

			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132287, user.getLanguage()), "0",4);
			HashMap map = new HashMap();
			//导入明细：
			boolean canImport = getProgressCanImport(key);
			try {
				for(int i=1;i<allSheets.length&&canImport;i++){
					ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
					Sheet detailSheet = allSheets[i];
					if (fieldTransObject!=null) {
						if (fieldTransObject instanceof ImportFieldTransAction && allSheetsJXL!=null) {//jxl
							params.put("sheetJXL", allSheetsJXL[i]);
						}
					}
					params.put("sheetindex", (i+1));
					writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132288,user.getLanguage()),i+1), "0");
					int detailRealRows = getSheetRealRows(detailSheet);
					if(detailRealRows<POIUtil.getLastRowNum(detailSheet) && isTipMessage(detailRealRows,detailSheet)){
						sheetEmptyRowMsg += ","+(i+1);
						ErrmsgRow += MessageFormat.format(SystemEnv.getHtmlLabelName(132289,user.getLanguage()),i+1,detailRealRows+1)+",";
					}
					int rowNum1 = detailRealRows;
					if(rowNum1<=1){
						continue;
					}
					hasDetail=true;
					int currentIndex1 = i;
					rowNumList.clear();//清除计数器
					CountDownLatch doneSignal1 = new CountDownLatch(1);//使用计数栅栏
					executorService.submit(new ImpExcelReader("importDetailData",doneSignal1, 0, rowNum1,currentIndex1
							,key,detailSheet,params,user,formid
							,modeid,validateMap,IdMap,checkMap,errorRow,clientaddress,MessageFormat.format(SystemEnv.getHtmlLabelName(524512,user.getLanguage()),i+1)//第"+(i+1)+"个sheet子表导入ALL线程
							,FieldInfo,map,maintable,Errmsg,i+1,billList,creatoridMap,addBillIdList,detailList,updateList,errorRowList,errorDetailMap,rowNum1-1,rowNumList,modeLogMap,errorTable
							,TimeZoneVar.getTimeZone(),isdetailright,impFieldIds));

					doneSignal1.await();
//					executorServic.shutdown();//固定线程池不能shutdown
					writeProgressMsg(key,MessageFormat.format(SystemEnv.getHtmlLabelName(132290,user.getLanguage()),i+1), "0");
				}

			} catch (Exception e) {
				rs.writeLog(e);
			}
			if (StringCacheMap.containsKey(key+"_cancel")) {
				StringCacheMap.remove(key+"_cancel");
			}
			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132291, user.getLanguage()), "0",4);

//			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132292, user.getLanguage()), "0",5);

			//--------------------------导入明细完毕触发接口，生成编号-------------------------------------------

			if(!hetong){//合同无需生成权限

				int pageexpandid = Util.getIntValue(Util.null2String(params.get("pageexpandid")));
				final Map IdMapf=IdMap;
				final int modeidf=modeid;
				final int formidf=formid;
				final int expandid = pageexpandid;
				final List updateListTemp = updateList;
				final List addBillIdListTemp = addBillIdList;
				final User userTemp = user;
				Thread thread=new Thread(new Runnable() {
					public void run() {
						RecordSet rs = new RecordSet();
						try {
							List  alist = new ArrayList();
							if(IdMapf.containsKey("addBillIdList")&&IdMapf.get("addBillIdList")!=null){
								alist = (List) IdMapf.get("addBillIdList");
								CodeBuilder codeBuild = new CodeBuilder(modeidf);
								codeBuild.getModeCodeByList(alist,formidf,modeidf);
							}
						} catch (Exception e) {
							e.printStackTrace();
						}

						//触发接口
						try {
							String sql = "select count(1) AS num from mode_pageexpanddetail WHERE  mainid = "+expandid+
									" union "+
									" select count(1) AS num from mode_actionview where expandid="+expandid;
							rs.execute(sql);
							int count = 0;
							while(rs.next()){
								count += rs.getInt("num");
							}
							if(count>0){
								ModeDataManager modeDataManager = new ModeDataManager();
								modeDataManager.setFormid(formidf);
								modeDataManager.setFormmodeid(modeidf);
								modeDataManager.setUser(userTemp);
								modeDataManager.setParams(params);
								for (int j = 0; j < addBillIdListTemp.size(); j++) {
									int addBillId = Util.getIntValue(StringHelper.null2String(addBillIdListTemp.get(j)).replaceAll("'",""));
									modeDataManager.setBillid(addBillId);
									modeDataManager.setImporttype(importtype);
									modeDataManager.setImporthref(importhref);
									modeDataManager.doInterface(expandid);
								}

								for (int j = 0; j < updateListTemp.size(); j++) {
									int addBillId = Util.getIntValue(StringHelper.null2String(updateListTemp.get(j)).replaceAll("'",""));
									modeDataManager.setBillid(addBillId);
									modeDataManager.setImporttype(importtype);
									modeDataManager.setImporthref(importhref);
									modeDataManager.doInterface(expandid);
								}
							}
						} catch (Exception e) {
							e.printStackTrace();
						}

					}
				});
				thread.start();
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				//如果权限和明细表字段有关,则在明细表数据全部插入完毕后再在这里统一进行权限重构,否则插入一条主表记录就使用多线程重构一条权限
				if (isdetailright) {
					try {
						for (int i = 0; i < billList.size(); i++) {
							int souceid = Util.getIntValue(StringHelper.null2String(billList.get(i)),-1);
							int creatorid = Util.getIntValue(StringHelper.null2String(creatoridMap.get(StringHelper.null2String(billList.get(i)))),-1);
							if(creatorid == -1 ){
								creatorid = user.getUID();
							}
							asynService.submit(new ImpAsynTask(ImpAsynTask.TASK_RIGHT, souceid, modeid,creatorid));
						}
//						int currentIndex1 = 0;
//						CountDownLatch doneSignal2 = null;
//						rowNumList.clear();//清除计数器
//						if((rowNum2)<100){
//							doneSignal2 = new CountDownLatch(1);//使用计数栅栏
//							executorService.submit(new ImpExcelReader("insertRight",doneSignal2, 0, rowNum2,currentIndex1
//									,key,null,params,user,formid
//									,modeid,validateMap,IdMap,checkMap,errorRow,clientaddress,"权限导入ALL线程"
//									,FieldInfo,map,maintable,Errmsg,1,billList,creatoridMap,addBillIdList,rightList,updateList,errorRowList,errorDetailMap,mainrows,rowNumList,modeLogMap,errorTable
//									,TimeZoneVar.getTimeZone(),isdetailright));
//						}else{
//							doneSignal2 = new CountDownLatch(cpuNum);//使用计数栅栏
//							int d = (rowNum2-rowNum2%cpuNum)/cpuNum;
//							for(int i=0;i<cpuNum;i++){
//								int start = i*d;
//								int end  = (i+1)*d;
//								if(i==cpuNum-1){
//									end = rowNum2;
//								}
//								executorService.submit(new ImpExcelReader("insertRight",doneSignal2, start, end,currentIndex
//										,key,sheet,params,user,formid
//										,modeid,validateMap,IdMap,checkMap,errorRow,clientaddress,"权限导入"+i+"线程"
//
//										,FieldInfo,new HashMap(),maintable,Errmsg,1,billList,creatoridMap,addBillIdList,rightList,updateList,errorRowList,errorDetailMap,mainrows,rowNumList,modeLogMap,errorTable
//										,TimeZoneVar.getTimeZone(),isdetailright));
//							}
//						}
//
//						doneSignal2.await();
//					executorService.shutdown();//固定线程池不能shutdown
					} catch (Exception e) {
						rs.writeLog(e);
					}
				}

			}

//			writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(132295, user.getLanguage()), "0",5);

			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132293, user.getLanguage()), "0");


			//转换为sqlwhere后，不需要再初始化数据到mode_reminddata表中
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			String fengeString = " ";
			if (user.getLanguage() != 8) {
				fengeString = "";
			}
			if (errorRow.size() > 0) {
				StringBuffer buf = new StringBuffer();
				Iterator it = errorRow.iterator();
				int xx = 0;
				while (it.hasNext()) {
					xx++;
					String v = (String) it.next();
					String[] strs = v.split(",");
					writeLog(xx + "		"+v+"	"+strs.length);
					if(strs.length==2){ //行出错
						String flagMsg = "";
						int index = strs[1].indexOf("~~weaverSplit~~");
						if(index!=-1){
							flagMsg = strs[1].substring(index+"~~weaverSplit~~".length());
							if(!"".equals(flagMsg)){
								flagMsg = ","+flagMsg;
							}
							strs[1] = strs[1].substring(0,index);
						}
						buf.append(fengeString
								+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
								+ fengeString
								+ strs[0]
								+ fengeString
								+ SystemEnv.getHtmlLabelName(27591, user.getLanguage())//个
								+ fengeString
								+ "sheet"
								+ fengeString
								+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
								+ fengeString
								+ strs[1]
								+ fengeString
								+ SystemEnv.getHtmlLabelName(27592, user.getLanguage())//行
								+ fengeString);
						buf.append(fengeString
								+ SystemEnv.getHtmlLabelName(27593, user.getLanguage())//导入出错
								+flagMsg
								+ "!\\n");
						writeLog(buf.toString());
					}else if(strs.length>2){ //数据不合法
						buf.append(fengeString
								+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
								+ fengeString
								+ strs[0]
								+ fengeString
								+ SystemEnv.getHtmlLabelName(27591, user.getLanguage())//个
								+ fengeString
								+ "sheet"
								+ fengeString
								+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
								+ fengeString
								+ strs[1]
								+ fengeString
								+ SystemEnv.getHtmlLabelName(27592, user.getLanguage())//行
								+ fengeString);
						buf.append(fengeString
								+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
								+ fengeString
								+ strs[2]
								+ fengeString
								+ SystemEnv.getHtmlLabelName(18621, user.getLanguage())//列
								+ fengeString);
						buf.append(fengeString
								+ SystemEnv.getHtmlLabelName(27593, user.getLanguage()));//导入出错
						buf.append("，");
						for(int k=3;k<strs.length;k++){
							buf.append(strs[k]);
							if(k!=strs.length-1){
								buf.append(",");
							}
						}
						if(strs.length==4){
							if(!strs[3].equals(SystemEnv.getHtmlLabelName(132247, 7)) && strs[3].indexOf(SystemEnv.getHtmlLabelName(385578, 7)) == -1){//导入验证错误    列为必填
								if(buf.indexOf(SystemEnv.getHtmlLabelName(132251, user.getLanguage()))>-1){	//132251 不存在无法更新
									buf.append("!");
								}else{
									if(user.getLanguage()==8)buf.append(" ");
									buf.append(SystemEnv.getHtmlLabelName(132306, user.getLanguage())+"!");	//132306 不存在
								}
							}
						}
						buf.append("\\n");
					}
				}
				Errmsg += buf.toString();
			}else{
				if(IdMap.size()==0){
					if(mainrows<1){
						Errmsg = SystemEnv.getHtmlLabelName(30790, user.getLanguage()) + "\\n";
					}else{
						Errmsg = SystemEnv.getHtmlLabelName(524514, user.getLanguage())+ "\\n";//没有成功导入或发生异常，请查看日志信息
					}
				}
			}
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
			if(StringHelper.isEmpty(Errmsg) || !StringHelper.isEmpty(sheetEmptyRowMsg)){
				writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(129463, user.getLanguage()), "0",5);
			}else{
				writeProgressMsgAndStep(key,SystemEnv.getHtmlLabelName(27593, user.getLanguage()), "0",5);
			}

		} catch (Exception e) {
			if(StringHelper.isEmpty(Errmsg)){
				Errmsg = SystemEnv.getHtmlLabelName(132296, user.getLanguage())+"："+e.getMessage();
			}
			writeLog(e);
		}finally{
			try {
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				String msg = "";
				if(addBillIdList.size()>0){
					msg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132297,user.getLanguage()),addBillIdList.size());
				}
				if(updateList.size()>0){
					msg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132298,user.getLanguage()),updateList.size());
				}
				if(delmainRow>0){
					msg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132299,user.getLanguage()),delmainRow);
				}
				if(!"".equals(msg)){
					msg = msg.substring(1);
					msg = ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132300,user.getLanguage()),mainrowsALL)+msg+"";
				}
				int ddtailErrorRow = 0;
				Set<String> set =  errorDetailMap.keySet();
				Iterator<String> it = set.iterator();
				while(it.hasNext()){
					String tempkey = it.next();
					Vector<Integer> d = errorDetailMap.get(tempkey);
					ddtailErrorRow += d.size();
				}
				String allErrorMmsg = createErrorFile(user, modeid,  formid, errorRowList, errorDetailMap,
						allSheets, ddtailErrorRow,isExcel2007);
				if("".equals(msg)){
					msg = ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132304,user.getLanguage()),mainrowsALL);
				}
				if(hasDetail){
					msg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132303,user.getLanguage()),detailList.size());
				}
				String importtypename = "";
				if(importtype==1){
					importtypename = SystemEnv.getHtmlLabelName(31259,user.getLanguage());
				}else if(importtype==2){
					importtypename = SystemEnv.getHtmlLabelName(517042,user.getLanguage());
				}else if(importtype==3){
					importtypename = SystemEnv.getHtmlLabelName(17744,user.getLanguage());
				}
				if(!StringHelper.isEmpty(importtypename)){
					importtypename = "["+importtypename+"]";
				}
				if(StringHelper.isEmpty(Errmsg)&&progressMap.containsKey(CANIMPORTMSG+"_"+key)){
					Errmsg = progressMap.get(CANIMPORTMSG+"_"+key);
				}
				if(!StringHelper.isEmpty(sheetEmptyRowMsg)){
					putMessage(MSG,key, importtypename+SystemEnv.getHtmlLabelName(27593, user.getLanguage())+msg+allErrorMmsg);
					if(!StringHelper.isEmpty(ErrmsgRow)){
						ErrmsgRow = ErrmsgRow.substring(0,ErrmsgRow.length()-1);
						ErrmsgRow = ErrmsgRow + SystemEnv.getHtmlLabelName(132305, user.getLanguage());
					}
					Errmsg += ErrmsgRow;
				}else if(StringHelper.isEmpty(Errmsg)){
					putMessage(MSG,key, importtypename+SystemEnv.getHtmlLabelName(129463, user.getLanguage())+msg+allErrorMmsg);
				}else{
					putMessage(MSG,key, importtypename+SystemEnv.getHtmlLabelName(27593, user.getLanguage())+msg+allErrorMmsg);
				}
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				String flag = Util.null2String(errorTable.size());
				int failrow = 0;
				String failurerow = "";
				if(errorTable.size()>0){
					failrow = errorTable.size();
					failurerow = failrow+"_imp123456"+UUID.randomUUID();
				}
				int addrow = addBillIdList.size();
				int updaterow = updateList.size();
				int adddetailrow = detailList.size();
				String insertSql = "insert into mode_batchimp_log(modeid,operatetype,ipaddress,operator,optdatetime,addrow,updaterow,delrow,adddetailrow,deldetailrow,failurerow,backupremark,backindex,filepath)" +
						" values("+modeid+","+importtype+",'"+clientaddress+"',"+user.getUID()+",'"+startStr+"',"+addrow+","+updaterow+","+delmainRow+","+adddetailrow+","+deldetailRow+",'"+failurerow+"','"+this.backupremark+"',"+this.backindex+",?)";
				RecordSet rs = new RecordSet();
				rs.executeUpdate(insertSql,filename);
				saveFailureLog(errorTable,modeid,failurerow);
				putMessage(ERRORFLAG,key, flag);
				putMessage(STATUS,key, "-1");
				putMessage(ERRMSG,key, Errmsg);
				putMessage(SEARCHID,key, failurerow);
			} catch (Exception e) {
				writeLog(e);
			}finally{
				Date endtime = new Date();
				long t = endtime.getTime() - starttime.getTime();
				String timestr = secondsToStr(t);
				putMessage(TIME,key, timestr);
				putMessage(ENDTIME,key, endtime.getTime()+"");
				ExpExcelUtil.removeImpUserState(user.getUID(),modeid+"");//导入完毕移除导入状态
			}
		}
		return Errmsg;

	}

	private String createErrorFile(User user, int modeid, int formid, List<Integer> errorRowList,
								   Hashtable<String, Vector<Integer>> errorDetailMap, Sheet[] allSheets, int ddtailErrorRow,boolean isExcel2007) {
		String allErrorMmsg = "";
		if(errorRowList.size()>0||ddtailErrorRow>0){
			if(errorRowList.size()>0){
				allErrorMmsg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132301,user.getLanguage()),errorRowList.size());
			}
			if(ddtailErrorRow>0){
				allErrorMmsg += ","+MessageFormat.format(SystemEnv.getHtmlLabelName(132302,user.getLanguage()),ddtailErrorRow);
			}
			allErrorMmsg = allErrorMmsg.substring(1);
			RecordSet rs = new RecordSet();
			String sql = "select * from modeinfo where Id="+modeid;
			rs.execute(sql);
			if(rs.next()&&allSheets!=null&&allSheets.length>0){
				Workbook wb=null;
				if (isExcel2007) {
					wb=new SXSSFWorkbook();
				}else {
					wb=new HSSFWorkbook();
				}
				Sheet sheet = wb.createSheet(SystemEnv.getHtmlLabelName(21778, user.getLanguage()));
				sheet.setColumnWidth(0, 6000);
				Row row = sheet.createRow(0);
				Cell cell = row.createCell(0);
				cell.setCellValue("ID");
//		        String validateids = "";
//		        sql = "select b.fieldid from mode_excelField a,mode_excelFieldDetail b where a.formid ="+formid+" and a.modeid="+modeid+" and b.mainid=a.id";
//		        rs.execute(sql);
//		        while(rs.next()){
//		        	validateids += rs.getString("fieldid")+",";
//		        }
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				Sheet mainSheet = allSheets[0];
				int mainSheetcol = POIUtil.getLastCellNum(mainSheet);
				for(int i=1;i<mainSheetcol;i++){
					String label = Util.null2String((String)POIUtil.getValue(mainSheet, 0, i));
					sheet.setColumnWidth(i, 6000);
					cell = row.createCell(i);
					cell.setCellValue(label);
				}
				Collections.sort(errorRowList);
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				for(int i=0;i<errorRowList.size();i++){
					int rows = errorRowList.get(i);
					int colnum=POIUtil.getLastCellNum(mainSheet);
					row=sheet.createRow((i+1));
					for(int j=0;j<colnum;j++){
						String val = Util.null2String(POIUtil.getValue(mainSheet, rows, j)).trim();
						cell = row.createCell(j);
						cell.setCellValue(val);
					}
				}
				ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
				for (int i=1;i<allSheets.length;i++) {
					Sheet detailsheet = allSheets[i];
					sheet=wb.createSheet(SystemEnv.getHtmlLabelName(17463, user.getLanguage())+i);
					row = sheet.createRow(0);
					int detailcol = POIUtil.getLastCellNum(detailsheet);
					for(int j=0;j<detailcol;j++){
						String label = Util.null2String((String)POIUtil.getValue(detailsheet, 0, j));
						sheet.setColumnWidth(j, 6000);
						cell = row.createCell(j);
						cell.setCellValue(label);
					}
					if(errorDetailMap.containsKey((i+1)+"")){
						Vector<Integer> d = errorDetailMap.get((i+1)+"");
						Collections.sort(d);
						Sheet detailSheet = allSheets[i];
						for(int k=0;k<d.size();k++){
							int rows = d.get(k);
							int allcols=POIUtil.getLastCellNum(detailSheet);
							row=sheet.createRow((k+1));
							for(int j=0;j<allcols;j++){
								String val = Util.null2String(POIUtil.getValue(detailSheet, rows, j)).trim();
								cell=row.createCell(j);
								cell.setCellValue(val);
							}
						}
					}
				}
				String uuid = this.createFile(wb);
				allErrorMmsg = ",<a class='errorRow' href='"+weaver.general.GCONST.getContextPath()+"/weaver/weaver.formmode.data.FileDownload?type=errorExcel&modeid="+modeid+"&isExcel2007="+isExcel2007+"&key="+uuid+"'>"+allErrorMmsg+"【"+SystemEnv.getHtmlLabelName(125264, user.getLanguage())+"】</a>";
			}
		}
		return allErrorMmsg;
	}

	private String createFile(Workbook wb){
		String uuid=StringUtils.getUnquieID();
		String excelPath = FileUtils.getExpCreateDir()+uuid;
		if(!new File(excelPath).exists()){
			new File(excelPath).mkdirs();
		}
		String path = excelPath+File.separator+uuid;
		File file = new File(path);
		OutputStream os = null;
		try {
			if(!file.exists()){
				file.createNewFile();
			}
			os = new FileOutputStream(file);
			wb.write(os);
			os.flush();
			wb.close();
		} catch (Exception e) {
			writeLog(e);
		}finally {
			try {
				if(os!=null){
					os.close();
				}
				if(wb!=null){
					wb.close();
				}
			} catch (IOException e) {
				writeLog(e);
			}
		}
		return uuid;
	}

	/**
	 * 验证Excel主表表头
	 * @param key
	 * @param sheet
	 * @param keyfield 重复验证字段
	 * @param modeId 模块id
	 * @param user 当前操作者
	 * @throws Exception
	 */
	private void verifyExcelMainHeader(String key,Sheet sheet,String keyfield,String conditionfield,int modeId,User user,FieldInfo FieldInfo,List<List<String>> impFieldIds) throws Exception {
		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
		ArrayList ManTableFieldlabel = FieldInfo.getManTableFieldlabel();
		ArrayList ManTableFieldHtmltypes = FieldInfo.getManTableFieldHtmltypes();
		ArrayList ManTableFieldIds = FieldInfo.getManTableFieldIds();
		ArrayList mainTableFieldNames = FieldInfo.getManTableFieldFieldNames();
		List<String> excelFieldIds = new ArrayList<>();//记录excel中的主表字段顺序

		//导入设置了必填，验证选择框框列和必填字段列是否存在
		Set<String> condFieldIds = new HashSet<>();//必填条件列
		Set<String> mustFieldIds = new HashSet<>();//必填字段列
		RecordSet rs = new RecordSet();
		String sql = "SELECT mefd.selectids,mefd.fieldid FROM mode_excelField mef,mode_excelfielddetail mefd,workflow_billfield wbf WHERE mef.id=mefd.mainid and mefd.selectids=wbf.id and "+CommonConstant.DB_ISNULL_FUN+"(wbf.viewtype,0)=0 and mef.modeid=?";
		rs.executeQuery(sql,modeId);
		while(rs.next()){
			String selectIds = Util.null2String(rs.getString("selectids"));
			String fieldId = Util.null2String(rs.getString("fieldid"));
			if(!"".equals(selectIds)){
				condFieldIds.add(selectIds);
			}
			mustFieldIds.addAll(Arrays.asList(fieldId.split(",")));
		}
		//重复验证字段
		Map<String, String> keyfieldmap = new HashMap<String, String>();
		if (!"".equals(keyfield)) {
			String[] arr1 = keyfield.split("\\|");
			for (String arr : arr1) {
				String[] arr2 = arr.split(",");
				for (String field : arr2) {
					if (!"".equals(field)) {
						keyfieldmap.put(field.toLowerCase(), null);
					}
				}
			}
		}
		//模板中的名称
		Map<String,String> mainFieldInfo = new HashMap<>();
		String  conditionfieldtemp = "";
		Map<String,Set<String>> fieldsInfo = new HashMap<>();
		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
		for(int i=0;i<ManTableFieldlabel.size();i++){
			String htmlyype = Util.null2String((String)ManTableFieldHtmltypes.get(i));
			String label = Util.null2String((String)ManTableFieldlabel.get(i)).trim();
			label=Util.formatMultiLang(label,String.valueOf(user.getLanguage())).toLowerCase();
			String fieldName = Util.null2String(mainTableFieldNames.get(i)).toLowerCase();
			String label_fieldname = label+"_"+fieldName;
			String fieldId = Util.null2String((String)ManTableFieldIds.get(i));

			mainFieldInfo.put(fieldId,label);
			if(htmlyype.equals("7")) continue;

			if(!"".equals(conditionfield) && fieldName.equalsIgnoreCase(conditionfield)){
				conditionfieldtemp = fieldId;
			}

			if (!"".equals(keyfield)&&keyfieldmap.containsKey(fieldName)) {
				keyfieldmap.put(fieldId, null);
				keyfieldmap.remove(fieldName);
			}

			Set<String> set;
			if(fieldsInfo.containsKey(label)){
				set = fieldsInfo.get(label);
			}else{
				set = new HashSet<>();
			}
			set.add(fieldId);
			fieldsInfo.put(label,set);

			if(fieldsInfo.containsKey(label_fieldname)){
				set = fieldsInfo.get(label_fieldname);
			}else{
				set = new HashSet<>();
			}
			set.add(fieldId);
			fieldsInfo.put(label_fieldname,set);
		}

		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态
		Map<String,String> excelLabel = new HashMap<>();//key:字段id，value：excel中的显示名
		int cols = POIUtil.getLastCellNum(sheet);
		Map<String,Integer> excelFieldCol = new HashMap<>();
		boolean conditionFlag = false;//条件字段验证标识
		int idColCount = 0;//id列数量
		for(int i=0;i<cols;i++){
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

			//excel中是否有模板中不存在的列
			String content = Util.null2String(POIUtil.getValue(sheet, 0, i)).trim().toLowerCase();//第一行：验证表头
			//第1个sheet中未找到[ID]列，请添加后重新导入。
			if("id".equalsIgnoreCase(content)){
				idColCount++;
				if(idColCount>1){
					setProgressCanImport(key,false);
					//第{sheetIndex}个sheet中找到{colCount}个[{colName}]列，请删除多余的{colName}列后重新导入。
					String tip = SystemEnv.getHtmlLabelName(504172, user.getLanguage());
					tip = tip.replace("{sheetIndex}","1")
							.replace("{colCount}",String.valueOf(idColCount))
							.replace("{colName}","ID");
					writeProgressMsg(key,tip, "0");
					throw new Exception(tip);
				}
				excelFieldIds.add("-2000");
				continue;
			}

			if(!fieldsInfo.containsKey(content)){
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中表头第{colIndex}列：{content}，不是模板中字段，请检查是否有误。
				String tip = SystemEnv.getHtmlLabelName(504173, user.getLanguage());
				tip = tip.replace("{sheetIndex}","1")
						.replace("{colIndex}",String.valueOf(i+1))
						.replace("{content}",content);
				writeProgressMsg(key,tip, "0");
				throw new Exception(tip);
			}

			Set<String> fieldIds = fieldsInfo.get(content);
			if(fieldIds.size()>1){
				setProgressCanImport(key,false);
				//504174 第{sheetIndex}个sheet中表头第{colIndex}列：{content}，在标准模板中找到{fieldCount}个对应字段，请按照以下格式修改列名后重新导入：显示名_数据库名称。
				//506661 第{sheetIndex}个sheet中表头第{colIndex}列：{content}，存在{fieldCount}个列名重复的对应字段，请按照以下格式修改列名后重新导入：显示名_数据库名称。
				String tip = SystemEnv.getHtmlLabelName(506661, user.getLanguage());
				tip = tip.replace("{sheetIndex}","1")
						.replace("{colIndex}",String.valueOf(i+1))
						.replace("{content}",content)
						.replace("{fieldCount}",String.valueOf(fieldIds.size()));
				writeProgressMsg(key,tip, "0");
				throw new Exception(tip);
			}

			String fieldId = fieldIds.iterator().next();
			if(!excelLabel.containsKey(fieldId)){
				excelLabel.put(fieldId,content);
			}
			//excel中是否有重复列名
			if(excelFieldCol.containsKey(fieldId)){
				int col = excelFieldCol.get(fieldId);
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中表头第{colIndex1}列：{colName1}，第{colIndex1}列：{colName2}，列名重复，请按照以下格式修改列名后重新导入：显示名_数据库名称。
				String tip = SystemEnv.getHtmlLabelName(504175, user.getLanguage());
				tip = tip.replace("{sheetIndex}","1")
						.replace("{colIndex1}",String.valueOf(col))
						.replace("{colName1}",excelLabel.get(fieldId))
						.replace("{colIndex2}",String.valueOf(i+1))
						.replace("{colName2}",content);
				writeProgressMsg(key,tip, "0");
				throw new Exception(tip);
			}else{
				int col = i+1;
				excelFieldCol.put(fieldId,col);
			}

			//导入设置了重复验证字段，excel中是否有重复验证字段列
			if (!"".equals(keyfield)&&keyfieldmap.containsKey(fieldId)) {
				keyfieldmap.put(fieldId, "exist");
			}
			//导入设置了条件字段，excel中是否有条件字段列
			if(conditionfieldtemp.equals(fieldId)){
				conditionFlag = true;
			}

			//导入设置了必填，验证选择框框列和必填字段列是否存在
			//第1个sheet中未找到导入必填条件列[状态】，请添加导入必填条件列后重新导入。
			if(condFieldIds.contains(fieldId)){
				condFieldIds.remove(fieldId);
			}
			//第1个sheet中未找到必填字段列[合同]，请添加必填字段列后重新导入。
			if(mustFieldIds.contains(fieldId)){
				mustFieldIds.remove(fieldId);
			}
			excelFieldIds.add(fieldId);
		}
		if (!"".equals(keyfield)) {
			String notexist="";
			for(Map.Entry<String, String> map:keyfieldmap.entrySet()){
				if (map.getValue()==null) {//模板中没有该字段
					String name=mainFieldInfo.get(map.getKey());
					notexist+=name+",";
				}
			}
			notexist=notexist.replaceAll(",$", "");
			if (!"".equals(notexist)) {
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中未找到重复验证字段列[{repVerifyField}]，请添加重复验证字段列后重新导入。
				String tip = SystemEnv.getHtmlLabelName(504179, user.getLanguage());
				tip = tip.replace("{sheetIndex}","1")
						.replace("{repVerifyField}",notexist);
				writeProgressMsg(key,tip, "0");
				throw new Exception(tip);
			}
		}


		if(!"".equals(conditionfield) && !conditionFlag){
			setProgressCanImport(key,false);
			//第{sheetIndex}个sheet中未找到重复验证字段列[{repVerifyField}]，请添加重复验证字段列后重新导入。
			String tip = SystemEnv.getHtmlLabelName(507416, user.getLanguage());
			tip = tip.replace("{sheetIndex}","1")
					.replace("{conditionfield}",mainFieldInfo.get(conditionfieldtemp));
			writeProgressMsg(key,tip, "0");
			throw new Exception(tip);
		}

		if(condFieldIds.size() > 0 ){
			StringBuffer conditionLabels = new StringBuffer();
			Iterator<String> it = condFieldIds.iterator();
			while(it.hasNext()){
				conditionLabels.append(",").append(mainFieldInfo.get(it.next()));
			}
			setProgressCanImport(key,false);
			//第{sheetIndex}个sheet中未找到导入必填条件列[{mustConditionCol}]，请添加导入必填条件列后重新导入。
			String tip = SystemEnv.getHtmlLabelName(504176, user.getLanguage());
			tip = tip.replace("{sheetIndex}","1")
					.replace("{mustConditionCol}",conditionLabels.substring(1));
			writeProgressMsg(key,tip, "0");
			throw new Exception(tip);
		}


		if(mustFieldIds.size() > 0 ){
			StringBuffer fieldLabels = new StringBuffer();
			Iterator<String> it = mustFieldIds.iterator();
			while(it.hasNext()){
				fieldLabels.append(",").append(mainFieldInfo.get(it.next()));
			}
			setProgressCanImport(key,false);
			//第{sheetIndex}个sheet中未找到导入必填字段列[{mustFieldCol}]，请添加导入必填字段列后重新导入。
			String tip = SystemEnv.getHtmlLabelName(504177, user.getLanguage());
			tip = tip.replace("{sheetIndex}","1")
					.replace("{mustFieldCol}",fieldLabels.substring(1));
			writeProgressMsg(key,tip, "0");
			throw new Exception(tip);
		}

		if(idColCount==0){
			setProgressCanImport(key,false);
			//第{sheetIndex}个sheet中未找到[{colName}]列，请添加后重新导入。
			String tip = SystemEnv.getHtmlLabelName(504178, user.getLanguage());
			tip = tip.replace("{sheetIndex}","1")
					.replace("{colName}","ID");
			writeProgressMsg(key,tip, "0");
			throw new Exception(tip);
		}
		impFieldIds.add(excelFieldIds);
	}

	private void verifyExcelDetailHeader(String key,Sheet[] allSheets,int modeId,User user,FieldInfo FieldInfo,List<List<String>> impFieldIds) throws Exception{
		ArrayList detailtablefieldlables=FieldInfo.getDetailTableFieldNames();//显示名
		ArrayList detailTableDbFieldNames=FieldInfo.getDetailDBFieldNames();//字段名
		ArrayList detailtablefieldids=FieldInfo.getDetailTableFields();
		ArrayList<Map<String,Set<String>>> detailFieldsInfo = new ArrayList<>();
		if(detailtablefieldlables.size()!=allSheets.length-1){//sheet个数验证
			setProgressCanImport(key,false);
			String Errmsg = MessageFormat.format(SystemEnv.getHtmlLabelName(132272, user.getLanguage()),allSheets.length,detailtablefieldlables.size()+1);
			writeProgressMsg(key,SystemEnv.getHtmlLabelName(132273, user.getLanguage()), "0");
			throw new Exception(Errmsg);
		}

		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

		//导入设置了必填，验证选择框框列和必填字段列是否存在
		Set<String> modeCondFieldIds = new HashSet<>();//该模块的所有必填条件列
		Set<String> modeMustFieldIds = new HashSet<>();//该模块的所有必填字段列
		RecordSet rs = new RecordSet();
		String sql = "SELECT mefd.selectids,mefd.fieldid FROM mode_excelField mef,mode_excelfielddetail mefd,workflow_billfield wbf WHERE mef.id=mefd.mainid and mefd.selectids=wbf.id and "+CommonConstant.DB_ISNULL_FUN+"(wbf.viewtype,0)=1 and mef.modeid=?";
		rs.executeQuery(sql,modeId);
		while(rs.next()){
			String selectIds = Util.null2String(rs.getString("selectids"));
			String fieldId = Util.null2String(rs.getString("fieldid"));
			if(!"".equals(selectIds)){
				modeCondFieldIds.add(selectIds);
			}
			modeMustFieldIds.addAll(Arrays.asList(fieldId.split(",")));
		}

		ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

		List<Set<String>> detailCondFieldIds = new ArrayList<>();//每个明细表必填条件列
		List<Set<String>> detailMustFieldIds = new ArrayList<>();//每个明细表必填字段列
		Map<String,String> fieldsInfo = new HashMap<>();
		for(int i=0;i<detailtablefieldlables.size();i++){//获取每个明细表中模板的字段label
			Map<String,Set<String>> detailField = new HashMap<>();
			ArrayList detailfieldnames = (ArrayList)detailtablefieldlables.get(i);
			ArrayList detailfieldids = (ArrayList)detailtablefieldids.get(i);
			ArrayList detailDbFieldName = (ArrayList)detailTableDbFieldNames.get(i);
			Set<String> condFieldIds = new HashSet<>();
			Set<String> mustFieldIds = new HashSet<>();
			boolean hasfield=false;
			for(int j=0;j<detailfieldids.size();j++){
				String f = StringHelper.null2String(detailfieldids.get(j));
				String[] arr = f.split("_");
				String dhtmltype = "";
				String fieldId = "";
				if(arr.length==4){
					fieldId = arr[0].substring("field".length());
					dhtmltype = arr[3];
					//if(dhtmltype.equals("6")){
					//	continue;
					//}
				}

				String fieldLabel = (String)detailfieldnames.get(j);
				String showLabel = Util.formatMultiLang(fieldLabel,String.valueOf(user.getLanguage())).trim().toLowerCase();
				String fieldName = Util.null2String(detailDbFieldName.get(j)).toLowerCase();

				fieldsInfo.put(fieldId,showLabel);
				Set<String> fieldIdSet;
				if(detailField.containsKey(showLabel)){
					fieldIdSet = detailField.get(showLabel);
				}else{
					fieldIdSet = new HashSet<>();
				}
				fieldIdSet.add(fieldId);
				detailField.put(showLabel,fieldIdSet);

				if(detailField.containsKey(showLabel+"_"+fieldName)){
					fieldIdSet = detailField.get(showLabel+"_"+fieldName);
				}else{
					fieldIdSet = new HashSet<>();
				}
				fieldIdSet.add(fieldId);
				detailField.put(showLabel+"_"+fieldName,fieldIdSet);
				if(modeCondFieldIds.contains(fieldId)){
					condFieldIds.add(fieldId);
				}
				if(modeMustFieldIds.contains(fieldId)){
					mustFieldIds.add(fieldId);
				}
				hasfield=true;
			}
			if(hasfield){
				detailCondFieldIds.add(condFieldIds);
				detailMustFieldIds.add(mustFieldIds);
				detailFieldsInfo.add(detailField);
			}
		}

		for(int i=0;i<allSheets.length-1&&getProgressCanImport(key);i++){//遍历明细表sheet
			ExpExcelUtil.refreshImpUserState(user.getUID(),key);//刷新导入状态

			List<String> excelFieldIds = new ArrayList<>();
			Map<String,Integer> excelField = new HashMap<>();//excel中是否有重复列名,key:字段id，value：该字段在excel中的第几列
			Map<String,String> excelLabel = new HashMap<>();//key:字段id，value：excel中的显示名
			Set<String> condFieldIds = new HashSet<>();
			Set<String> mustFieldIds = new HashSet<>();
			Sheet detailSheet = allSheets[i+1];
			int cols = POIUtil.getLastCellNum(detailSheet);
			Map<String,Set<String>> detailField = new HashMap<>();
			ArrayList detailFieldIds = (ArrayList)detailtablefieldids.get(i);
			if(i<detailCondFieldIds.size()){
				condFieldIds = detailCondFieldIds.get(i);
				mustFieldIds = detailMustFieldIds.get(i);
				detailField = detailFieldsInfo.get(i);
			}

			int mainIdColCount = 0;//mainid列的数量
			Map<String,Integer> repeatFieldIds = getRepeatElement(detailFieldIds);//模板中相同显示名的列及数量
			for(int j=0;j<cols;j++){//遍历列
				String content = Util.null2String(POIUtil.getValue(detailSheet, 0, j)).trim().toLowerCase();
				if("mainid".equalsIgnoreCase(content)){
					mainIdColCount++;
					if(mainIdColCount>1){
						setProgressCanImport(key,false);
						String Errmsg = SystemEnv.getHtmlLabelName(504172, user.getLanguage());
						Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
								.replace("{colCount}",String.valueOf(mainIdColCount))
								.replace("{colName}","MAINID");
						writeProgressMsg(key,Errmsg, "0");
						throw new Exception(Errmsg);
					}
					excelFieldIds.add("-2001");
					continue;
				}

				if(!detailField.containsKey(content)){
					setProgressCanImport(key,false);
					String Errmsg = SystemEnv.getHtmlLabelName(504173, user.getLanguage());
					Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
							.replace("{colIndex}",String.valueOf(j+1))
							.replace("{content}",content);
					writeProgressMsg(key,Errmsg, "0");
					throw new Exception(Errmsg);
				}

				Set<String> fieldIds = detailField.get(content);
				if(fieldIds.size()>1){
					setProgressCanImport(key,false);
					//504174 第{sheetIndex}个sheet中表头第{colIndex}列：{content}，在标准模板中找到{fieldCount}个对应字段，请按照以下格式修改列名后重新导入：显示名_数据库名称。
					//506661 第{sheetIndex}个sheet中表头第{colIndex}列：{content}，存在{fieldCount}个列名重复的对应字段，请按照以下格式修改列名后重新导入：显示名_数据库名称。
					String Errmsg = SystemEnv.getHtmlLabelName(506661, user.getLanguage());
					Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
							.replace("{colIndex}",String.valueOf(j+1))
							.replace("{content}",content)
							.replace("{fieldCount}",String.valueOf(fieldIds.size()));
					writeProgressMsg(key,Errmsg, "0");
					throw new Exception(Errmsg);
				}

				String fieldId = fieldIds.iterator().next();
				if(!excelLabel.containsKey(fieldId)){
					excelLabel.put(fieldId,content);
				}
				if(excelField.containsKey(fieldId)){
					int col = excelField.get(fieldId);
					setProgressCanImport(key,false);
					//第{sheetIndex}个sheet中表头第{colIndex1}列：{colName1}，第{colIndex1}列：{colName2}，列名重复，请按照以下格式修改列名后重新导入：显示名_数据库名称。
					String Errmsg = SystemEnv.getHtmlLabelName(504175, user.getLanguage());
					Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
							.replace("{colIndex1}",String.valueOf(col))
							.replace("{colName1}",excelLabel.get(fieldId))
							.replace("{colIndex2}",String.valueOf(j+1))
							.replace("{colName2}",content);
					writeProgressMsg(key,Errmsg, "0");
					throw new Exception(Errmsg);
				}else{
					excelField.put(fieldId,j+1);
				}


				//第1个sheet中未找到导入必填条件列[状态]，请添加导入必填条件列后重新导入。
				if(condFieldIds.contains(fieldId)){
					condFieldIds.remove(fieldId);
				}

				//第1个sheet中未找到必填字段列[合同]，请添加必填字段列后重新导入。
				if(mustFieldIds.contains(fieldId)){
					mustFieldIds.remove(fieldId);
				}
				excelFieldIds.add(fieldId);
			}

			//第1个sheet中未找到导入必填条件列[状态]，请添加导入必填条件列后重新导入。
			if(condFieldIds.size() > 0 ){
				StringBuffer tip = new StringBuffer();
				Iterator<String> it = condFieldIds.iterator();
				while(it.hasNext()){
					tip.append(",").append(fieldsInfo.get(it.next()));
				}
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中未找到导入必填条件列[{mustConditionCol}]，请添加导入必填条件列后重新导入。
				String Errmsg = SystemEnv.getHtmlLabelName(504176, user.getLanguage());
				Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
						.replace("{mustConditionCol}",tip.substring(1));
				writeProgressMsg(key,Errmsg, "0");
				throw new Exception(Errmsg);
			}

			if(mustFieldIds.size()>0){
				StringBuffer tip = new StringBuffer();
				Iterator<String> it = mustFieldIds.iterator();
				while(it.hasNext()){
					tip.append(",").append(fieldsInfo.get(it.next()));
				}
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中未找到导入必填字段列[{mustFieldCol}]，请添加导入必填字段列后重新导入。
				String Errmsg = SystemEnv.getHtmlLabelName(504177, user.getLanguage());
				Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf(i+2))
						.replace("{mustFieldCol}",tip.substring(1));
				writeProgressMsg(key,Errmsg, "0");
				throw new Exception(Errmsg);
			}

			if(mainIdColCount==0){
				setProgressCanImport(key,false);
				//第{sheetIndex}个sheet中未找到[{colName}]列，请添加后重新导入。
				String Errmsg = SystemEnv.getHtmlLabelName(504178, user.getLanguage());
				Errmsg = Errmsg.replace("{sheetIndex}",String.valueOf((i+2)))
						.replace("{colName}","MAINID");
				writeProgressMsg(key,Errmsg, "0");
				throw new Exception(Errmsg);
			}
			impFieldIds.add(excelFieldIds);
		}
	}

	/**
	 * 得到list中重复的元素
	 * @param list
	 * @return
	 */
	public Map<String,Integer> getRepeatElement(List<String> list){
		Map<String,Integer> repeatElements = new HashMap<>();
		for (int i=0;i<list.size();i++) {
			String value = list.get(i);
			if (repeatElements.containsKey(value)) {
				int count = repeatElements.get(value);
				count++;
				repeatElements.put(value,count);
			}else {
				repeatElements.put(value,1);
			}
		}
		return repeatElements;
	}
	static String secondsToStr(long time) {
		String result = "";
		int seconds = new Double(time / 1000).intValue();
		int hour = 0;
		int minute = 0;
		int second = 0;
		if (seconds > 60) {
			if (seconds > 3600) {
				hour = seconds / 3600;
				minute = seconds % 3600 / 60;
				second = seconds % 3600 % 60 % 60;
			} else {
				second = seconds % 60;
				minute = seconds / 60;
			}
		} else {
			second = seconds;
		}
		result = parseStr(hour) + ":" + parseStr(minute) + ":"
				+ parseStr(second);
		return result;
	}

	private static String parseStr(int time) {
		if (time >= 10) {
			return time + "";
		}
		return "0" + time;
	}

	public static void putMessage(String smallkey,String pubkey,String msgStr) {
		progressMap.put(smallkey+"_"+pubkey, msgStr);

		Map dataMap  = new HashMap();
		dataMap.put(CANIMPORT, StringHelper.null2String(progressMap.get(CANIMPORT+"_"+pubkey)));
		dataMap.put(CANIMPORTMSG, StringHelper.null2String(progressMap.get(CANIMPORTMSG+"_"+pubkey)));
		dataMap.put(STATUS, StringHelper.null2String(progressMap.get(STATUS+"_"+pubkey)));
		dataMap.put(STEP, StringHelper.null2String(progressMap.get(STEP+"_"+pubkey)));
		dataMap.put(STARTTIME, StringHelper.null2String(progressMap.get(STARTTIME+"_"+pubkey)));

		dataMap.put(ERRMSG, StringHelper.null2String(progressMap.get(ERRMSG+"_"+pubkey)));
		dataMap.put(TIME, StringHelper.null2String(progressMap.get(TIME+"_"+pubkey)));
		dataMap.put(ENDTIME, StringHelper.null2String(progressMap.get(ENDTIME+"_"+pubkey)));
		dataMap.put(IMPADDR, StringHelper.null2String(progressMap.get(IMPADDR+"_"+pubkey)));
		dataMap.put(MSG, StringHelper.null2String(progressMap.get(MSG+"_"+pubkey)));
		dataMap.put(SEARCHID, StringHelper.null2String(progressMap.get(SEARCHID+"_"+pubkey)));
		dataMap.put(ERRORFLAG, StringHelper.null2String(progressMap.get(ERRORFLAG+"_"+pubkey)));
		ExpExcelUtil.putObject(MODEIMP+"_"+pubkey, dataMap,true);
	}




	public static void setProgressCanImport(String key,boolean canImport) {
		key = StringHelper.null2String(key);
		putMessage(CANIMPORT,key, canImport?"1":"0");
	}

	public static void setProgressCanImport(String key,boolean canImport,String msg) {
		key = StringHelper.null2String(key);
		progressMap.put(CANIMPORT+"_"+key, canImport?"1":"0");
		putMessage(CANIMPORTMSG,key, msg);
	}

	public static boolean getProgressCanImport(String key) {
		key = StringHelper.null2String(key);
		boolean f = true;
		boolean isInMap = false;
		if(progressMap.containsKey(CANIMPORT+"_"+key)){
			isInMap  = true;
			String str = Util.null2String(progressMap.get(CANIMPORT+"_"+key));
			if("0".equals(str)){
				f = false;
			}
		}
		return f;
	}

	public static void writeProgressMsg(String key,String msg,String status) {
		progressMap.put(MSG+"_"+key, StringHelper.null2String(msg));
		putMessage(STATUS,key, StringHelper.null2String(status));
	}

	public static void writeProgressMsgAndStep(String key,String msg,String status,int step) {
		progressMap.put(MSG+"_"+key, StringHelper.null2String(msg));
		progressMap.put(STATUS+"_"+key, StringHelper.null2String(status));
		putMessage(STEP,key, StringHelper.null2String(step));
	}

	public void writeErrorRow(){
		writeLog("---------------------  start -------------------------");
		for(int i=0;i<errorRow.size();i++){
			writeLog(i+"	"+errorRow.get(i));
		}
		writeLog("---------------------  end   -------------------------");
	}

	/**
	 * 正则表达式字段校验
	 * @param fieldid
	 * @param value
	 * @return
	 */
	public boolean checkDataByExpression(String fieldid,String value){
		if(Util.null2String(value).equals("")){
			return true;
		}else if(checkMap.containsKey(fieldid)){
			String expression = checkMap.get(fieldid);
			Pattern pattern = Pattern.compile(expression);
			Matcher matcher = pattern.matcher(value);
			boolean bool = matcher.find();
			return bool;
		}
		return true;
	}


	public String getClientaddress() {
		return clientaddress;
	}

	public void setClientaddress(String clientaddress) {
		this.clientaddress = clientaddress;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}


	/**
	 * 获取sheet中的真实的行数，如果遇到空白行则终止
	 * @param sheet
	 * @return
	 */
	public static int getSheetRealRows(Sheet sheet) {
		int rsCols =POIUtil.getLastCellNum(sheet); //列数
		int rsRows =POIUtil.getLastRowNum(sheet); //POI和jxl相比,行数从0开始
		int afterRows = rsRows;
		boolean isBlankRow = false;
		for (int i = 1; i < rsRows; i++) { //统计行中为空的单元格数
			for (int j = 0; j < rsCols; j++) {
				String val = POIUtil.getValue(sheet, i, j);
				if (!StringHelper.isEmpty(val)){
					break;
				}
				if(j==rsCols-1){//空行
					isBlankRow = true;
				}
			}
			if(isBlankRow){
				afterRows = i;
				break;
			}
		}
		return afterRows;
	}
	public void saveFailureLog(ArrayList errorTable,int modeid,String searchid){
		//解析错误信息
		String fengeString = " ";
		if(errorTable.size() > 0)
		{
			Iterator itor = errorTable.iterator();
			int xx = 0;
			RecordSet rs = new RecordSet();
			while (itor.hasNext()) {
				String errormsg = "";
				String tablename = "";
				String fieldname = "";
				String detailmation = "";
				xx++;
				String v2 = (String) itor.next();
				String[] strs = v2.split("[+]");
				if(strs.length==2){ //行出错
					String flagMsg = "";
					int index = strs[1].indexOf("~~weaverSplit~~");
					if(index!=-1){
						flagMsg = strs[1].substring(index+"~~weaverSplit~~".length());
						if(!"".equals(flagMsg)){
							flagMsg = ","+flagMsg;
						}
						strs[1] = strs[1].substring(0,index);
					}
					errormsg=fengeString
							+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
							+ fengeString
							+ strs[0]
							+ fengeString
							+ SystemEnv.getHtmlLabelName(27591, user.getLanguage())//个
							+ fengeString
							+ "sheet"
							+ fengeString
							+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
							+ fengeString
							+ strs[1]
							+ fengeString
							+ SystemEnv.getHtmlLabelName(27592, user.getLanguage())//行
							+ fengeString
							+fengeString
							+ SystemEnv.getHtmlLabelName(27593, user.getLanguage())//导入出错
							+flagMsg;
				}else if(strs.length>2){ //数据不合法
					errormsg=fengeString
							+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
							+ fengeString
							+ strs[0]
							+ fengeString
							+ SystemEnv.getHtmlLabelName(27591, user.getLanguage())//个
							+ fengeString
							+ "sheet"
							+ fengeString
							+ SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
							+ fengeString
							+ strs[1]
							+ fengeString
							+ SystemEnv.getHtmlLabelName(27592, user.getLanguage())//行
							+ fengeString
							+ fengeString
							+ (strs[2].equals("")?"": (SystemEnv.getHtmlLabelName(15323, user.getLanguage())//第
							+ fengeString
							+ strs[2]
							+ fengeString
							+ SystemEnv.getHtmlLabelName(18621, user.getLanguage())//列
							+ fengeString))
							+fengeString
							+ SystemEnv.getHtmlLabelName(27593, user.getLanguage())+",<br/>"//导入出错
							+strs[3]
							+fengeString;
				}
				if(strs.length >= 4 && strs.length < 10){
					if(!strs[3].equals(SystemEnv.getHtmlLabelName(132247, 7)) && strs[3].indexOf(SystemEnv.getHtmlLabelName(385578, 7)) == -1){// 导入验证错误     列为必填
						if(errormsg.indexOf(SystemEnv.getHtmlLabelName(132251, user.getLanguage()))>-1){	//132251 不存在无法更新
							errormsg += "!";
						}else{
							if(strs[3].equals("")){
								errormsg+=SystemEnv.getHtmlLabelName(514873, user.getLanguage())+"!";	//514873 导入数据存在空行
							}else{
								errormsg+=SystemEnv.getHtmlLabelName(132306, user.getLanguage())+"!";	//132306 不存在
							}
						}
					}
					if(strs.length > 6){
						tablename = strs[7];
						fieldname = strs[4]+"("+strs[5]+","+strs[6]+")";
						detailmation = strs[8];
					}else {
						tablename = strs[4];
						detailmation = strs[5];
					}
				}else if(strs.length == 10){
					if(!strs[3].equals("导入验证错误") && strs[3].indexOf("列为必填") == -1){
						if(errormsg.indexOf(SystemEnv.getHtmlLabelName(132251, user.getLanguage()))>-1){	//132251 不存在无法更新
							errormsg += "!";
						}else{
							errormsg+=strs[4]+"!";
						}
					}
					tablename = strs[8];
					fieldname = strs[5]+"("+strs[6]+","+strs[7]+")";
					if (strs[5].equals(Util.getSeparator()+"")) {//重复验证字段为组合验证可能会出现多个字段的情况,需要在加入前拼接格式,这里直接取,
						fieldname=strs[7];
					}
					detailmation = strs[9];
				}
				if(fieldname.equals("(,)")){
					fieldname = "";
				}
				String insertsql = "insert into mode_impfailurelog(modeid,errormsg,tablename,tablefield,detailmation,searchid) values(?,?,?,?,?,?)";
//				('"+modeid+"','"+errormsg+"','"+tablename+
//						"','"+fieldname+"','"+detailmation+"','"+searchid+"')";
				rs.executeUpdate(insertsql,modeid,errormsg,tablename,fieldname,detailmation,searchid);
			}
		}
	}

	/**
	 * 批量导入必填列
	 * @param modeId 模块id
	 * @param fieldName 重复验证字段字段名称
	 * @param importtype 导入类型
	 */
	public int getMandatoryFieldCount(int modeId,String fieldName,int importtype){
		Set<String> set = new HashSet<>();
		//导入必填字段
		RecordSet rs = new RecordSet();
		String sql = "SELECT mefd.fieldid FROM mode_excelField mef,mode_excelfielddetail mefd WHERE mef.id=mefd.mainid and mef.modeid=?";
		rs.executeQuery(sql,modeId);
		while(rs.next()){
			String fieldid = Util.null2String(rs.getString("fieldid"));
			if(!"".equals(fieldid)){
				set.addAll(Arrays.asList(fieldid.split(",")));
			}
		}

		//重复验证字段
		if("".equals(fieldName)){
			sql = "SELECT wbf.id FROM workflow_billfield wbf,modeinfo mi WHERE mi.formid=wbf.billid and "+ CommonConstant.DB_ISNULL_FUN+"(viewtype,0)=0 and mi.id=? and wbf.fieldname=?";
			rs.executeQuery(sql,modeId,fieldName);
			if(rs.next()){
				set.add(rs.getString("id"));
			}
		}
		return set.size();
	}

	/**
	 * 如果是真实结束的行，与excel API 中统计总行树在同一行，那么不提示空行
	 */
	public boolean isTipMessage(int realRow,Sheet sheet){

		boolean isTip = false;
		int rsCols =POIUtil.getLastCellNum(sheet); //列数
		int rsRows = POIUtil.getLastRowNum(sheet); //行数
		for (int i = realRow+1; i < rsRows && !isTip; i++) { //统计行中为空的单元格数
			for (int j = 0; j < rsCols; j++) {
				String val =  POIUtil.getValue(sheet, i, j);
				if (!StringHelper.isEmpty(val)){
					isTip = true;
					break;
				}
			}
		}

		return isTip;
	}

	/**
	 * 判断模块默认共享是否有模块明细表字段
	 * @param modeid
	 * @return
	 */
	private boolean getIsDetailRight(int modeid){
		boolean result = false;
		RecordSet rs = new RecordSet();
		String sql = "select count(*) count from workflow_billfield where id in(select relatedid from moderightinfo where modeid=? and sharetype=1000) and viewtype=1";
		rs.executeQuery(sql, modeid);
		if (rs.next()) {
			int count = Util.getIntValue(rs.getString("count"));
			result=count>0;
		}
		return result;
	}

	private void closeStream(InputStream stream){
		if (stream!=null) {
			try {
				stream.close();
			} catch (IOException e) {
				writeLog(e);
			}finally {
				if (stream!=null) {
					try {
						stream.close();
					} catch (IOException e) {
						writeLog(e);
					}
				}
			}
		}
	}

	/**
	 * 备份表结构及数据
	 * @param sourceTable 要备份的数据表
	 * @param modeid 模块id
	 * @param isMain 是否是主表
	 * @param backindex 备份索引
	 * @param sqlwhere 要备份数据被的哪些数据
	 * @return
	 */
	private boolean BackUpTable(String sourceTable,int modeid,boolean isMain,int backindex,String sqlwhere){
		RecordSet rs = new RecordSet();
		String sql="";
		String suffix=this.suffix+backindex;
		String backTable=sourceTable+suffix;
		if (rs.getDBType().indexOf("sqlserver")>=0) {
			sql="select * into "+backTable+" from "+sourceTable+" "+sqlwhere;
		}else if("mysql".equals(rs.getDBType())){
			sql="create table "+backTable+" like "+sourceTable;
			rs.executeUpdate(sql);
			sql="insert into "+backTable+" select * from "+sourceTable;
		}
		else if (rs.getDBType().indexOf("postgresql")>=0) {
			sql="select * into "+backTable+" from "+sourceTable+" "+sqlwhere;
		}
		else {
			sql="create table "+backTable+" as select * from "+sourceTable+" "+sqlwhere;
		}
		boolean result = rs.executeUpdate(sql);
		if (!result) {
			super.writeLog("备份表失败,sql:"+sql);
		}
		if (isMain) {//是主表
			//formmodeisrecover 标识该条数据是否还原过 0未还原 1已还原
			sql=" alter table "+backTable +" add formmodeisrecover int ";
			rs.executeUpdate(sql);
			//formmodelogid  mode_impfailurelog日志表id,标识是哪次日志操作恢复的
			sql=" alter table "+backTable +" add formmodelogid int ";
			rs.executeUpdate(sql);
			sql="update "+backTable+" set formmodeisrecover=0";
			rs.executeUpdate(sql);
		}
		return result;
	}

	/**
	 * 获取备份次数
	 * @param modeid
	 * @return
	 */
	private synchronized int getAndUpdateBackIndex(int modeid){
		RecordSet rs = new RecordSet();
		int backindex=1;
		String sql = "select currbackindex from mode_databatchimport where modeid=?";
		rs.executeQuery(sql, modeid);
		if (rs.next()) {
			backindex=Util.getIntValue(rs.getString("currbackindex"), 0)+1;
		}else {
			sql="insert into mode_databatchimport (modeid,currbackindex) values(?,?)";
			rs.executeUpdate(sql, modeid,0);
		}
		sql="update mode_databatchimport set currbackindex=? where modeid=?";
		rs.executeUpdate(sql, backindex,modeid);
		return backindex;
	}
}
