add two group into one group in c# - 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();
}

Related

Nested XML from list with needed data on multiple lines

I need to format an XML to a given hierarchy from a list (List<>). The list contains, for the banking information, data spread across multiple rows as shown in the image.
The XML output needs to be formatted like this:
<ROOT>
<DocumentElement>
<Supplier>
<Company>STV</Company>
<Code>000199</Code>
<Name>TrafTrans</Name>
<BankAccounts>
<SupplierBankAccount>
<Bban>220-012510-63</Bban>
<Name>B1</Name>
</SupplierBankAccount>
<SupplierBankAccount>
<Bban>RUIL</Bban>
<Name>RUIL</Name>
</SupplierBankAccount>
</BankAccounts>
<SupplierAddresses>
<SupplierAddress>
<Type>PostalAddress</Type>
<Name>Loc TrafTrans</Name>
<IsDefault>true</IsDefault>
<AddressParts>
<SupplierAddressPart>
<AddressPartKey>STREET_NAME</AddressPartKey>
<AddressPartText>Somewhere</AddressPartText>
</SupplierAddressPart>
<SupplierAddressPart>
<AddressPartKey>COUNTRY</AddressPartKey>
<AddressPartText>SPAIN</AddressPartText>
</SupplierAddressPart>
</AddressParts>
</SupplierAddress>
</SupplierAddresses>
</Supplier>
</DocumentElement>
</ROOT>
I already have a method that converts a list to an XML and returns a string. But the problem is that this only formats one item from the list and there could be additional info in the following items.
public static string SuppliersToXML(List<SupplierItem> supplier)
{
CultureInfo ci = new CultureInfo("en-US");
XmlDocument doc = new XmlDocument();
var root = doc.CreateElement("ROOT");
var rootNode = doc.AppendChild(root);
var docElem = doc.CreateElement("DocumentElement");
var docElemNode = rootNode.AppendChild(docElem);
foreach (var item in supplier)
{
var supplierElem = doc.CreateElement("Supplier");
var companyElem = (XmlNode)doc.CreateElement("Company");
companyElem.InnerText = item.Company.ToString();
//more code...
supplierElem.AppendChild(companyElem);
//more code...
}
return doc.OuterXml;
}
I have found the answer myself, it may not be the prettiest code ever written. But it does the job.
public static string SuppliersToXML(List<SupplierItem> supplier)
{
//A distinct select is needed because bank info can be on multiple lines. So first a list is generated with correct info except for bank information
List<SupplierItem> distinctsupplier = supplier
.GroupBy(p => p.Code)
.Select(g => g.First())
.ToList();
CultureInfo ci = new CultureInfo("en-US");
XmlDocument doc = new XmlDocument();
var root = doc.CreateElement("ROOT");
var rootNode = doc.AppendChild(root);
var docElem = doc.CreateElement("DocumentElement");
var docElemNode = rootNode.AppendChild(docElem);
foreach (var item in distinctsupplier)
{
var supplierElem = doc.CreateElement("Supplier");
var companyElem = (XmlNode)doc.CreateElement("Company");
companyElem.InnerText = item.Company.ToString();
var codeElem = (XmlNode)doc.CreateElement("Code");
codeElem.InnerText = item.Code.ToString();
var codeName = (XmlNode)doc.CreateElement("Name");
codeName.InnerText = item.Name.ToString();
//supplieridentifier part
var supplierIdsElem = doc.CreateElement("SupplierIdentifiers");
var supplierIdElem = doc.CreateElement("SupplierIdentifier");
var supplierIdValueElem = (XmlNode)doc.CreateElement("SupplierIDValue");
supplierIdValueElem.InnerText = item.SupplierIDValue;
//supplieraddress part
var supplierAddressesElem = doc.CreateElement("SupplierAddresses");
var supplierAddressElem = doc.CreateElement("SupplierAddress");
var supplierTypeValueElem = (XmlNode)doc.CreateElement("Type");
supplierTypeValueElem.InnerText = item.Type;
var supplierNameValueElem = (XmlNode)doc.CreateElement("Name");
supplierNameValueElem.InnerText = item.AddressName;
var supplierDefaultValueElem = (XmlNode)doc.CreateElement("IsDefault");
supplierDefaultValueElem.InnerText = item.AddressIsDefault;
//address part
var AddressPartElem = doc.CreateElement("AddressParts");
var supplierAddressPartsElem = doc.CreateElement("SupplierAddressPart");
//Street
var AddressPartElemStreetKeyElem = (XmlNode)doc.CreateElement("AddressPartKey");
AddressPartElemStreetKeyElem.InnerText = item.AddressStreetKey;
var AddressPartElemStreetValueElem = (XmlNode)doc.CreateElement("AddressPartText");
AddressPartElemStreetValueElem.InnerText = item.AddressStreetText;
//Country
var AddressPartElemCountryKeyElem = (XmlNode)doc.CreateElement("AddressPartKey");
AddressPartElemCountryKeyElem.InnerText = item.AddressCountryKey;
var AddressPartElemCountryValueElem = (XmlNode)doc.CreateElement("AddressPartText");
AddressPartElemCountryValueElem.InnerText = item.AddressCountryText;
//add elements to supplierelem
supplierElem.AppendChild(companyElem);
supplierElem.AppendChild(codeElem);
supplierElem.AppendChild(codeName);
//bankaccounts part
var bankAccountElem = doc.CreateElement("BankAccounts");
//select all rows that contain multiple lines, so the bank info can be extracted, for a certain supplier
var bankInformation = supplier.Where(s => s.Code == item.Code).ToList();
foreach (var bankitem in bankInformation)
{
if (item.Code == bankitem.Code)
{
var bankAccountSupplElem = doc.CreateElement("SupplierBankAccount");
var bankAccountBbanElem = doc.CreateElement("Bban");
var bankAccountBbanValueElem = (XmlNode)doc.CreateElement("Bban");
bankAccountBbanValueElem.InnerText = bankitem.Bban;
var bankAccountNameElem = doc.CreateElement("Name");
var bankAccountNameValueElem = (XmlNode)doc.CreateElement("Name");
bankAccountNameValueElem.InnerText = bankitem.BankName;
var bankAccountElemNode = supplierElem.AppendChild(bankAccountElem);
var bankAccountSupplElemNode = bankAccountElemNode.AppendChild(bankAccountSupplElem);
bankAccountSupplElemNode.AppendChild(bankAccountBbanValueElem);
bankAccountSupplElemNode.AppendChild(bankAccountNameValueElem);
}
}
//add address elements to supplierelem
var supplierAddressesElemNode = supplierElem.AppendChild(supplierAddressesElem);
var supplierAddressElemNode = supplierAddressesElemNode.AppendChild(supplierAddressElem);
supplierAddressElemNode.AppendChild(supplierTypeValueElem);
supplierAddressElemNode.AppendChild(supplierNameValueElem);
supplierAddressElemNode.AppendChild(supplierDefaultValueElem);
//add addressparts to supplieraddressesnode
//Street
var AddressPartElemNode = supplierAddressElemNode.AppendChild(AddressPartElem);
var supplierAddressPartsElemNode = AddressPartElemNode.AppendChild(supplierAddressPartsElem);
supplierAddressPartsElemNode.AppendChild(AddressPartElemStreetKeyElem);
supplierAddressPartsElemNode.AppendChild(AddressPartElemStreetValueElem);
//Country (first reinitialize supplieraddresspart)
supplierAddressPartsElem = doc.CreateElement("SupplierAddressPart");
var supplierAddressPartsCountryElemNode = AddressPartElemNode.AppendChild(supplierAddressPartsElem);
supplierAddressPartsCountryElemNode.AppendChild(AddressPartElemCountryKeyElem);
supplierAddressPartsCountryElemNode.AppendChild(AddressPartElemCountryValueElem);
//add all supplierelements to docelemnode
docElemNode.AppendChild(supplierElem);
}
return doc.OuterXml;
}

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);

