Home > Software design >  How do I add headers to a csv file with C#?
How do I add headers to a csv file with C#?

Time:09-16

my code converts an inventory xml file to a csv file. It works as intended. Now I want to add headers, the issue is, when I add the headers into my code, the list of of items disappear. The desired output is, to add a total of 6 headers and finally, add the corresponding values to each header. The image below, demonstrates what the expected output should be. Expected results

After I added, string csvHeader, the headers get created but the corresponding values are not showing. As shown below. enter image description here

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace myApp{
    class WriteToCSVFile{
        static void Main(String[] args){

            // Open file and rename it.
            //string name;
            string xml = File.ReadAllText("C:\\bartact_inventory.xml");
            XDocument Xdoc = XDocument.Parse(xml);
            string csvHeader = "Application/Fitment"   ","   "Part #"   ","   "Item Description"   
            ","   "Vendor"   ","   "QOH"   ","   "Unit Of Measure";
            XElement xeQBXML = Xdoc.Element("QBXML");
            XElement xeQBXMLMsgsRs = xeQBXML.Element("QBXMLMsgsRs");
            XElement XDEGeneralSummaryReportQueryRs = 
            xeQBXMLMsgsRs.Element("GeneralSummaryReportQueryRs");
            XElement xeReportRet = XDEGeneralSummaryReportQueryRs.Element("ReportRet");
            XElement xeReportData = xeReportRet.Element("ReportData");
            List<XElement> xeDataRows = xeReportData.Elements("DataRow").ToList();
            List<string> csvRows = new List<string>();
            
            for (int rowdata = 0; rowdata < xeDataRows.Count; rowdata  )
            {
                string csvRow = "";
                //string csvHeader = "";
                XElement xeData = xeDataRows[rowdata];
                XElement RowData = xeData.Elements("RowData").ToList().ElementAt(0);
                //Returns Values from RowData which includes year or category and item part number
                string[] partIDs = RowData.Attribute("value").Value.Split(":");
                if(partIDs.Length == 2)
                {
                    csvRow = partIDs[0]   ","   partIDs[1]   ",";
                    //Returns all ColData 
                    List<XElement> xeColData = xeData.Elements("ColData").ToList();
                    for (int colData = 0; colData < xeColData.Count; colData  )
                    {
                        XElement partAttributes = xeColData.ElementAt(colData);
                        string colID = partAttributes.Attribute("colID").Value;
                        string value = partAttributes.Attribute("value").Value;
                        csvRow  = value   ",";

                    }
                    // add cr 
                    //File.WriteAllText("C:\\bartact_inventory.csv",);
                    csvRows.Add(csvRow);

                }

            }
            
          File.WriteAllText("C:\\bartact_inventoy1.csv",string.Join("\n",csvHeader,"\n",csvRows));
        }
    }   
}

CodePudding user response:

Instead of:

string.Join("\n",csvHeader,"\n",csvRows)

Try:

string.Join("\n",csvHeader, string.Join("\n",csvRows.ToArray()))

CodePudding user response:

I'd suggest a couple of changes. First, instead of adding the header when you write the file, add it to your csvRows List before the loop that adds the data:

csvRows.Add(csvHeader);

Second, I wouldn't use the File.WriteAllText and a Join but rather use File.WriteAllLines which lets you skip the join.

File.WriteAllText("C:\\bartact_inventory1.csv", csvRows);

Which at least in my test does what you want. There is also a decent library (ChoETL) that handles writing CSV files along with data conversions etc. that might be worth looking at.

CodePudding user response:

Would recommend to use string builder for all places where we have new line or carriage return operations. For instance instead of doing Join("\n") using new line symbol we can do the following stuff

        var sb = new StringBuilder();
        sb.AppendLine(csvHeader);
        foreach (var csvRow in csvRows)
        {
            sb.AppendLine(csvRow);
        }

        File.WriteAllText("bartact_inventoy1.csv", sb.ToString());

Here the catch, sb.AppendLine will produce proper output with not just new line symbol but also with carriage return (CR)enter image description here

PS: seems in your example you also missed

string colID = partAttributes.Attribute("colID").Value

to be added to output

  • Related