I have a list of entries that belong to different components, some of these entries are duplicated between several components, I now want you to show me a table based on this order ("Number\tStatus\tComponents\tDescription") in which you show all entries and their components but for duplicated entries you only show them once but in the column tComponents you show all components in which the entry is duplicated separated with a comma
as Example :
I have already written the following two codes but it doesn't work as described above, it generates its own table for each component and what I don't want, I want a table with all entries and their associated components and for duplicate entries write the entries once and in which components are duplicated separated with a comma.
public void ReleaseNotes(string unit, string repository, List<string> paths, string commit, string branch, string anfangTag, string endeTag, string compareBranch, DateTime? startDate, DateTime? endDate, string targetFile) { // Connect to Azure DevOps Services var connection = connectionService.GetTfsConnection(); GitVersionDescriptor sourceVersion = null; GitVersionDescriptor targetVersion = null; var release = new Release(unit, repository, paths.Any() ? paths : new List<string>() { string.Empty }); Console.WriteLine($"ReleaseNotes generation to file: '{targetFile}' starting...{Environment.NewLine}"); StringBuilder stringBuilder = new StringBuilder(); // Dictionary zum Speichern von bereits behandelten Komponenten Dictionary<string, HashSet<int>> processedWorkItems = new Dictionary<string, HashSet<int>>(); foreach (ReleaseUnit releaseUnit in release.ReleaseUnits) { // Prüfen, ob die Komponente bereits behandelt wurde if (processedWorkItems.ContainsKey(releaseUnit.Name)) { continue; } Console.WriteLine($"Collect data for '{releaseUnit.Name}':"); if (!string.IsNullOrEmpty(commit)) sourceVersion = new GitVersionDescriptor { VersionType = GitVersionType.Commit, Version = commit }; if (!string.IsNullOrEmpty(branch)) sourceVersion = new GitVersionDescriptor { VersionType = GitVersionType.Branch, Version = branch }; if (!string.IsNullOrEmpty(anfangTag)) sourceVersion = new GitVersionDescriptor { VersionType = GitVersionType.Tag, Version = anfangTag }; if (!string.IsNullOrEmpty(compareBranch)) targetVersion = new GitVersionDescriptor { VersionType = GitVersionType.Branch, Version = compareBranch }; if (!string.IsNullOrEmpty(endeTag)) targetVersion = new GitVersionDescriptor { VersionType = GitVersionType.Tag, Version = endeTag }; List<WorkItem> features = new List<WorkItem>(); List<WorkItem> bugs = new List<WorkItem>(); Version releaseUnitVersion = null; foreach (var artifactUnit in releaseUnit.ArtifactUnits) { Version version; var workItems = GetWorkItems(artifactUnit, sourceVersion, targetVersion, startDate, endDate, out version).ToList(); bugs.AddRange(workItems.Where(a => (string)a.Fields["System.WorkItemType"] == "Fehler")); features.AddRange(workItems.Where(a => (string)a.Fields["System.WorkItemType"] != "Fehler")); if (releaseUnitVersion == null || releaseUnitVersion < version) { releaseUnitVersion = version; } } //Markiere die Komponente als behandelt if (features.Any()) { var uniqueFeatureIds = new HashSet<int>(features.Select(f => f.Id.GetValueOrDefault())); processedWorkItems[releaseUnit.Name] = uniqueFeatureIds; } var headerName = $"{releaseUnit.Name}:"; stringBuilder.AppendLine(headerName); stringBuilder.AppendLine(new string('=', headerName.Length)); if (releaseUnitVersion != null) { stringBuilder.AppendLine(); stringBuilder.AppendLine($"V{releaseUnitVersion}"); } // Remove WorkItems with Tag 'Intern' bugs = RemoveInternWorkItems(bugs); features = RemoveInternWorkItems(features); PrintDetails("1. Fehlerbehebungen", bugs, releaseUnit.Name, stringBuilder); PrintDetails("2. Neue Funktionen", features, releaseUnit.Name, stringBuilder); stringBuilder.AppendLine(); stringBuilder.AppendLine($"{Environment.NewLine}{Environment.NewLine}{DescriptionInProgress}"); stringBuilder.AppendLine(); stringBuilder.AppendLine(); } // Write results to separate file File.AppendAllText(targetFile, stringBuilder.ToString()); Console.WriteLine("Generation finished."); Console.WriteLine(); } private static void PrintDetails(string category, List<WorkItem> workItems, string releaseUnitName, StringBuilder stringBuilder) { stringBuilder.AppendLine($"{Environment.NewLine}{category}"); if (workItems.Any()) { stringBuilder.AppendLine("Nummer\tStatus\tKomponenten\tBeschreibung"); stringBuilder.AppendLine("------\t------\t-----------\t------------"); foreach (var workItem in workItems) { var id = workItem.Id; // Überprüfen, ob die ID bereits gedruckt wurde if (stringBuilder.ToString().Contains($"{id}")) { //stringBuilder.AppendLine($"\t\t\t\tDuplikat entfernt (ID: {id})"); continue; // Überspringe Duplikate } var state = workItem.Fields["System.State"].ToString(); var title = workItem.Fields["System.Title"]; var componente = releaseUnitName; var tabsAfterState = "\t"; if (!string.IsNullOrEmpty(state) && state.Length <= 8) { tabsAfterState += "\t"; } stringBuilder.AppendLine($"{id}\t{state}{tabsAfterState}{componente}{tabsAfterState}{title}"); // Zugriff auf Fields vor der Gruppierung workItem.Fields.TryGetValue("HZD.ReleaseNotes", out var releaseNotesHtml); if (releaseNotesHtml != null) { var releaseNotes = HtmlConverter.ConvertToPlainText(releaseNotesHtml.ToString()); var lines = releaseNotes.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line)) continue; stringBuilder.AppendLine($"\t\t\t{tabsAfterState}\t{Regex.Replace(line, "^ \\* ", "- ")}"); } stringBuilder.AppendLine(); } } } else { stringBuilder.AppendLine(NoWorkItems); } }