Let's discuss how to implement Generic CSV Writer which may take an input from any list and return a CSV string or write to a certain file, if specified. Although, this is a generic C# implementation and can be used in any .NET Framework supporting generics. Yet, we are going to discuss this with .NET Core. We are going to use .NET Core Console Application which is in continuation to Welcome to .NET Core Console Application.
Add new Class in DotNetCore.ConsoleApplication
We are going to add a new class CsvWriter in DotNetCore.ConsoleApplication.
- Open existing solution in Visual Studio 2015.
- Now, add a new class CsvWriter.cs.
- Open Add New Item Screen through DotNetCore.ConsoleApplication Context Menu of Common folder >> Add >> Class >> Installed >> .NET Core >> Class.
- Name it CsvWriter.cs.
- Click OK button.
- Add CsvWriter implementation.
- Write<T> (IList<T> list, bool includeHeader = true).
- Creates and returns the generated CSV.
- Write<T> (IList<T> list, string fileName, bool includeHeader = true)
Creates and returns the generated CSV and saves the generated CSV to the specified path. - CreateCsvHeaderLine
- Creates CSV header line, if includeHeader is set true.
- CreateCsvLine<T>(T item, PropertyInfo[] properties).
Creates a CSV line for the given type of the object.
- CreateCsvLine(IList<string> list).
Creates a CSV line for the given list of the string by joining them, demarcated by comma.
- CreateCsvItem
Adds the provided value item to the processed list, used to create CSV line.
- CreateCsvStringListItem
Adds the provided string list as a single item to the processed list, which is used to create CSV line.
- CreateCsvStringArrayItem
Adds the provided string array as a single item to the processed list, which is used to create CSV line.
- CreateCsvStringItem
Adds the provided string value item to the processed list, used to create CSV line.
- ProcessStringEscapeSequence
Processes the provided data to handle double quotes and comma value. If we do not apply escape sequences, they can corrupt the data.
- WriteFile
Writes the generated CSV data to the file.
- public class CsvWriter {
- privateconst string DELIMITER = ",";
-
- public string Write < T > (IList < T > list, bool includeHeader = true) {
- StringBuildersb = new StringBuilder();
-
- Type type = typeof(T);
-
- PropertyInfo[] properties = type.GetProperties();
-
- if (includeHeader) {
- sb.AppendLine(this.CreateCsvHeaderLine(properties));
- }
-
- foreach(var item in list) {
- sb.AppendLine(this.CreateCsvLine(item, properties));
- }
-
- returnsb.ToString();
- }
-
- public string Write < T > (IList < T > list, string fileName, bool includeHeader = true) {
- string csv = this.Write(list, includeHeader);
-
- this.WriteFile(fileName, csv);
-
- return csv;
- }
-
- private string CreateCsvHeaderLine(PropertyInfo[] properties) {
- List < string > propertyValues = new List < string > ();
-
- foreach(var prop in properties) {
- stringstringformatString = string.Empty;
- string value = prop.Name;
-
- var attribute = prop.GetCustomAttribute(typeof(DisplayAttribute));
- if (attribute != null) {
- value = (attribute as DisplayAttribute).Name;
- }
-
- this.CreateCsvStringItem(propertyValues, value);
- }
-
- returnthis.CreateCsvLine(propertyValues);
- }
-
- private string CreateCsvLine < T > (T item, PropertyInfo[] properties) {
- List < string > propertyValues = new List < string > ();
-
- foreach(var prop in properties) {
- stringstringformatString = string.Empty;
- object value = prop.GetValue(item, null);
-
- if (prop.PropertyType == typeof(string)) {
- this.CreateCsvStringItem(propertyValues, value);
- } else if (prop.PropertyType == typeof(string[])) {
- this.CreateCsvStringArrayItem(propertyValues, value);
- } else if (prop.PropertyType == typeof(List < string > )) {
- this.CreateCsvStringListItem(propertyValues, value);
- } else {
- this.CreateCsvItem(propertyValues, value);
- }
- }
-
- returnthis.CreateCsvLine(propertyValues);
- }
-
- private string CreateCsvLine(IList < string > list) {
- returnstring.Join(CsvWriter.DELIMITER, list);
- }
-
- private void CreateCsvItem(List < string > propertyValues, object value) {
- if (value != null) {
- propertyValues.Add(value.ToString());
- } else {
- propertyValues.Add(string.Empty);
- }
- }
-
- private void CreateCsvStringListItem(List < string > propertyValues, object value) {
- string formatString = "\"{0}\"";
- if (value != null) {
- value = this.CreateCsvLine((List < string > ) value);
- propertyValues.Add(string.Format(formatString, this.ProcessStringEscapeSequence(value)));
- } else {
- propertyValues.Add(string.Empty);
- }
- }
-
- private void CreateCsvStringArrayItem(List < string > propertyValues, object value) {
- string formatString = "\"{0}\"";
- if (value != null) {
- value = this.CreateCsvLine(((string[]) value).ToList());
- propertyValues.Add(string.Format(formatString, this.ProcessStringEscapeSequence(value)));
- } else {
- propertyValues.Add(string.Empty);
- }
- }
-
- private void CreateCsvStringItem(List < string > propertyValues, object value) {
- string formatString = "\"{0}\"";
- if (value != null) {
- propertyValues.Add(string.Format(formatString, this.ProcessStringEscapeSequence(value)));
- } else {
- propertyValues.Add(string.Empty);
- }
- }
-
- private string ProcessStringEscapeSequence(object value) {
- returnvalue.ToString().Replace("\"", "\"\"");
- }
-
- public bool WriteFile(string fileName, string csv) {
- boolfileCreated = false;
-
- if (!string.IsNullOrWhiteSpace(fileName)) {
- File.WriteAllText(fileName, csv);
-
- fileCreated = true;
- }
-
- returnfileCreated;
- }
- }
Add Test Model Class in DotNetCore.ConsoleApplication
We are going to add a new class TestVM in DotNetCore.ConsoleApplication.
- Open the existing Solution in Visual Studio 2015.
- Now, add a new class TestVM.cs.
- Open Add New Item Screen through DotNetCore.ConsoleApplication Context Menu of Common folder >> Add >> Class >> Installed >> .NET Core >> Class.
- Name it TestVM.cs.
- Click OK button.
- Add TestVM implementation.
- Update Program.cs to initialize List<TestVM> with the dummy data and call CsvWriter.
- public class TestVM {
- [Display(Name = "Test Id")]
- publicintTestId {
- get;
- set;
- }
- [Display(Name = "Name")]
- public string TestName {
- get;
- set;
- }
- }
-
- public class Program {
- public static void Main(string[] args) {
- Console.WriteLine("Welcome to .NET Core Console Application");
- List < TestVM > tests = new List < TestVM > {
- newTestVM {
- TestId = 1, TestName = "Bill Gates"
- },
- newTestVM {
- TestId = 2, TestName = "Warren Buffett"
- },
- newTestVM {
- TestId = 3, TestName = "Amancio Ortega"
- },
- newTestVM {
- TestId = 4, TestName = "Carlos Slim Helu"
- }
- };
- stringstringfileName = string.Format("{0}\\test.csv", System.AppContext.BaseDirectory);
- CsvWritercsvWriter = new CsvWriter();
- csvWriter.Write(tests, fileName, true);
- Console.WriteLine("{0} has been created.", fileName);
- Console.ReadKey();
- }
- }
Run Application in Debug Mode - Press F5 or Debug Menu >> Start Debugging or Start Console Application button on the toolbar to start the Application in the debugging mode. It will start an Application Console in the debug mode.
- It will generate test.csv at given path. Therefore at C:\ASP.NET Core\CSV Writer\DotNetCore\ConsoleApplication.NetCore\bin\Debug\netcoreapp1.0.
Sample Source Code
I have placed the sample code for this session in ".NET Core CSV Writer_Code.zip" in CodePlex repository.