Last active
June 29, 2020 05:56
-
-
Save MaciejLisCK/8804658 to your computer and use it in GitHub Desktop.
C# CSV Builder using lambda (with escape)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var csvBuilder = new CsvBuilder<User>(); | |
var users = new User[] | |
{ | |
new User() { FirstName = "Maciej", LastName = "Lis", BirthDate = new DateTime(1986,10,31) }, | |
new User() { FirstName = "Krzysztof", LastName = "Lis", BirthDate = new DateTime(1960,1,1), Notes = "Like \".NET Framework\"."}, | |
new User() { FirstName = "Barbara", LastName = "Lis", BirthDate = new DateTime(1960,2,12), Notes = "Buy:\n- 1 orange\n- milk" }, | |
}; | |
var csv = csvBuilder | |
.Build(users, | |
u => u.LastName, | |
u => u.BirthDate.ToShortDateString(), | |
u => u.Notes); | |
var csvWithHeader = csvBuilder | |
.Build(users, | |
new [] {"Last Name", "Birth Date", "Notes"}, | |
u => u.LastName, | |
u => u.BirthDate.ToShortDateString(), | |
u => u.Notes); | |
Console.WriteLine(csv); | |
Console.WriteLine(); | |
Console.WriteLine(csvWithHeader); | |
Console.ReadKey(); | |
} | |
} | |
public class User | |
{ | |
public string FirstName { get; set; } | |
public string LastName { get; set; } | |
public DateTime BirthDate { get; set; } | |
public string Notes { get; set; } | |
} | |
public class CsvBuilder<T> | |
{ | |
protected string[] _escapeIndicators = new[] { ",", "\n", "\"" }; | |
public string Build(IEnumerable<T> objects, params Func<T, string>[] columnsGetters) | |
{ | |
var csv = new StringBuilder(); | |
foreach (var @object in objects) | |
{ | |
var values = columnsGetters.Select(cg => cg(@object)); | |
var row = BuildRow(values); | |
csv.Append(row); | |
} | |
return csv.ToString(); | |
} | |
public string Build(IEnumerable<T> objects, IEnumerable<string> columnsNames, params Func<T, string>[] columnsGetters) | |
{ | |
bool isHeadersAndColumnsLengthEqual = columnsNames.Count() == columnsGetters.Length; | |
if (!isHeadersAndColumnsLengthEqual) | |
throw new ArgumentException("Header length and columns length are not equal."); | |
var header = BuildRow(columnsNames); | |
var values = Build(objects, columnsGetters); | |
var headerWithValues = header + values; | |
return headerWithValues; | |
} | |
protected string BuildRow(IEnumerable<string> values) | |
{ | |
var row = new StringBuilder(); | |
foreach (var value in values) | |
{ | |
var safeValue = value ?? String.Empty; | |
if (HasToEscape(safeValue)) | |
safeValue = EscapeValue(safeValue); | |
row.Append(safeValue); | |
row.Append(","); | |
} | |
row.Length -= 1; | |
row.AppendLine(); | |
return row.ToString(); | |
} | |
protected bool HasToEscape(string value) | |
{ | |
return _escapeIndicators.Any(i => value.Contains(i)); | |
} | |
protected string EscapeValue(string value) | |
{ | |
value = value.Replace("\"", "\"\""); | |
value = "\"" + value + "\""; | |
return value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Lis,1986-10-31, | |
Lis,1960-01-01,"Like "".NET Framework""." | |
Lis,1960-02-12,"Buy: | |
- 1 orange | |
- milk" | |
Last Name,Birth Date,Notes | |
Lis,1986-10-31, | |
Lis,1960-01-01,"Like "".NET Framework""." | |
Lis,1960-02-12,"Buy: | |
- 1 orange | |
- milk" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment