diff options
| author | Roy Ben Shabat <roy.mail.net@gmail.com> | 2025-09-09 16:30:00 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <roy.mail.net@gmail.com> | 2025-09-09 16:30:00 +0300 |
| commit | ba37d5082917551fd9a2b194fa1489f1fd86f39b (patch) | |
| tree | e60ec8ec66d7852c5231968983063bd3fe225a0f /Software/Visual_Studio/Tango.CSV | |
| parent | f87208b19e183d309a3bcacd26ecc74c4da728d4 (diff) | |
| download | Tango-ba37d5082917551fd9a2b194fa1489f1fd86f39b.tar.gz Tango-ba37d5082917551fd9a2b194fa1489f1fd86f39b.zip | |
FSE Improved Statistics + Dynamic CSV Export !
Diffstat (limited to 'Software/Visual_Studio/Tango.CSV')
| -rw-r--r-- | Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs | 126 | ||||
| -rw-r--r-- | Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj | 1 |
2 files changed, 127 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs b/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs new file mode 100644 index 000000000..1c460d5e3 --- /dev/null +++ b/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.CSV +{ + public class CsvDynamicWriter + { + private sealed class ColumnInfo + { + public string Name; + public string Default; + public int Index; + public int CreationOrder; + } + + private readonly Dictionary<string, ColumnInfo> _colMap = new Dictionary<string, ColumnInfo>(); + private readonly List<ColumnInfo> _cols = new List<ColumnInfo>(); + private int _creationCounter = 0; + + private readonly List<Dictionary<string, string>> _rows = new List<Dictionary<string, string>>(); + private Dictionary<string, string> _currentRow = new Dictionary<string, string>(); + + /// <summary> + /// Writes a value to the specified column in the current row. + /// If the column does not exist, it is created with the given default value and index. + /// Column order in the CSV header is by (Index asc, CreationOrder asc). + /// </summary> + public void Write(string value, string columnName, string defaultValue, int index) + { + ColumnInfo col; + if (!_colMap.TryGetValue(columnName, out col)) + { + col = new ColumnInfo + { + Name = columnName, + Default = defaultValue, + Index = index, + CreationOrder = _creationCounter++ + }; + _colMap[columnName] = col; + _cols.Add(col); + + // Backfill all prior rows with the column's default. + foreach (var row in _rows) + { + if (!row.ContainsKey(columnName)) + row[columnName] = defaultValue; + } + } + // If the column already exists, we keep the original index/default. + // (If you need reindexing, add an explicit method to change col.Index.) + + _currentRow[columnName] = value ?? ""; + } + + /// <summary> + /// Moves to the next row, finalizing the current one. + /// Missing cells get their column default value. + /// </summary> + public void Next() + { + if (_currentRow == null) _currentRow = new Dictionary<string, string>(); + + foreach (var col in _cols) + { + if (!_currentRow.ContainsKey(col.Name)) + _currentRow[col.Name] = col.Default ?? ""; + } + + _rows.Add(_currentRow); + _currentRow = new Dictionary<string, string>(); + } + + /// <summary> + /// Saves the CSV to disk using the column order defined by (Index, CreationOrder). + /// </summary> + public void Save(string filePath) + { + // Auto-finalize last row if it has any values. + if (_currentRow != null && _currentRow.Count > 0) + Next(); + + var orderedCols = _cols + .OrderBy(c => c.Index) + .ThenBy(c => c.CreationOrder) + .ToList(); + + var sb = new StringBuilder(); + + // Header + sb.AppendLine(string.Join(",", orderedCols.Select(c => EscapeCsv(c.Name)))); + + // Rows + foreach (var row in _rows) + { + var values = new List<string>(orderedCols.Count); + for (int i = 0; i < orderedCols.Count; i++) + { + var name = orderedCols[i].Name; + string v; + if (!row.TryGetValue(name, out v)) + { + // Shouldn't happen (Next() fills), but be defensive. + v = orderedCols[i].Default ?? ""; + } + values.Add(EscapeCsv(v)); + } + sb.AppendLine(string.Join(",", values)); + } + + File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8); + } + + private static string EscapeCsv(string input) + { + if (input == null) return ""; + if (input.IndexOfAny(new[] { ',', '"', '\n', '\r' }) >= 0) + return "\"" + input.Replace("\"", "\"\"") + "\""; + return input; + } + } +} diff --git a/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj b/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj index b6743bede..0fc1948a4 100644 --- a/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj +++ b/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj @@ -81,6 +81,7 @@ </Compile> <Compile Include="CsvDefinition.cs" /> <Compile Include="CsvDestination.cs" /> + <Compile Include="CsvDynamicWriter.cs" /> <Compile Include="CsvFile.cs" /> <Compile Include="CsvFileLinqExtensions.cs" /> <Compile Include="CsvFileReader.cs" /> |
