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.
After I added, string csvHeader, the headers get created but the corresponding values are not showing. As shown below.
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)
PS: seems in your example you also missed
string colID = partAttributes.Attribute("colID").Value
to be added to output