|
| 1 | +--- |
| 2 | +title: Grouping Data Example Using RadSpreadProcessing |
| 3 | +description: Learn how to group data in a worksheet using RadSpreadProcessing for Document Processing. |
| 4 | +type: how-to |
| 5 | +page_title: How to Group Data in RadSpreadProcessing |
| 6 | +meta_title: How to Group Data in RadSpreadProcessing |
| 7 | +slug: grouping-data-using-radspreadprocessing |
| 8 | +tags: document, processing, group, column, excel, spread |
| 9 | +res_type: kb |
| 10 | +ticketid: 1692310 |
| 11 | +--- |
| 12 | + |
| 13 | +<style> |
| 14 | +img[alt$="><"] { |
| 15 | + border: 1px solid lightgrey; |
| 16 | +} |
| 17 | +</style> |
| 18 | + |
| 19 | +## Environment |
| 20 | + |
| 21 | +| Version | Product | Author | |
| 22 | +| ---- | ---- | ---- | |
| 23 | +| 2025.2.520| RadSpreadProcessing |[Desislava Yordanova](https://www.telerik.com/blogs/author/desislava-yordanova)| |
| 24 | + |
| 25 | +## Description |
| 26 | + |
| 27 | +This article shows how to generate a worksheet with **grouped** data from a **flat** collection of records as an input. |
| 28 | + |
| 29 | +>caption Flat vs. Grouped Data |
| 30 | +
|
| 31 | + |
| 32 | + |
| 33 | +## Solution |
| 34 | + |
| 35 | +Note that the grouping should be performed separately beforehand, and only then can the Worksheet be populated with the grouped data. |
| 36 | + |
| 37 | +Once you have the grouped data, the SpreadProcessing functionality (in a similar way to MS Excel) allows you to assign the outline level to all rows that belong to the same group. |
| 38 | +To make it clear and simple, let's take the following example - a flat list of products stored in CSV data: |
| 39 | + |
| 40 | +### Preparing Grouped Data |
| 41 | + |
| 42 | +1. Group your flat data (e.g. Northwind.Products) before populating the worksheet. |
| 43 | +2. Use LINQ or other methods to group rows based on a specific column (e.g. CategoryID). |
| 44 | + |
| 45 | +Use the following code snippet to group rows in a worksheet: |
| 46 | + |
| 47 | +```csharp |
| 48 | + internal class Program |
| 49 | + { |
| 50 | + static void Main(string[] args) |
| 51 | + { |
| 52 | + string fileName = "sample.csv"; |
| 53 | + Workbook workbook; |
| 54 | + |
| 55 | + CsvFormatProvider csv_formatProvider = new CsvFormatProvider(); |
| 56 | + |
| 57 | + using (Stream input = new FileStream(fileName, FileMode.Open)) |
| 58 | + { |
| 59 | + workbook = csv_formatProvider.Import(input, TimeSpan.FromSeconds(10)); |
| 60 | + |
| 61 | + } |
| 62 | + Worksheet worksheet = workbook.ActiveWorksheet; |
| 63 | + |
| 64 | + // Convert worksheet data to DataTable |
| 65 | + DataTable dataTable = WorksheetToDataTable(worksheet); |
| 66 | + |
| 67 | + // Apply grouping and outlining |
| 68 | + Workbook groupedWorkbook= ApplyGroupingToWorksheet(dataTable, new Workbook()); |
| 69 | + |
| 70 | + Telerik.Windows.Documents.Spreadsheet.FormatProviders.IWorkbookFormatProvider xlsx_formatProvider = |
| 71 | + new Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml.Xlsx.XlsxFormatProvider(); |
| 72 | + |
| 73 | + string outputFilePath = "output.xlsx"; |
| 74 | + File.Delete(outputFilePath); |
| 75 | + using (Stream output = new FileStream(outputFilePath, FileMode.Create)) |
| 76 | + { |
| 77 | + xlsx_formatProvider.Export(workbook, output, TimeSpan.FromSeconds(10)); |
| 78 | + } |
| 79 | + |
| 80 | + Process.Start(new ProcessStartInfo() { FileName = outputFilePath, UseShellExecute = true }); |
| 81 | + |
| 82 | + outputFilePath = "groupedOutput.xlsx"; |
| 83 | + File.Delete(outputFilePath); |
| 84 | + using (Stream output = new FileStream(outputFilePath, FileMode.Create)) |
| 85 | + { |
| 86 | + xlsx_formatProvider.Export(groupedWorkbook, output, TimeSpan.FromSeconds(10)); |
| 87 | + } |
| 88 | + |
| 89 | + Process.Start(new ProcessStartInfo() { FileName = outputFilePath, UseShellExecute = true }); |
| 90 | + } |
| 91 | + static DataTable WorksheetToDataTable(Worksheet worksheet) |
| 92 | + { |
| 93 | + DataTable dataTable = new DataTable(); |
| 94 | + |
| 95 | + // Get used range |
| 96 | + CellRange usedRange = worksheet.UsedCellRange; |
| 97 | + |
| 98 | + // Add columns to DataTable (assuming first row contains headers) |
| 99 | + for (int col = 0; col < usedRange.ColumnCount; col++) |
| 100 | + { |
| 101 | + string columnName = worksheet.Cells[0, col].GetValue().Value.RawValue.ToString(); |
| 102 | + dataTable.Columns.Add(columnName ?? $"Column{col}"); |
| 103 | + } |
| 104 | + |
| 105 | + // Add data rows |
| 106 | + for (int row = 1; row < usedRange.RowCount; row++) |
| 107 | + { |
| 108 | + DataRow dataRow = dataTable.NewRow(); |
| 109 | + for (int col = 0; col < usedRange.ColumnCount; col++) |
| 110 | + { |
| 111 | + dataRow[col] = worksheet.Cells[row, col].GetValue().Value.RawValue ?? string.Empty; |
| 112 | + } |
| 113 | + dataTable.Rows.Add(dataRow); |
| 114 | + } |
| 115 | + |
| 116 | + return dataTable; |
| 117 | + } |
| 118 | + |
| 119 | + static Workbook ApplyGroupingToWorksheet(DataTable dataTable, Workbook workbook) |
| 120 | + { |
| 121 | + // Group the data by the sixth column (index 5) |
| 122 | + var groupedResults = from p in dataTable.AsEnumerable() |
| 123 | + group p by p.Field<string>("categoryID") into g |
| 124 | + select new |
| 125 | + { |
| 126 | + categoryID = g.Key, |
| 127 | + productID = string.Join(";", from i in g select i.Field<string>("productID")), |
| 128 | + productName = string.Join(";", from i in g select i.Field<string>("productName")), |
| 129 | + quantityPerUnit = string.Join(";", from i in g select i.Field<string>("quantityPerUnit")), |
| 130 | + CustomunitPriceerLastname = string.Join(";", from i in g select i.Field<string>("unitPrice")), |
| 131 | + unitsInStock = string.Join(";", from i in g select i.Field<string>("unitsInStock")), |
| 132 | + unitsOnOrder = string.Join(";", from i in g select i.Field<string>("unitsOnOrder")) |
| 133 | + }; |
| 134 | + |
| 135 | + |
| 136 | + workbook.Worksheets.Add(); |
| 137 | + Worksheet worksheet = workbook.ActiveWorksheet; |
| 138 | + worksheet.Cells[0, 1].SetValue("productID"); |
| 139 | + worksheet.Cells[0, 2].SetValue("productName"); |
| 140 | + worksheet.Cells[0, 3].SetValue("quantityPerUnit"); |
| 141 | + worksheet.Cells[0, 4].SetValue("unitPrice"); |
| 142 | + // Header is row 0, data starts at row 1 |
| 143 | + int currentRow = 1; |
| 144 | + |
| 145 | + // Process each group |
| 146 | + foreach (var group in groupedResults) |
| 147 | + { |
| 148 | + worksheet.Cells[currentRow, 1].SetValue("CategoryID "+group.categoryID); |
| 149 | + currentRow++; |
| 150 | + |
| 151 | + string[] productsIDs= group.productID.Split(';'); |
| 152 | + string[] productNames = group.productName.Split(';'); |
| 153 | + string[] quantityPerUnits = group.quantityPerUnit.Split(';'); |
| 154 | + string[] unitPrices = group.CustomunitPriceerLastname.Split(';'); |
| 155 | + string[] unitsInStocks = group.unitsInStock.Split(';'); |
| 156 | + string[] unitsOnOrders = group.unitsOnOrder.Split(';'); |
| 157 | + |
| 158 | + int start = currentRow; |
| 159 | + int end= currentRow+ productsIDs.Length - 1; |
| 160 | + for (int i = 0; i < productsIDs.Length; i++) |
| 161 | + { |
| 162 | + worksheet.Cells[currentRow, 1].SetValue(productsIDs[i]); |
| 163 | + worksheet.Cells[currentRow, 2].SetValue(productNames[i]); |
| 164 | + worksheet.Cells[currentRow, 3].SetValue(quantityPerUnits[i]); |
| 165 | + worksheet.Cells[currentRow, 4].SetValue(unitPrices[i]); |
| 166 | + worksheet.Cells[currentRow, 5].SetValue(unitsInStocks[i]); |
| 167 | + worksheet.Cells[currentRow, 6].SetValue(unitsOnOrders[i]); |
| 168 | + currentRow++; |
| 169 | + } |
| 170 | + worksheet.Rows[start, end].Group(); |
| 171 | + } |
| 172 | + return workbook; |
| 173 | + } |
| 174 | + } |
| 175 | +``` |
| 176 | +Modify the example to suit your specific data structure and requirements. |
| 177 | + |
| 178 | +## See Also |
| 179 | + |
| 180 | +- [Grouping in SpreadProcessing]({%slug radspreadprocessing-features-grouping%}) |
0 commit comments