CSV Parse out object c# - c#

I need some help with parsing out a CSV we get it like this
OrderNumber,LineNumber,CustomerNumber,CustomerName,AddressLine1,AddressLine2,AddressLine3,AddressLine4,AddressLine5,PostCode,ProductCode,ProductName,Ordered,Left,Picked
we can have multiple lines for an order so we would get
order Number
CustomerNumber
CustomerName
AddressLine1
AddressLine2
AddressLine3
AddressLine4
AddressLine5
PostCode
matching multiple times I need a way of parsing this out to be this structure
<orderDespatchRequest>
<despatchDetails>
<clientCustomerId>CustomerNumber</clientCustomerId>
<clientOrderNumber>OrderNumber</clientOrderNumber>
<dateDespatch>2015-07-01T00:00:00</dateDespatch>
<despatchedDetail>
<orderDespatchDetail>
<lineNumber>LineNumber</lineNumber>
<productCode>ProductCode</productCode>
<productName>ProductName</productName>
<quantity>Picked</quantity>
</orderDespatchDetail>
</despatchedDetail>
</despatchDetails>
</orderDespatchRequest>
Hope someone can Help?
This is what I have got so far
public bool ExtractCSV(string file)
{
#region set up new dataTable
dt = new DataTable("Header");
dt.Columns.Add("OrderNumber", typeof(string));
dt.Columns.Add("Company", typeof(string));
dt.Columns.Add("AddressLine1", typeof(string));
dt.Columns.Add("AddressLine2", typeof(string));
dt.Columns.Add("AddressLine3", typeof(string));
dt.Columns.Add("AddressLine4", typeof(string));
dt.Columns.Add("AddressLine5", typeof(string));
dt.Columns.Add("PostCode", typeof(string));
detailTable = new DataTable("Details");
detailTable.Columns.Add("OrderNumber", typeof(string));
detailTable.Columns.Add("LineNumber", typeof(int));
detailTable.Columns.Add("ProductCode", typeof(string));
detailTable.Columns.Add("ProductName", typeof(string));
detailTable.Columns.Add("OrderQty", typeof(int));
detailTable.Columns.Add("OutstandingQty", typeof(int));
detailTable.Columns.Add("DespatchedQty", typeof(string));
detailTable.PrimaryKey = new DataColumn[] { detailTable.Columns["OrderNumber"] };
#endregion
#region Fill the table
// read in the csv file
string[] csvRows = File.ReadAllLines(file);
string[] fields = null;
foreach (string csvRow in csvRows)
{
fields = csvRow.Split(',');
string orderNumber = fields[0].ToString();
string customerNumber = fields[2].ToString();
string Company = fields[3].ToString();
string AddressLine1 = fields[4].ToString();
string AddressLine2 = fields[5].ToString();
string AddressLine3 = fields[6].ToString();
string AddressLine4 = fields[7].ToString();
string AddressLine5 = fields[8].ToString();
string PostCode = fields[9].ToString();
int LineNumber = Convert.ToInt32(fields[1]);
string ProductCode = fields[10].ToString();
string ProductName = fields[11].ToString();
int OrderQty = Convert.ToInt32(fields[12]);
int OutstandingQty = Convert.ToInt32(fields[13]);
int DespatchedQty = Convert.ToInt32(fields[14]);
dt.Rows.Add(orderNumber, Company, AddressLine1, AddressLine2, AddressLine3, AddressLine4, AddressLine5,PostCode);
detailTable.Rows.Add(orderNumber, ProductCode, ProductName, OrderQty, OutstandingQty, DespatchedQty);
}
#endregion
var query = from row in detailTable.AsEnumerable()
group row by row.Field<string>("OrderNumber") into grp
select new DataClass()
{
OrderNumber = grp.Key,
Details = grp
};
OrderDespatchDetail detail = new OrderDespatchDetail();
DespatchDetails despatchDetail = new DespatchDetails();
string orderNo = string.Empty;
string custNo = string.Empty;
foreach (DataRow item in query)
{
DataRow found = dt.Rows.Find(item.Field<string>("OrderNumber"));
if (orderNo != found.Field<string>("OrderNumber"))
{
}
detail.LineNumber = item.Field<int>("LineNumber");
detail.ProductCode = item.Field<string>("ProductCode");
detail.ProductName = item.Field<string>("ProductName");
detail.Quantity = item.Field<int>("");
}
OrderDespatchRequest request = new OrderDespatchRequest();
request.despatchDetails = despatchDetail;
return SendOrderDespatch(request);
}
Could be well off the path with it.
Regards
Aidan