Search user by profile property

How i can search by profile property? MSDN say use ProfileSearchManager, but it not working.
I want search users by MobilePhone property.
SPServiceContext serviceContext = SPServiceContext.GetContext(site);
UserProfileManager upm = new UserProfileManager(serviceContext);
ProfileSearchManager sp = ProfileSearchManager.GetProfileSearchManager(serviceContext);
string[] searchPattern = { "123" };
ProfileBase[] searchResults = sp.Search(searchPattern, ProfileSearchFlags.User);
foreach (ProfileBase profile in searchResults)
{
Console.WriteLine(profile.DisplayName);
}
using (SPSite site = new SPSite(siteUrl))
{
using (var qRequest = new KeywordQuery(site)
{
QueryText = "MobilePhone:*" +"123" ,
EnableQueryRules = true,
EnableSorting = false,
SourceId = new Guid("Enter here Result Source Guid"),
TrimDuplicates = false
})
{
//Get properties you want here
qRequest.SelectProperties.Add("FirstName");
qRequest.SelectProperties.Add("LastName");
SearchExecutor e = new SearchExecutor();
ResultTableCollection rt = e.ExecuteQuery(qRequest);
var tab = rt.Filter("TableType", KnownTableTypes.RelevantResults);
var result = tab.FirstOrDefault();
DataTable resultTable = result.Table;
}
}

Multiple Array Insertion in C# using Foreach statement

