/// <summary> /// Converts a List<T> to a DataTable. /// </summary> /// <typeparam name="T">The type of the list collection.</typeparam> /// <param name="list">List instance reference.</param> /// <param name="settings">Settings for creating the DataTable</param> /// <returns>A DataTable of the converted list collection.</returns> public static DataTable ToDataTable <T>(this IList <T> list, DataTableSettings settings = null) { var entityType = list.FirstOrDefault()?.GetType() ?? typeof(T); // Lists of type System.String and System.Enum (which includes enumerations and structs) must be handled differently // than primitives and custom objects (e.g. an object that is not type System.Object). if (entityType == typeof(string)) { var dataTable = new DataTable(entityType.Name); dataTable.Columns.Add(entityType.Name, entityType); // Iterate through each item in the list. There is only one cell, so use index 0 to set the value. foreach (T item in list) { var row = dataTable.NewRow(); row[0] = item; dataTable.Rows.Add(row); } return(dataTable); } if (entityType.BaseType == typeof(Enum)) { var dataTable = new DataTable(entityType.Name); dataTable.Columns.Add(entityType.Name, typeof(string)); // Iterate through each item in the list. There is only one cell, so use index 0 to set the value. foreach (string namedConstant in Enum.GetNames(entityType)) { var row = dataTable.NewRow(); row[0] = namedConstant; dataTable.Rows.Add(row); } return(dataTable); } // Check if the type of the list is a primitive type or not. Note that if the type of the list is a custom // object (e.g. an object that is not type System.Object), the underlying type will be null. var underlyingType = Nullable.GetUnderlyingType(entityType) ?? entityType; var primitiveTypes = new List <Type> { typeof(byte), typeof(char), typeof(decimal), typeof(double), typeof(short), typeof(int), typeof(long), typeof(sbyte), typeof(float), typeof(ushort), typeof(uint), typeof(ulong), }; var typeIsPrimitive = primitiveTypes.Contains(underlyingType); // If the type of the list is a primitive, perform a simple conversion. // Otherwise, map the object's properties to columns and fill the cells with the properties' values. if (typeIsPrimitive) { var dataTable = new DataTable(underlyingType.Name); dataTable.Columns.Add(underlyingType.Name, underlyingType); // Iterate through each item in the list. There is only one cell, so use index 0 to set the value. foreach (T item in list) { var row = dataTable.NewRow(); row[0] = item; dataTable.Rows.Add(row); } return(dataTable); } else { // TODO: // 1. Convert lists of type System.Object to a data table. // 2. Handle objects with nested objects (make the column name the name of the object and print "system.object" as the value). var dataTable = new DataTable(settings?.DataTableName ?? entityType.Name); var propertyDescriptorCollection = TypeDescriptor.GetProperties(entityType); List <DataTableColumnSetting> columnsToCreate = new List <DataTableColumnSetting>(); // Iterate through each property in the object and add that property name as a new column in the data table. foreach (PropertyDescriptor propertyDescriptor in propertyDescriptorCollection) { bool isExportable = settings == null; bool adjustToContents = false; double?width = null; string displayName = propertyDescriptor.Name; var columnSetting = settings?.Columns.FirstOrDefault(c => c.PropertyName == propertyDescriptor.Name); if (columnSetting != null) { isExportable = columnSetting.IsExportable; adjustToContents = columnSetting.AdjustToContents; width = columnSetting.Width; displayName = columnSetting.DisplayName ?? columnSetting.PropertyName; } foreach (var attribute in propertyDescriptor.Attributes) { if (attribute is ExcelExportAttribute excelExportAttribute) { isExportable = excelExportAttribute.IsExportable; adjustToContents = excelExportAttribute.AdjustToContents; width = excelExportAttribute.Width; } //if (attribute is DisplayAttribute displayAttribute) //{ // displayName = displayAttribute.GetName(); //} else if (attribute is DisplayNameAttribute displayNameAttribute) { displayName = displayNameAttribute.DisplayName; } } if (isExportable) { // Data tables cannot have nullable columns. The cells can have null values, but the actual columns themselves cannot be nullable. // Therefore, if the current property type is nullable, use the underlying type (e.g. if the type is a nullable int, use int). var propertyType = Nullable.GetUnderlyingType(propertyDescriptor.PropertyType) ?? propertyDescriptor.PropertyType; columnsToCreate.Add(new DataTableColumnSetting { DisplayName = displayName, AdjustToContents = adjustToContents, Width = width, PropertyName = propertyDescriptor.Name, PropertyType = propertyType, Order = columnSetting?.Order ?? 0 }); } } foreach (var columnToCreate in columnsToCreate.Where(c => c.Order > 0).OrderBy(c => c.Order).Concat(columnsToCreate.Where(c => c.Order == 0))) { var column = dataTable.Columns.Add(columnToCreate.DisplayName, columnToCreate.PropertyType); if (columnToCreate.AdjustToContents) { column.ExtendedProperties.Add("AdjustToContents", columnToCreate.AdjustToContents); } if (columnToCreate.Width != null) { column.ExtendedProperties.Add("Width", columnToCreate.Width.Value); } } // Iterate through each object in the list and add a new row in the data table. // Then iterate through each property in the object and add the property's value to the current cell. // Once all properties in the current object have been used, add the row to the data table. foreach (T item in list) { var row = dataTable.NewRow(); foreach (PropertyDescriptor propertyDescriptor in propertyDescriptorCollection) { var columnToCreate = columnsToCreate.FirstOrDefault(c => c.PropertyName == propertyDescriptor.Name); if (columnToCreate != null) { var value = propertyDescriptor.GetValue(item); row[columnToCreate.DisplayName] = value ?? DBNull.Value; } } dataTable.Rows.Add(row); } return(dataTable); } }
protected virtual async Task <DataTable> ConvertSearchResultToDataTableAsync <T>(string company, string grideCode, int?gridViewId, IEnumerable <T> searchResult) { var grid = await _gridQueries.GetGrid(grideCode, company); if (grid == null) { throw new AtlasTechnicalException($"No grid configuration found for {grideCode}."); } DataTableSettings settings = new DataTableSettings(); settings.DataTableName = grid.Name; if (gridViewId.HasValue) { // Use the selected grid view to configure the columns var userGridViewDto = await _gridViewQueries.GetUserGridViewById(_identityService.GetUserName(), company, gridViewId.Value); if (grid == null) { throw new AtlasTechnicalException($"No grid view found for id {gridViewId.Value}."); } var agGridColumns = JsonConvert.DeserializeObject <List <AgGridColumnDto> >(userGridViewDto.GridViewColumnConfig); //var agGridColumnConfigToD = agGridColumnConfig.AgGridColumns.Where(c => !c.Hide).ToList(); foreach (var agGridColumn in agGridColumns) { var gridColumnDto = grid.Columns.FirstOrDefault(c => c.FieldName.Equals(agGridColumn.ColId, StringComparison.InvariantCultureIgnoreCase)); if (gridColumnDto != null) { settings.Columns.Add(new DataTableColumnSetting { DisplayName = gridColumnDto.FriendlyName, IsExportable = !agGridColumn.Hide, // gridColumnDto.IsVisible, PropertyName = gridColumnDto.FieldName, Order = agGridColumns.IndexOf(agGridColumn) + 1 }); } } } else { // Use the grid configuration to configure the columns foreach (var gridColumnDto in grid.Columns) { settings.Columns.Add(new DataTableColumnSetting { DisplayName = gridColumnDto.FriendlyName, IsExportable = gridColumnDto.IsVisible, PropertyName = gridColumnDto.FieldName }); } } var dataTable = searchResult.ToList().ToDataTable(settings); return(dataTable); }