As an example the following should get you started.
Read the CSV File
var rows = (from row in File.ReadAllLines("Test.csv")
let item = row.Split(',')
select new
{
OrderNumber = item[0],
LineNumber = item[1],
CustomerID = item[2],
Company = item[3],
AddressLine1 = item[4],
AddressLine2 = item[5],
AddressLine3 = item[6],
AddressLine4 = item[7],
AddressLine5 = item[8],
PostCode = item[9],
ProductCode = item[10].ToString(),
ProductName = item[11].ToString(),
OrderQty = item[12],
OutstandingQty = item[13],
DespatchedQty = item[14]
}).ToList();
Group the data per order into a dynamic type.
var orders = from p in rows
group p by new { OrderNumber = p.OrderNumber, CustomerID = p.CustomerID } into g
select new { OrderNumber = g.Key.OrderNumber, CustomerID = g.Key.CustomerID, OrderLines = g.ToList() };
Create the XML file (please note the output xml will not match your exact requirement, but this example should get you going).
var xEle = new XElement("Orders",
from order in orders
select new XElement("Order",
new XAttribute("OrderNumber", order.OrderNumber),
new XElement("CustomerId", order.CustomerID)
, from line in order.OrderLines
select new XElement("Line", new XAttribute("ProductCode", line.ProductCode),
new XElement("OrderQty", line.OrderQty))));
xEle.Save("orders.xml");
Console.WriteLine("Converted to XML");

Related

add two group into one group in c#