private void Updated_ModRecFGA()
{
try
{
DRFGAModifiedRecord TABLE = new DRFGAModifiedRecord();
foreach (ArrayFunc Row in ArrayFunc.QueryResult)
{
foreach (ArrayFunc Row2 in ArrayFunc.QueryResult1)
{
TABLE.RecordDocID = Row.FGACol1;
TABLE.DRNo = Row.FGACol2;
TABLE.DDNum = Row.FGACol3;
TABLE.LineNumber = Row.FGACol4;
TABLE.Itemnmbr = Row2.updItemCode;
TABLE.Itemdesc = Row2.updItemDesc;
TABLE.Pallet = Row2.updPallets;
TABLE.BagsNo = Row2.updBagsNo;
TABLE.TotalLoaded = Row2.updTotalKgs;
TABLE.PostStat = Row2.updPostStat;
TABLE.ProdCode = Row2.updProdcode;
TABLE.VariantCode = Row2.updVariantCode;
TABLE.DateModify = DateTime.Now.ToShortDateString();
TABLE.TimeModify = DateTime.Now.ToShortTimeString();
TABLE.UserModify = "Mik";//GlobalvarClass.LogUser;
TABLE.ReasonModify = GlobalvarClass.GetModReasOnDR;
TABLE.FileType = "New";
saveREC(TABLE);
gfunc.MsgBox("Saved", 1);
}
}
ArrayFunc.QueryResult.Clear();
ArrayFunc.QueryResult1.Clear();
GlobalvarClass.GetModReasOnDR = string.Empty;
}
catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); }
}
Is there another proper way to use this kind of code something like this to avoid duplicate? I know it duplicate because of two foreach statement
Just combine the two using linq. Remember to include using System.Linq; in your using clause.
var results = ArrayFunc.QueryResult.SelectMany(l1 => ArrayFunc.QueryResult1, (l1, l2) =>
new DRFGAModifiedRecord
{
RecordDocID = l1.FGACol1,
DRNo = l1.FGACol2,
DDNum = l1.FGACol3,
LineNumber = l1.FGACol4,
Itemnmbr = l2.updItemCode,
Itemdesc = l2.updItemDesc,
Pallet = l2.updPallets,
BagsNo = l2.updBagsNo,
TotalLoaded = l2.updTotalKgs,
PostStat = l2.updPostStat,
ProdCode = l2.updProdcode,
VariantCode = l2.updVariantCode,
DateModify = DateTime.Now.ToShortDateString(),
TimeModify = DateTime.Now.ToShortTimeString(),
UserModify = "Mik",//GlobalvarClass.LogUser
ReasonModify = GlobalvarClass.GetModReasOnDR,
FileType = "New"
}).ToList();
foreach (row in results)
{
saveREC(row);
gfunc.MsgBox("Saved", 1);
}
Alternatively you can do it with a query expression:
var result = (from l1 in ArrayFunc.QueryResult
from l2 in ArrayFunc.QueryResult1
select new DRFGAModifiedRecord { RecordDocID = l1.FGACol1 ... }).ToList();

When doing linq to xml and displaying data in datagridview my code only parses one file in directory folder

How come during the linq to xml parse my code is only reading one fo the xml files in the folder rather than all of them?
private void button1_Click(object sender, EventArgs e)
{
string[] fileEntries = Directory.GetFiles(#"", "*.cfg*");
foreach (string fileName in fileEntries)
{
XDocument doc = XDocument.Load(fileName);
var query = from x in doc.Descendants("")
select new
{
MaxChild = x.Element("Max").Value,
MinChild = x.Element("Min").Value
};
var query2 = from y in doc.Descendants("")
select new
{
MaxChild = y.Element("Max").Value,
MinChild = y.Element("Min").Value
};
var query3 = from z in doc.Descendants("")
select new
{
MaxChild = z.Element("Max").Value,
MinChild = z.Element("Min").Value
};
var bs3 = new BindingSource { DataSource = query.Union(query2.Union(query3)) };
dataGridView1.AutoGenerateColumns = true;
dataGridView1.AutoSize = true;
dataGridView1.DataSource = bs3;
dataGridView1.Columns[0].HeaderText = "Max";
dataGridView1.Columns[1].HeaderText = "Min";
}
}
You're iterating over the files in the directory - but simply reassigning the datasource each time. In other words, it's exactly the same problem as in your earlier question, except that instead of it being to do with three queries, it's to do with reassigning it for each file.
Try this instead, using a single query:
var query = from file in fileEntries
let doc = XDocument.Load(file)
from x in doc.Descendants("XAxisCalib")
.Concat(doc.Descendants("YAxisCalib"))
.Concat(doc.Descendants("ZAxisCalib"))
select new
{
// Include this to see the file for each value
File = file,
MaxChild = x.Element("Max").Value,
MinChild = x.Element("Min").Value
};
var bs3 = new BindingSource { DataSource = query };
dataGridView1.AutoGenerateColumns = true;
dataGridView1.AutoSize = true;
dataGridView1.DataSource = bs3;
EDIT: Okay, if you know there's going to be exactly one of each element, it's fairly easy:
var query = from file in fileEntries
let doc = XDocument.Load(file)
let x = doc.Descendants("XAxisCalib").Single()
let y = doc.Descendants("YAxisCalib").Single()
let z = doc.Descendants("ZAxisCalib").Single()
select new
{
// Include this to see the file for each value
File = file,
MaxChildX = x.Element("Max").Value,
MinChildX = x.Element("Min").Value,
MaxChildY = y.Element("Max").Value,
MinChildY = y.Element("Min").Value,
MaxChildZ = z.Element("Max").Value,
MinChildZ = z.Element("Min").Value
};

Categories