Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the name of headers in CSV file using CSVHelper in C#

I am using CSV Helper library to produce CSV files for the user to to populate and upload into the system. My issue is that the WriteHeader method just writes the attributes of a class with names like "PropertyValue", which is not user friendly. Is there a method I can use to make the text produced user friendly but is still able to successfully map the class to the files data?

My code looks like the following:

public ActionResult UploadPropertyCSV(HttpPostedFileBase file)
    {
        List<PropertyModel> properties = new List<PropertyModel>();
        RIMEDb dbContext = new RIMEDb();
        bool success = false;
        foreach (string requestFiles in Request.Files)
        {
            if (file != null && file.ContentLength > 0 && file.FileName.EndsWith(".csv")) 
            {
                using(StreamReader str = new StreamReader(file.InputStream))
                {
                    using(CsvHelper.CsvReader theReader = new CsvHelper.CsvReader(str))
                    {
                        while (theReader.Read())
                        {
                            RIMUtil.PropertyUploadCSVRowHelper row = new RIMUtil.PropertyUploadCSVRowHelper()
                            {
                                UnitNumber = theReader.GetField(0),
                                StreetNumber = theReader.GetField(1),
                                StreetName = theReader.GetField(2),
                                AlternateAddress = theReader.GetField(3),
                                City = theReader.GetField(4)
                            };

                            Property property = new Property();
                            property.UnitNumber = row.UnitNumber;
                            property.StreetNumber = row.StreetNumber;
                            property.StreetName = row.StreetName;
                            property.AlternateAddress = row.AlternateAddress;
                            property.City = dbContext.PostalCodes.Where(p => p.PostalCode1 == row.PostalCode).FirstOrDefault().City;

                            dbContext.Properties.Add(property);
                            try
                            {
                                dbContext.SaveChanges();
                                success = true;
                            }
                            catch(System.Data.Entity.Validation.DbEntityValidationException ex)
                            {
                                success = false;
                                RIMUtil.LogError("Ptoblem validating fields in database. Please check your CSV file for errors.");
                            }
                            catch(Exception e)
                            {
                                RIMUtil.LogError("Error saving property to database. Please check your CSV file for errors.");
                            }
                        }
                    }
                }
            }
        }
        return Json(success);
    }

I'm wondering if theres some metadata tag or something I can put on top of each attribute in my PropertyUploadCSVRowHelper class to put the text I want produced in the file

Thanks in advance

like image 666
Mark Avatar asked Jun 27 '16 00:06

Mark


People also ask

Can CSV files have headers?

A header of the CSV file is an array of values assigned to each of the columns. It acts as a row header for the data. Initially, the CSV file is converted to a data frame and then a header is added to the data frame. The contents of the data frame are again stored back into the CSV file.


2 Answers

Not sure if this existed 2 years ago but now, we can change the property/column name by using the following attribute function:

[CsvHelper.Configuration.Attributes.Name("Column/Field Name")] 

Full code:

using CsvHelper;
using System.Collections.Generic;
using System.IO;

namespace Test
{
    class Program
    {
        class CsvColumns
        {
            private string column_01;

            [CsvHelper.Configuration.Attributes.Name("Column 01")] // changes header/column name Column_01 to Column 01
            public string Column_01 { get => column_01; set => column_01 = value; }
        }

        static void Main(string[] args)
        {
            List<CsvColumns> csvOutput = new List<CsvColumns>();
            CsvColumns rows = new CsvColumns();
            rows.Column_01 = "data1";
            csvOutput.Add(rows);

            string filename = "test.csv";
            using (StreamWriter writer = File.CreateText(filename))
            {
                CsvWriter csv = new CsvWriter(writer);
                csv.WriteRecords(csvOutput);
            }
        }
    }
}
like image 185
Zunair Avatar answered Nov 14 '22 23:11

Zunair


This might not be answering your question directly as you said you wanted to use csvhelper, but if you're only writing small size files (this is a simple function that I use to generate csv. Note, csvhelper will be much better for larger files as this is just building a string and not streaming the data.

Just customise the columns array in the code below variable to suit your needs.

public string GetCsv(string[] columns, List<object[]> data)
{
    StringBuilder CsvData = new StringBuilder();

    //add column headers
    string[] s = new string[columns.Length];
    for (Int32 j = 0; j < columns.Length; j++)
    {
        s[j] = columns[j];
        if (s[j].Contains("\"")) //replace " with ""
            s[j].Replace("\"", "\"\"");
        if (s[j].Contains("\"") || s[j].Contains(" ")) //add "'s around any string with space or "
            s[j] = "\"" + s[j] + "\"";
    }
    CsvData.AppendLine(string.Join(",", s));

    //add rows
    foreach (var row in data)
    {
        for (int j = 0; j < columns.Length; j++)
        {
            s[j] = row[j] == null ? "" : row[j].ToString();
            if (s[j].Contains("\"")) //replace " with ""
                s[j].Replace("\"", "\"\"");
            if (s[j].Contains("\"") || s[j].Contains(" ")) //add "'s around any string with space or "
                s[j] = "\"" + s[j] + "\"";
        }
        CsvData.AppendLine(string.Join(",", s));
    }

    return CsvData.ToString();

}

Here is a fiddle example of how to use it: https://dotnetfiddle.net/2WHf6o

Good luck.

like image 35
Gary Holland Avatar answered Nov 14 '22 22:11

Gary Holland