I have two groups like below, theyh have different data. Based on both I need to create an xml file .
How can I write a for-loop for both groups and generate a single xml file?
var groups = checkFile.AsEnumerable().GroupBy(x => new { DocNum = x.Field<int>("orderid"), Type = x.Field<string>("Type"), ProdName = x.Field<string>("ProdName"), Status = x.Field<string>("Status"), productno = x.Field<string>("productno"), uom = x.Field<string>("uom"), customer = x.Field<string>("customer"), remark = x.Field<string>("remark"), U_JobNumber = x.Field<string>("U_JobNumber"), U_SalesPerson = x.Field<string>("U_SalesPerson"), U_POnum = x.Field<string>("U_POnum"), U_JobType = x.Field<string>("U_JobType"), PlannedQty = x.Field<decimal>("PlannedQty"), OriginNum = x.Field<int?>("OriginNum"), orderdate = x.Field<DateTime>("orderdate"), duedate = x.Field<DateTime>("duedate"), DocTotal = x.Field<decimal>("DocTotal") });
var groups2 = checkFile2.AsEnumerable().GroupBy(x => new { DocNum = x.Field<int>("DocNum") });
//now i need to take both group data inside this loop to print the file
foreach (var group in groups)
{
var stringwriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { Indent = true }))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
xmlWriter.WriteEndElement();
}
var xml = stringwriter.ToString();
XmlDocument docSave = new XmlDocument();
docSave.LoadXml(stringwriter.ToString());
docSave.Save(System.IO.Path.Combine(#SystemSettings.ImportBankStatementPendingFolderPath, "DocNum -" + group.Key.DocNum + ".xml"));
count++;
}
Try following :
DataTable checkFile = new DataTable();
var groups = checkFile.AsEnumerable().GroupBy(x => new
{
DocNum = x.Field<int>("orderid"),
Type = x.Field<string>("Type"),
ProdName = x.Field<string>("ProdName"),
Status = x.Field<string>("Status"),
productno = x.Field<string>("productno"),
uom = x.Field<string>("uom"),
customer = x.Field<string>("customer"),
remark = x.Field<string>("remark"),
U_JobNumber = x.Field<string>("U_JobNumber"),
U_SalesPerson = x.Field<string>("U_SalesPerson"),
U_POnum = x.Field<string>("U_POnum"),
U_JobType = x.Field<string>("U_JobType"),
PlannedQty = x.Field<decimal>("PlannedQty"),
OriginNum = x.Field<int?>("OriginNum"),
orderdate = x.Field<DateTime>("orderdate"),
duedate = x.Field<DateTime>("duedate"),
DocTotal = x.Field<decimal>("DocTotal")
});
DataTable checkFile2 = new DataTable();
//now i need to take both group data inside this loop to print the file
foreach (var group in groups)
{
List<DataRow> groups2 = checkFile2.AsEnumerable().Where(x => group.Key.DocNum == x.Field<int>("DocNum")).ToList();
}

Linq Expression works on Desktop but errors on Server

This is the strangest thing I've ever seen, but hopefully someone else has because I am clueless. I have the following code:
DataTable dt = (DataTable)dataGridView1.DataSource;
List<InvoiceItem> itemList = new List<InvoiceItem>();
int listSize = 30;
int listIndex = 0;
try
{
itemList = (from DataRow dr in dt.Rows
select new InvoiceItem()
{
CustomerRef = dr["CustomerRef"].ToString(),
Description = dr["Description"].ToString(),
ItemRef = dr["ItemRef"].ToString(),
Rate = Convert.ToDouble(dr["Rate"].ToString()),
Quantity = Convert.ToDouble(dr["Quantity"].ToString()),
PONumber = dr["PONumber"].ToString(),
UnitOfMeasure = dr["UnitOfMeasure"].ToString(),
RefNumber = dr["RefNumber"].ToString(),
Total = Convert.ToDouble(dr["Total"].ToString()),
Address1 = dr["Address1"].ToString(),
Address2 = dr["Address2"].ToString(),
Address3 = dr["Address3"].ToString(),
Address4 = dr["Address4"].ToString(),
City = dr["City"].ToString(),
State = dr["State"].ToString(),
PostalCode = dr["PostalCode"].ToString(),
ServiceDate = string.IsNullOrEmpty(dr["ServiceDate"].ToString()) ? (DateTime?)null : DateTime.Parse(dr["ServiceDate"].ToString()),
TxnDate = string.IsNullOrEmpty(dr["TxnDate"].ToString()) ? DateTime.Now : DateTime.Parse(dr["TxnDate"].ToString()),
Note = dr["Note"].ToString()
}).ToList();
List<string> list = new List<string>();
list = loadItems();
List<InvoiceItem> createNewItemsList = new List<InvoiceItem>();
foreach (var importing in itemList)
{
var matchingvalues = list.Where(l => l.Contains(importing.ItemRef));
//If there is no match in Quickbooks already...
if (matchingvalues.Count() < 1)
{
createNewItemsList.Add(new InvoiceItem
{
ItemRef = importing.ItemRef,
UnitOfMeasure = importing.UnitOfMeasure
});
}
}
Here is the Code for loadItems():
private List<string> loadItems()
{
string request = "ItemQueryRq";
connectToQB();
int count = getCount(request);
IMsgSetResponse responseMsgSet = sessionManager.processRequestFromQB(BuildItemQuery());
string[] itemList = parseItemQueryRs(responseMsgSet, count);
disconnectFromQB();
List<string> list = new List<string>(itemList);
return list;
}
Here is a view of the error:
here shows list count:
When I run this code on my deskotp, if matchingvalues.Count() = 0 it executes the code correctly. However, when I run the exact same code in debug on the server, that line of code errors out with "Object reference not set to an instance of an object." Can anybody explain why this might happen and if there is any work around for it?

DataTable Row Count is Empty

I'm attempting to take a list of Contacts that are retrieved from an OleDB query, add them to a List and then load the List into a DataTable. When I count the number of items in the list it results in the correct number (27000).
However, when I count the number of rows in the DataTable, it results in 0. After doing this I want to write the DataTable to CSV using FileHelpers, however the CSV file is empty.
This is the code I am using;
var listOfContacts = new List<Contact>();
using (OleDbConnection dbfCon = new OleDbConnection(dbfConstr))
{
dbfCon.Open();
var dbfCmd = new OleDbCommand(#"SELECT ct_id, ct_cmpid, ct_empid,
ct_pplid, ct_cntid, ct_pplnm, ct_date, ct_time, ct_type, ct_doneby, ct_desc
FROM contacts", dbfCon);
using (var myReader = dbfCmd.ExecuteReader())
{
while (myReader.Read())
{
var newContact = new Contact()
{
ContactID = Convert.ToInt32(myReader[0]),
CompanyID = Convert.ToInt32(myReader[1]),
EmployeeID = Convert.ToInt32(myReader[2]),
PersonID = Convert.ToInt32(myReader[3]),
ContractID = Convert.ToInt32(myReader[4]),
PersonName = myReader[5].ToString(),
ContactDate = Convert.ToDateTime(myReader[6]),
ContactTime = Convert.ToDateTime(myReader[7]),
TypeOfContact = myReader[8].ToString(),
ContactMadeBy = myReader[9].ToString(),
ContactDescription = myReader[10].ToString(),
};
listOfContacts.Add(newContact);
}
}
DataTable dTable = new DataTable();
dTable.Columns.Add("ContactID");
dTable.Columns.Add("CompanyID");
dTable.Columns.Add("EmployeeID");
dTable.Columns.Add("PersonID");
dTable.Columns.Add("ContractID");
dTable.Columns.Add("PersonName");
dTable.Columns.Add("ContactDate");
dTable.Columns.Add("ContactTime");
dTable.Columns.Add("TypeOfContact");
dTable.Columns.Add("ContactMadeBy");
dTable.Columns.Add("ContactDescription");
MessageBox.Show(listOfContacts.Count.ToString());
foreach (var contact in listOfContacts)
{
var newRow = dTable.NewRow();
newRow["ContactID"] = contact.ContactID;
newRow["CompanyID"] = contact.CompanyID;
newRow["EmployeeID"] = contact.EmployeeID;
newRow["PersonID"] = contact.PersonID;
newRow["ContractID"] = contact.ContractID;
newRow["PersonName"] = contact.PersonName;
newRow["ContactDate"] = contact.ContactDate;
newRow["ContactTime"] = contact.ContactTime;
newRow["TypeOfContact"] = contact.TypeOfContact;
newRow["ContactMadeBy"] = contact.ContactMadeBy;
newRow["ContactDescription"] = contact.ContactDescription;
}
MessageBox.Show(dTable.Rows.Count.ToString());
You can see the two MessageBox that result in the numbers, am I loading the Data into the DataTable incorrectly?
You have to add the new row to the DataTable:
foreach (var contact in listOfContacts)
{
var newRow = dTable.NewRow();
newRow["ContactID"] = contact.ContactID;
newRow["CompanyID"] = contact.CompanyID;
newRow["EmployeeID"] = contact.EmployeeID;
newRow["PersonID"] = contact.PersonID;
newRow["ContractID"] = contact.ContractID;
newRow["PersonName"] = contact.PersonName;
newRow["ContactDate"] = contact.ContactDate;
newRow["ContactTime"] = contact.ContactTime;
newRow["TypeOfContact"] = contact.TypeOfContact;
newRow["ContactMadeBy"] = contact.ContactMadeBy;
newRow["ContactDescription"] = contact.ContactDescription;
dTable.Rows.Add(newRow); // YOU NEED THIS LINE TO ADD THE NEWROW TO DATATABLE
}
In your foreach loop add this at the end :
dTable.Rows.Add(newRow);

Sorting a DataTable by columns in a file

I am reading a csv file and sorting it.
I am trying to sort a DataTable to give me a output based on Bankname from datatable
here is the code I already have:
DataTable dt = new DataTable();
dt.Columns.Add("accountholder", typeof(string));
dt.Columns.Add("accountnumber", typeof(int));
dt.Columns.Add("accounttype", typeof(string));
dt.Columns.Add("bankname", typeof(string));
dt.Columns.Add("branch", typeof(string));
dt.Columns.Add("amount", typeof(double));
dt.Columns.Add("date", typeof(DateTime));
string line;
//CultureInfo culture = CultureInfo.InvariantCulture;
StreamReader sr = new StreamReader(#"C:\\Test\\debitorders.csv");
StreamWriter sw = new StreamWriter(#"C:\\Test\\output.txt");
while ((line = sr.ReadLine()) != null)
{
if (line.Length > 0)
{
string[] inputArray = line.Split(new char[] { ',' });
dt.Rows.Add(new object[] {
inputArray[0].Trim().Substring(0,1),
inputArray[1].Trim(),
long.Parse(inputArray[2].Trim()),
inputArray[3].Trim(),
inputArray[4].Trim(),
inputArray[5].Trim(),
(long)(100 * double.Parse(inputArray[6].Trim())),
DateTime.Parse(inputArray[7].Trim())
});
DateTime date = account.Field<DateTime>("date");
string[] outputLine = new string[]{
initial,
accountholder,
accountnumber.ToString(),
accounttype,
bankname,
branch,
amount.ToString(),
date.ToShortDateString()
};
Console.WriteLine(string.Join(",",outputLine));
}
}
Console.ReadLine();
Any help will be appreciated.
Thank you
Your code and posted desired result doesn't seem to be consistent so you probably have to adapt my code to your needs. But my code example will show you how to get rid of the DataTable and DataRow stuff. Instead LINQ methods are used where possible and a simple helper method for reading the csv file. If you have any further questions about the code let me know.
//reading the csv and create anonymous object for each line
var inputEntries = File.ReadLines(#"C:\\Test\\debitorders.csv")
.Select(line =>
{
var values = line.Split(',');
return new
{
AccountHolder = values[0].Trim().Substring(0,1) + values[1].Trim(),
AccountNumber = long.Parse(values[2].Trim()),
AccountType = values[3].Trim(),
BankName = values[4].Trim(),
Branch = values[5].Trim(),
Amount = 100 * double.Parse(values[6].Trim()),
Date = DateTime.Parse(values[7].Trim())
};
});
var banks = inputEntries
.OrderBy(e => e.BankName)
.GroupBy(e => e.BankName, e => e);
//output data
foreach(var bank in banks)
{
//output bank header
var AccountName = bank.Key;
if (AccountName.Length >= 16)
{
AccountName = AccountName.Substring(0, 16);
}
else
{
AccountName += new string(' ', 16 - AccountName.Length);
}
var NumberOfAccounts = bank.Count();
var TotalAmount = bank.Select(acc => acc.Amount).Sum();
var Header = NumberOfAccounts.ToString("000") + TotalAmount.ToString("0000000000");
Console.WriteLine(Header);
//sort accounts
var sortedAccounts = bank
.OrderBy( acc=> acc.AccountHolder)
.OrderByDescending(acc => acc.Amount);
//output accounts
foreach( var account in sortedAccounts)
{
var outputLine =
account.AccountHolder +
account.AccountNumber +
account.AccountType +
account.Amount +
account.Date.ToShortDateString();
Console.WriteLine(outputLine);
}
}

join datatable and collection and return a listin LINQ C#

I have a dataTable Dt
**Code value stdcode desc****
code1 value1 abcd12 abcjkdh
code2 value2 cdfg34 sdfiuysd
. . . .
. . . .
I have a list stdallCodes
**stdcode desc**
abcd12 sdfsd
fhry67 uisydif
I want to join these two using linq on stdcode
Please provide solution
I have tried converting the datatable to list and tried joining both
List<stdcode> listCodes = new List<stdcode>();
listCodes = (from row in dataTable.AsEnumerable() select row).ToList<stdcode>();
List<stdcode> ResultCodes = from codes in stdallCodes join dataCode in listCodes on codes.stdcode equals dataCode.stdcode select codes;
some error not converting
I want to have a list as result which contains stdcode,code and value columns
Try this out:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace DataTableJoin
{
class Program
{
class StdCode
{
public string STDCode { get; set; }
public string Description { get; set; }
}
static void Main(string[] args)
{
DataTable dt = new DataTable();
DataColumn dc = new DataColumn();
dt.Columns.Add(new DataColumn("Code"));
dt.Columns.Add(new DataColumn("Value"));
dt.Columns.Add(new DataColumn("STDCode"));
dt.Columns.Add(new DataColumn("Description"));
DataRow row = dt.NewRow();
row["Code"] = "code1";
row["Value"] = "value1";
row["STDCode"] = "abcd12";
row["Description"] = "abcjkdh";
dt.Rows.Add(row);
row = dt.NewRow();
row["Code"] = "code2";
row["Value"] = "value2";
row["STDCode"] = "cdfg34";
row["Description"] = "cdfg34";
dt.Rows.Add(row);
List<StdCode> listCodes = new List<StdCode>()
{
new StdCode(){ STDCode = "abcd12", Description="sdfsd"},
new StdCode(){ STDCode="fhry67", Description = "uisydif"}
};
var query = dt.AsEnumerable().
Select(item => new
{
Code = item.Field<string>("Code"),
Value = item.Field<string>("Value"),
STDCode = item.Field<string>("STDCode"),
Description = item.Field<string>("Description")
});
var query1 = listCodes.Join(query, x => x.STDCode, y => y.STDCode, (x, y) => y);
Console.WriteLine("Code\tValue\tSTDCode\tDescription");
foreach (var r in query1)
{
Console.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}", r.Code , r.Value , r.STDCode , r.Description));
}
}
}
}
Output:-
Code Value STDCode Description
code1 value1 abcd12 abcjkdh
Press any key to continue . . .
Edit
var query1 = listCodes.Join(query, x => x.STDCode, y => y.STDCode, (x, y) => new{
y.Code,
y.Value,
y.STDCode,
y.Description,
x.MyField
} );
Try this out much simpler:
class Program
{
static void Main(string[] args)
{
DataTable dtName = new DataTable();
dtName.Columns.Add("Code");
dtName.Columns.Add("FirstName");
dtName.Columns.Add("lastName");
dtName.Rows.Add("1", "Abhishek", "Shukla");
dtName.Rows.Add("2", "Deepak", "Singh");
dtName.Rows.Add("3", "Vinay", "Negi");
DataTable dtHomeTowns = new DataTable();
dtHomeTowns.Columns.Add("Code");
dtHomeTowns.Columns.Add("HomeTown");
dtHomeTowns.Columns.Add("State");
dtHomeTowns.Rows.Add("1", "Ajmer", "Rajasthan");
dtHomeTowns.Rows.Add("2", "Bhiwadi", "Rajasthan");
dtHomeTowns.Rows.Add("3", "Guwahati", "Orissa");
var list = (from names in dtName.AsEnumerable()
join town in dtHomeTowns.AsEnumerable() on names["Code"] equals town["Code"]
select new
{
Code = names["Code"],
FirstName = names["FirstName"],
lastName = names["lastName"],
HomeTown = town["HomeTown"],
State = town["State"],
}).ToList();
foreach (var item in list)
{
Console.WriteLine(String.Format("Code:{0}, FirstName: {1},LastName : {2},HomeTown:{3},State:{4}", item.Code, item.FirstName, item.lastName, item.HomeTown, item.State));
}
Console.ReadKey();
}
}
Hope this Helps!

Categories