private static void AdjustValueFromColumnType(Cell cell, int columnIndex, ResultSet crs) { // change type was giving odd results when a culture was passed in on the thread, for example German 5.324145E1 came out as 5324145 instead of 53.24145 // we give it invariant culture to fix this. It will be up to the end user to apply formatting. cell.Value = Convert.ChangeType(cell.Value, crs.Columns[columnIndex].Type ?? ConvertXmlTypeToType(cell.Type), CultureInfo.InvariantCulture); }
private void AddRows(IEnumerable<Tuple> rows, List<Cell> cells, int rowColumnCount, ResultSet crs) { var start = 0; var columnCountFromColumnAxis = crs.Columns.Count - rowColumnCount; var finish = columnCountFromColumnAxis - 1; var cellsIndexer = 0; var cellsCount = cells.Count(); var ordinal = 0; if (!rows.Any() && cells.Count > 0) { // data coming back from the cube only has cell for actual data, nulls are not represented. We need to fill in those cells so that the data appears // in the correct columns var ordinals = cells.Select(a => a.Ordinal); Enumerable.Range(0, columnCountFromColumnAxis) .Except(ordinals) .ToList() .ForEach(a => cells.Add(new Cell() { Ordinal = a})); cells.ForEach(a => AdjustValueFromColumnType(a, a.Ordinal, crs)); crs.Rows.Add(new Row() { Cells = cells.OrderBy(a => a.Ordinal).ToList() }); } else { // tokened maps that get properties from members in the row var memberProperties = _columnMap.GetMemberProperties(); var columnsAdded = memberProperties.Count(); AddColumnsFromRowProperties(crs, memberProperties); foreach (var row in rows) { var r = new Row(); // main row data foreach (var member in row.Members) { r.Cells.Add(new Cell() { FormattedValue = member.Caption, Value = member.Caption, Ordinal = ordinal++ }); } // dimension property row data // this is done as another pass since dimension properties columns are added at the end of normal columns from row foreach (var property in row.Members.Where(member => member.DimensionProperties != null).SelectMany(member => member.DimensionProperties)) { r.Cells.Add(new Cell() { FormattedValue = property.Value, Value = property.Value, Ordinal = ordinal++ }); } // cells are in a single dimension array, have to determine which row it belongs to to intermix the row data correctly for (var i = start; i <= finish; i++) { var cellToAdd = new Cell(); // cell indexer can go past its range, only try to get values while in range if (!(cellsIndexer >= cellsCount)) { // get this cell var cell = cells[cellsIndexer]; // if the ordinal of the cell is the column we are looking at, add it's values, otherwise an empty cell is added. // this is done because the xml coming back does not include nulls/empty data. We have to fill in the gap or the subsequent objects will throw the data off if (Convert.ToInt32(cell.Ordinal) == i) { cellToAdd = cell; AdjustValueFromColumnType(cellToAdd, cell.Ordinal % (columnCountFromColumnAxis) + rowColumnCount, crs); cellsIndexer++; } } cellToAdd.Ordinal = ordinal++; r.Cells.Add(cellToAdd); } // go threw the members again, this time for the special columns, this is done here since the columns for them are done at the end // if we tried to adding the cells in the for above, it would through the ordinals off for all cells. if (columnsAdded > 0) { for (var i = 0; i < row.Members.Count; i++ ) { var previousCount = r.Cells.Count; r.Cells.AddRange(AddCellsFromMemberProperties(memberProperties, row.Members[i], ordinal, i)); if (previousCount != r.Cells.Count) { // advance the ordinal since extra columns were added, the normal process would only take into consideration // the cells visible in ssms ordinal = r.Cells.Last().Ordinal + 1; } } } crs.Rows.Add(r); start += columnCountFromColumnAxis; finish += columnCountFromColumnAxis; } } }
private static IEnumerable<Cell> AddCellsFromMemberProperties(IEnumerable<ColumnMap> specialColumns, Member member, int cellOrdinal, int columnOrdinal) { Func<ColumnMap, Cell> newCell = (map) => { object formattedValue = map.GetMemberProperty(member); var value = formattedValue; var type = "string"; if (map.IsLevelNumber) { type = "xsd:int"; value = Convert.ChangeType(formattedValue, typeof (int), CultureInfo.InvariantCulture); } var cell = new Cell() { Ordinal = cellOrdinal++, FormattedValue = formattedValue, Type = type, Value = value }; return cell; }; return specialColumns .Where(a => a.DoesMapMatchMember(member, columnOrdinal)) .Select(newCell); }