/// <summary> /// 解析标量 /// </summary> /// <param name="type"></param> /// <param name="jsonValue"></param> /// <param name="report"></param> /// <returns></returns> private static object ParseScalar(string type, JsonParser.JsonValueContext jsonValue, ReportWrap report) { IToken token = jsonValue.boolValue ?? jsonValue.intValue ?? jsonValue.floatValue ?? jsonValue.strValue ?? null; if (token != null) { object result = BaseUtil.GetScalar(type, token.Text.Trim('"')); if (result != null) { return(result); } else { if (BaseUtil.IsInteger(type) || BaseUtil.IsFloat(type)) { report.OnError(string.Format("值\"{0}\"无法转换成{1},或超出{1}的精度范围.", token.Text.Trim('"'), type), token); } else { report.OnError(string.Format("值\"{0}\"无法转换成{1}.", token.Text.Trim('"'), type), token); } } } else { report.OnError(string.Format("\"{0}\"无法转换成{1}.", jsonValue.GetText(), type), jsonValue); } return(null); }
/// <summary> /// 结构 /// </summary> /// <param name="attributes"></param> /// <param name="type"></param> /// <param name="cellData"></param> /// <param name="errors"></param> /// <returns></returns> private object GetStruct(AttributeTable attributes, Struct type, ICell cellData, List <string> errors) { string text = null; if (cellData == null || cellData.CellType == CellType.Blank) { text = ""; } else if (cellData.CellType == CellType.String) { text = cellData.StringCellValue; } else if (cellData.CellType == CellType.Numeric) { text = cellData.NumericCellValue.ToString(); } else if (cellData.CellType == CellType.Boolean) { text = cellData.BooleanCellValue.ToString(); } text = text.Trim(); if (!string.IsNullOrEmpty(text)) { return(BaseUtil.GetStruct(attributes, type, text, errors)); } errors.Add(string.Format("内容无法转换成有效的{0}。", type.Name)); return(null); }
/// <summary> /// 解析单个值 /// </summary> /// <param name="type"></param> /// <param name="typeDefined"></param> /// <param name="attributes"></param> /// <param name="jsonValue"></param> /// <param name="report"></param> /// <returns></returns> private static object ParseSingleValue(string type, object typeDefined, AttributeTable attributes, JsonParser.JsonValueContext jsonValue, ReportWrap report) { if (typeDefined is Enum) { return(ParseEnum(typeDefined as Enum, jsonValue, report)); } else if (typeDefined is Struct) { return(ParseStruct(typeDefined as Struct, jsonValue, report)); } else if (typeDefined is Table) { return(ParseTable(typeDefined as Table, jsonValue, report)); } else if (BaseUtil.IsBaseType(type)) { return(ParseScalar(type, jsonValue, report)); } return(null); }
/// <summary> /// 解析枚举 /// </summary> /// <param name="type"></param> /// <param name="jsonValue"></param> /// <param name="report"></param> /// <returns></returns> private static object ParseEnum(Enum type, JsonParser.JsonValueContext jsonValue, ReportWrap report) { IToken token = jsonValue.strValue ?? jsonValue.intValue ?? jsonValue.floatValue; if (token != null) { object result = BaseUtil.GetEnum(type, token.Text.Trim('"')); if (result != null) { return(result); } else { report.OnError(string.Format("值\"{0}\"无法转换成枚举{1}.", token.Text.Trim('"'), type), token); } } else { report.OnError(string.Format("\"{0}\"无法转换成枚举{1}.", jsonValue.GetText(), type), jsonValue); } return(null); }
private static void ParseTable(Table table, CsvTable dataset, CSV csv) { var titleRowIndex = csv.titleRow - 1; var dataBeginRowIndex = csv.dataBeginRow - 1; var columnName2ColumnIndex = new Dictionary <string, int>(); //验证标题行有效性 if (titleRowIndex < 0 || titleRowIndex >= dataset.Count) { LogError(csv.filePath, titleRowIndex, -1, "标题行不存在!"); return; } //验证数据起始行有效性 if ((dataBeginRowIndex < 0 || dataBeginRowIndex >= dataset.Count)) { LogError(csv.filePath, dataBeginRowIndex, -1, "数据起始行不存在!"); return; } //检查标题行是否有重复的列名 CsvRow titleRow = dataset[titleRowIndex]; for (int i = 0; i < titleRow.Count; i++) { string colName = titleRow[i].text != null ? titleRow[i].text.Trim() : ""; if (string.IsNullOrEmpty(colName)) { continue; } if (columnName2ColumnIndex.ContainsKey(colName)) { LogError(csv.filePath, titleRowIndex, i, string.Format("标题行有重复列名:{0}!", colName)); } else { columnName2ColumnIndex.Add(colName, i); } } //检查标题行是否有有效数据 if (columnName2ColumnIndex.Count == 0) { LogError(csv.filePath, titleRowIndex, -1, "标题行没有有效的数据!"); return; } //检测数据表中是否缺少字段 foreach (var field in table.Fields) { var fieldName = field.DataField; if (!columnName2ColumnIndex.ContainsKey(fieldName)) { LogError(csv.filePath, titleRowIndex, -1, string.Format("标题行缺少名为\"{0}\"的列!", fieldName)); } } //找出所有带索引的列 var indexKeys = new HashSet <string>(); foreach (var index in table.Attributes.GetAttributes <Index>()) { foreach (var indexKey in index.IndexFields) { foreach (var field in table.Fields) { if (field.Name.Equals(indexKey)) { indexKeys.Add(field.DataField); } } } } //转换数据 for (int i = dataBeginRowIndex; i < dataset.Count; i++) { //忽略空行 if (dataset[i].isEmpty) { LogWarning(csv.filePath, i, -1, "整行内容为空,忽略!"); continue; } foreach (var field in table.Fields) { string fieldName = field.DataField; object fieldValue = null; object fieldDefaultValue = field.DefaultValue; if (!columnName2ColumnIndex.ContainsKey(fieldName) || (columnName2ColumnIndex[fieldName] < 0 || columnName2ColumnIndex[fieldName] >= dataset[i].Count)) { //缺少对应的数据列 | 列索引超出数据行总列数 if (BaseUtil.IsBaseType(field.Type)) { fieldValue = BaseUtil.GetDefaultValue(field.Type, fieldDefaultValue); } } else { bool isIndex = indexKeys.Contains(fieldName); bool isUnique = field.Attributes.GetAttribute <Unique>() != null; bool isNullable = field.Attributes.HasAttribute <Nullable>(); int columnIndex = columnName2ColumnIndex[fieldName]; CsvCol column = dataset[i][columnIndex]; string columnText = column.text; bool isEmpty = string.IsNullOrEmpty(columnText); if (BaseUtil.IsBaseType(field.Type)) { if (field.IsArray) { } else { object scalarValue = null; if (isEmpty) { if (!isNullable) { LogError(csv.filePath, i, columnIndex, string.Format("列{0}不允许为空!", fieldName)); } if (isUnique) { LogError(csv.filePath, i, columnIndex, string.Format("列{0}有唯一性约束,不允许为空!", fieldName)); } if (isIndex) { LogError(csv.filePath, i, columnIndex, string.Format("列{0}有索引,不允许为空!", fieldName)); } scalarValue = BaseUtil.GetDefaultValue(field.Type, fieldDefaultValue); } else { scalarValue = BaseUtil.GetScalar(field.Type, columnText); if (scalarValue == null) { LogError(csv.filePath, i, columnIndex, string.Format("'{0}'无法转换成一个'{1}'!", columnText, field.Type)); } } } } else if (field.TypeDefined is Model.Struct) { } else if (field.TypeDefined is Model.Enum) { } } } } }
/// <summary> /// 数组 /// </summary> /// <param name="attributes"></param> /// <param name="type"></param> /// <param name="typeDefined"></param> /// <param name="cellData"></param> /// <param name="errors"></param> /// <returns></returns> private object GetArray(AttributeTable attributes, string type, object typeDefined, ICell cellData, List <string> errors) { string cellText = null; if (cellData == null || cellData.CellType == CellType.Blank) { cellText = ""; } else if (cellData.CellType == CellType.String) { cellText = cellData.StringCellValue.Trim(); } else if (cellData.CellType == CellType.Numeric) { cellText = cellData.NumericCellValue.ToString(); } else if (cellData.CellType == CellType.Boolean) { cellText = cellData.BooleanCellValue.ToString(); } if (cellText == null) { cellText = ""; errors.Add(string.Format("内容无法转换成有效的{0}数组。", type)); } cellText = cellText.Trim(); var separator = ","; var arrayValue = attributes.GetAttribute <ArrayLiteral>(); if (arrayValue != null) { separator = arrayValue.separator; if (cellText.StartsWith(arrayValue.beginning)) { cellText = cellText.Substring(arrayValue.beginning.Length); } if (cellText.EndsWith(arrayValue.ending)) { cellText = cellText.Substring(0, cellText.Length - arrayValue.ending.Length); } } var texts = string.IsNullOrEmpty(cellText) ? new string[] { } : cellText.Split(new string[] { separator }, StringSplitOptions.None); if (BaseUtil.IsBaseType(type)) { return(BaseUtil.GetScalarArray(type, texts, errors)); } else if (typeDefined is Model.Enum) { return(BaseUtil.GetEnumArray(typeDefined as Model.Enum, texts, errors)); } else if (typeDefined is Model.Struct) { return(BaseUtil.GetStructArray(attributes, typeDefined as Model.Struct, texts, errors)); } return(null); }
/// <summary> /// 标量 /// </summary> /// <param name="type"></param> /// <param name="cell"></param> /// <param name="error"></param> /// <returns></returns> private object GetScalar(string type, ICell cell, List <string> errors) { object result = null; if (cell.CellType == CellType.Numeric) { if ((type.Equals("byte") || type.Equals("int8")) && sbyte.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= sbyte.MaxValue) { result = (sbyte)cell.NumericCellValue; } else if ((type.Equals("ubyte") || type.Equals("uint8")) && byte.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= byte.MaxValue) { result = (byte)cell.NumericCellValue; } else if ((type.Equals("short") || type.Equals("int16")) && short.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= short.MaxValue) { result = (short)cell.NumericCellValue; } else if ((type.Equals("ushort") || type.Equals("uint16")) && ushort.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= ushort.MaxValue) { result = (ushort)cell.NumericCellValue; } else if (type.Equals("int") || type.Equals("int32") && int.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= int.MaxValue) { result = (int)cell.NumericCellValue; } else if (type.Equals("uint") || type.Equals("uint32") && uint.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= uint.MaxValue) { result = (uint)cell.NumericCellValue; } else if (type.Equals("long") || type.Equals("int64") && long.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= long.MaxValue) { result = (long)cell.NumericCellValue; } else if (type.Equals("ulong") || type.Equals("uint64") && ulong.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= ulong.MaxValue) { result = (ulong)cell.NumericCellValue; } else if ((type.Equals("float") || type.Equals("float32")) && float.MinValue <= cell.NumericCellValue && cell.NumericCellValue <= float.MaxValue) { result = (float)cell.NumericCellValue; } else if ((type.Equals("double") || type.Equals("double64")) && double.MinValue <= cell.NumericCellValue && cell.NumericCellValue > double.MaxValue) { result = cell.NumericCellValue; } else if (type.Equals("bool")) { result = cell.NumericCellValue != 0; } else if (type.Equals("string")) { result = cell.NumericCellValue.ToString(); } } else if (cell.CellType == CellType.Boolean) { if (type.Equals("bool")) { result = cell.BooleanCellValue; } else if (type.Equals("string")) { result = cell.BooleanCellValue.ToString(); } } else if (cell.CellType == CellType.String) { if (type.Equals("string")) { result = cell.StringCellValue.ToString(); } } if (result == null) { if (BaseUtil.IsInteger(type) || BaseUtil.IsFloat(type)) { errors.Add(string.Format("内容不是一个有效的{0},或者超出了{0}的有效精度.", type)); } else { errors.Add(string.Format("内容不是一个有效的{0}.", type)); } } return(result); }
public override void Read(Table table) { var xls = table.Attributes.GetAttribute <XLS>(); var filePath = xls.filePath; var sheetName = xls.sheetName; var titleRowIndex = xls.titleRow - 1; var dataBeginRowIndex = xls.dataBeginRow - 1; var dataSet = new List <object[]>(); var dataSetWidth = table.Fields.Count; var indexKeys = new HashSet <string>(); foreach (var index in table.Attributes.GetAttributes <Index>()) { foreach (var dataKey in index.IndexFields) { foreach (var field in table.Fields) { if (field.Name.Equals(dataKey)) { indexKeys.Add(field.DataField); } } } } var dataKeyList = new List <string>(); var dataKey2FieldSchema = new Dictionary <string, TableField>(); foreach (var field in table.Fields) { dataKeyList.Add(field.DataField); dataKey2FieldSchema.Add(field.DataField, field); } using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var ext = Path.GetExtension(filePath).ToLower(); IWorkbook workbook = null; if (ext == ".xlsx") { workbook = new XSSFWorkbook(stream); } else if (ext == ".xls") { workbook = new HSSFWorkbook(stream); } else { ReportXlsError("未知的文件类型!", filePath); return; } var sheet = workbook.GetSheet(sheetName); if (sheet == null) { ReportXlsError("文件未找到表:" + sheetName + "。", filePath, sheetName); return; } var titleRow = sheet.GetRow(titleRowIndex); if (titleRow == null) { ReportXlsError("标题行不存在,无法导出。", filePath, sheetName, titleRowIndex); return; } var fieldName2CellIndex = new Dictionary <string, int>(); var cellIndex2FieldName = new Dictionary <int, string>(); //title for (var i = 0; i <= titleRow.LastCellNum; i++) { var cell = titleRow.GetCell(i); if (cell == null || cell.CellType == CellType.Blank) { continue; } if (cell.CellType == CellType.String) { if (fieldName2CellIndex.ContainsKey(cell.StringCellValue)) { ReportXlsError("标题列名重复出现。", filePath, sheetName, titleRowIndex, i); } else { fieldName2CellIndex.Add(cell.StringCellValue, i); cellIndex2FieldName.Add(i, cell.StringCellValue); } } else { ReportXlsError("标题列内容不是字符格式。", filePath, sheetName, titleRowIndex, i); } } foreach (var fieldName in dataKey2FieldSchema.Keys) { if (!fieldName2CellIndex.ContainsKey(fieldName)) { ReportXlsError("标题行中未找到列 " + fieldName + "。", filePath, sheetName, titleRowIndex); } } //data var uniqueChecker = new Dictionary <int, Dictionary <object, List <int> > >(); for (var rowIndex = dataBeginRowIndex; rowIndex <= sheet.LastRowNum; rowIndex++) { var row = sheet.GetRow(rowIndex); if (row == null) { continue; } var colCount = 0; for (var j = 0; j < dataKeyList.Count; j++) { if (fieldName2CellIndex.ContainsKey(dataKeyList[j])) { var cellData = row.GetCell(fieldName2CellIndex[dataKeyList[j]]); if (cellData != null && cellData.CellType != CellType.Blank) { colCount++; } } } if (colCount == 0) { continue; } var dataSetRow = new object[dataSetWidth]; for (var j = 0; j < dataKeyList.Count; j++) { var linkName = dataKeyList[j]; if (!fieldName2CellIndex.ContainsKey(linkName)) { continue; } var cellIndex = fieldName2CellIndex[linkName]; var cellData = row.GetCell(cellIndex); var field = dataKey2FieldSchema[linkName]; var isUnique = field.Attributes.GetAttribute <Unique>() != null; var isBaseType = BaseUtil.IsBaseType(field.Type) && field.TypeDefined == null; string fieldError = null; object fieldValue = null; var errors = new List <string>(); if (field.IsArray) { fieldValue = GetArray(field.Attributes, field.Type, field.TypeDefined, cellData, errors); } else { if (field.TypeDefined is Model.Struct) { fieldValue = GetStruct(field.Attributes, field.TypeDefined as Struct, cellData, errors); } else if (field.TypeDefined is Model.Enum) { fieldValue = GetEnum(field.TypeDefined as Model.Enum, cellData, errors); } else if (isBaseType) { var isIndex = indexKeys.Contains(field.DataField); var isNullable = field.Attributes.HasAttribute <Model.Attributes.Nullable>(); var defaultValue = field.DefaultValue; if (cellData == null || cellData.CellType == CellType.Blank) { if (!isNullable || isUnique) { errors.Add(String.Format("内容不允许为空!")); } else if (isIndex) { errors.Add(String.Format("索引字段不允许为空!")); } else { fieldValue = defaultValue != null ? defaultValue : 0; } } else if (BaseUtil.IsBaseType(field.Type)) { fieldValue = GetScalar(field.Type, cellData, errors); } } } if (errors.Count > 0) { fieldError = string.Join("\n", errors); } if (fieldError != null) { ReportXlsError(fieldError, filePath, sheetName, rowIndex, cellIndex); } dataSetRow[j] = fieldValue; if (isBaseType && isUnique && fieldValue != null) { if (!uniqueChecker.ContainsKey(cellIndex)) { uniqueChecker.Add(cellIndex, new Dictionary <object, List <int> >()); } if (!uniqueChecker[cellIndex].ContainsKey(fieldValue)) { uniqueChecker[cellIndex].Add(fieldValue, new List <int>()); } uniqueChecker[cellIndex][fieldValue].Add(rowIndex); } } dataSet.Add(dataSetRow); } foreach (var cellIndex in uniqueChecker.Keys) { var formatedCellIndex = FormatXlsColumnName(cellIndex); foreach (var val in uniqueChecker[cellIndex].Keys) { if (uniqueChecker[cellIndex][val].Count > 1) { var txts = new List <string>(); var firstRowIndex = uniqueChecker[cellIndex][val][0]; foreach (var rowIndex in uniqueChecker[cellIndex][val]) { txts.Add((rowIndex + 1).ToString() + "行"); } ReportXlsError(String.Format("{0} 列在 {1} 出现了相同的内容:\"{2}\"。", cellIndex2FieldName[cellIndex], string.Join(",", txts), val), filePath, sheetName); } } } } }
/// <summary> /// 获取列表格式的结构 /// </summary> /// <param name="literal"></param> /// <param name="type"></param> /// <param name="text"></param> /// <param name="errors"></param> /// <returns></returns> private static object GetStruct(StructLiteral literal, Model.Struct type, string text, List <string> errors) { text = text.Trim(); //查找自定义的分割规则 var separator = ","; if (literal != null) { separator = literal.separator; if (text.StartsWith(literal.beginning)) { text = text.Substring(literal.beginning.Length); } if (text.EndsWith(literal.ending)) { text = text.Substring(0, text.Length - literal.ending.Length); } } //分割字符串 var texts = new string[] { }; if (!string.IsNullOrEmpty(text)) { texts = text.Split(new string[] { separator }, StringSplitOptions.None); } //解析字符串 var values = new Dictionary <string, object>(); for (int i = 0; i < texts.Length; i++) { var txt = texts[i].Trim(); if (i < type.Fields.Count) { var field = type.Fields[i]; var fieldType = field.Type; if (BaseUtil.IsInteger(fieldType) || BaseUtil.IsFloat(fieldType) || BaseUtil.IsBool(fieldType)) { object value = BaseUtil.GetScalar(fieldType, txt); if (value != null) { values.Add(field.Name, value); } else { errors.Add(string.Format("第{0}个元素{1}无法解析成{2}。", i, txt, fieldType)); } } else if (BaseUtil.IsString(fieldType)) { values.Add(field.Name, txt); } else if (field.TypeDefined is Model.Enum) { var value = BaseUtil.GetEnum(field.TypeDefined as Model.Enum, txt); if (value != null) { values.Add(field.Name, value); } else { errors.Add(string.Format("第{0}个元素{1}无法解析成{2}。", i, txt, fieldType)); } } else if (field.TypeDefined is Model.Struct) { var value = GetStruct(field.Attributes, field.TypeDefined as Model.Struct, txt, errors); if (value != null) { values.Add(field.Name, value); } } } else { errors.Add(string.Format("第{0}个元素将被忽略,因为{1}的字段数量只有{2}个。", i, type.Name, type.Fields.Count)); } } for (int i = texts.Length; i < type.Fields.Count; i++) { errors.Add(String.Format("字段{0}没有对应的数据项,因为数据只有{1}个元素。", type.Fields[i].Name, texts.Length)); } return(values); }