/// <summary> /// 用于将指定的字段用自定义函数进行检查 /// </summary> public static bool CheckFunc(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { // 提取func:后声明的自定义函数名 const string START_STRING = "func:"; if (!checkRule.CheckRuleString.StartsWith(START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("自定义函数检查规则声明错误,必须以\"{0}\"开头,后面跟MyCheckFunction.cs中声明的函数名\n", START_STRING); return(false); } else { string funcName = checkRule.CheckRuleString.Substring(START_STRING.Length, checkRule.CheckRuleString.Length - START_STRING.Length).Trim(); Type myCheckFunctionClassType = typeof(MyCheckFunction); if (myCheckFunctionClassType != null) { MethodInfo dynMethod = myCheckFunctionClassType.GetMethod(funcName, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(FieldInfo), typeof(string).MakeByRefType() }, null); if (dynMethod == null) { errorString = string.Format("自定义函数检查规则声明错误,{0}.cs中找不到符合要求的名为\"{1}\"的函数,函数必须形如public static bool funcName(FieldInfo fieldInfo, out string errorString)\n", myCheckFunctionClassType.Name, funcName); return(false); } else { errorString = null; object[] inputParams = new object[] { fieldInfo, errorString }; bool checkResult = true; try { checkResult = (bool)dynMethod.Invoke(null, inputParams); } catch (Exception exception) { errorString = string.Format("运行自定义检查函数{0}错误,请修正代码后重试\n{1}", funcName, exception); return(false); } if (inputParams[1] != null) { errorString = inputParams[1].ToString(); } if (checkResult == true) { return(true); } else { errorString = string.Format("未通过自定义函数规则检查,存在以下错误:\n{0}\n", errorString); return(false); } } } else { errorString = string.Format("自定义函数检查规则无法使用,找不到{0}类\n", myCheckFunctionClassType.Name); return(false); } } }
/// <summary> /// 用于数据唯一性检查,适用于string、int、long、float或lang类型 /// 注意:string型、lang型如果填写或者找到的value为空字符串,允许出现多次为空的情况 /// 注意:lang型默认只检查key不能重复,如果还想检查不同key对应的value也不能相同则需要声明为unique[value] /// </summary> public static bool CheckUnique(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String || fieldInfo.DataType == DataType.Date || fieldInfo.DataType == DataType.Time) { _CheckInputDataUnique(fieldInfo.DataType, fieldInfo.Data, out errorString); if (errorString == null) { return(true); } else { errorString = string.Format("数据类型为{0}的字段中,存在以下重复数据:\n", fieldInfo.DataType.ToString()) + errorString; return(false); } } else if (fieldInfo.DataType == DataType.Lang) { // 只检查key则与string、int、float型的操作相同 if ("unique".Equals(checkRule.CheckRuleString, StringComparison.CurrentCultureIgnoreCase)) { _CheckInputDataUnique(fieldInfo.DataType, fieldInfo.LangKeys, out errorString); if (errorString == null) { return(true); } else { errorString = "要求仅检查lang型数据的key值不重复,但存在以下重复key:\n" + errorString; return(false); } } else if ("unique[value]".Equals(checkRule.CheckRuleString, StringComparison.CurrentCultureIgnoreCase)) { _CheckInputDataUnique(fieldInfo.DataType, fieldInfo.Data, out errorString); if (errorString == null) { return(true); } else { errorString = "要求检查lang型数据的key值与Value值均不重复,但存在以下重复数据:\n" + errorString; return(false); } } else { errorString = string.Format("唯一性检查规则用于lang型的声明错误,输入的检查规则字符串为{0}。而lang型声明unique仅检查key不重复,声明为unique[value]一并检查value不重复\n", checkRule.CheckRuleString); return(false); } } else { errorString = string.Format("唯一性检查规则只适用于string、int、long、float、lang、date或time类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } }
/// <summary> /// 检查HeroEquipment表,凡是填写的英雄都必须填写在所有品阶下四个槽位可穿戴装备信息 /// </summary> public static bool CheckHeroEquipmentTable(TableInfo tableInfo, out string errorString) { // 从配置文件中读取英雄的所有品阶(key:品阶, value:恒为true) Dictionary <int, bool> HERO_QUALITY = new Dictionary <int, bool>(); // 每品阶英雄所需穿戴的装备数量 const int HERO_EQUIPMENT_COUNT = 4; const string HERO_QUALITY_CONFIG_KEY = "$heroQuality"; if (AppValues.ConfigData.ContainsKey(HERO_QUALITY_CONFIG_KEY)) { string configString = AppValues.ConfigData[HERO_QUALITY_CONFIG_KEY]; // 去除首尾花括号后,通过英文逗号分隔每个有效值即可 if (!(configString.StartsWith("{") && configString.EndsWith("}"))) { errorString = string.Format("表示英雄所有品阶的配置{0}错误,必须在首尾用一对花括号包裹整个定义内容,请修正后重试\n", HERO_QUALITY_CONFIG_KEY); return(false); } string temp = configString.Substring(1, configString.Length - 2).Trim(); string[] values = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (values.Length < 1) { errorString = string.Format("表示英雄所有品阶的配置{0}错误,不允许为空值,请修正后重试\n", HERO_QUALITY_CONFIG_KEY); return(false); } for (int i = 0; i < values.Length; ++i) { string oneValueString = values[i].Trim(); int oneValue; if (int.TryParse(oneValueString, out oneValue) == true) { if (HERO_QUALITY.ContainsKey(oneValue)) { Utils.LogWarning(string.Format("警告:表示英雄所有品阶的配置{0}错误,出现了相同的品阶\"{1}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", HERO_QUALITY_CONFIG_KEY, oneValue)); } else { HERO_QUALITY.Add(oneValue, true); } } else { errorString = string.Format("表示英雄所有品阶的配置{0}错误,出现了非int型有效值的规则定义,其为\"{1}\",请修正后重试\n", HERO_QUALITY_CONFIG_KEY, oneValueString); return(false); } } } else { errorString = string.Format("config配置文件找不到名为\"{0}\"的表示英雄所有品阶的配置,无法进行HeroEquipment整表的检查,请填写配置后再重试\n", HERO_QUALITY_CONFIG_KEY); return(false); } // 获取检查涉及的字段数据 const string HERO_ID_FIELD_NAME = "heroId"; const string HERO_QUALITY_FIELD_NAME = "heroQuality"; const string SEQ_FIELD_NAME = "seq"; List <object> heroIdList = null; List <object> heroQualityList = null; List <object> equipmentSeqList = null; if (tableInfo.GetFieldInfoByFieldName(HERO_ID_FIELD_NAME) != null) { heroIdList = tableInfo.GetFieldInfoByFieldName(HERO_ID_FIELD_NAME).Data; } else { errorString = string.Format("HeroEquipment表中找不到名为{0}的字段,无法进行整表检查,请修正后重试\n", HERO_ID_FIELD_NAME); return(false); } if (tableInfo.GetFieldInfoByFieldName(HERO_QUALITY_FIELD_NAME) != null) { heroQualityList = tableInfo.GetFieldInfoByFieldName(HERO_QUALITY_FIELD_NAME).Data; } else { errorString = string.Format("HeroEquipment表中找不到名为{0}的字段,无法进行整表检查,请修正后重试\n", HERO_QUALITY_FIELD_NAME); return(false); } if (tableInfo.GetFieldInfoByFieldName(SEQ_FIELD_NAME) != null) { equipmentSeqList = tableInfo.GetFieldInfoByFieldName(SEQ_FIELD_NAME).Data; } else { errorString = string.Format("HeroEquipment表中找不到名为{0}的字段,无法进行整表检查,请修正后重试\n", SEQ_FIELD_NAME); return(false); } // 先对heroId、quality、seq三个字段进行非空检查,避免填写空值 if (AppValues.IsAllowedNullNumber == true) { FieldCheckRule numberNotEmptyCheckRule = new FieldCheckRule(); numberNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; numberNotEmptyCheckRule.CheckRuleString = "notEmpty"; TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(HERO_ID_FIELD_NAME), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("HeroEquipment表中{0}字段中{1}\n", HERO_ID_FIELD_NAME, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(HERO_QUALITY_FIELD_NAME), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("HeroEquipment表中{0}字段中{1}\n", HERO_QUALITY_FIELD_NAME, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(SEQ_FIELD_NAME), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("HeroEquipment表中{0}字段中{1}\n", SEQ_FIELD_NAME, errorString); return(false); } } // 记录实际填写的信息(key:从外层到内层依次表示heroId、quality、seq,最内层value为从0开始计的数据行序号) Dictionary <int, Dictionary <int, Dictionary <int, int> > > inputData = new Dictionary <int, Dictionary <int, Dictionary <int, int> > >(); int dataCount = tableInfo.GetKeyColumnFieldInfo().Data.Count; StringBuilder errorStringBuilder = new StringBuilder(); for (int i = 0; i < dataCount; ++i) { int heroId = (int)heroIdList[i]; int heroQuality = (int)heroQualityList[i]; int seq = (int)equipmentSeqList[i]; if (!inputData.ContainsKey(heroId)) { inputData.Add(heroId, new Dictionary <int, Dictionary <int, int> >()); } Dictionary <int, Dictionary <int, int> > qualityInfo = inputData[heroId]; if (!qualityInfo.ContainsKey(heroQuality)) { qualityInfo.Add(heroQuality, new Dictionary <int, int>()); } Dictionary <int, int> seqInfo = qualityInfo[heroQuality]; if (seqInfo.ContainsKey(seq)) { errorStringBuilder.AppendFormat("第{0}行与第{1}行完全重复\n", i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, seqInfo[seq] + AppValues.DATA_FIELD_DATA_START_INDEX + 1); } else { seqInfo.Add(seq, i); } } string repeatedLineErrorString = errorStringBuilder.ToString(); if (!string.IsNullOrEmpty(repeatedLineErrorString)) { errorString = string.Format("HeroEquipment表中以下行中的heroId、heroQuality、seq字段与其他行存在完全重复的错误:\n{0}\n", repeatedLineErrorString); return(false); } // 检查配置的每个英雄是否都含有所有品阶下四个槽位的可穿戴装备信息 foreach (var heroInfo in inputData) { var qualityInfo = heroInfo.Value; List <int> qualityList = new List <int>(qualityInfo.Keys); List <int> LEGAL_QUALITY_LIST = new List <int>(HERO_QUALITY.Keys); foreach (int quality in LEGAL_QUALITY_LIST) { // 检查是否含有所有品阶 if (!qualityList.Contains(quality)) { errorStringBuilder.AppendFormat("英雄(heroId={0})缺少品质为{1}的装备配置\n", heroInfo.Key, quality); } } // 检查每个品阶下是否配全了四个槽位的装备信息 foreach (var oneQualityInfo in qualityInfo) { var seqInfo = oneQualityInfo.Value; List <int> seqList = new List <int>(seqInfo.Keys); for (int seq = 1; seq <= HERO_EQUIPMENT_COUNT; ++seq) { if (!seqList.Contains(seq) && LEGAL_QUALITY_LIST.Contains(oneQualityInfo.Key)) { errorStringBuilder.AppendFormat("英雄(heroId={0})在品质为{1}下缺少第{2}个槽位的装备配置\n", heroInfo.Key, oneQualityInfo.Key, seq); } } } } string lackDataErrorString = errorStringBuilder.ToString(); if (string.IsNullOrEmpty(lackDataErrorString)) { errorString = null; return(true); } else { errorString = string.Format("HeroEquipment表中存在以下配置缺失:\n{0}\n", lackDataErrorString); return(false); } }
/// <summary> /// 按配置的特殊索引导出方式输出json文件(如果声明了在生成的json文件开头以注释形式展示列信息,将生成更直观的嵌套字段信息,而不同于普通导出规则的列信息展示) /// </summary> public static bool SpecialExportTableToJson(TableInfo tableInfo, string exportRule, out string errorString) { exportRule = exportRule.Trim(); // 解析按这种方式导出后的json文件名 int colonIndex = exportRule.IndexOf(':'); if (colonIndex == -1) { errorString = string.Format("导出配置\"{0}\"定义错误,必须在开头声明导出lua文件名\n", exportRule); return(false); } string fileName = exportRule.Substring(0, colonIndex).Trim(); // 判断是否在最后的花括号内声明table value中包含的字段 int leftBraceIndex = exportRule.LastIndexOf('{'); int rightBraceIndex = exportRule.LastIndexOf('}'); // 解析依次作为索引的字段名 string indexFieldNameString = null; // 注意分析花括号时要考虑到未声明table value中的字段而在某索引字段完整性检查规则中用花括号声明了有效值的情况 if (exportRule.EndsWith("}") && leftBraceIndex != -1) { indexFieldNameString = exportRule.Substring(colonIndex + 1, leftBraceIndex - colonIndex - 1); } else { indexFieldNameString = exportRule.Substring(colonIndex + 1, exportRule.Length - colonIndex - 1); } string[] indexFieldDefine = indexFieldNameString.Split(new char[] { '-' }, System.StringSplitOptions.RemoveEmptyEntries); // 用于索引的字段列表 List <FieldInfo> indexField = new List <FieldInfo>(); // 索引字段对应的完整性检查规则 List <string> integrityCheckRules = new List <string>(); if (indexFieldDefine.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,用于索引的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{{otherFieldName1,otherFieldName2}}的格式配置\n", exportRule); return(false); } // 检查字段是否存在且为int、float、string或lang型 foreach (string fieldDefine in indexFieldDefine) { string fieldName = null; // 判断是否在字段名后用小括号声明了该字段的完整性检查规则 int leftBracketIndex = fieldDefine.IndexOf('('); int rightBracketIndex = fieldDefine.IndexOf(')'); if (leftBracketIndex > 0 && rightBracketIndex > leftBracketIndex) { fieldName = fieldDefine.Substring(0, leftBracketIndex); string integrityCheckRule = fieldDefine.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1).Trim(); if (string.IsNullOrEmpty(integrityCheckRule)) { errorString = string.Format("导出配置\"{0}\"定义错误,用于索引的字段\"{1}\"若要声明完整性检查规则就必须在括号中填写否则不要加括号\n", exportRule, fieldName); return(false); } integrityCheckRules.Add(integrityCheckRule); } else { fieldName = fieldDefine.Trim(); integrityCheckRules.Add(null); } FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (fieldInfo.DataType != DataType.Int && fieldInfo.DataType != DataType.Long && fieldInfo.DataType != DataType.Float && fieldInfo.DataType != DataType.String && fieldInfo.DataType != DataType.Lang) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"为{2}型,但只允许为int、long、float、string或lang型\n", exportRule, fieldName, fieldInfo.DataType); return(false); } // 对索引字段进行非空检查 if (fieldInfo.DataType == DataType.String) { FieldCheckRule stringNotEmptyCheckRule = new FieldCheckRule(); stringNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; stringNotEmptyCheckRule.CheckRuleString = "notEmpty[trim]"; TableCheckHelper.CheckNotEmpty(fieldInfo, stringNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,string型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } else if (fieldInfo.DataType == DataType.Lang) { FieldCheckRule langNotEmptyCheckRule = new FieldCheckRule(); langNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; langNotEmptyCheckRule.CheckRuleString = "notEmpty[key|value]"; TableCheckHelper.CheckNotEmpty(fieldInfo, langNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,lang型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } else if (AppValues.IsAllowedNullNumber == true) { FieldCheckRule numberNotEmptyCheckRule = new FieldCheckRule(); numberNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; numberNotEmptyCheckRule.CheckRuleString = "notEmpty"; TableCheckHelper.CheckNotEmpty(fieldInfo, numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,{1}型索引字段\"{2}\"中存在以下空值,而作为索引的key不允许为空\n{3}\n", exportRule, fieldInfo.DataType.ToString(), fieldName, errorString); return(false); } } indexField.Add(fieldInfo); } // 解析table value中要输出的字段名 List <FieldInfo> tableValueField = new List <FieldInfo>(); // 如果在花括号内配置了json value中要输出的字段名 if (exportRule.EndsWith("}") && leftBraceIndex != -1 && leftBraceIndex < rightBraceIndex) { string tableValueFieldName = exportRule.Substring(leftBraceIndex + 1, rightBraceIndex - leftBraceIndex - 1); string[] fieldNames = tableValueFieldName.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries); if (fieldNames.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,花括号中声明的table value中的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{{otherFieldName1,otherFieldName2}}的格式配置\n", exportRule); return(false); } // 检查字段是否存在 foreach (string fieldName in fieldNames) { FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中的字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (tableValueField.Contains(fieldInfo)) { Utils.LogWarning(string.Format("警告:导出配置\"{0}\"定义中,声明的table value中的字段存在重复,字段名为{1}(列号{2}),本工具只生成一次,请修正错误\n", exportRule, fieldName, Utils.GetExcelColumnName(fieldInfo.ColumnSeq + 1))); } else { tableValueField.Add(fieldInfo); } } } else if (exportRule.EndsWith("}") && leftBraceIndex == -1) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中花括号不匹配\n", exportRule); return(false); } // 如果未在花括号内声明,则默认将索引字段之外的所有字段进行填充 else { List <string> indexFieldNameList = new List <string>(indexFieldDefine); foreach (FieldInfo fieldInfo in tableInfo.GetAllClientFieldInfo()) { if (!indexFieldNameList.Contains(fieldInfo.FieldName)) { tableValueField.Add(fieldInfo); } } } // 解析完依次作为索引的字段以及table value中包含的字段后,按索引要求组成相应的嵌套数据结构 Dictionary <object, object> data = new Dictionary <object, object>(); int rowCount = tableInfo.GetKeyColumnFieldInfo().Data.Count; for (int i = 0; i < rowCount; ++i) { Dictionary <object, object> temp = data; // 生成除最内层的数据结构 for (int j = 0; j < indexField.Count - 1; ++j) { FieldInfo oneIndexField = indexField[j]; var tempData = oneIndexField.Data[i]; if (!temp.ContainsKey(tempData)) { temp.Add(tempData, new Dictionary <object, object>()); } temp = (Dictionary <object, object>)temp[tempData]; } // 最内层的value存数据的int型行号(从0开始计) FieldInfo lastIndexField = indexField[indexField.Count - 1]; var lastIndexFieldData = lastIndexField.Data[i]; if (!temp.ContainsKey(lastIndexFieldData)) { temp.Add(lastIndexFieldData, i); } else { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导出时发现第{2}行与第{3}行在各个索引字段的值完全相同,导出被迫停止,请修正错误后重试\n", tableInfo.TableName, exportRule, i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, temp[lastIndexFieldData]); Utils.LogErrorAndExit(errorString); return(false); } } // 进行数据完整性检查 if (AppValues.IsNeedCheck == true) { TableCheckHelper.CheckTableIntegrity(indexField, data, integrityCheckRules, out errorString); if (errorString != null) { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导时未通过数据完整性检查,导出被迫停止,请修正错误后重试:\n{2}\n", tableInfo.TableName, exportRule, errorString); return(false); } } // 生成导出的文件内容 StringBuilder content = new StringBuilder(); // 生成数据内容开头 content.AppendLine("{"); // 当前缩进量 int currentLevel = 1; // 逐层按嵌套结构输出数据 _GetIndexFieldData(content, data, tableValueField, ref currentLevel, out errorString); if (errorString != null) { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导出时发现以下错误,导出被迫停止,请修正错误后重试:\n{2}\n", tableInfo.TableName, exportRule, errorString); return(false); } // 去掉最后一行后多余的英文逗号,此处要特殊处理当表格中没有任何数据行时的情况 if (content.Length > 1) { content.Remove(content.Length - 1, 1); } // 生成数据内容结尾 content.AppendLine("}"); string exportString = _ToTightJsonString(content.ToString()); // 如果声明了要整理为带缩进格式的形式 if (AppValues.ExportJsonIsFormat == true) { exportString = _FormatJson(exportString); } // 保存为json文件 if (Utils.SaveJsonFile(tableInfo.TableName, exportString) == true) { errorString = null; return(true); } else { errorString = "保存为json文件失败\n"; return(false); } }
/// <summary> /// 用于输入数据的非空检查,适用于int、long、float、string、lang、date、time、json或tableString型 /// 注意:string类型要求字符串不能为空但允许为连续空格字符串,如果也不允许为连续空格字符串,需要声明为notEmpty[trim] /// 注意:lang类型声明notEmpty[key]只检查是否填写了key值,声明notEmpty[value]只检查填写的key在相应的lang文件中能找到对应的value,声明notEmpty[key|value]或notEmpty则包含这两个要求 /// </summary> public static bool CheckNotEmpty(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { // 存储检查出的空值对应的行号 List <int> emptyDataLines = new List <int>(); if (fieldInfo.DataType == DataType.String) { if (checkRule.CheckRuleString.Equals("notEmpty", StringComparison.CurrentCultureIgnoreCase)) { _CheckInputDataNotEmpty(fieldInfo.Data, emptyDataLines, false); } else if (checkRule.CheckRuleString.Equals("notEmpty[trim]", StringComparison.CurrentCultureIgnoreCase)) { _CheckInputDataNotEmpty(fieldInfo.Data, emptyDataLines, true); } else { errorString = string.Format("数据非空检查规则用于string型的声明错误,输入的检查规则字符串为{0}。而string型声明notEmpty要求字符串不能为空但允许为连续空格字符串,如果也不允许为连续空格字符串,需要声明为notEmpty[trim]\n", checkRule.CheckRuleString); return(false); } } else if (fieldInfo.DataType == DataType.Lang) { if (checkRule.CheckRuleString.Equals("notEmpty[key]", StringComparison.CurrentCultureIgnoreCase)) { _CheckInputDataNotEmpty(fieldInfo.LangKeys, emptyDataLines, true); } else if (checkRule.CheckRuleString.Equals("notEmpty[value]", StringComparison.CurrentCultureIgnoreCase)) { for (int i = 0; i < fieldInfo.LangKeys.Count; ++i) { // 忽略无效集合元素下属子类型的空值,忽略未填写key的 if (fieldInfo.LangKeys[i] == null || string.IsNullOrEmpty(fieldInfo.LangKeys[i].ToString())) { continue; } if (fieldInfo.Data[i] == null) { emptyDataLines.Add(i); } } } else if (checkRule.CheckRuleString.Equals("notEmpty", StringComparison.CurrentCultureIgnoreCase) || checkRule.CheckRuleString.Equals("notEmpty[key|value]", StringComparison.CurrentCultureIgnoreCase)) { for (int i = 0; i < fieldInfo.LangKeys.Count; ++i) { // 忽略无效集合元素下属子类型的空值 if (fieldInfo.LangKeys[i] == null) { continue; } // 填写的key不能为空或连续空格字符串,且必须能在lang文件中找到对应的value if (string.IsNullOrEmpty(fieldInfo.LangKeys[i].ToString().Trim()) || fieldInfo.Data[i] == null) { emptyDataLines.Add(i); } } } else { errorString = string.Format("数据非空检查规则用于lang型的声明错误,输入的检查规则字符串为{0}。而lang型声明notEmpty[key]只检查是否填写了key值,声明notEmpty[value]只检查填写的key在相应的lang文件中能找到对应的value,声明notEmpty[key|value]或notEmpty则包含这两个要求\n", checkRule.CheckRuleString); return(false); } } else if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float) { if (AppValues.IsAllowedNullNumber == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 如果int、long、float型字段下取值为null,可能填写的为空值,也可能是父集合类型标为无效 if (fieldInfo.ParentField != null && (bool)fieldInfo.ParentField.Data[i] == false) { continue; } else if (fieldInfo.Data[i] == null) { emptyDataLines.Add(i); } } } } else if (fieldInfo.DataType == DataType.Date || fieldInfo.DataType == DataType.Time) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 如果date、time型字段下取值为null,可能填写的为空值,也可能是父集合类型标为无效 if (fieldInfo.ParentField != null && (bool)fieldInfo.ParentField.Data[i] == false) { continue; } else if (fieldInfo.Data[i] == null) { emptyDataLines.Add(i); } } } else if (fieldInfo.DataType == DataType.Json || fieldInfo.DataType == DataType.TableString || fieldInfo.DataType == DataType.MapString) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 如果json、tableString型字段下取值为null,可能填写的为空值,也可能是父集合类型标为无效 if (fieldInfo.ParentField != null && (bool)fieldInfo.ParentField.Data[i] == false) { continue; } else if (fieldInfo.Data[i] == null) { emptyDataLines.Add(i); } } } else { errorString = string.Format("数据非空检查规则只适用于int、long、float、string、lang、date、time、json、tableString或mapString类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } if (emptyDataLines.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); errorStringBuild.Append("存在以下空数据,行号分别为:"); string separator = ", "; foreach (int lineNum in emptyDataLines) { errorStringBuild.AppendFormat("{0}{1}", lineNum + AppValues.DATA_FIELD_DATA_START_INDEX + 1, separator); } // 去掉末尾多余的", " errorStringBuild.Remove(errorStringBuild.Length - separator.Length, separator.Length); errorStringBuild.Append("\n"); errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } }
/// <summary> /// 用于int、long、float三种数值类型或date、time两种时间类型的范围检查,或string、lang两种字符串类型的长度检查 /// </summary> public static bool CheckRange(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { bool isNumberDataType = fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float; bool isTimeDataType = fieldInfo.DataType == DataType.Date || fieldInfo.DataType == DataType.Time; bool isStringDataType = fieldInfo.DataType == DataType.String || fieldInfo.DataType == DataType.Lang; if (isNumberDataType == false && isTimeDataType == false && isStringDataType == false) { errorString = string.Format("值范围检查只能用于int、long、float三种数值类型或date、time两种时间类型的字段,或者用于检查string、lang型字符串的长度,而该字段为{0}型\n", fieldInfo.DataType); return(false); } // 检查填写的检查规则是否正确 bool isIncludeFloor; bool isIncludeCeil; bool isCheckFloor; bool isCheckCeil; double floorValue = 0; double ceilValue = 0; DateTime floorDateTime = DateTimeValue.REFERENCE_DATE; DateTime ceilDateTime = DateTimeValue.REFERENCE_DATE; // 规则首位必须为方括号或者圆括号 if (checkRule.CheckRuleString.StartsWith("(")) { isIncludeFloor = false; } else if (checkRule.CheckRuleString.StartsWith("[")) { isIncludeFloor = true; } else { errorString = "值范围检查定义错误:必须用英文(或[开头,表示有效范围是否包含等于下限的情况\n"; return(false); } // 规则末位必须为方括号或者圆括号 if (checkRule.CheckRuleString.EndsWith(")")) { isIncludeCeil = false; } else if (checkRule.CheckRuleString.EndsWith("]")) { isIncludeCeil = true; } else { errorString = "值范围检查定义错误:必须用英文)或]结尾,表示有效范围是否包含等于上限的情况\n"; return(false); } // 去掉首尾的括号 string temp = checkRule.CheckRuleString.Substring(1, checkRule.CheckRuleString.Length - 2); // 通过英文逗号分隔上下限 string[] floorAndCeilString = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (floorAndCeilString.Length != 2) { errorString = "值范围检查定义错误:必须用一个英文逗号分隔值范围的上下限\n"; return(false); } string floorString = floorAndCeilString[0].Trim(); string ceilString = floorAndCeilString[1].Trim(); // 提取下限数值 if (floorString.Equals("*")) { isCheckFloor = false; } else { isCheckFloor = true; if (isNumberDataType == true || isStringDataType == true) { if (double.TryParse(floorString, out floorValue) == false) { errorString = string.Format("值范围检查定义错误:下限不是合法的数字,你输入的为{0}\n", floorString); return(false); } } else { if (fieldInfo.DataType == DataType.Date) { try { DateTimeFormatInfo dateTimeFormat = new DateTimeFormatInfo(); dateTimeFormat.ShortDatePattern = DateTimeValue.APP_DEFAULT_DATE_FORMAT; floorDateTime = Convert.ToDateTime(floorString, dateTimeFormat); } catch { errorString = string.Format("值范围检查定义错误:date型下限声明不合法,必须按{0}的形式填写,你输入的为{1}\n", DateTimeValue.APP_DEFAULT_DATE_FORMAT, floorString); return(false); } } else { try { DateTimeFormatInfo dateTimeFormat = new DateTimeFormatInfo(); dateTimeFormat.ShortTimePattern = DateTimeValue.APP_DEFAULT_TIME_FORMAT; // 此函数会将DateTime的日期部分自动赋值为当前时间 DateTime tempDateTime = Convert.ToDateTime(floorString, dateTimeFormat); floorDateTime = new DateTime(DateTimeValue.REFERENCE_DATE.Year, DateTimeValue.REFERENCE_DATE.Month, DateTimeValue.REFERENCE_DATE.Day, tempDateTime.Hour, tempDateTime.Minute, tempDateTime.Second); } catch { errorString = string.Format("值范围检查定义错误:time型下限声明不合法,必须按{0}的形式填写,你输入的为{1}\n", DateTimeValue.APP_DEFAULT_TIME_FORMAT, floorString); return(false); } } } } // 提取上限数值 if (ceilString.Equals("*")) { isCheckCeil = false; } else { isCheckCeil = true; if (isNumberDataType == true || isStringDataType == true) { if (double.TryParse(ceilString, out ceilValue) == false) { errorString = string.Format("值范围检查定义错误:上限不是合法的数字,你输入的为{0}\n", ceilString); return(false); } } else { if (fieldInfo.DataType == DataType.Date) { try { DateTimeFormatInfo dateTimeFormat = new DateTimeFormatInfo(); dateTimeFormat.ShortDatePattern = DateTimeValue.APP_DEFAULT_DATE_FORMAT; ceilDateTime = Convert.ToDateTime(ceilString, dateTimeFormat); } catch { errorString = string.Format("值范围检查定义错误:date型上限声明不合法,必须按{0}的形式填写,你输入的为{1}\n", DateTimeValue.APP_DEFAULT_DATE_FORMAT, ceilString); return(false); } } else { try { DateTimeFormatInfo dateTimeFormat = new DateTimeFormatInfo(); dateTimeFormat.ShortDatePattern = DateTimeValue.APP_DEFAULT_TIME_FORMAT; // 此函数会将DateTime的日期部分自动赋值为当前时间 DateTime tempDateTime = Convert.ToDateTime(ceilString, dateTimeFormat); ceilDateTime = new DateTime(DateTimeValue.REFERENCE_DATE.Year, DateTimeValue.REFERENCE_DATE.Month, DateTimeValue.REFERENCE_DATE.Day, tempDateTime.Hour, tempDateTime.Minute, tempDateTime.Second); } catch { errorString = string.Format("值范围检查定义错误:time型上限声明不合法,必须按{0}的形式填写,你输入的为{1}\n", DateTimeValue.APP_DEFAULT_TIME_FORMAT, ceilString); return(false); } } } } // 判断上限是否大于下限 if (isNumberDataType == true || isStringDataType == true) { if (isCheckFloor == true && isCheckCeil == true && floorValue >= ceilValue) { errorString = string.Format("值范围检查定义错误:上限值必须大于下限值,你输入的下限为{0},上限为{1}\n", floorString, ceilString); return(false); } } else { if (isCheckFloor == true && isCheckCeil == true && floorDateTime >= ceilDateTime) { errorString = string.Format("值范围检查定义错误:上限值必须大于下限值,你输入的下限为{0},上限为{1}\n", floorDateTime.ToString(DateTimeValue.APP_DEFAULT_DATE_FORMAT), ceilDateTime.ToString(DateTimeValue.APP_DEFAULT_DATE_FORMAT)); return(false); } } // 进行检查 // 存储检查出的非法值(key:数据索引, value:填写值) Dictionary <int, object> illegalValue = new Dictionary <int, object>(); if (isCheckFloor == true && isCheckCeil == false) { if (isIncludeFloor == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值或本身为空值 if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue < floorValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh < floorValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue < floorDateTime) { illegalValue.Add(i, inputValue); } } } } else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue <= floorValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh <= floorValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue <= floorDateTime) { illegalValue.Add(i, inputValue); } } } } } else if ((isCheckFloor == false && isCheckCeil == true)) { if (isIncludeCeil == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue > ceilDateTime) { illegalValue.Add(i, inputValue); } } } } else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue >= ceilDateTime) { illegalValue.Add(i, inputValue); } } } } } else if ((isCheckFloor == true && isCheckCeil == true)) { if (isIncludeFloor == false && isIncludeCeil == false) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue <= floorValue || inputValue >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh <= floorValue || lengh >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue <= floorDateTime || inputValue >= ceilDateTime) { illegalValue.Add(i, inputValue); } } } } else if (isIncludeFloor == true && isIncludeCeil == false) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue < floorValue || inputValue >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh < floorValue || lengh >= ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue < floorDateTime || inputValue >= ceilDateTime) { illegalValue.Add(i, inputValue); } } } } else if (isIncludeFloor == false && isIncludeCeil == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue <= floorValue || inputValue > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh <= floorValue || lengh > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue <= floorDateTime || inputValue > ceilDateTime) { illegalValue.Add(i, inputValue); } } } } else if (isIncludeFloor == true && isIncludeCeil == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null) { continue; } if (isNumberDataType == true) { double inputValue = Convert.ToDouble(fieldInfo.Data[i]); if (inputValue < floorValue || inputValue > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else if (isStringDataType == true) { int lengh = System.Text.Encoding.Default.GetBytes(fieldInfo.Data[i].ToString().ToCharArray()).Length; if (lengh < floorValue || lengh > ceilValue) { illegalValue.Add(i, fieldInfo.Data[i]); } } else { DateTime inputValue = (DateTime)fieldInfo.Data[i]; if (inputValue < floorDateTime || inputValue > ceilDateTime) { illegalValue.Add(i, inputValue); } } } } } if (illegalValue.Count > 0) { StringBuilder illegalValueInfo = new StringBuilder(); if (isNumberDataType == true || isStringDataType == true) { foreach (var item in illegalValue) { illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不满足要求\n", item.Key + ExcelTableSetting.DataFieldDataStartRowIndex + 1, item.Value); } } else if (fieldInfo.DataType == DataType.Date) { foreach (var item in illegalValue) { illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不满足要求\n", item.Key + ExcelTableSetting.DataFieldDataStartRowIndex + 1, ((DateTime)(item.Value)).ToString(DateTimeValue.APP_DEFAULT_DATE_FORMAT)); } } else if (fieldInfo.DataType == DataType.Time) { foreach (var item in illegalValue) { illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不满足要求\n", item.Key + ExcelTableSetting.DataFieldDataStartRowIndex + 1, ((DateTime)(item.Value)).ToString(DateTimeValue.APP_DEFAULT_TIME_FORMAT)); } } errorString = illegalValueInfo.ToString(); return(false); } else { errorString = null; return(true); } }
// catch(Exception e) // { // AppLog.LogErrorAndExit(string.Format("合并表格失败,因为{0}",e)); // } // return newTableInfo; //} /// <summary> /// 合并表格 /// </summary> /// <param name="newTableName">新表的名字,如:item</param> /// <param name="tableInfoList">待合并的表,TableInfo </param> /// <param name="errorString">错误输出</param> /// <returns></returns> public static TableInfo MergeTable(string newTableName, List <TableInfo> tableInfoList, out string errorString) { AppLog.Log(string.Format("开始合并表格:{0}", newTableName)); errorString = null; TableInfo newTableInfo = new TableInfo(); TableInfo oldTableInfo = tableInfoList[0]; //新表的基本信息 newTableInfo.ExcelFilePath = oldTableInfo.ExcelFilePath; newTableInfo.ExcelName = oldTableInfo.ExcelName; newTableInfo.TableName = newTableName; newTableInfo.ExcelDirectory = oldTableInfo.ExcelDirectory; newTableInfo.TableConfigData = oldTableInfo.TableConfigData; newTableInfo.TableConfigData2 = oldTableInfo.TableConfigData2; newTableInfo.TableConfig = oldTableInfo.TableConfig; FieldInfo newPrimaryKeyField = new FieldInfo(); FieldInfo oldPrimaryKeyField = oldTableInfo.GetKeyColumnFieldInfo(); newPrimaryKeyField.TableName = oldPrimaryKeyField.TableName; newPrimaryKeyField.SheetName = oldPrimaryKeyField.SheetName; //Excel表第1行信息 newPrimaryKeyField.Desc = oldPrimaryKeyField.Desc; //Excel表第2行信息 newPrimaryKeyField.FieldName = oldPrimaryKeyField.FieldName; //Excel表第3行信息 newPrimaryKeyField.DataType = oldPrimaryKeyField.DataType; newPrimaryKeyField.DataTypeString = oldPrimaryKeyField.DataTypeString; newPrimaryKeyField.ExtraParam = oldPrimaryKeyField.ExtraParam;//类似:date(input=#1970sec|toLua=yyyy年MM月dd日 HH时mm分ss秒) //Excel表第4行信息 newPrimaryKeyField.CheckRule = oldPrimaryKeyField.CheckRule; //Excel表第5行信息 newPrimaryKeyField.DatabaseFieldName = oldPrimaryKeyField.DatabaseFieldName; newPrimaryKeyField.DatabaseFieldType = oldPrimaryKeyField.DatabaseFieldType; newPrimaryKeyField.DatabaseInfoString = oldPrimaryKeyField.DatabaseInfoString; //合并主键及数据 StringBuilder tempMergeTable1 = new StringBuilder(); foreach (TableInfo tableInfoTemp in tableInfoList) { FieldInfo fieldInfoTemp = tableInfoTemp.GetKeyColumnFieldInfo(); if (newPrimaryKeyField.FieldName.Equals(fieldInfoTemp.FieldName) == false) { AppLog.LogErrorAndExit(string.Format("合并遇到错误:合并表格的主键名必须一致,表{0}的主键名为{1}与其他表格主键为{2}不同,其他表格包括:{3}", tableInfoTemp.ExcelName, fieldInfoTemp.FieldName, newPrimaryKeyField.FieldName, tempMergeTable1.ToString())); } if (newPrimaryKeyField.DataType.Equals(fieldInfoTemp.DataType) == false) { AppLog.LogErrorAndExit(string.Format("合并遇到错误:合并表格的主键名及类型必须一致,表{0}的主键名为{1}(类型为:{2})与其他表格主键类型为{3},其他表格包括:{4}", tableInfoTemp.ExcelName, fieldInfoTemp.FieldName, fieldInfoTemp.DataType, newPrimaryKeyField.DataType, tempMergeTable1.ToString())); } //if (newPrimaryKeyField.DatabaseInfoString.Equals(fieldInfoTemp.DatabaseInfoString) == false) //{ // AppLog.LogErrorAndExit(string.Format("合并遇到错误:合并表格的主键导入数据库(Excel第{0}行)必须一致:表{1}的导入数据库{2}与其他表格主键不同,其他表格包括:{3}", ExcelTableSetting.DataFieldExportDataBaseFieldInFoRowIndex, tableInfoTemp.ExcelName, fieldInfoTemp.DatabaseInfoString, tempMergeTable1.ToString())); //} newPrimaryKeyField = FieldInfo.AddDataByOtherField(newPrimaryKeyField, fieldInfoTemp, fieldInfoTemp.Data.Count, 0, out errorString); if (errorString != null) { AppLog.LogErrorAndExit("合并遇到错误:" + errorString); } } // 唯一性检查 FieldCheckRule uniqueCheckRule = new FieldCheckRule(); uniqueCheckRule.CheckType = TableCheckType.Unique; uniqueCheckRule.CheckRuleString = "unique"; TableCheckHelper.CheckUnique(newPrimaryKeyField, uniqueCheckRule, out errorString); if (errorString != null) { AppLog.LogErrorAndExit(string.Format("合并后名为{0}的表格主键存在重复值:{1}", newTableName, errorString)); } newTableInfo.AddField(newPrimaryKeyField); // 合并其他字段及字段类型,但不合并数据 List <string> newTableFieldNames = new List <string>(); newTableFieldNames.Add(newPrimaryKeyField.FieldName); StringBuilder tempMergeTable2 = new StringBuilder(); foreach (TableInfo tableInfoTemp in tableInfoList) { List <FieldInfo> listFieldInfoTemp = tableInfoTemp.GetAllFieldInfo(); foreach (FieldInfo tempFieldInfo in listFieldInfoTemp) { //如果是主键就跳过 if (tempFieldInfo.FieldName.Equals(newPrimaryKeyField.FieldName)) { continue; } //如果已合并过该字段,则进行检查字段类型、数据库类型是否相同 if (newTableFieldNames.Contains(tempFieldInfo.FieldName)) { FieldInfo tempNewTableInfoFieldInfo = newTableInfo.GetFieldInfoByFieldName(tempFieldInfo.FieldName); if (tempFieldInfo.DataType.Equals(tempNewTableInfoFieldInfo.DataType) == false) { AppLog.LogErrorAndExit(string.Format("合并遇到错误:合并表格的字段名与类型必须一致,表{0}中为{1}的字段(类型为:{2})与其他表格同名字段类型为{3},其他表格包括:{4}", tableInfoTemp.ExcelName, tempFieldInfo.FieldName, tempFieldInfo.DataType, tempNewTableInfoFieldInfo.DataType, tempMergeTable2.ToString())); } //if (tempFieldInfo.DatabaseInfoString.Equals(tempNewTableInfoFieldInfo.DatabaseInfoString) == false) //{ // AppLog.LogErrorAndExit(string.Format("合并遇到错误:合并表格的字段名与类型必须一致,表{0}中为{1}的字段(导出入数据类型为:{2})与其他表格同名字段导入数据库类型为{3},其他表格包括:{4}", tableInfoTemp.ExcelName, tempFieldInfo.FieldName, tempFieldInfo.DatabaseInfoString, tempNewTableInfoFieldInfo.DatabaseInfoString, tempMergeTable2.ToString())); //} if (tempNewTableInfoFieldInfo.ChildField == null) { if (tempFieldInfo.ChildField != null) { tempNewTableInfoFieldInfo.ChildField = tempFieldInfo.ChildField; } } else { if (tempNewTableInfoFieldInfo.ChildField.Count == tempFieldInfo.ChildField.Count) { //继续判断其他条件 } else { AppLog.LogErrorAndExit(string.Format("合并遇到错误:表{0}中为{1}的字段的ChildField数量与其他表格不同,其他表格包括:{2}", tableInfoTemp.ExcelName, tempFieldInfo.FieldName, tempMergeTable2.ToString())); } } } else//如果未合并,则直接合并 { FieldInfo newField = new FieldInfo(); //Excel表第1行信息 newField.Desc = tempFieldInfo.Desc; //Excel表第2行信息 newField.FieldName = tempFieldInfo.FieldName; //Excel表第3行信息 newField.DataType = tempFieldInfo.DataType; newField.DataTypeString = tempFieldInfo.DataTypeString; newField.ExtraParam = tempFieldInfo.ExtraParam; //类似:date(input=#1970sec|toLua=yyyy年MM月dd日 HH时mm分ss秒) //Excel表第4行信息 newField.CheckRule = tempFieldInfo.CheckRule; //Excel表第5行信息 newField.DatabaseFieldName = tempFieldInfo.DatabaseFieldName; newField.DatabaseFieldType = tempFieldInfo.DatabaseFieldType; newField.DatabaseInfoString = tempFieldInfo.DatabaseInfoString; newField.ChildField = tempFieldInfo.ChildField; newField.ChildFieldString = tempFieldInfo.ChildFieldString; newTableFieldNames.Add(newField.FieldName); newTableInfo.AddField(newField); } } tempMergeTable2.Append(tableInfoTemp.ExcelName); } List <FieldInfo> listFieldInfoTemp2 = newTableInfo.GetAllFieldInfo(); //移除各字段中ChildField字段的数据 foreach (FieldInfo tempFieldInfo in listFieldInfoTemp2) { if (tempFieldInfo.ChildField == null) { continue; } foreach (FieldInfo ChildFieldInfo1 in tempFieldInfo.ChildField) { if (ChildFieldInfo1.ChildField == null) { ChildFieldInfo1.Data = null; continue; } else { foreach (FieldInfo ChildFieldInfo2 in tempFieldInfo.ChildField) { if (ChildFieldInfo2.ChildField == null) { ChildFieldInfo2.Data = null; continue; } else { foreach (FieldInfo ChildFieldInfo3 in tempFieldInfo.ChildField) { if (ChildFieldInfo3.ChildField == null) { ChildFieldInfo3.Data = null; continue; } else { foreach (FieldInfo ChildFieldInfo4 in tempFieldInfo.ChildField) { if (ChildFieldInfo4.ChildField == null) { ChildFieldInfo4.Data = null; continue; } else { foreach (FieldInfo ChildFieldInfo5 in tempFieldInfo.ChildField) { if (ChildFieldInfo5.ChildField == null) { ChildFieldInfo5.Data = null; continue; } else { //暂时只支持5层ChildField,后续再考虑递归 } } } } } } } } } } } //合并其他字段数据,遍历新表所有字段 foreach (FieldInfo tempFieldInfo in listFieldInfoTemp2) { FieldInfo fieldA = tempFieldInfo; //如果是主键就跳过 if (fieldA.FieldName.Equals(newPrimaryKeyField.FieldName)) { continue; } FieldInfo fieldB; FieldInfo FieldReturn = new FieldInfo(); foreach (TableInfo tableInfoTemp in tableInfoList) //遍历所有待合并表 { if (tableInfoTemp.IsContainField(fieldA.FieldName)) //如果存在字段就获取到该字段 { fieldB = tableInfoTemp.GetFieldInfoByFieldName(fieldA.FieldName); } else { fieldB = new FieldInfo(); fieldB.Data = null; } fieldA = FieldInfo.AddDataByOtherField(fieldA, fieldB, tableInfoTemp.GetKeyColumnFieldInfo().Data.Count, 0, out errorString); } //newTableInfo.AddField(fieldA); } return(newTableInfo); }
/// <summary> /// 用于int、long、float、string、date或time型取值不允许为指定集合值中的一个的检查 /// </summary> public static bool CheckIllegal(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { List <object> repeatedSetValue = null; List <int> errorDataIndex = null; string setValueDefineString = checkRule.CheckRuleString.Substring(1).Trim(); _GetValueIsInSet(fieldInfo.Data, fieldInfo.DataType, setValueDefineString, false, out repeatedSetValue, out errorDataIndex, out errorString); if (errorString == null) { if (repeatedSetValue.Count > 0) { foreach (object setValue in repeatedSetValue) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String) { Utils.LogWarning(string.Format("警告:字段{0}(列号:{1})的非法值检查规则定义中,出现了相同的非法值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, Utils.GetExcelColumnName(fieldInfo.ColumnSeq + 1), setValue)); } else if (fieldInfo.DataType == DataType.Date) { DateTime dataTimeSetValue = (DateTime)setValue; Utils.LogWarning(string.Format("警告:字段{0}(列号:{1})的非法值检查规则定义中,出现了相同的非法值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, Utils.GetExcelColumnName(fieldInfo.ColumnSeq + 1), dataTimeSetValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT))); } else if (fieldInfo.DataType == DataType.Time) { DateTime dataTimeSetValue = (DateTime)setValue; Utils.LogWarning(string.Format("警告:字段{0}(列号:{1})的非法值检查规则定义中,出现了相同的非法值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, Utils.GetExcelColumnName(fieldInfo.ColumnSeq + 1), dataTimeSetValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT))); } } } if (errorDataIndex.Count > 0) { StringBuilder illegalValueInfo = new StringBuilder(); foreach (int dataIndex in errorDataIndex) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String) { illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"属于非法取值中的一个\n", dataIndex + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldInfo.Data[dataIndex]); } else if (fieldInfo.DataType == DataType.Date) { DateTime dataTimeValue = (DateTime)fieldInfo.Data[dataIndex]; illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"属于非法取值中的一个\n", dataIndex + AppValues.DATA_FIELD_DATA_START_INDEX + 1, dataTimeValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT)); } else if (fieldInfo.DataType == DataType.Time) { DateTime dataTimeValue = (DateTime)fieldInfo.Data[dataIndex]; illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"属于非法取值中的一个\n", dataIndex + AppValues.DATA_FIELD_DATA_START_INDEX + 1, dataTimeValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT)); } } errorString = illegalValueInfo.ToString(); return(false); } else { return(true); } } else { errorString = errorString + "\n"; return(false); } }
/// <summary> /// 用于string型按指定格式解析后,取值必须在另一字段(可能还是这张表格也可能跨表)中有对应值的检查 /// ref2:table[entry_dungeon_drop.drop_id](split{1;x;y;z}(;))(except{0}) /// </summary> /// <param name="fieldInfo">字段信息</param> /// <param name="checkRule">检查信息</param> /// <param name="errorString">错误信息</param> /// <returns></returns> public static bool CheckRefStr(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { int IDPosition = 0; bool DataTypeString = true; // 首先要求字段类型只能为int、long、float或string型 if (!(fieldInfo.DataType == DataType.String)) { errorString = string.Format("值引用检查规则只适用于string类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } else { string tableName; string fieldIndexDefine; // 解析ref2规则中目标列所在表格以及字段名 const string START_STRING = "refStr:"; if (!checkRule.CheckRuleString.StartsWith(START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("值引用检查规则声明错误test,必须以\"{0}\"开头,后面跟表格名-字段名test\n", START_STRING); return(false); } else { string temp = checkRule.CheckRuleString.Substring(START_STRING.Length).Trim();//去掉前面的fef2:字符 if (string.IsNullOrEmpty(temp)) { errorString = string.Format("值引用检查规则声明错误,\"{0}\"的后面必须跟表格名-字段名\n", START_STRING); return(false); } else { // 判断是否在最后以(except{xx,xx})的格式声明无需ref2规则检查的特殊值 List <object> exceptValues = new List <object>(); int leftBracketIndex = temp.LastIndexOf("(except"); int rightBracketIndex = temp.LastIndexOf(')'); if (leftBracketIndex != -1 && rightBracketIndex > leftBracketIndex) { // 取出括号中的排除值声明 const string EXCEPT_DEFINE_START_STRING = "except"; string exceptDefineString = temp.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1).Trim();//提取except括号内的声明内容 if (!exceptDefineString.StartsWith(EXCEPT_DEFINE_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("值引用检查规则声明错误,若要声明ref检查所忽略的特殊值,需在最后以(except{xx,xx})的形式声明,而你在括号中声明为\"{0}\"\n", exceptDefineString); return(false); } else { // 检查排除值的声明(即有效值声明格式)是否合法 string exceptValuesDefine = exceptDefineString.Substring(EXCEPT_DEFINE_START_STRING.Length).Trim(); exceptValues = Utils.GetEffectiveValue(exceptValuesDefine, fieldInfo.DataType, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,排除值的声明非法,{0}\n", errorString); return(false); } // 将定义字符串去掉except声明部分 temp = temp.Substring(0, leftBracketIndex).Trim(); } } // 判断是否在最后以(split{1;x;y;z}(;))的格式声明无需refStr规则检查的特殊值 List <object> splitValues = new List <object>(); int splitleftBracketIndex = temp.IndexOf("(split"); int splitrightBracketIndex = temp.LastIndexOf(')'); if (splitleftBracketIndex != -1 && splitrightBracketIndex > splitleftBracketIndex) { // 取出括号中的排除值声明 const string SPLIT_DEFINE_START_STRING = "split"; string splitDefineString = temp.Substring(splitleftBracketIndex + 1, splitrightBracketIndex - splitleftBracketIndex - 1).Trim();//提取split括号内的声明内容 if (!splitDefineString.StartsWith(SPLIT_DEFINE_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("值引用检查规则声明错误,若要声明refStr检查所忽略的特殊值,需以(split{1;x;y;z}(;))的形式声明,而你在括号中声明为\"{0}\"\n", splitDefineString); return(false); } else { // 检查排除值的声明(即有效值声明格式)是否合法 string splitValuesDefine = splitDefineString.Substring(SPLIT_DEFINE_START_STRING.Length).Trim(); splitValues = Utils.GetEffectiveValue(splitValuesDefine, fieldInfo.DataType, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,排除值的声明非法,{0}\n", errorString); return(false); } if (splitValues.Count < 2) { errorString = string.Format("值引用检查规则声明错误,split{1;x;y;z}内至少包含2个元素,而你在括号中声明为\"{0}\"\n", splitDefineString); return(false); } try { IDPosition = int.Parse(splitValues[0].ToString()); } catch { errorString = string.Format("值引用检查规则声明错误,split{1;x;y;z}中第1个元素必须为正整数,而你在括号中声明为\"{0}\"\n", splitDefineString); return(false); } if (IDPosition == 0) { errorString = string.Format("值引用检查规则声明错误,split{1;x;y;z}中第1个元素必须为正整数,不能为0,而你在括号中声明为\"{0}\"\n", splitDefineString); return(false); } // 将定义字符串去掉except声明部分 temp = temp.Substring(0, splitleftBracketIndex).Trim(); } } FieldInfo targetFieldInfo = null; const string START_STRING2 = "table["; int rightBracketIndex2 = temp.LastIndexOf(']'); if (temp.StartsWith(START_STRING2, StringComparison.CurrentCultureIgnoreCase)) //如果是以 refStr:table开头则 { temp = temp.Substring(START_STRING2.Length, rightBracketIndex2 - 6).Trim(); //提交[]内的表名和字段 if (string.IsNullOrEmpty(temp)) { errorString = string.Format("值引用检查规则声明错误,\"{0}\"的后面必须跟[表格名.字段名,表格名.字段名]\n", START_STRING2); return(false); } //检查表名和字段 string[] values = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < values.Length; ++i) { string tempNameField = values[i].Trim(); // 解析参考表名、列名声明 targetFieldInfo = null; int hyphenIndex = tempNameField.LastIndexOf('.'); if (hyphenIndex == -1) { tableName = tempNameField; fieldIndexDefine = null; } else { tableName = tempNameField.Substring(0, hyphenIndex).Trim(); fieldIndexDefine = tempNameField.Substring(hyphenIndex + 1, tempNameField.Length - hyphenIndex - 1); } if (!AppValues.TableInfo.ContainsKey(tableName)) { errorString = string.Format("值引用检查规则声明错误,找不到名为 {0} 的表格\n", tableName); return(false); } if (string.IsNullOrEmpty(fieldIndexDefine)) { targetFieldInfo = AppValues.TableInfo[tableName].GetKeyColumnFieldInfo(); } else { TableInfo targetTableInfo = AppValues.TableInfo[tableName]; targetFieldInfo = GetFieldByIndexDefineString(fieldIndexDefine, targetTableInfo, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中无法根据索引字符串\"{1}\"找到要参考的字段,错误信息为:{2}\n", tableName, fieldIndexDefine, errorString); return(false); } } // 检查目标字段必须为相同的数据类型 if (targetFieldInfo.DataType == DataType.Int) { DataTypeString = false; //errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中通过索引字符串\"{1}\"找到的参考字段的数据类型为{2},而要检查字段的数据类型为{3},无法进行不同数据类型字段的引用检查\n", tableName, fieldIndexDefine, targetFieldInfo.DataType.ToString(), fieldInfo.DataType.ToString()); //return false; } } Dictionary <string, object> unreferencedInfo = new Dictionary <string, object>(); for (int j = 0; j < values.Length; ++j) { string tempNameField = values[j].Trim(); // 解析参考表名、列名声明 targetFieldInfo = null; int hyphenIndex = tempNameField.LastIndexOf('.'); if (hyphenIndex == -1) { tableName = tempNameField; fieldIndexDefine = null; } else { tableName = tempNameField.Substring(0, hyphenIndex).Trim(); fieldIndexDefine = tempNameField.Substring(hyphenIndex + 1, tempNameField.Length - hyphenIndex - 1); } if (string.IsNullOrEmpty(fieldIndexDefine)) { targetFieldInfo = AppValues.TableInfo[tableName].GetKeyColumnFieldInfo(); } else { TableInfo targetTableInfo = AppValues.TableInfo[tableName]; targetFieldInfo = GetFieldByIndexDefineString(fieldIndexDefine, targetTableInfo, out errorString); } List <object> targetFieldData = targetFieldInfo.Data; // 存储找不到引用对应关系的数据信息(key:行号, value:填写的数据) Dictionary <string, object> tempunreferencedInfo = new Dictionary <string, object>(); if (DataTypeString == false) { string FirstSplit = splitValues[1].ToString();//第一分隔符 string SecondSplit = null; for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值以及空字符串 if (fieldInfo.Data[i] == null || string.IsNullOrEmpty(fieldInfo.Data[i].ToString())) { continue; } // 忽略不进行ref检查的排除值 else if (exceptValues.Contains(fieldInfo.Data[i])) { continue; } string[] FirstSplitData = null;//使用第一分隔符,获得的数组 int z = 0; int splitDataInt = 0; switch (splitValues.Count) { case 2: FirstSplitData = fieldInfo.Data[i].ToString().Split(FirstSplit[0]); foreach (string splitData in FirstSplitData) { z++; if (splitData == null) { tempunreferencedInfo.Add(i + "_" + z.ToString(), splitDataInt); continue; } try { splitDataInt = int.Parse(splitData); } catch { tempunreferencedInfo.Add(i + "_" + z.ToString(), splitData); continue; } if (!targetFieldData.Contains(splitDataInt)) { tempunreferencedInfo.Add(i + "_" + z.ToString(), splitDataInt); } } break; case 3: FirstSplitData = fieldInfo.Data[i].ToString().Split(FirstSplit[0]); SecondSplit = splitValues[2].ToString(); foreach (string splitData in FirstSplitData) { z++; if (splitData == null) { tempunreferencedInfo.Add(i + "_" + z.ToString(), splitDataInt); continue; } string[] SecondSplitData = splitData.Split(SecondSplit[0]); if (SecondSplitData.Length < IDPosition - 1) { tempunreferencedInfo.Add(i + "_" + z.ToString(), SecondSplitData.ToString()); continue; } try { splitDataInt = int.Parse(SecondSplitData[IDPosition - 1].ToString()); } catch { tempunreferencedInfo.Add(i + "_" + z.ToString(), SecondSplitData[IDPosition - 1].ToString()); continue; } if (!targetFieldData.Contains(splitDataInt)) { tempunreferencedInfo.Add(i + "_" + z.ToString(), splitDataInt); } } break; default: break; } } } if (tempunreferencedInfo.Count == 0) { break; } if (unreferencedInfo.Count > 0) { List <string> tempList = new List <string>(); foreach (KeyValuePair <string, object> kvp in unreferencedInfo) { if (tempunreferencedInfo.ContainsKey(kvp.Key)) { //存在处理 } else { tempList.Add(kvp.Key); } } foreach (string k in tempList) { unreferencedInfo.Remove(k);//不存在就移除 } } else { if (tempunreferencedInfo.Count > 0) { foreach (KeyValuePair <string, object> kvp in tempunreferencedInfo) { unreferencedInfo.Add(kvp.Key, kvp.Value); } } } } if (unreferencedInfo.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); errorStringBuild.AppendLine("存在以下未找到引用关系的数据行:"); foreach (var item in unreferencedInfo) { string[] item2 = item.Key.ToString().Split('_'); int irow = int.Parse(item2[0]) + AppValues.DATA_FIELD_DATA_START_INDEX + 1; errorStringBuild.AppendFormat("第{0}行第{1}组数据\"{2}\"在对应参考列不存在\n", irow.ToString(), item2[1], item.Value); } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } } errorString = null; return(true); } } } }
/// <summary> /// 获取有效值声明{1,5,10}或数值范围声明[1,5]中符合要求的值集合(有效值声明支持int、float、string型,数值范围声明仅支持int型) /// </summary> public static List <object> GetEffectiveValue(string inputDefineString, DataType dataType, out string errorString) { if (string.IsNullOrEmpty(inputDefineString)) { errorString = "未声明获取值集合的规则"; return(null); } List <object> result = new List <object>(); string defineString = inputDefineString.Trim(); List <FieldCheckRule> fieldCheckRules = TableCheckHelper.GetCheckRules(defineString, out errorString); if (errorString != null) { errorString = "获取值集合规则声明错误," + errorString; return(null); } if (fieldCheckRules.Count > 1) { errorString = "获取值集合规则声明错误,仅支持从一个有效值声明或数值范围声明中取符合要求的值集合,不支持用&&组合的规则"; return(null); } FieldCheckRule checkRule = fieldCheckRules[0]; switch (checkRule.CheckType) { case TableCheckType.Effective: { if (dataType == DataType.Int || dataType == DataType.Float) { // 去除首尾花括号后,通过英文逗号分隔每个有效值即可 if (!(checkRule.CheckRuleString.StartsWith("{") && checkRule.CheckRuleString.EndsWith("}"))) { errorString = "获取值集合规则所采用的值有效性声明错误:必须在首尾用一对花括号包裹整个定义内容"; return(null); } string temp = checkRule.CheckRuleString.Substring(1, checkRule.CheckRuleString.Length - 2).Trim(); if (string.IsNullOrEmpty(temp)) { errorString = "获取值集合规则所采用的值有效性声明错误:至少需要输入一个有效值"; return(null); } string[] values = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (dataType == DataType.Int) { for (int i = 0; i < values.Length; ++i) { string oneValueString = values[i].Trim(); int oneValue; if (int.TryParse(oneValueString, out oneValue) == true) { if (result.Contains(oneValue)) { Utils.LogWarning(string.Format("警告:获取值集合规则所采用的值有效性声明(\"{0}\")中,出现了相同的有效值\"{1}\",本工具忽略此问题,需要你之后修正错误\n", checkRule.CheckRuleString, oneValue)); } else { result.Add(oneValue); } } else { errorString = string.Format("获取值集合规则所采用的值有效性声明错误:出现了非int型有效值定义,其为\"{0}\"", oneValueString); return(null); } } } else { for (int i = 0; i < values.Length; ++i) { string oneValueString = values[i].Trim(); float oneValue; if (float.TryParse(oneValueString, out oneValue) == true) { if (result.Contains(oneValue)) { Utils.LogWarning(string.Format("警告:获取值集合规则所采用的值有效性声明(\"{0}\")中,出现了相同的有效值\"{1}\",本工具忽略此问题,需要你之后修正错误\n", checkRule.CheckRuleString, oneValue)); } else { result.Add(oneValue); } } else { errorString = string.Format("获取值集合规则所采用的值有效性声明错误:出现了非float型有效值定义,其为\"{0}\"", oneValueString); return(null); } } } } else if (dataType == DataType.String) { // 用于分隔有效值声明的字符,默认为英文逗号 char separator = ','; // 去除首尾花括号后整个有效值声明内容 string effectiveDefineString = checkRule.CheckRuleString; // 右边花括号的位置 int rightBraceIndex = checkRule.CheckRuleString.LastIndexOf('}'); if (rightBraceIndex == -1) { errorString = "获取值集合规则所采用的string型值有效性声明错误:必须用一对花括号包裹整个定义内容"; return(null); } // 如果声明了分隔有效值的字符 if (rightBraceIndex != checkRule.CheckRuleString.Length - 1) { int leftBracketIndex = checkRule.CheckRuleString.LastIndexOf('('); int rightBracketIndex = checkRule.CheckRuleString.LastIndexOf(')'); if (leftBracketIndex < rightBraceIndex || rightBracketIndex < leftBracketIndex) { errorString = "获取值集合规则所采用的string型值有效性声明错误:需要在最后面的括号中声明分隔各个有效值的一个字符,如果使用默认的英文逗号作为分隔符,则不必在最后面用括号声明自定义分隔字符"; return(null); } string separatorString = checkRule.CheckRuleString.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1); if (separatorString.Length > 1) { errorString = string.Format("获取值集合规则所采用的string型值有效性声明错误:自定义有效值的分隔字符只能为一个字符,而你输入的为\"{0}\"", separatorString); return(null); } separator = separatorString[0]; // 取得前面用花括号包裹的有效值声明 effectiveDefineString = checkRule.CheckRuleString.Substring(0, rightBraceIndex + 1).Trim(); } // 去除花括号 effectiveDefineString = effectiveDefineString.Substring(1, effectiveDefineString.Length - 2); if (string.IsNullOrEmpty(effectiveDefineString)) { errorString = "获取值集合规则所采用的string型值有效性声明错误:至少需要输入一个有效值"; return(null); } string[] effectiveValueDefine = effectiveDefineString.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries); if (effectiveValueDefine.Length == 0) { errorString = "获取值集合规则所采用的string型值有效性声明错误:至少需要输入一个有效值"; return(null); } foreach (string effectiveValue in effectiveValueDefine) { if (result.Contains(effectiveValue)) { Utils.LogWarning(string.Format("警告:获取值集合规则所采用的string型值有效性声明(\"{0}\")中,出现了相同的有效值\"{1}\",本工具忽略此问题,需要你之后修正错误\n", checkRule.CheckRuleString, effectiveValue)); } else { result.Add(effectiveValue); } } } else { errorString = string.Format("获取值集合规则所采用的值有效性声明只能用于int、float或string型的字段,而该字段为{0}型", dataType); return(null); } break; } case TableCheckType.Range: { if (dataType == DataType.Int) { bool isIncludeFloor; bool isIncludeCeil; int floorValue = 0; int ceilValue = 0; // 规则首位必须为方括号或者圆括号 if (checkRule.CheckRuleString.StartsWith("(")) { isIncludeFloor = false; } else if (checkRule.CheckRuleString.StartsWith("[")) { isIncludeFloor = true; } else { errorString = "获取值集合规则所采用的数值范围声明错误:必须用英文(或[开头,表示有效范围是否包含等于下限的情况"; return(null); } // 规则末位必须为方括号或者圆括号 if (checkRule.CheckRuleString.EndsWith(")")) { isIncludeCeil = false; } else if (checkRule.CheckRuleString.EndsWith("]")) { isIncludeCeil = true; } else { errorString = "获取值集合规则所采用的数值范围声明错误,采用的数值范围声明错误:必须用英文)或]结尾,表示有效范围是否包含等于上限的情况"; return(null); } // 去掉首尾的括号 string temp = checkRule.CheckRuleString.Substring(1, checkRule.CheckRuleString.Length - 2); // 通过英文逗号分隔上下限 string[] floorAndCeilString = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (floorAndCeilString.Length != 2) { errorString = "获取值集合规则所采用的数值范围声明错误:必须用英文逗号分隔值范围的上下限"; return(null); } string floorString = floorAndCeilString[0].Trim(); string ceilString = floorAndCeilString[1].Trim(); // 提取上下限数值 if (int.TryParse(ceilString, out ceilValue) == false) { errorString = string.Format("获取值集合规则所采用的数值范围声明错误:上限不是合法的数字,你输入的为{0}", ceilString); return(null); } if (int.TryParse(floorString, out floorValue) == false) { errorString = string.Format("获取值集合规则所采用的数值范围声明错误:下限不是合法的数字,你输入的为{0}", floorString); return(null); } // 判断上限是否大于下限 if (floorValue >= ceilValue) { errorString = string.Format("获取值集合规则所采用的数值范围声明错误:上限值必须大于下限值,你输入的下限为{0},上限为{1}", floorValue, ceilString); return(null); } if (!isIncludeFloor) { ++floorValue; } if (!isIncludeCeil) { --ceilValue; } for (int i = floorValue; i <= ceilValue; ++i) { result.Add(i); } } else { errorString = string.Format("获取值集合规则所采用的数值范围声明只能用于int型的字段,而该字段为{0}型", dataType); return(null); } break; } default: { errorString = "获取值集合规则声明错误,仅支持从一个有效值声明或数值范围声明中取符合要求的值集合"; break; } } if (errorString == null) { return(result); } else { return(null); } }
public static TableInfo AnalyzeTable(DataTable dt, string filePath, out string errorString) { if (dt.Rows.Count < ExcelTableSetting.DataFieldDataStartRowIndex) { errorString = "表格格式不符合要求,必须在表格前五行中依次声明字段描述、字段名、数据类型、检查规则、导出到MySQL数据库中的配置"; return(null); } if (dt.Columns.Count < 2) { errorString = "表格中至少需要配置2个字段"; return(null); } TableInfo tableInfo = new TableInfo(); tableInfo.ExcelFilePath = filePath; tableInfo.ExcelName = Path.GetFileNameWithoutExtension(filePath); tableInfo.TableName = ExcelMethods.GetTableName(tableInfo.ExcelName, "-", ExcelFolder.TheLanguage); string tableName = tableInfo.ExcelName; string temps = Path.GetDirectoryName(filePath); int tempi = temps.LastIndexOf(@"\"); string temps2 = temps.Substring(tempi, temps.Length - tempi); tableInfo.ExcelDirectory = temps2.Substring(1); // 当前解析到的列号 int curColumnIndex = 0; // 解析第一列(主键列,要求数据类型为int、long或string且数据非空、唯一) DataType primaryKeyColumnType = _AnalyzeDataType(dt.Rows[ExcelTableSetting.DataFieldDataTypeRowIndex][0].ToString().Trim()); if (!(primaryKeyColumnType == DataType.Int || primaryKeyColumnType == DataType.Long || primaryKeyColumnType == DataType.String)) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "主键列的类型只能为int、long或string"; return(null); } else { // 解析出主键列,然后检查是否非空、唯一,如果是string型主键还要检查是否符合变量名的规范(只能由英文字母、数字、下划线组成) FieldInfo primaryKeyField = _AnalyzeOneField(dt, tableInfo, 0, null, out curColumnIndex, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "主键列解析错误\n" + errorString; return(null); } // 主键列字段名不允许为空 else if (primaryKeyField == null)//else if (primaryKeyField.IsIgnoreClientExport == true) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "主键列必须指定字段名\n" + errorString; return(null); } else { // 唯一性检查 FieldCheckRule uniqueCheckRule = new FieldCheckRule(); uniqueCheckRule.CheckType = TableCheckType.Unique; uniqueCheckRule.CheckRuleString = "unique"; TableCheckHelper.CheckUnique(primaryKeyField, uniqueCheckRule, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "主键列存在重复错误\n" + errorString; return(null); } // string型主键检查是否符合变量名的规范 if (primaryKeyColumnType == DataType.String) { StringBuilder errorStringBuilder = new StringBuilder(); for (int row = 0; row < primaryKeyField.Data.Count; ++row) { string tempError = null; TableCheckHelper.CheckFieldName(primaryKeyField.Data[row].ToString(), out tempError); if (tempError != null) { errorStringBuilder.AppendFormat("第{0}行所填主键{1}\n", row + ExcelTableSetting.DataFieldDataStartRowIndex + 1, tempError); } } if (!string.IsNullOrEmpty(errorStringBuilder.ToString())) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "string型主键列存在非法数据\n" + errorStringBuilder.ToString(); return(null); } } // 非空检查(因为string型检查是否符合变量名规范时以及未声明数值型字段中允许空时,均已对主键列进行过非空检查,这里只需对数据值字段且声明数值型字段中允许空的情况下进行非空检查) if (ExcelFolder.IsAllowedNullNumber == true && (primaryKeyColumnType == DataType.Int || primaryKeyColumnType == DataType.Long)) { FieldCheckRule notEmptyCheckRule = new FieldCheckRule(); uniqueCheckRule.CheckType = TableCheckType.NotEmpty; uniqueCheckRule.CheckRuleString = "notEmpty"; TableCheckHelper.CheckNotEmpty(primaryKeyField, notEmptyCheckRule, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, 0) + "主键列存在非空错误\n" + errorString; return(null); } } tableInfo.AddField(primaryKeyField); } } // 存储定义过的字段名,不允许有同名字段assddds(key:字段名, value:列号) Dictionary <string, int> clientFieldNames = new Dictionary <string, int>(); //Dictionary<string, int> serverFieldNames = new Dictionary<string, int>(); // 先加入主键列 clientFieldNames.Add(tableInfo.GetKeyColumnFieldInfo().FieldName, 0); // if(tableInfo.GetKeyColumnFieldInfo().DatabaseFieldName!=null) // serverFieldNames.Add(tableInfo.GetKeyColumnFieldInfo().DatabaseFieldName, 0); // 解析剩余的列 while (curColumnIndex < dt.Columns.Count) { int nextColumnIndex = curColumnIndex; FieldInfo oneField = _AnalyzeOneField(dt, tableInfo, nextColumnIndex, null, out curColumnIndex, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, nextColumnIndex) + errorString; return(null); } else { // 跳过未声明变量名以及数据库导出信息的无效列 if (oneField != null) { // 检查字段名是否重复 if (clientFieldNames.ContainsKey(oneField.FieldName)) { errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, nextColumnIndex) + string.Format("表格中存在字段名同为{0}的字段,分别位于第{1}列和第{2}列", oneField.FieldName, ExcelMethods.GetExcelColumnName(clientFieldNames[oneField.FieldName] + 1), ExcelMethods.GetExcelColumnName(oneField.ColumnSeq + 1)); return(null); } else { tableInfo.AddField(oneField); clientFieldNames.Add(oneField.FieldName, oneField.ColumnSeq); } // 检查字段名是否重复 //if (serverFieldNames.ContainsKey(oneField.DatabaseFieldName)) //{ // errorString = _GetTableAnalyzeErrorString(tableName, dt.TableName, nextColumnIndex) + string.Format("表格中存在字段名同为{0}的字段,分别位于第{1}列和第{2}列", oneField.DatabaseFieldName, ExcelMethods.GetExcelColumnName(serverFieldNames[oneField.DatabaseFieldName] + 1), ExcelMethods.GetExcelColumnName(oneField.ColumnSeq + 1)); // return null; //} //else // { // tableInfo.AddField(oneField); // serverFieldNames.Add(oneField.DatabaseFieldName, oneField.ColumnSeq); // } } } } errorString = null; return(tableInfo); }
/// <summary> /// 用于int、long、float或string型取值必须在另一字段(可能还是这张表格也可能跨表)中有对应值的检查 /// </summary> public static bool CheckRef(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { string temp = null; List <object> exceptValues = new List <object>(); string tableName; string fieldIndexDefine; FieldInfo targetFieldInfo = null; // 首先要求字段类型只能为int、long、float或string型 if (!(fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String)) { errorString = string.Format("值引用检查规则只适用于int、long、float或string类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } else { // 解析ref规则中目标列所在表格以及字段名 const string START_STRING = "ref:"; if (!checkRule.CheckRuleString.StartsWith(START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("值引用检查规则声明错误,必须以\"{0}\"开头,后面跟表格名-字段名\n", START_STRING); return(false); } else { temp = checkRule.CheckRuleString.Substring(START_STRING.Length).Trim();//去掉前面的fef:字符 if (string.IsNullOrEmpty(temp)) { errorString = string.Format("值引用检查规则声明错误,\"{0}\"的后面必须跟表格名-字段名\n", START_STRING); return(false); } else { // 判断是否在最后以(except{xx,xx})的格式声明无需ref规则检查的特殊值 // List<object> exceptValues = new List<object>(); int leftBracketIndex = temp.IndexOf('('); int rightBracketIndex = temp.LastIndexOf(')'); if (leftBracketIndex != -1 && rightBracketIndex > leftBracketIndex) { // 取出括号中的排除值声明 const string EXCEPT_DEFINE_START_STRING = "except"; string exceptDefineString = temp.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1).Trim();//提取except括号内的声明内容 if (!exceptDefineString.StartsWith(EXCEPT_DEFINE_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("值引用检查规则声明错误,若要声明ref检查所忽略的特殊值,需在最后以(except{xx,xx})的形式声明,而你在括号中声明为\"{0}\"\n", exceptDefineString); return(false); } else { // 检查排除值的声明(即有效值声明格式)是否合法 string exceptValuesDefine = exceptDefineString.Substring(EXCEPT_DEFINE_START_STRING.Length).Trim(); exceptValues = Utils.GetEffectiveValue(exceptValuesDefine, fieldInfo.DataType, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,排除值的声明非法,{0}\n", errorString); return(false); } // 将定义字符串去掉except声明部分 temp = temp.Substring(0, leftBracketIndex).Trim(); } } // FieldInfo targetFieldInfo = null; #region 多表多字段情况 ref:table[entry_item.item_id,entry_item_weapon.weapon_id,entry_partner.entry_id](except{0}) const string START_STRING2 = "table["; int rightBracketIndex2 = temp.LastIndexOf(']'); if (temp.StartsWith(START_STRING2, StringComparison.CurrentCultureIgnoreCase)) //如果是以 ref:table开头则 { temp = temp.Substring(START_STRING2.Length, rightBracketIndex2 - 6).Trim(); //提交[]内的表名和字段 if (string.IsNullOrEmpty(temp)) { errorString = string.Format("值引用检查规则声明错误,\"{0}\"的后面必须跟[表格名.字段名,表格名.字段名]\n", START_STRING2); return(false); } //检查表名和字段 // FieldInfo targetFieldInfo2 = null; string[] values = temp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < values.Length; ++i) { string tempNameField = values[i].Trim(); // 解析参考表名、列名声明 targetFieldInfo = null; int hyphenIndex = tempNameField.LastIndexOf('.'); if (hyphenIndex == -1) { tableName = tempNameField; fieldIndexDefine = null; } else { tableName = tempNameField.Substring(0, hyphenIndex).Trim(); fieldIndexDefine = tempNameField.Substring(hyphenIndex + 1, tempNameField.Length - hyphenIndex - 1); } if (!AppValues.TableInfo.ContainsKey(tableName)) { errorString = string.Format("值引用检查规则声明错误,找不到名为 {0} 的表格\n", tableName); return(false); } if (string.IsNullOrEmpty(fieldIndexDefine)) { targetFieldInfo = AppValues.TableInfo[tableName].GetKeyColumnFieldInfo(); } else { TableInfo targetTableInfo = AppValues.TableInfo[tableName]; targetFieldInfo = GetFieldByIndexDefineString(fieldIndexDefine, targetTableInfo, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中无法根据索引字符串\"{1}\"找到要参考的字段,错误信息为:{2}\n", tableName, fieldIndexDefine, errorString); return(false); } } // 检查目标字段必须为相同的数据类型 if (fieldInfo.DataType != targetFieldInfo.DataType) { errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中通过索引字符串\"{1}\"找到的参考字段的数据类型为{2},而要检查字段的数据类型为{3},无法进行不同数据类型字段的引用检查\n", tableName, fieldIndexDefine, targetFieldInfo.DataType.ToString(), fieldInfo.DataType.ToString()); return(false); } } Dictionary <int, object> unreferencedInfo = new Dictionary <int, object>(); Dictionary <int, object> tempunreferencedInfo2 = new Dictionary <int, object>(); for (int j = 0; j < values.Length; ++j) { string tempNameField = values[j].Trim(); // 解析参考表名、列名声明 targetFieldInfo = null; int hyphenIndex = tempNameField.LastIndexOf('.'); if (hyphenIndex == -1) { tableName = tempNameField; fieldIndexDefine = null; } else { tableName = tempNameField.Substring(0, hyphenIndex).Trim(); fieldIndexDefine = tempNameField.Substring(hyphenIndex + 1, tempNameField.Length - hyphenIndex - 1); } if (string.IsNullOrEmpty(fieldIndexDefine)) { targetFieldInfo = AppValues.TableInfo[tableName].GetKeyColumnFieldInfo(); } else { TableInfo targetTableInfo = AppValues.TableInfo[tableName]; targetFieldInfo = GetFieldByIndexDefineString(fieldIndexDefine, targetTableInfo, out errorString); } List <object> targetFieldData = targetFieldInfo.Data; // 存储找不到引用对应关系的数据信息(key:行号, value:填写的数据) Dictionary <int, object> tempunreferencedInfo = new Dictionary <int, object>(); if (unreferencedInfo.Count == 0) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值或本身为空值 if (fieldInfo.Data[i] == null) { continue; } // 忽略不进行ref检查的排除值 else if (exceptValues.Contains(fieldInfo.Data[i])) { continue; } if (!targetFieldData.Contains(fieldInfo.Data[i])) { tempunreferencedInfo.Add(i, fieldInfo.Data[i]); } } } else if (fieldInfo.DataType == DataType.String) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值以及空字符串 if (fieldInfo.Data[i] == null || string.IsNullOrEmpty(fieldInfo.Data[i].ToString())) { continue; } // 忽略不进行ref检查的排除值 else if (exceptValues.Contains(fieldInfo.Data[i])) { continue; } if (!targetFieldData.Contains(fieldInfo.Data[i])) { tempunreferencedInfo.Add(i, fieldInfo.Data[i]); } } } if (tempunreferencedInfo.Count == 0) { break; } else { foreach (KeyValuePair <int, object> kvp in tempunreferencedInfo) { unreferencedInfo.Add(kvp.Key, kvp.Value); } continue; } } else { foreach (KeyValuePair <int, object> kvp in unreferencedInfo) { if (targetFieldData.Contains(kvp.Value)) { if (!tempunreferencedInfo2.ContainsKey(kvp.Key)) { tempunreferencedInfo2.Add(kvp.Key, kvp.Value); } } } } } if (tempunreferencedInfo2.Count > 0) { foreach (KeyValuePair <int, object> kvp in tempunreferencedInfo2) { if (unreferencedInfo.ContainsKey(kvp.Key)) { unreferencedInfo.Remove(kvp.Key); } } } if (unreferencedInfo.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); errorStringBuild.AppendLine("存在以下未找到引用关系的数据行:"); foreach (var item in unreferencedInfo) { errorStringBuild.AppendFormat("第{0}行数据\"{1}\"在对应参考列不存在\n", item.Key + AppValues.DATA_FIELD_DATA_START_INDEX + 1, item.Value); } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } } #endregion 多表多字段情况 ref:table[entry_item.item_id,entry_item_weapon.weapon_id,entry_partner.entry_id](except{0}) // 解析参考表名、列名声明 int hyphenIndex2 = temp.LastIndexOf('-'); if (hyphenIndex2 == -1) { tableName = temp; fieldIndexDefine = null; } else { tableName = temp.Substring(0, hyphenIndex2).Trim(); fieldIndexDefine = temp.Substring(hyphenIndex2 + 1, temp.Length - hyphenIndex2 - 1); } if (!AppValues.TableInfo.ContainsKey(tableName)) { errorString = string.Format("值引用检查规则声明错误,找不到名为{0}的表格\n", START_STRING); return(false); } if (string.IsNullOrEmpty(fieldIndexDefine)) { targetFieldInfo = AppValues.TableInfo[tableName].GetKeyColumnFieldInfo(); } else { TableInfo targetTableInfo = AppValues.TableInfo[tableName]; targetFieldInfo = GetFieldByIndexDefineString(fieldIndexDefine, targetTableInfo, out errorString); if (errorString != null) { errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中无法根据索引字符串\"{1}\"找到要参考的字段,错误信息为:{2}\n", tableName, fieldIndexDefine, errorString); return(false); } } // 检查目标字段必须为相同的数据类型 if (fieldInfo.DataType != targetFieldInfo.DataType) { errorString = string.Format("值引用检查规则声明错误,表格\"{0}\"中通过索引字符串\"{1}\"找到的参考字段的数据类型为{2},而要检查字段的数据类型为{3},无法进行不同数据类型字段的引用检查\n", tableName, fieldIndexDefine, targetFieldInfo.DataType.ToString(), fieldInfo.DataType.ToString()); return(false); } else { List <object> targetFieldData = targetFieldInfo.Data; // 存储找不到引用对应关系的数据信息(key:行号, value:填写的数据) Dictionary <int, object> unreferencedInfo = new Dictionary <int, object>(); if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float) { for (int i2 = 0; i2 < fieldInfo.Data.Count; ++i2) { // 忽略无效集合元素下属子类型的空值或本身为空值 if (fieldInfo.Data[i2] == null) { continue; } // 忽略不进行ref检查的排除值 else if (exceptValues.Contains(fieldInfo.Data[i2])) { continue; } if (!targetFieldData.Contains(fieldInfo.Data[i2])) { unreferencedInfo.Add(i2, fieldInfo.Data[i2]); } } } else if (fieldInfo.DataType == DataType.String) { for (int i3 = 0; i3 < fieldInfo.Data.Count; ++i3) { // 忽略无效集合元素下属子类型的空值以及空字符串 if (fieldInfo.Data[i3] == null || string.IsNullOrEmpty(fieldInfo.Data[i3].ToString())) { continue; } // 忽略不进行ref检查的排除值 else if (exceptValues.Contains(fieldInfo.Data[i3])) { continue; } if (!targetFieldData.Contains(fieldInfo.Data[i3])) { unreferencedInfo.Add(i3, fieldInfo.Data[i3]); } } } if (unreferencedInfo.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); errorStringBuild.AppendLine("存在以下未找到引用关系的数据行:"); foreach (var item in unreferencedInfo) { errorStringBuild.AppendFormat("第{0}行数据\"{1}\"在对应参考列不存在\n", item.Key + AppValues.DATA_FIELD_DATA_START_INDEX + 1, item.Value); } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } } } } } }
/// <summary> /// 解析一条表格检查规则 /// 注意:要把config配置的规则彻底解析为TABLE_CHECK_TYPE定义的基本的检查规则,故要考虑如果是config配置的规则中继续嵌套config配置规则的情况 /// </summary> private static List <FieldCheckRule> _GetOneCheckRule(string ruleString, out string errorString) { List <FieldCheckRule> oneCheckRule = new List <FieldCheckRule>(); errorString = null; if (ruleString.StartsWith("notEmpty", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.NotEmpty; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("unique", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Unique; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("sum", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.CheckSum; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("refStr", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.RefStr; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("ref", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Ref; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("mapString", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.MapString; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("jsonString", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.JsonString; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith(">") || ruleString.StartsWith(">=")) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.GreaterThan; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("func", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Func; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("file2", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.File2; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("file", StringComparison.CurrentCultureIgnoreCase)) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.File; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("$")) { // 到config文件中找到对应的检查规则 if (AppValues.ConfigData.ContainsKey(ruleString)) { string configRuleString = AppValues.ConfigData[ruleString]; // 不同检查规则通过&&分隔 string[] ruleStringInConfigRule = configRuleString.Split(new string[] { "&&" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < ruleStringInConfigRule.Length; ++i) { string oneRule = ruleStringInConfigRule[i].Trim(); if (oneRule.Equals(string.Empty)) { continue; } // 递归调用自身,解析config中配置的检查规则 List <FieldCheckRule> configCheckRules = _GetOneCheckRule(oneRule, out errorString); if (errorString != null) { errorString = string.Format("config文件中名为\"{0}\"的配置\"{1}\"有误:", ruleString, configRuleString) + errorString; return(null); } else { oneCheckRule.AddRange(configCheckRules); } } } else { errorString = string.Format("config文件中找不到名为\"{0}\"的检查规则配置", ruleString); return(null); } } else if (ruleString.StartsWith("!") && ruleString.IndexOf("{") > 0) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Illegal; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("{")) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Effective; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else if (ruleString.StartsWith("(") || ruleString.StartsWith("[")) { FieldCheckRule checkRule = new FieldCheckRule(); checkRule.CheckType = TableCheckType.Range; checkRule.CheckRuleString = ruleString; oneCheckRule.Add(checkRule); } else { errorString = "未知的检查规则"; return(null); } return(oneCheckRule); }
public static bool CheckItemIDBate(TableInfo tableInfo, int num, out string errorString) { // 获取检查涉及的字段数据 const string itemIdName = "id"; const string itemMainTypeName = "main_type"; const string itemSubTypeName = "sub_type"; const string itemColorName = "color"; const string itemLvlName = "item_lvl"; const string itemTypeName = "type"; List <object> itemIdValueList = null; List <object> itemMainTypeValueList = null; List <object> itemSubTypeValueList = null; List <object> itemColorValueList = null; List <object> itemLvlValueList = null; List <object> itemTypeValueList = null; //获取字段内容 if (tableInfo.GetFieldInfoByFieldName(itemIdName) != null) { itemIdValueList = tableInfo.GetFieldInfoByFieldName(itemIdName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemIdName); return(false); } if (tableInfo.GetFieldInfoByFieldName(itemMainTypeName) != null) { itemMainTypeValueList = tableInfo.GetFieldInfoByFieldName(itemMainTypeName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemMainTypeName); return(false); } if (tableInfo.GetFieldInfoByFieldName(itemSubTypeName) != null) { itemSubTypeValueList = tableInfo.GetFieldInfoByFieldName(itemSubTypeName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemSubTypeName); return(false); } if (tableInfo.GetFieldInfoByFieldName(itemColorName) != null) { itemColorValueList = tableInfo.GetFieldInfoByFieldName(itemColorName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemColorName); return(false); } if (tableInfo.GetFieldInfoByFieldName(itemLvlName) != null) { itemLvlValueList = tableInfo.GetFieldInfoByFieldName(itemLvlName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemLvlName); return(false); } if (tableInfo.GetFieldInfoByFieldName(itemTypeName) != null) { itemTypeValueList = tableInfo.GetFieldInfoByFieldName(itemTypeName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfo.TableName, itemTypeName); return(false); } //先对以上字段非空检查 if (ExcelFolder.IsAllowedNullNumber == true) { FieldCheckRule numberNotEmptyCheckRule = new FieldCheckRule(); numberNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; numberNotEmptyCheckRule.CheckRuleString = "notEmpty"; TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(itemMainTypeName), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("{0}表中{1}字段中{2}\n", tableInfo.TableName, itemMainTypeName, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(itemSubTypeName), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("{0}表中{1}字段中{2}\n", tableInfo.TableName, itemSubTypeName, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(itemColorName), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("{0}表中{1}字段中{2}\n", tableInfo.TableName, itemColorName, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(itemLvlName), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("{0}表中{1}字段中{2}\n", tableInfo.TableName, itemLvlName, errorString); return(false); } TableCheckHelper.CheckNotEmpty(tableInfo.GetFieldInfoByFieldName(itemTypeName), numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("{0}表中{1}字段中{2}\n", tableInfo.TableName, itemTypeName, errorString); return(false); } } //resources-资源表 const string resourcesTableName = "resources"; const string resourcesIDName = "id"; TableInfo tableInfoCheckResources = null; List <object> ResourcesIdValueList = null; if (AppValues.TableInfo.ContainsKey(resourcesTableName)) { tableInfoCheckResources = AppValues.TableInfo[resourcesTableName]; if (tableInfoCheckResources.GetFieldInfoByFieldName(resourcesIDName) != null) { ResourcesIdValueList = tableInfoCheckResources.GetFieldInfoByFieldName(resourcesIDName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfoCheckResources.TableName, resourcesIDName); return(false); } } //resources-背包表 const string packageTableName = "package"; const string packageIDName = "package"; TableInfo tableInfoCheckPackage = null; List <object> packageIdValueList = null; if (AppValues.TableInfo.ContainsKey(packageTableName)) { tableInfoCheckPackage = AppValues.TableInfo[packageTableName]; if (tableInfoCheckPackage.GetFieldInfoByFieldName(packageIDName) != null) { packageIdValueList = tableInfoCheckPackage.GetFieldInfoByFieldName(packageIDName).Data; } else { errorString = string.Format("\"{0}\"表中找不到名为\"{1}\"的字段,无法进行整表检查,请修正后重试\n", tableInfoCheckPackage.TableName, packageIDName); return(false); } } int dataCount = tableInfo.GetKeyColumnFieldInfo().Data.Count; StringBuilder errorStringBuilder = new StringBuilder(); for (int i = 0; i < dataCount; ++i) { int itemIdValue = (int)itemIdValueList[i]; int itemMainTypeValue = (int)itemMainTypeValueList[i]; int itemSubTypeValue = (int)itemSubTypeValueList[i]; int itemColorValue = (int)itemColorValueList[i]; int itemLvlValue = (int)itemLvlValueList[i]; int itemTypeValue = (int)itemTypeValueList[i]; if (itemMainTypeValue < 100 || itemMainTypeValue > 999) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,值范围应在[100,999]之间\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemMainTypeName, itemMainTypeValue); } if (itemSubTypeValue < 0 || itemSubTypeValue > 99) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,值范围应在[0,99]之间\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemSubTypeName, itemSubTypeValue); } if (itemColorValue < 0 || itemColorValue > 9) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,值范围应在[0,9]之间\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemColorName, itemColorValue); } if (itemLvlValue < 0 || itemLvlValue > 999) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,值范围应在[0,999]之间\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemLvlName, itemLvlValue); } int readid = itemMainTypeValue * 1000000 + itemSubTypeValue * 10000 + itemColorValue * 1000 + itemLvlValue; if (itemIdValue.ToString().Substring(0, num) != readid.ToString().Substring(0, num)) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,应为{3}\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemIdName, itemIdValue, readid); } if (itemMainTypeValue == 100) { if (ResourcesIdValueList != null) { if (!ResourcesIdValueList.Contains(itemIdValue)) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,因为main_type=100的必须要在{3}有对应id\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemIdName, itemIdValue, resourcesTableName); } } } if (itemMainTypeValue == 100 && itemTypeValue == 1) { continue; } if (packageIdValueList != null) { if (!packageIdValueList.Contains(itemTypeValue)) { errorStringBuilder.AppendFormat("第{0}行字段{1}值{2}不符合要求,因为type字段的值必须要在{3}有对应id\n", i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, itemTypeName, itemTypeValue, packageTableName); } } } string lackDataErrorString = errorStringBuilder.ToString(); if (string.IsNullOrEmpty(lackDataErrorString)) { errorString = null; return(true); } else { errorString = string.Format("{0}表中存在以下配置缺失:\n{1}\n", tableInfo.TableName, lackDataErrorString); return(false); } }
/// <summary> /// 用于检查string型的文件路径对应的文件是否存在 /// </summary> public static bool CheckFile(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { // 先判断是否输入了Client目录的路径 if (AppValues.App_Config_ClientPath == null) { errorString = "文件存在性检查无法进行:必须在程序运行时传入Client目录的路径\n"; return(false); } else if (fieldInfo.DataType == DataType.String) { int colonIndex = checkRule.CheckRuleString.IndexOf(":"); if (colonIndex == -1) { errorString = "文件存在性检查定义错误:必须在英文冒号后声明相对于Client目录的路径\n"; return(false); } else { // 存储不存在的文件信息(key:行号, value:输入的文件名) Dictionary <int, string> inexistFileInfo = new Dictionary <int, string>(); // 存储含有\或/的非法文件名信息 List <int> illegalFileNames = new List <int>(); // 判断规则中填写的文件的路径与Client路径组合后是否为一个已存在路径 string inputPath = checkRule.CheckRuleString.Substring(colonIndex + 1, checkRule.CheckRuleString.Length - colonIndex - 1).Trim(); string pathString = FileModule.CombinePath(AppValues.App_Config_ClientPath, inputPath); if (!Directory.Exists(pathString)) { errorString = string.Format("文件存在性检查定义错误:声明的文件所在目录不存在,请检查定义的路径是否正确,最终拼得的路径为{0}\n", pathString); return(false); } // 提取file和冒号之间的字符串,判断是否声明扩展名 const string START_STRING = "file"; string extensionString = checkRule.CheckRuleString.Substring(START_STRING.Length, colonIndex - START_STRING.Length).Trim(); // 如果声明了扩展名,则遍历出目标目录下所有该扩展名的文件,然后逐行判断文件是否存在 if (!string.IsNullOrEmpty(extensionString)) { if (extensionString.StartsWith("(") && extensionString.EndsWith(")")) { // 提取括号中定义的扩展名 string extension = extensionString.Substring(1, extensionString.Length - 2).Trim(); // 判断扩展名是否合法(只能为数字或小写英文字母) foreach (char c in extension) { if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) { errorString = string.Format("文件存在性检查定义错误:声明文件扩展名不合法,文件扩展名只能由小写英文字母和数字组成,你填写的为{0}\n", extension); return(false); } } // 存储该目录下为该扩展名的文件的文件名 Dictionary <string, bool> existFileNames = new Dictionary <string, bool>(); DirectoryInfo folder = new DirectoryInfo(pathString); foreach (FileInfo file in folder.GetFiles("*." + extension)) { // 注意file.Name中包含扩展名,需要除去 int dotIndex = file.Name.LastIndexOf('.'); string fileNameWithoutExtension = file.Name.Substring(0, dotIndex); existFileNames.Add(fileNameWithoutExtension, true); } for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值 if (fieldInfo.Data[i] == null) { continue; } // 文件名中不允许含有\或/,即不支持文件在填写路径的非同级目录 string inputFileName = fieldInfo.Data[i].ToString().Trim(); if (string.IsNullOrEmpty(inputFileName)) { continue; } else if (inputFileName.IndexOf('\\') != -1 || inputFileName.IndexOf('/') != -1) { illegalFileNames.Add(i); } else { if (!existFileNames.ContainsKey(inputFileName)) { inexistFileInfo.Add(i, inputFileName); } } } } else { errorString = "文件存在性检查定义错误:如果要声明扩展名,\"file\"与英文冒号之间必须在英文括号内声明扩展名\n"; return(false); } } // 如果没有声明扩展名,则每行数据都用File.Exists判断是否存在 else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值 if (fieldInfo.Data[i] == null) { continue; } // 文件名中不允许含有\或/,即不支持文件在填写路径的非同级目录 string inputFileName = fieldInfo.Data[i].ToString().Trim(); if (string.IsNullOrEmpty(inputFileName)) { continue; } else if (inputFileName.IndexOf('\\') != -1 || inputFileName.IndexOf('/') != -1) { illegalFileNames.Add(i); } else { string path = FileModule.CombinePath(pathString, inputFileName); if (!File.Exists(path)) { inexistFileInfo.Add(i, inputFileName); } } } } if (inexistFileInfo.Count > 0 || illegalFileNames.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); if (illegalFileNames.Count > 0) { errorStringBuild.Append("单元格中填写的文件名中不允许含有\"\\\"或\"/\",即要求填写的文件必须在填写路径的同级目录,以下行对应的文件名不符合此规则:"); string separator = ", "; foreach (int lineNum in illegalFileNames) { errorStringBuild.AppendFormat("{0}{1}", lineNum + ExcelTableSetting.DataFieldDataStartRowIndex + 1, separator); } // 去掉末尾多余的", " errorStringBuild.Remove(errorStringBuild.Length - separator.Length, separator.Length); errorStringBuild.Append("\n"); } if (inexistFileInfo.Count > 0) { errorStringBuild.AppendLine("存在以下找不到的文件:"); foreach (var item in inexistFileInfo) { errorStringBuild.AppendFormat("第{0}行数据,填写的文件名为{1}\n", item.Key + ExcelTableSetting.DataFieldDataStartRowIndex + 1, item.Value); } } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } } } else { errorString = string.Format("文件存在性检查定义只能用于string型的字段,而该字段为{0}型\n", fieldInfo.DataType); return(false); } }
/// <summary> /// 用于检查string型的文件路径对应的文件是否存在 /// </summary> public static bool CheckFile2(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { // 先判断是否输入了Client目录的路径 if (AppValues.ClientPath == null) { errorString = "文件存在性检查无法进行:必须在程序运行时传入Client目录的路径\n"; return(false); } else if (fieldInfo.DataType == DataType.String) { int colonIndex = checkRule.CheckRuleString.IndexOf(":"); if (colonIndex == -1) { errorString = "文件存在性检查定义错误:必须在英文冒号后声明相对于Client目录的路径\n"; return(false); } else { // 存储不存在的文件信息(key:行号, value:输入的文件名) Dictionary <int, string> inexistFileInfo = new Dictionary <int, string>(); // 存储含有\或/的非法文件名信息 List <int> illegalFileNames = new List <int>(); // 判断规则中填写的文件的路径与Client路径组合后是否为一个已存在路径 string inputPath = checkRule.CheckRuleString.Substring(colonIndex + 1, checkRule.CheckRuleString.Length - colonIndex - 1).Trim(); string pathString = Utils.CombinePath(AppValues.ClientPath, inputPath); if (!Directory.Exists(pathString)) { errorString = string.Format("文件存在性检查定义错误:声明的文件所在目录不存在,请检查定义的路径是否正确,最终拼得的路径为{0}\n", pathString); return(false); } // 提取file和冒号之间的字符串,判断是否声明扩展名 const string START_STRING = "file2"; string extensionString = checkRule.CheckRuleString.Substring(START_STRING.Length, colonIndex - START_STRING.Length).Trim(); // 如果声明了扩展名,则遍历出目标目录下所有该扩展名的文件,然后逐行判断文件是否存在 if (string.IsNullOrEmpty(extensionString)) { // 如果没有声明扩展名,则每行数据都用File.Exists判断是否存在 for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值 if (fieldInfo.Data[i] == null) { continue; } // 文件名中不允许含有\或/,即不支持文件在填写路径的非同级目录 string inputFileName = fieldInfo.Data[i].ToString().Trim(); if (string.IsNullOrEmpty(inputFileName)) { continue; } else if (inputFileName.IndexOf('\\') != -1 || inputFileName.IndexOf('/') != -1) { illegalFileNames.Add(i); } else { //string path = Utils.CombinePath(pathString, inputFileName); // string[] paths = Utils.GetAllFolders(pathString, "", false); string[] paths = Directory.GetDirectories(pathString); bool exists = ((System.Collections.IList)paths).Contains(pathString + "\\" + inputFileName); if (!exists) { inexistFileInfo.Add(i, inputFileName); } } } } else { if (extensionString.StartsWith("(") && extensionString.EndsWith(")")) { // 提取括号中定义的扩展名 string extension = extensionString.Substring(1, extensionString.Length - 2).Trim(); if (extension != "*") { // 判断扩展名是否合法(只能为数字或小写英文字母) foreach (char c in extension) { if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) { errorString = string.Format("文件存在性检查定义错误:声明文件扩展名不合法,文件扩展名只能为*号或由小写英文字母和数字组成,你填写的为{0}\n", extension); return(false); } } } Dictionary <string, List <string> > tempfile = Utils.GetFileInfo(pathString, extension, SearchOption.AllDirectories, out errorString); if (errorString != null) { return(false); } for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值 if (fieldInfo.Data[i] == null || fieldInfo.Data[i].ToString() == "0") { continue; } // 文件名中不允许含有\或/,即不支持文件在填写路径的非同级目录 string inputFileName = fieldInfo.Data[i].ToString().Trim(); if (string.IsNullOrEmpty(inputFileName)) { continue; } else if (inputFileName.IndexOf('\\') != -1 || inputFileName.IndexOf('/') != -1) { illegalFileNames.Add(i); } else { if (!tempfile.ContainsKey(inputFileName)) { inexistFileInfo.Add(i, inputFileName); } } } } else { errorString = "文件存在性检查定义错误:如果要声明扩展名,\"file2\"与英文冒号之间必须在英文括号内声明扩展名\n"; return(false); } } if (inexistFileInfo.Count > 0 || illegalFileNames.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); if (illegalFileNames.Count > 0) { errorStringBuild.Append("单元格中填写的文件名中不允许含有\"\\\"或\"/\",即要求填写的文件必须在填写路径的同级目录,以下行对应的文件名不符合此规则:"); string separator = ", "; foreach (int lineNum in illegalFileNames) { errorStringBuild.AppendFormat("{0}{1}", lineNum + AppValues.DATA_FIELD_DATA_START_INDEX + 1, separator); } // 去掉末尾多余的", " errorStringBuild.Remove(errorStringBuild.Length - separator.Length, separator.Length); errorStringBuild.Append("\n"); } if (inexistFileInfo.Count > 0) { errorStringBuild.AppendLine("存在以下找不到的文件:"); foreach (var item in inexistFileInfo) { errorStringBuild.AppendFormat("第{0}行数据,填写的文件名为{1}\n", item.Key + AppValues.DATA_FIELD_DATA_START_INDEX + 1, item.Value); } } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } } } else { errorString = string.Format("文件存在性检查定义只能用于string型的字段,而该字段为{0}型\n", fieldInfo.DataType); return(false); } }
/// <summary> /// 用于int、long型字段组合成ID,sum:main_type*1000000+sub_type*10000+color*1000+lvl /// main_type*1000000,sub_type*10000,color*1000,lvl。等价于该字段值必须是同一行的这些值之和:main_type*1000000+sub_type*10000+color*1000+lvl /// </summary> public static bool CheckSum(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { string temp = null; // 首先要求字段类型只能为int、long型 if (!(fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long)) { errorString = string.Format("sum检查规则只适用于int和long类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } // 解析sum规则中目标列所在表格以及字段名 const string START_STRING = "sum:"; if (!checkRule.CheckRuleString.StartsWith(START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("sum检查规则声明错误,必须以\"{0}\"开头,后面跟字段名*倍数\n", START_STRING); return(false); } temp = checkRule.CheckRuleString.Substring(START_STRING.Length).Trim();//去掉前面的sum:字符 if (string.IsNullOrEmpty(temp)) { errorString = string.Format("sum检查规则声明错误,\"{0}\"的后面必须跟字段名*倍数\n", START_STRING); return(false); } string[] values = temp.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries); // 存储引用字段的信息(字段名,倍数) Dictionary <string, long> RuleValues = new Dictionary <string, long>(); TableInfo thisTableInfo = AppValues.TableInfo[fieldInfo.TableName]; for (int i = 0; i < values.Length; ++i) { string oneValueString = values[i].Trim(); string[] oneValue = oneValueString.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries); if (oneValue.Length == 0) { errorString = "sum检查定义中出现了错误,,因为定义为空值"; return(false); } else { FieldInfo targetFieldInfo = GetFieldByIndexDefineString(oneValue[0].Trim(), thisTableInfo, out errorString); if (errorString != null) { errorString = string.Format("sum检查规则声明错误,表格\"{0}\"中无法根据索引字符串\"{1}\"找到要参考的字段,错误信息为:{2}\n", thisTableInfo, oneValue[0].Trim(), errorString); return(false); } DataType dt = thisTableInfo.GetFieldInfoByFieldName(oneValue[0].Trim()).DataType; if (!(dt == DataType.Int || dt == DataType.Long)) { errorString = string.Format("sum检查规则只适用于int和long类型的字段,而字段{0}的类型为{1}\n", oneValue[0].Trim(), dt.ToString()); return(false); } } if (oneValue.Length == 1) { RuleValues.Add(oneValue[0].Trim(), 1); } else if (oneValue.Length == 2) { RuleValues.Add(oneValue[0].Trim(), Convert.ToInt64(oneValue[1].Trim())); } else { errorString = string.Format("sum检查定义中出现了错误,请检查,其定义为\"{0}\"\n", checkRule); return(false); } } long temNum; // 存储不符合sum规则的数据信息(key:行号, value:填写的数据) Dictionary <int, string> unreferencedInfo = new Dictionary <int, string>(); for (int i = 0; i < fieldInfo.Data.Count; ++i) { // 忽略无效集合元素下属子类型的空值或本身为空值 if (fieldInfo.Data[i] == null) { continue; } temNum = 0; foreach (KeyValuePair <string, long> kvp in RuleValues) { temNum = temNum + Convert.ToInt64(thisTableInfo.GetFieldInfoByFieldName(kvp.Key).Data[i]) * kvp.Value; } if (Convert.ToInt64(fieldInfo.Data[i]) == temNum) { } else { unreferencedInfo.Add(i, string.Format("{0}不符合sum组合规则,正确应为:{1}", fieldInfo.Data[i].ToString(), temNum)); } } if (unreferencedInfo.Count > 0) { StringBuilder errorStringBuild = new StringBuilder(); errorStringBuild.AppendLine("存在以下不符合sum关系的数据行:"); foreach (var item in unreferencedInfo) { errorStringBuild.AppendFormat("第{0}行数据\"{1}\"\n", item.Key + ExcelTableSetting.DataFieldDataStartRowIndex + 1, item.Value); } errorString = errorStringBuild.ToString(); return(false); } else { errorString = null; return(true); } }
/// <summary> /// 特殊导出erlang /// </summary> /// <param name="tableInfo"></param> /// <param name="exportRule"></param> /// <param name="errorString"></param> /// <returns></returns> public static bool SpecialExportTableToErlang(TableInfo tableInfo, string exportRule, out string errorString) { errorString = null; exportRule = exportRule.Trim(); // 解析按这种方式导出后的erlang文件名 int colonIndex = exportRule.IndexOf(':'); if (colonIndex == -1) { errorString = string.Format("导出配置\"{0}\"定义错误,必须在开头声明导出lua文件名\n", exportRule); return(false); } string fileName = exportRule.Substring(0, colonIndex).Trim(); // 判断是否在最后的花括号内声明table value中包含的字段 int leftBraceIndex = exportRule.LastIndexOf('{'); int rightBraceIndex = exportRule.LastIndexOf('}'); // 解析依次作为索引的字段名 string indexFieldNameString = null; // 注意分析花括号时要考虑到未声明table value中的字段而在某索引字段完整性检查规则中用花括号声明了有效值的情况 if (exportRule.EndsWith("}") && leftBraceIndex != -1) { indexFieldNameString = exportRule.Substring(colonIndex + 1, leftBraceIndex - colonIndex - 1); } else { indexFieldNameString = exportRule.Substring(colonIndex + 1, exportRule.Length - colonIndex - 1); } string[] indexFieldDefine = indexFieldNameString.Split(new char[] { '-' }, System.StringSplitOptions.RemoveEmptyEntries); // 用于索引的字段列表 List <FieldInfo> indexField = new List <FieldInfo>(); // 索引字段对应的完整性检查规则 List <string> integrityCheckRules = new List <string>(); if (indexFieldDefine.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,用于索引的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{otherFieldName1,otherFieldName2}的格式配置\n", exportRule); return(false); } // 检查字段是否存在且为int、float、string或lang型 foreach (string fieldDefine in indexFieldDefine) { string fieldName = null; // 判断是否在字段名后用小括号声明了该字段的完整性检查规则 int leftBracketIndex = fieldDefine.IndexOf('('); int rightBracketIndex = fieldDefine.IndexOf(')'); if (leftBracketIndex > 0 && rightBracketIndex > leftBracketIndex) { fieldName = fieldDefine.Substring(0, leftBracketIndex); string integrityCheckRule = fieldDefine.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1).Trim(); if (string.IsNullOrEmpty(integrityCheckRule)) { errorString = string.Format("导出配置\"{0}\"定义错误,用于索引的字段\"{1}\"若要声明完整性检查规则就必须在括号中填写否则不要加括号\n", exportRule, fieldName); return(false); } integrityCheckRules.Add(integrityCheckRule); } else { fieldName = fieldDefine.Trim(); integrityCheckRules.Add(null); } FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (fieldInfo.DataType != DataType.Int && fieldInfo.DataType != DataType.Long && fieldInfo.DataType != DataType.Float && fieldInfo.DataType != DataType.String && fieldInfo.DataType != DataType.Lang) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"为{2}型,但只允许为int、long、float、string或lang型\n", exportRule, fieldName, fieldInfo.DataType); return(false); } // 对索引字段进行非空检查 if (fieldInfo.DataType == DataType.String) { FieldCheckRule stringNotEmptyCheckRule = new FieldCheckRule(); stringNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; stringNotEmptyCheckRule.CheckRuleString = "notEmpty[trim]"; TableCheckHelper.CheckNotEmpty(fieldInfo, stringNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,string型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } else if (fieldInfo.DataType == DataType.Lang) { FieldCheckRule langNotEmptyCheckRule = new FieldCheckRule(); langNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; langNotEmptyCheckRule.CheckRuleString = "notEmpty[key|value]"; TableCheckHelper.CheckNotEmpty(fieldInfo, langNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,lang型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } else if (CheckTableInfo.IsAllowedNullNumber == true) { FieldCheckRule numberNotEmptyCheckRule = new FieldCheckRule(); numberNotEmptyCheckRule.CheckType = TableCheckType.NotEmpty; numberNotEmptyCheckRule.CheckRuleString = "notEmpty"; TableCheckHelper.CheckNotEmpty(fieldInfo, numberNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,{1}型索引字段\"{2}\"中存在以下空值,而作为索引的key不允许为空\n{3}\n", exportRule, fieldInfo.DataType.ToString(), fieldName, errorString); return(false); } } indexField.Add(fieldInfo); } // 解析table value中要输出的字段名 List <FieldInfo> tableValueField = new List <FieldInfo>(); // 如果在花括号内配置了table value中要输出的字段名 if (exportRule.EndsWith("}") && leftBraceIndex != -1 && leftBraceIndex < rightBraceIndex) { string tableValueFieldName = exportRule.Substring(leftBraceIndex + 1, rightBraceIndex - leftBraceIndex - 1); string[] fieldNames = tableValueFieldName.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries); if (fieldNames.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,花括号中声明的table value中的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{otherFieldName1,otherFieldName2}的格式配置\n", exportRule); return(false); } // 检查字段是否存在 foreach (string fieldName in fieldNames) { FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中的字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (tableValueField.Contains(fieldInfo)) { AppLog.LogWarning(string.Format("警告:导出配置\"{0}\"定义中,声明的table value中的字段存在重复,字段名为{1}(列号{2}),本工具只生成一次,请修正错误\n", exportRule, fieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1))); } else { tableValueField.Add(fieldInfo); } } } else if (exportRule.EndsWith("}") && leftBraceIndex == -1) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中花括号不匹配\n", exportRule); return(false); } // 如果未在花括号内声明,则默认将索引字段之外的所有字段进行填充 else { List <string> indexFieldNameList = new List <string>(indexFieldDefine); foreach (FieldInfo fieldInfo in tableInfo.GetAllClientFieldInfo()) { if (!indexFieldNameList.Contains(fieldInfo.FieldName)) { tableValueField.Add(fieldInfo); } } } // 解析完依次作为索引的字段以及table value中包含的字段后,按索引要求组成相应的嵌套数据结构 Dictionary <object, object> data = new Dictionary <object, object>(); int rowCount = tableInfo.GetKeyColumnFieldInfo().Data.Count; for (int i = 0; i < rowCount; ++i) { Dictionary <object, object> temp = data; // 生成除最内层的数据结构 for (int j = 0; j < indexField.Count - 1; ++j) { FieldInfo oneIndexField = indexField[j]; var tempData = oneIndexField.Data[i]; if (!temp.ContainsKey(tempData)) { temp.Add(tempData, new Dictionary <object, object>()); } temp = (Dictionary <object, object>)temp[tempData]; } // 最内层的value存数据的int型行号(从0开始计) FieldInfo lastIndexField = indexField[indexField.Count - 1]; var lastIndexFieldData = _GetOneField(lastIndexField, i, 1, out errorString); if (!temp.ContainsKey(lastIndexFieldData)) { temp.Add(lastIndexFieldData, i); } else { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导出时发现第{2}行与第{3}行在各个索引字段的值完全相同,导出被迫停止,请修正错误后重试\n", tableInfo.TableName, exportRule, i + ExcelTableSetting.DataFieldDataStartRowIndex + 1, temp[lastIndexFieldData]); AppLog.LogErrorAndExit(errorString); return(false); } } // 进行数据完整性检查 if (CheckTableInfo.IsNeedCheck == true) { TableCheckHelper.CheckTableIntegrity(indexField, data, integrityCheckRules, out errorString); if (errorString != null) { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导时未通过数据完整性检查,导出被迫停止,请修正错误后重试:\n{2}\n", tableInfo.TableName, exportRule, errorString); return(false); } } // 生成导出的文件内容 StringBuilder content = new StringBuilder(); // 生成数据内容开头 content.AppendLine("%%--- coding:utf-8 ---"); content.Append("-module(").Append(ErlangStruct.ExportNameBeforeAdd + tableInfo.TableName).AppendLine(")."); string oneFieldString = null; // 当前缩进量 int currentLevel = 1; foreach (var key in data.Keys) { // 生成key if (key.GetType() == typeof(int) || key.GetType() == typeof(float)) { content.Append("get(").Append(key).AppendLine(")->"); } else if (key.GetType() == typeof(string)) { content.Append("get(").Append(key).AppendLine(")->"); } else { errorString = string.Format("SpecialExportTableToErlang中出现非法类型的索引列类型{0}", key.GetType()); AppLog.LogErrorAndExit(errorString); return(false); } // content.Append(_GetErlangIndentation(currentLevel)); content.Append(" #{"); // 如果已是最内层,输出指定table value中的数据 if (data[key].GetType() == typeof(int)) { int column = 0; foreach (FieldInfo fieldInfo in tableValueField) { column++; if (column > 1) { content.Append(_GetErlangIndentation(currentLevel)); } int rowIndex = (int)data[key]; oneFieldString = _GetOneField(fieldInfo, rowIndex, currentLevel, out errorString); if (errorString != null) { errorString = string.Format("导出表格{0}失败,", tableInfo.TableName) + errorString; return(false); } else { if (column > 1) { content.Append(","); } content.Append("'").Append(fieldInfo.DatabaseFieldName).Append("' => ").AppendLine(oneFieldString); } } } content.AppendLine(" },"); } // 生成数据内容结尾 content.AppendLine("get(_N) -> false."); content.AppendLine("get_list() ->"); content.Append("\t["); foreach (var key in data.Keys) { content.Append(key).Append(","); } content.Remove(content.Length - 1, 1); content.Append("]"); string exportString = content.ToString(); //if (ErlangStruct.IsNeedColumnInfo == true) // exportString = _GetColumnInfo(tableInfo) + exportString; // 保存为erlang文件 if (SaveErlang.SaveErlangFile(tableInfo.ExcelName, ExcelMethods.GetSaveTableName(fileName), exportString) == true) { errorString = null; return(true); } else { errorString = "保存为erlang文件失败\n"; return(false); } }
public static TableInfo AnalyzeTable(DataTable dt, string tableName, out string errorString) { TableInfo tableInfo = new TableInfo(); tableInfo.TableName = tableName; // 当前解析到的列号 int curColumnIndex = 0; // 解析第一列(主键列,要求数据类型为string或int且数据非空、唯一) DataType primaryKeyColumnType = _AnalyzeDataType(dt.Rows[AppValues.FIELD_DATA_TYPE_INDEX][0].ToString().Trim()); if (!(primaryKeyColumnType == DataType.Int || primaryKeyColumnType == DataType.String)) { errorString = _GetTableAnalyzeErrorString(tableName, 0) + "主键列的类型只能为int或string"; return(null); } else { // 解析出第一列,然后检查主键唯一性,如果是string型主键还要检查是否非空、是否符合变量名的规范(只能由英文字母、数字、下划线组成) FieldInfo primaryKeyField = _AnalyzeOneField(dt, tableName, 0, null, out curColumnIndex, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, 0) + "主键列解析错误\n" + errorString; return(null); } else { // 唯一性检查 FieldCheckRule uniqueCheckRule = new FieldCheckRule(); uniqueCheckRule.CheckType = TABLE_CHECK_TYPE.UNIQUE; uniqueCheckRule.CheckRuleString = "unique"; TableCheckHelper.CheckUnique(primaryKeyField, uniqueCheckRule, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, 0) + "主键列存在重复错误\n" + errorString; return(null); } // string型主键检查是否非空、是否符合变量名的规范 if (primaryKeyColumnType == DataType.String) { StringBuilder errorStringBuilder = new StringBuilder(); for (int row = 0; row < primaryKeyField.Data.Count; ++row) { string tempError = null; TableCheckHelper.CheckFieldName(primaryKeyField.Data[row].ToString(), out tempError); if (tempError != null) { errorStringBuilder.AppendFormat("第{0}行所填主键{1}\n", row + AppValues.FIELD_DATA_START_INDEX + 1, tempError); } } if (!string.IsNullOrEmpty(errorStringBuilder.ToString())) { errorString = _GetTableAnalyzeErrorString(tableName, 0) + "string型主键列存在非法数据\n" + errorStringBuilder.ToString(); } } tableInfo.AddField(primaryKeyField); } } // 存储定义过的字段名,不允许有同名字段(key:字段名, value:列号) Dictionary <string, int> fieldNames = new Dictionary <string, int>(); // 解析剩余的列 while (curColumnIndex < dt.Columns.Count) { int nextColumnIndex = curColumnIndex; FieldInfo oneField = _AnalyzeOneField(dt, tableName, nextColumnIndex, null, out curColumnIndex, out errorString); if (errorString != null) { errorString = _GetTableAnalyzeErrorString(tableName, nextColumnIndex) + errorString; return(null); } else { // 跳过未声明变量名的无效列 if (oneField != null) { // 检查字段名是否重复 if (fieldNames.ContainsKey(oneField.FieldName)) { errorString = _GetTableAnalyzeErrorString(tableName, nextColumnIndex) + string.Format("表格中存在字段名同为{0}的字段,分别位于第{1}列和第{2}列", oneField.FieldName, Utils.GetExcelColumnName(fieldNames[oneField.FieldName] + 1), Utils.GetExcelColumnName(oneField.ColumnSeq + 1)); return(null); } else { tableInfo.AddField(oneField); fieldNames.Add(oneField.FieldName, oneField.ColumnSeq); } } } } errorString = null; return(tableInfo); }
/// <summary> /// 按配置的特殊索引导出方式输出lua文件(如果声明了在生成的lua文件开头以注释形式展示列信息,将生成更直观的嵌套字段信息,而不同于普通导出规则的列信息展示) /// </summary> public static bool SpecialExportTableToLua(TableInfo tableInfo, string exportRule, out string errorString) { // 解析按这种方式导出后的lua文件名 int colonIndex = exportRule.IndexOf(':'); if (colonIndex == -1) { errorString = string.Format("导出配置\"{0}\"定义错误,必须在开头声明导出lua文件名\n", exportRule); return(false); } string fileName = exportRule.Substring(0, colonIndex).Trim(); // 判断是否在花括号内声明table value中包含的字段 int leftBraceIndex = exportRule.IndexOf('{'); int rightBraceIndex = exportRule.LastIndexOf('}'); // 解析依次作为索引的字段名 string indexFieldNameString = null; if (leftBraceIndex != -1) { indexFieldNameString = exportRule.Substring(colonIndex + 1, leftBraceIndex - colonIndex - 1); } else { indexFieldNameString = exportRule.Substring(colonIndex + 1, exportRule.Length - colonIndex - 1); } string[] indexFieldNames = indexFieldNameString.Split(new char[] { '-' }, System.StringSplitOptions.RemoveEmptyEntries); List <FieldInfo> indexField = new List <FieldInfo>(); if (indexFieldNames.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,用于索引的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{otherFieldName1,otherFieldName2}的格式配置\n", exportRule); return(false); } // 检查字段是否存在且为int、float、string或lang型 foreach (string fieldName in indexFieldNames) { FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (fieldInfo.DataType != DataType.Int && fieldInfo.DataType != DataType.Float && fieldInfo.DataType != DataType.String && fieldInfo.DataType != DataType.Lang) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的索引字段\"{1}\"为{2}型,但只允许为int、float、string或lang型\n", exportRule, fieldName, fieldInfo.DataType); return(false); } // 强制对string、lang型索引字段进行非空检查 if (fieldInfo.DataType == DataType.String) { FieldCheckRule stringNotEmptyCheckRule = new FieldCheckRule(); stringNotEmptyCheckRule.CheckType = TABLE_CHECK_TYPE.NOT_EMPTY; stringNotEmptyCheckRule.CheckRuleString = "notEmpty[trim]"; TableCheckHelper.CheckNotEmpty(fieldInfo, stringNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,string型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } else if (fieldInfo.DataType == DataType.Lang) { FieldCheckRule langNotEmptyCheckRule = new FieldCheckRule(); langNotEmptyCheckRule.CheckType = TABLE_CHECK_TYPE.NOT_EMPTY; langNotEmptyCheckRule.CheckRuleString = "notEmpty[key|value]"; TableCheckHelper.CheckNotEmpty(fieldInfo, langNotEmptyCheckRule, out errorString); if (errorString != null) { errorString = string.Format("按配置\"{0}\"进行自定义导出错误,lang型索引字段\"{1}\"中存在以下空值,而作为索引的key不允许为空\n{2}\n", exportRule, fieldName, errorString); return(false); } } indexField.Add(fieldInfo); } // 注意:这里不做强制检查来确保用于索引的字段中不会出现空值,需自行在相关字段配置notEmpty检查规则 // 解析table value中要输出的字段名 List <FieldInfo> tableValueField = new List <FieldInfo>(); // 如果在花括号内配置了table value中要输出的字段名 if (leftBraceIndex != -1 && rightBraceIndex != -1 && leftBraceIndex < rightBraceIndex) { string tableValueFieldName = exportRule.Substring(leftBraceIndex + 1, rightBraceIndex - leftBraceIndex - 1); string[] fieldNames = tableValueFieldName.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries); if (fieldNames.Length < 1) { errorString = string.Format("导出配置\"{0}\"定义错误,花括号中声明的table value中的字段不能为空,请按fileName:indexFieldName1-indexFieldName2{otherFieldName1,otherFieldName2}的格式配置\n", exportRule); return(false); } // 检查字段是否存在 foreach (string fieldName in fieldNames) { FieldInfo fieldInfo = tableInfo.GetFieldInfoByFieldName(fieldName); if (fieldInfo == null) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中的字段\"{1}\"不存在\n", exportRule, fieldName); return(false); } if (tableValueField.Contains(fieldInfo)) { Utils.LogWarning(string.Format("警告:导出配置\"{0}\"定义中,声明的table value中的字段存在重复,字段名为{1}(列号{2}),本工具只生成一次,请修正错误\n", exportRule, fieldName, Utils.GetExcelColumnName(fieldInfo.ColumnSeq + 1))); } else { tableValueField.Add(fieldInfo); } } } else if (leftBraceIndex + rightBraceIndex != -2 || leftBraceIndex > rightBraceIndex) { errorString = string.Format("导出配置\"{0}\"定义错误,声明的table value中花括号不匹配\n", exportRule); return(false); } // 如果未在花括号内声明,则默认将索引字段之外的所有字段进行填充 else { List <string> indexFieldNameList = new List <string>(indexFieldNames); foreach (FieldInfo fieldInfo in tableInfo.GetAllFieldInfo()) { if (!indexFieldNameList.Contains(fieldInfo.FieldName)) { tableValueField.Add(fieldInfo); } } } // 解析完依次作为索引的字段以及table value中包含的字段后,按索引要求组成相应的嵌套数据结构 Dictionary <object, object> data = new Dictionary <object, object>(); int rowCount = tableInfo.GetKeyColumnFieldInfo().Data.Count; for (int i = 0; i < rowCount; ++i) { Dictionary <object, object> temp = data; // 生成除最内层的数据结构 for (int j = 0; j < indexField.Count - 1; ++j) { FieldInfo oneIndexField = indexField[j]; var tempData = oneIndexField.Data[i]; if (!temp.ContainsKey(tempData)) { temp.Add(tempData, new Dictionary <object, object>()); } temp = (Dictionary <object, object>)temp[tempData]; } // 最内层的value存数据的int型行号(从0开始计) FieldInfo lastIndexField = indexField[indexField.Count - 1]; var lastIndexFieldData = lastIndexField.Data[i]; if (!temp.ContainsKey(lastIndexFieldData)) { temp.Add(lastIndexFieldData, i); } else { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导出时发现第{2}行与第{3}行在各个索引字段的值完全相同,导出被迫停止,请修正错误后重试\n", tableInfo.TableName, exportRule, i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, temp[lastIndexFieldData]); Utils.LogErrorAndExit(errorString); return(false); } } // 生成导出的文件内容 StringBuilder content = new StringBuilder(); // 生成数据内容开头 content.AppendLine("return {"); // 当前缩进量 int currentLevel = 1; // 逐层按嵌套结构输出数据 _GetIndexFieldData(content, data, tableValueField, ref currentLevel, out errorString); if (errorString != null) { errorString = string.Format("错误:对表格{0}按\"{1}\"规则进行特殊索引导出时发现以下错误,导出被迫停止,请修正错误后重试:\n{2}\n", tableInfo.TableName, exportRule, errorString); return(false); } // 生成数据内容结尾 content.AppendLine("}"); string exportString = content.ToString(); if (AppValues.IsNeedColumnInfo == true) { StringBuilder columnInfo = new StringBuilder(); // 变量名前的缩进量 int level = 0; // 按层次结构通过缩进形式生成索引列信息 foreach (FieldInfo fieldInfo in indexField) { columnInfo.Append(_GetOneFieldColumnInfo(fieldInfo, level)); ++level; } // 生成table value中包含字段的信息(首尾用花括号包裹) columnInfo.AppendLine(string.Concat(_COMMENT_OUT_STRING, _GetFieldNameIndentation(level), "{")); ++level; foreach (FieldInfo fieldInfo in tableValueField) { columnInfo.Append(_GetOneFieldColumnInfo(fieldInfo, level)); } --level; columnInfo.AppendLine(string.Concat(_COMMENT_OUT_STRING, _GetFieldNameIndentation(level), "}")); exportString = string.Concat(columnInfo, System.Environment.NewLine, exportString); } // 保存为lua文件 Utils.SaveLuaFile(fileName, exportString); errorString = null; return(true); }
/// <summary> /// 用于int、long、float、date或time型同一行某字段值必须大于等于或大于另一字段值的检查 /// 注意:要进行比较的两个字段可以为同种数据类型,也可以任意比较int、long、float三种数值型大小 /// </summary> public static bool CheckGreaterThan(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { bool isNumberDataType = false; if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float) { isNumberDataType = true; } else if (fieldInfo.DataType == DataType.Date || fieldInfo.DataType == DataType.Time) { isNumberDataType = false; } else { errorString = string.Format("值大小比较检查规则只能用于int、long、float三种数值类型或date、time两种时间类型的字段,而该字段为{0}型\n", fieldInfo.DataType); return(false); } bool isContainsEqual = checkRule.CheckRuleString.StartsWith(">="); TableInfo tableInfo = AppValues.TableInfo[fieldInfo.TableName]; string comparedFieldString = null; if (isContainsEqual == true) { comparedFieldString = checkRule.CheckRuleString.Substring(2).Trim(); } else { comparedFieldString = checkRule.CheckRuleString.Substring(1).Trim(); } // 根据索引字符串定义,找到要与其比较的字段 FieldInfo comparedField = GetFieldByIndexDefineString(comparedFieldString, tableInfo, out errorString); if (errorString != null) { errorString = string.Format("值大小比较检查规则定义错误:{0}\n", errorString); return(false); } // 检查与其比较的字段是否类型匹配 if (comparedField.DataType == DataType.Int || comparedField.DataType == DataType.Long || comparedField.DataType == DataType.Float) { if (isNumberDataType == false) { errorString = string.Format("值大小比较检查规则定义错误:该字段为{0}型,而声明的与其进行比较的字段为{1}型,不支持数值型与时间型的比较\n", fieldInfo.DataType, comparedField.DataType); return(false); } } else if (comparedField.DataType == DataType.Date || comparedField.DataType == DataType.Time) { if (isNumberDataType == true) { errorString = string.Format("值大小比较检查规则定义错误:该字段为{0}型,而声明的与其进行比较的字段为{1}型,不支持数值型与时间型的比较\n", fieldInfo.DataType, comparedField.DataType); return(false); } if (comparedField.DataType != fieldInfo.DataType) { errorString = string.Format("值大小比较检查规则定义错误:该字段为{0}型,而声明的与其进行比较的字段为{1}型,date型无法与time型进行比较\n", fieldInfo.DataType, comparedField.DataType); return(false); } } // 对这两个字段中的每行数据进行值大小比较检查(任一字段中某行数据为无效数据则忽略对该行两字段数值的比较) // 记录检查出的不满足要求的数据,其中object数组含3个元素,分别为未通过检查的数据所在Excel的行号、该字段的值、与其比较的字段的值 List <object[]> illegalValue = new List <object[]>(); if (isNumberDataType == true) { if (isContainsEqual == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } double fieldDataValue = Convert.ToDouble(fieldInfo.Data[i]); double comparedFieldDataValue = Convert.ToDouble(comparedField.Data[i]); if (fieldDataValue < comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldInfo.Data[i], comparedField.Data[i] }); } } } else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } double fieldDataValue = Convert.ToDouble(fieldInfo.Data[i]); double comparedFieldDataValue = Convert.ToDouble(comparedField.Data[i]); if (fieldDataValue <= comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldInfo.Data[i], comparedField.Data[i] }); } } } } else if (fieldInfo.DataType == DataType.Date) { if (isContainsEqual == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } DateTime fieldDataValue = (DateTime)fieldInfo.Data[i]; DateTime comparedFieldDataValue = (DateTime)comparedField.Data[i]; if (fieldDataValue < comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldDataValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT), comparedFieldDataValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT) }); } } } else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } DateTime fieldDataValue = (DateTime)fieldInfo.Data[i]; DateTime comparedFieldDataValue = (DateTime)comparedField.Data[i]; if (fieldDataValue <= comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldDataValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT), comparedFieldDataValue.ToString(AppValues.APP_DEFAULT_DATE_FORMAT) }); } } } } else if (fieldInfo.DataType == DataType.Time) { if (isContainsEqual == true) { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } DateTime fieldDataValue = (DateTime)fieldInfo.Data[i]; DateTime comparedFieldDataValue = (DateTime)comparedField.Data[i]; if (fieldDataValue < comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldDataValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT), comparedFieldDataValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT) }); } } } else { for (int i = 0; i < fieldInfo.Data.Count; ++i) { if (fieldInfo.Data[i] == null || comparedField.Data[i] == null) { continue; } DateTime fieldDataValue = (DateTime)fieldInfo.Data[i]; DateTime comparedFieldDataValue = (DateTime)comparedField.Data[i]; if (fieldDataValue <= comparedFieldDataValue) { illegalValue.Add(new object[3] { i + AppValues.DATA_FIELD_DATA_START_INDEX + 1, fieldDataValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT), comparedFieldDataValue.ToString(AppValues.APP_DEFAULT_TIME_FORMAT) }); } } } } if (illegalValue.Count > 0) { StringBuilder errorStringBuilder = new StringBuilder(); errorStringBuilder.AppendFormat("以下行中数据不满足{0}的值大小比较检查规则\n", isContainsEqual == true ? ">=" : ">"); for (int i = 0; i < illegalValue.Count; ++i) { object[] oneIllegalValue = illegalValue[i]; errorStringBuilder.AppendFormat("第{0}行中,本字段所填值为\"{1}\",与其比较的的字段所填值为\"{2}\"\n", oneIllegalValue[0], oneIllegalValue[1], oneIllegalValue[2]); } errorString = errorStringBuilder.ToString(); return(false); } else { errorString = null; return(true); } }
/// <summary> /// 用于检查mapString型当逻辑上某列对应不同的类型取值时,其数据按是否要求含有或不允许有某些元素 /// </summary> public static bool CheckMapString(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { if (fieldInfo.DataType != DataType.MapString) { errorString = string.Format("mapString型的内容检查只适用于mapString类型的字段,要检查的这列类型为{0}\n", fieldInfo.DataType.ToString()); return(false); } MapStringCheckRule mapStringCheckRule = new MapStringCheckRule(); // 解析检查规则 const string CHECK_RULE_START_STRING = "mapString:"; string checkRuleString = null; if (checkRule.CheckRuleString.Equals(CHECK_RULE_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = "mapString型的内容检查规则声明中必须含有具体的检查规则\n"; return(false); } else if (!checkRule.CheckRuleString.StartsWith(CHECK_RULE_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("mapString型的内容检查规则声明错误,必须以\"{0}\"开头\n", CHECK_RULE_START_STRING); return(false); } else { checkRuleString = checkRule.CheckRuleString.Substring(CHECK_RULE_START_STRING.Length).Trim(); } // 通过|分隔不同条件下的内容检查规则 string[] checkRuleList = checkRuleString.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); // 解析每一种条件下对应的mapString内容 for (int i = 0; i < checkRuleList.Length; ++i) { // 条件解析 MapStringCondition mapStringCondition = new MapStringCondition(); string oneCheckRule = checkRuleList[i].Trim(); string tempCheckRule = oneCheckRule; if (string.IsNullOrEmpty(oneCheckRule)) { errorString = "mapString型的内容检查规则声明错误,不允许含有空的规则声明,请检查是否含有多余的|分隔符\n"; return(false); } const string IF_CONDITION_START_STRING = "if("; if (oneCheckRule.Equals(IF_CONDITION_START_STRING, StringComparison.CurrentCultureIgnoreCase) || !oneCheckRule.StartsWith(IF_CONDITION_START_STRING, StringComparison.CurrentCultureIgnoreCase)) { errorString = string.Format("mapString型的内容检查规则声明错误,必须在if后面的括号中声明其他字段需满足的条件。若无要求,请填写为\"if(all)\",你填写的为{0}\n", oneCheckRule); return(false); } tempCheckRule = tempCheckRule.Substring(IF_CONDITION_START_STRING.Length); int rightBracket = tempCheckRule.IndexOf(')'); if (rightBracket == -1) { errorString = string.Format("mapString型的内容检查规则声明错误,if后面的右括号缺失,你填写的为{0}\n", oneCheckRule); return(false); } if (rightBracket == tempCheckRule.Length - 1) { errorString = string.Format("mapString型的内容检查规则声明错误,在if后面的括号中声明其他字段需满足的条件之后,还需在方括号内声明对mapString型下属字段的要求\n", oneCheckRule); return(false); } string ifConditionString = tempCheckRule.Substring(0, rightBracket).Trim(); if (string.IsNullOrEmpty(ifConditionString)) { errorString = "mapString型的内容检查规则声明错误,if后的括号中为空,若要设置为在任何条件下,请填写为\"if(all)\"\n"; return(false); } else if ("all".Equals(ifConditionString, StringComparison.CurrentCultureIgnoreCase)) { Condition condition = new Condition(); condition.FieldInfo = null; mapStringCondition.ConditionList.Add(condition); } else { // 通过英文逗号分隔要同时满足的条件 string[] ifConditionStringList = ifConditionString.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < ifConditionStringList.Length; j++) { Condition condition = new Condition(); string oneKeyValuePairString = ifConditionStringList[j].Trim(); string fieldName = null; StringBuilder fieldNameBuilder = new StringBuilder(); int charIndex = 0; bool isFoundSignOfRelation = false; for (charIndex = 0; charIndex < oneKeyValuePairString.Length; ++charIndex) { char c = oneKeyValuePairString[charIndex]; if (c == '=' || c == '>' || c == '<') { fieldName = fieldNameBuilder.ToString().Trim(); isFoundSignOfRelation = true; break; } else { fieldNameBuilder.Append(c); } } if (string.IsNullOrEmpty(fieldName)) { errorString = string.Format("mapString型的内容检查规则声明错误,if后的括号中({0})未声明字段名,请按字段名、关系符、取值的形式进行声明,如type>1\n", oneKeyValuePairString); return(false); } else if (isFoundSignOfRelation == false) { errorString = string.Format("mapString型的内容检查规则声明错误,if后的括号中({0})未声明关系符,请按字段名、关系符、取值的形式进行声明,如type>1\n", oneKeyValuePairString); return(false); } // 检查字段是否存在 FieldInfo targetFieldInfo = TableCheckHelper.GetFieldByIndexDefineString(fieldName, AppValues.TableInfo[fieldInfo.TableName], out errorString); if (errorString != null) { errorString = string.Format("mapString型的内容检查规则声明错误,无法根据索引字符串\"{0}\"在表格{1}找到要对应的字段,错误信息为:{2}\n", fieldName, fieldInfo.TableName, errorString); return(false); } // 检查字段类型是否符合要求 if (targetFieldInfo.DataType != DataType.Int && targetFieldInfo.DataType != DataType.Long && targetFieldInfo.DataType != DataType.Float && targetFieldInfo.DataType != DataType.Bool && targetFieldInfo.DataType != DataType.String) { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})的数据类型为{1},而mapString型内容检查规则中,if条件字段只能为int、long、float、bool或string型\n", fieldName, targetFieldInfo.DataType); return(false); } condition.FieldInfo = targetFieldInfo; // 解析填写的关系符 string signOfRelation = null; StringBuilder signOfRelationBuilder = new StringBuilder(); if (charIndex == oneKeyValuePairString.Length) { errorString = string.Format("mapString型的内容检查规则声明错误,if后的括号中({0})未声明取值,请按字段名、关系符、取值的形式进行声明,如type>1\n", oneKeyValuePairString); return(false); } for (; charIndex < oneKeyValuePairString.Length; ++charIndex) { char c = oneKeyValuePairString[charIndex]; if (c == '=' || c == '>' || c == '<') { signOfRelationBuilder.Append(c); } else { break; } } signOfRelation = signOfRelationBuilder.ToString(); if (signOfRelation == "=") { condition.Relation = Relation.Equal; } else if (signOfRelation == ">") { condition.Relation = Relation.GreaterThan; } else if (signOfRelation == ">=") { condition.Relation = Relation.GreaterThanOrEqual; } else if (signOfRelation == "<") { condition.Relation = Relation.LessThan; } else if (signOfRelation == "<=") { condition.Relation = Relation.LessThanOrEqual; } else { errorString = string.Format("mapString型的内容检查规则声明错误,关系符非法,只支持=、>、>=、<、<=,你填写的为{0}\n", oneKeyValuePairString); return(false); } // bool、string型只有关系符= if (condition.Relation != Relation.Equal && (targetFieldInfo.DataType == DataType.Bool || targetFieldInfo.DataType == DataType.String)) { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})为{1}类型,只能进行等于判定,而你设置的关系符为{2}\n", fieldName, targetFieldInfo.DataType, condition.Relation); return(false); } // 解析填写的取值 string valueString = oneKeyValuePairString.Substring(charIndex).Trim(); if (targetFieldInfo.DataType == DataType.Int) { int value = 0; if (int.TryParse(valueString, out value) == false) { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})对应int型的取值({1})非法\n", fieldName, valueString); return(false); } else { condition.Value = value; } } else if (targetFieldInfo.DataType == DataType.Long) { long value = 0; if (long.TryParse(valueString, out value) == false) { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})对应long型的取值({1})非法\n", fieldName, valueString); return(false); } else { condition.Value = value; } } else if (targetFieldInfo.DataType == DataType.Float) { double value = 0; if (double.TryParse(valueString, out value) == false) { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})对应float型的取值({1})非法\n", fieldName, valueString); return(false); } else { condition.Value = value; } } else if (targetFieldInfo.DataType == DataType.Bool) { if ("1".Equals(valueString) || "true".Equals(valueString, StringComparison.CurrentCultureIgnoreCase)) { condition.Value = true; } else if ("0".Equals(valueString) || "false".Equals(valueString, StringComparison.CurrentCultureIgnoreCase)) { condition.Value = true; } else { errorString = string.Format("mapString型的内容检查规则声明错误,条件字段({0})对应bool型的取值({1})非法,bool型的值应用数字1、0或true、false进行声明\n", fieldName, valueString); return(false); } } else if (targetFieldInfo.DataType == DataType.String) { condition.Value = valueString; } else { errorString = "用CheckMapString函数处理非法的mapString型检查规则中定义的条件字段类型"; AppLog.LogErrorAndExit(errorString); return(false); } mapStringCondition.ConditionList.Add(condition); } } // mapString型下属字段要求解析 string mapStringRequiredString = tempCheckRule.Substring(rightBracket + 1).Trim(); if (!mapStringRequiredString.StartsWith("[") || !mapStringRequiredString.EndsWith("]")) { errorString = string.Format("mapString型的内容检查规则声明错误,每条检查规则中的字段要求声明必须在if条件声明后,在方括号内声明,你填写的为{0}\n", mapStringRequiredString); return(false); } mapStringRequiredString = mapStringRequiredString.Substring(1, mapStringRequiredString.Length - 2).Trim(); MapStringRequiredInfo mapStringRequiredInfo = _GetMapStringRequiredInfo(mapStringRequiredString, fieldInfo, out errorString); if (errorString != null) { errorString = string.Format("mapString型的内容检查规则声明错误,输入的字段要求错误,你填写的为\"{0}\",错误原因为:{1}\n", mapStringRequiredString, errorString); return(false); } else { mapStringCheckRule.CheckRuleList.Add(mapStringCondition, mapStringRequiredInfo); } } // 按解析出的检查规则对mapString型进行检查 StringBuilder errorStringBuilder = new StringBuilder(); int ruleIndex = 0; foreach (var item in mapStringCheckRule.CheckRuleList) { MapStringCondition condition = item.Key; MapStringRequiredInfo requiredInfo = item.Value; StringBuilder oneConditionStringBuilder = new StringBuilder(); // 先找出其他列满足检查条件的行 // 记录符合检查条件的数据索引值(从0计),这里先将所有数据行加入,然后逐步排除不满足条件的数据行 List <int> targetDataIndex = new List <int>(); int dataCount = fieldInfo.Data.Count; for (int i = 0; i < dataCount; ++i) { targetDataIndex.Add(i); } List <int> emptyConditionRowIndex = new List <int>(); for (int conditionIndex = 0; conditionIndex < condition.ConditionList.Count; ++conditionIndex) { Condition oneCondition = condition.ConditionList[conditionIndex]; // 排除标为all的条件 if (oneCondition.FieldInfo != null) { List <int> tempEmptyConditionRowIndex = null; _GetTargetDataIndex(oneCondition, targetDataIndex, oneCondition.FieldInfo, out tempEmptyConditionRowIndex); if (tempEmptyConditionRowIndex != null && tempEmptyConditionRowIndex.Count > 0) { foreach (int rowIndex in tempEmptyConditionRowIndex) { if (!emptyConditionRowIndex.Contains(rowIndex)) { emptyConditionRowIndex.Add(rowIndex); } } } } } if (emptyConditionRowIndex.Count > 0) { string warningString = string.Format("警告:mapString型字段\"{0}\"(列号:{1})的检查条件({2})中的字段,因为以下行中数据无效,视为不满足条件,不对对应行中的mapString进行检查:{3}\n", fieldInfo.FieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1), checkRuleList[ruleIndex], Utils.CombineString(emptyConditionRowIndex, ",")); AppLog.LogWarning(warningString); } // 对满足检查条件的数据行进行mapString内容检查 List <int> emptyDataRowIndex = new List <int>(); foreach (int index in targetDataIndex) { // 若为空值,跳过检查,但进行警告 if (fieldInfo.Data[index] == null) { emptyDataRowIndex.Add(index + ExcelTableSetting.DataFieldDataStartRowIndex + 1); continue; } JsonData jsonData = fieldInfo.Data[index] as JsonData; if (_CheckMapStringData(jsonData, requiredInfo, out errorString) == false) { oneConditionStringBuilder.AppendFormat("第{0}行填写的数据({1}):\n{2}\n", index + ExcelTableSetting.DataFieldDataStartRowIndex + 1, fieldInfo.JsonString[index], errorString); } } string oneConditionString = oneConditionStringBuilder.ToString(); if (!string.IsNullOrEmpty(oneConditionString)) { errorStringBuilder.AppendFormat("以下行数据未通过检查规则\"{0}\":\n{1}", checkRuleList[ruleIndex], oneConditionString); } if (emptyDataRowIndex.Count > 0) { string warningString = string.Format("警告:在对mapString型字段\"{0}\"(列号:{1})执行检查条件({2})时,因为以下行中数据无效,跳过对mapString的检查:{3}\n", fieldInfo.FieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1), checkRuleList[ruleIndex], Utils.CombineString(emptyDataRowIndex, ",")); AppLog.LogWarning(warningString); } ++ruleIndex; } errorString = errorStringBuilder.ToString(); if (string.IsNullOrEmpty(errorString)) { errorString = null; return(true); } else { return(false); } }
/// <summary> /// 用于int、long、float、string、date或time型取值必须为指定有效取值中的一个的检查 /// </summary> public static bool CheckEffective(FieldInfo fieldInfo, FieldCheckRule checkRule, out string errorString) { List <object> repeatedSetValue = null; List <int> errorDataIndex = null; _GetValueIsInSet(fieldInfo.Data, fieldInfo.DataType, checkRule.CheckRuleString, true, out repeatedSetValue, out errorDataIndex, out errorString); if (errorString == null) { if (repeatedSetValue.Count > 0) { foreach (object setValue in repeatedSetValue) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String) { AppLog.LogWarning(string.Format("警告:字段{0}(列号:{1})的值有效性检查规则定义中,出现了相同的有效值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1), setValue)); } else if (fieldInfo.DataType == DataType.Date) { DateTime dataTimeSetValue = (DateTime)setValue; AppLog.LogWarning(string.Format("警告:字段{0}(列号:{1})的值有效性检查规则定义中,出现了相同的有效值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1), dataTimeSetValue.ToString(DateTimeValue.APP_DEFAULT_DATE_FORMAT))); } else if (fieldInfo.DataType == DataType.Time) { DateTime dataTimeSetValue = (DateTime)setValue; AppLog.LogWarning(string.Format("警告:字段{0}(列号:{1})的值有效性检查规则定义中,出现了相同的有效值\"{2}\",本工具忽略此问题继续进行检查,需要你之后修正规则定义错误\n", fieldInfo.FieldName, ExcelMethods.GetExcelColumnName(fieldInfo.ColumnSeq + 1), dataTimeSetValue.ToString(DateTimeValue.APP_DEFAULT_TIME_FORMAT))); } } } if (errorDataIndex.Count > 0) { StringBuilder illegalValueInfo = new StringBuilder(); foreach (int dataIndex in errorDataIndex) { if (fieldInfo.DataType == DataType.Int || fieldInfo.DataType == DataType.Long || fieldInfo.DataType == DataType.Float || fieldInfo.DataType == DataType.String) { illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不属于有效取值中的一个\n", dataIndex + ExcelTableSetting.DataFieldDataStartRowIndex + 1, fieldInfo.Data[dataIndex]); } else if (fieldInfo.DataType == DataType.Date) { DateTime dataTimeValue = (DateTime)fieldInfo.Data[dataIndex]; illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不属于有效取值中的一个\n", dataIndex + ExcelTableSetting.DataFieldDataStartRowIndex + 1, dataTimeValue.ToString(DateTimeValue.APP_DEFAULT_DATE_FORMAT)); } else if (fieldInfo.DataType == DataType.Time) { DateTime dataTimeValue = (DateTime)fieldInfo.Data[dataIndex]; illegalValueInfo.AppendFormat("第{0}行数据\"{1}\"不属于有效取值中的一个\n", dataIndex + ExcelTableSetting.DataFieldDataStartRowIndex + 1, dataTimeValue.ToString(DateTimeValue.APP_DEFAULT_TIME_FORMAT)); } } errorString = illegalValueInfo.ToString(); return(false); } else { return(true); } } else { errorString = errorString + "\n"; return(false); } }