private void SetColumnNameAndType(Column column, string defaultName, Type defalutType = null) { var cm = GetColumnMap(column, defaultName); if (null != cm) { column.Name = cm.Value.ToString(); if (null != defalutType) { column.Type = GetTypeFromDbType(cm.Type); } } else { column.Name = defaultName; column.Type = defalutType; } }
private Type GetTypeForColumn(IEnumerable<Cell> cells, Column column, int columnCount) { var type = typeof(string); // all columns from row axis, make it string if (column.CellOrdinal == 0) { return type; } // If the user passed in a dbtype as part of the parms, use that var columnMap = GetColumnMap(column); if (null != columnMap && null != columnMap.Type) { return GetTypeFromDbType(columnMap.Type); } var columnPosition = column.CellOrdinal; if (column.CellOrdinal == columnCount) { columnPosition = 0; } // using the ordinal of the cell along with the column count we can determine which column a cell belongs too. // this gets all the cells for the current column and gets the distinct types var x = cells.Where(c => ((c.Ordinal + 1) % columnCount) == columnPosition).Select(t => t.Type).Distinct().ToList(); if (x.Count() > 1) { // if a non number comes back, the type is null, so non numbers are null // on counts of greater than 1 and no nulls, we have multiple number types, make them all double to accommodate the differences // TODO: find a test case for nulls and see how this works if ( !x.Contains(null) ) { // mix of numbers not doubles, default to int type = !x.Contains("xsd:double") ? typeof(int) : typeof(double); } else { type = typeof(string); } } else { // entire column maybe null, default to string, otherwise check if (x.Count() == 1) { type = ConvertXmlTypeToType(x.First()); } } return type; }
private int AddColumnsFromRowAxis(IEnumerable<Tuple> rows, ResultSet crs) { var dimensionProperties = new List<string>(); var columnCount = 0; if (null != rows && rows.Any()) { foreach (var member in rows.First().Members) { var column = new Column {ColumnOrdinal = columnCount++}; SetColumnNameAndType(column, member.LevelName, typeof(string)); column.Items.Add(column.Name); crs.Columns.Add(column); } var dimensionPropertyColumns = rows.SelectMany( (row) => row.Members.SelectMany( // Project the dimension properties so we also get the member's index within the row for each: (member, memberIndex) => member.DimensionProperties.Select( (dimensionProp) => new { DimensionProperty = dimensionProp, MemberIndex = memberIndex }), // Turn all this business into what we're really looking for: (member, x) => new { //ParentColumn = member.LevelName, ChildColumn = x.DimensionProperty.UniqueName, MemberIndex = x.MemberIndex })).Distinct(); // dimension properties are looked at for all rows where the columns above is just the first row // it is very possible to get data in further down rows for a dimension properties that doesn't exist on the first row // an example is in org with parent child where a property may exist for only one level foreach (var dimensionProperty in dimensionPropertyColumns) { var propertyColumn = new Column() {ColumnOrdinal = columnCount}; //only add column if not already added // each column can have a dimension property that may already be present var columnName = dimensionProperty.MemberIndex.ToString(CultureInfo.InvariantCulture) + dimensionProperty.ChildColumn; if (!dimensionProperties.Any(a => string.Equals(a, columnName))) { SetColumnNameAndType(propertyColumn, columnName, typeof(string)); columnCount++; crs.Columns.Add(propertyColumn); propertyColumn.Items.Add(propertyColumn.Name); dimensionProperties.Add(dimensionProperty.ChildColumn); } } } return columnCount; }
private ColumnMap GetColumnMap(Column column, string columnName = null) { var name = columnName ?? column.Name; var nameMatch =_columnMap.SingleOrDefault(a => string.Equals(a.NameWithoutPrefixes, name)); var valueMatch = _columnMap.SingleOrDefault(a => string.Equals(a.Value.ToString(), name)); var ordinalMatch = _columnMap.SingleOrDefault(a => ConvertIt(a.NameWithoutPrefixes) == column.ColumnOrdinal); return nameMatch ?? valueMatch ?? ordinalMatch; }
private void AddColumnsFromColumnAxis(IEnumerable<Tuple> columns, IEnumerable<Cell> cells, ResultSet crs) { var cellOrdinal = 0; var columnOrdinal = crs.Columns.Count; foreach (var tuple in columns) { var sb = new StringBuilder(); var column = new Column(); foreach (var member in tuple.Members) { sb.Append(member.UniqueName); column.Items.Add(member.Caption); } column.CellOrdinal = ++cellOrdinal; column.ColumnOrdinal = columnOrdinal++; SetColumnNameAndType(column, sb.ToString()); crs.Columns.Add(column); } // this is done after all the columns are added because we need to know the total column count for any of the modus math to work correctly // at least any of the modulus math i could think of so far :) crs.Columns.Where(a => a.Type == null).ToList().ForEach(a => a.Type = GetTypeForColumn(cells, a, cellOrdinal)); }