Why is the first match being duplicated in a loop? - c#

I have two tables called tableFileTemp2 and tableFile. I need a distinct list of computers merging the path and file columns into tableFile tables path column...
tableFileTemp2 //source
+-------+----------+--------+-------+
| host | path | date | file |
+-------+----------+--------+-------+
| comp1 | c:\ | xydate | x.exe |
| comp1 | c:\Temp\ | xydate | x.exe |
| comp2 | c:\win\ | xydate | y.exe |
| comp2 | c:\win\ | xydate | z.exe |
+-------+----------+--------+-------+
tableFile //this is the result, apparently the first path+file is being duplicated for each machine
+-------+---------------------------------------------------+--------+------+
| host | path | date | file |
+-------+---------------------------------------------------+--------+------+
| comp1 | c:\x.exe<br>c:\x.exe<br>c:\Temp\x.exe<br> | xydate | null |
| comp2 | c:\win\y.exe<br>c:\win\y.exe<br>c:\win\z.exe<br> | xydate | null |
+-------+---------------------------------------------------+--------+------+
tableFile //expected result
+-------+----------------------------------+--------+------+
| host | path | date | file |
+-------+----------------------------------+--------+------+
| comp1 | c:\x.exe<br>c:\Temp\x.exe<br> | xydate | null |
| comp2 | c:\win\y.exe<br>c:\win\z.exe<br> | xydate | null |
+-------+----------------------------------+--------+------+
my code:
for (int s = 0; s < tableFileTemp2.Rows.Count; s++)
{
if (tableFile.Rows.Count != 0)
{
for (int t = 0; t < tableFile.Rows.Count; t++)
{
if (string.Equals(tableFile.Rows[t][0].ToString(), tableFileTemp2.Rows[s][0].ToString(), StringComparison.OrdinalIgnoreCase))
{
tableFile.Rows[t][1] = tableFile.Rows[t][1].ToString() + tableFileTemp2.Rows[s][1].ToString() + tableFileTemp2.Rows[s][3].ToString() + "<br>";
break;
}
else if (t == (tableFile.Rows.Count - 1))
{
tableFile.Rows.Add(tableFileTemp2.Rows[s][0].ToString(), (tableFileTemp2.Rows[s][1].ToString() + tableFileTemp2.Rows[s][3].ToString() + "<br>"), tableFileTemp2.Rows[s][2], null);
}
}
}
else
{
tableFile.Rows.Add(tableFileTemp2.Rows[s][0].ToString(), (tableFileTemp2.Rows[s][1].ToString() + tableFileTemp2.Rows[s][3].ToString() + "<br>"), tableFileTemp2.Rows[s][2], null);
}
}

As you say in your comment that you still have the original CSV that the data came from. We can do this with LINQ.
+-------+----------+--------+-------+
| host | path | date | file |
+-------+----------+--------+-------+
| comp1 | c:\ | xydate | x.exe |
| comp1 | c:\Temp\ | xydate | x.exe |
| comp2 | c:\win\ | xydate | y.exe |
| comp2 | c:\win\ | xydate | z.exe |
+-------+----------+--------+-------+
Then the code looks like.
var results =
from thing in
(from line in tableFileCSV.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None)
let row = line.Split(',')
select new
{
Host = row[0],
Path = row[1] + row[3] + "</br>",
Date = row[2],
File = row[3] // <- Are you sure you want this to be null and not the file value?
})
group new { thing.Path, thing.Date, thing.File } by new { thing.Host } into g
select new
{
Host = g.Key.Host,
Path = g.Select(i => i.Path).Aggregate((a, b) => a + b),
Date = g.Select(i => i.Date).FirstOrDefault(),
File = "File",
};
// If you want to get a look at it.
foreach (var item in results)
{
Console.WriteLine("{0} {1} {2} {3}", item.Host, item.Path, item.Date, item.File);
}
Where the tableFileCSV is your original data in a CSV.
This can then be passed into a datatable.
var dt = new DataTable();
dt.Columns.Add("Host");
dt.Columns.Add("Path");
dt.Columns.Add("Date");
dt.Columns.Add("File");
foreach (var item in results)
{
dt.Rows.Add(item.Host,item.Path,item.Date,item.File);
}

Related

Delete rows with null values from a csv file in c#

How can I delete a row which contains null values from a comma separated csv file in c# ?
Example:
| FirstName | LastName | Email | Address |
|---------------------|------------------|---------------|--------------|
| lmn | lmn |lmn#lmn.com |DemoAddress |
| xy | xy |xy#xy.com |DemoAddress |
| demo | demo | | |
| demo2 | demo2 |xy#xy.com |DemoAddress |
Outcome:
| FirstName | LastName | Email | Address |
|---------------------|------------------|---------------|--------------|
| lmn | lmn |lmn#lmn.com |DemoAddress |
| xy | xy |xy#xy.com |DemoAddress |
| demo2 | demo2 |xy#xy.com |DemoAddress |
I tried the following code but doesn't work as expected
private string filterCSV(string strFilePath)
{
var columnIndex = 3;
var line = File.ReadAllLines(strFilePath);
var n = line.Where(x => x[columnIndex].Equals(""));
string result = string.Join("\r", not.ToArray());
return result;
}
Adding answer for future reference
private void RemoveBlanks(string datapath)
{
List<CSV> records;
using (var reader = new StreamReader(datapath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
records = csv.GetRecords<CSV>().ToList();
for(int i = 0; i < records.Count;++i)
{
if (records[i].Email== "" && records[i].Address == "")
{
records.RemoveAt(i);
}
}
}
using (var writer = new StreamWriter(datapath))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(records);
}
}

Unpivot data excel with merged column using SSIS

I'm using SSIS to export from Excel to text and in my case, I need to export where the file contains merged columns anyone can help or have suggest for my case?
Input Excel
A B C D E
+-------------+-----------------+-----------------+
| Shop Name | Monday | Tuesday |
| +---------+-------+---------+-------+
| | Jackson | Steve | Jackson | Steve |
+-------------+---------+-------+---------+-------+
| 7Eleven | 11 | 30 | 23 | 21 |
+-------------+---------+-------+---------+-------+
| Delta Shop | 43 | 12 | 33 | 2 |
+-------------+---------+-------+---------+-------+
Output Expected
+-------------+---------+-------------+-------+
| Shop_Name | Day | Member_Name | Point |
+-------------+---------+-------------+-------+
| 7Eleven | Monday | Jackson | 11 |
+-------------+---------+-------------+-------+
| 7Eleven | Monday | Steve | 30 |
+-------------+---------+-------------+-------+
| Delta Shop | Monday | Jackson | 43 |
+-------------+---------+-------------+-------+
| Delta Shop | Monday | Steve | 12 |
+-------------+---------+-------------+-------+
| 7Eleven | Tuesday | Jackson | 23 |
+-------------+---------+-------------+-------+
| 7Eleven | Tuesday | Steve | 21 |
+-------------+---------+-------------+-------+
| Delta Shop | Tuesday | Jackson | 33 |
+-------------+---------+-------------+-------+
| Delta Shop | Tuesday | Steve | 2 |
+-------------+---------+-------------+-------+
Using oledb and ACE driver (Microsoft Office) to read excel file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace ConsoleApplication124
{
class Program
{
static void Main(string[] args)
{
string connStr = "Provider=Microsoft.ACE.OLEDB.15.0;Data Source=c:\\temp\\test.xlsx;Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"";
string query = "Select * From [Sheet1$]";
OleDbDataAdapter adapter = new OleDbDataAdapter(query, connStr);
DataTable dt = new DataTable();
adapter.Fill(dt);
string[] days = dt.Rows[0].ItemArray.Skip(1).Select(x => (x == DBNull.Value) ? string.Empty : ((string)x).Trim()).ToArray();
string[] people = dt.Rows[1].ItemArray.Skip(1).Select(x => (x == DBNull.Value) ? string.Empty : ((string)x).Trim()).ToArray();
int numberDays = days.Where(x => x != string.Empty).Count();
int numberPeople = people.Where(x => x != string.Empty).Distinct().Count();
string[] columnNames = { "Shop_Name", "Day", "Member_Name", "Point" };
Console.WriteLine(string.Join(",", columnNames));
for (int row = 2; row < dt.Rows.Count; row++)
{
string[] columns = dt.Rows[row].ItemArray.Select(x => (x == DBNull.Value) ? string.Empty : ((string)x).Trim()).ToArray();
string shop = columns[0];
for (int col = 1; col < dt.Rows[row].ItemArray.Count(); col++)
{
object point = dt.Rows[row].Field<string>(col);
if (point != null)
{
string pointStr = ((string)point).Trim();
int dayIndex = numberPeople * ((col - 1) / numberPeople);
string day = days[dayIndex];
string person = people[col - 1];
string[] outputData = { shop, day, person, pointStr };
Console.WriteLine(string.Join(",", outputData));
}
}
}
Console.ReadLine();
}
}
}

Join 2 datatable on difference columns

I have 2 DataTable. I want to use LINQ to join the 2 datatable on difference columns. How to do that?
Table A:
+--------+-------+-------+
| ACol1 | ACol2 | ACol3 |
+--------+-------+-------+
| 1 | tbA12 | tbA13 |
| 2 | tbA22 | tbA23 |
| 3 | tbA32 | tbA33 |
| 4 | tbA42 | tbA43 |
| 5 | tbA52 | tbA53 |
+--------+-------+-------+
Table B:
+-------+-------+-------+
| BCol1 | BCol2 | BCol3 |
+-------+-------+-------+
| 1 | XX | tbB13 |
| XX | 1 | tbB23 |
| XX | 2 | tbB33 |
| 4 | XX | tbB43 |
+-------+-------+-------+
SQL Query:
SELECT a.*, b.BCol3
FROM tableA a
JOIN tableB b ON a.ACol1=b.BCol1 OR a.ACol1=b.BCol2
Expected Result:
+--------+-------+-------+-------+
| ACol1 | ACol2 | ACol3 | BCol3 |
+--------+-------+-------+-------+
| 1 | tbA12 | tbA13 | tbB13 |
| 1 | tbA12 | tbA13 | tbB23 |
| 2 | tbA22 | tbA23 | tbB33 |
| 4 | tbA42 | tbA43 | tbB43 |
+--------+-------+-------+-------+
Currently my LINQ query are below:
var query1= from rowA in tableA.AsEnumerable()
join rowB in tableB.AsEnumerable()
on rowA["ACol1"].ToString() equals rowB["BCol1"].ToString()
select new
{
rowA["ACol1"],
rowA["ACol2"],
rowA["ACol3"],
rowB["BCol3"]
};
var query2= from rowA in tableA.AsEnumerable()
join rowB in tableB.AsEnumerable()
on rowA["ACol1"].ToString() equals rowB["BCol2"].ToString()
{
rowA["ACol1"],
rowA["ACol2"],
rowA["ACol3"],
rowB["BCol3"]
};
var result=query1.Union(query2);
Any better idea how to solve this?
LINQ support for JOIN with non-trivial conditions is very limited. You could do a cross join + move your condition to where clause.
var query1= from rowA in tableA.AsEnumerable()
from rowB in tableB.AsEnumerable()
where rowA["ACol1"].ToString() == rowB["BCol1"].ToString()
|| rowA["ACol1"].ToString() == rowB["BCol2"].ToString()
select new
{
rowA["ACol1"],
rowA["ACol2"],
rowA["ACol3"],
rowB["BCol3"]
};
Try this:-
var result = from a in tableA.AsEnumerable()
from b in tableB.AsEnumerable()
where a.Field<string>("ACol1") == b.Field<string>("BCol1")
|| a.Field<string>("ACol1") == b.Field<string>("BCol2")
select new
{
a["ACol1"],
a["ACol2"],
a["ACol3"],
b["BCol3"]
};
Here is the complete working Fiddle, you can copy paste the same in your editor and test because its not supporting AsEnumerable in DotNetFiddle.

dynamic menustrip

I m trying to create dynamic menu using C# WinForm Project. My database structure is mentioned below. I can create the top menu ie "FILE", "EDIT", "SEARCH". But I cannot run the recursive function for the Child menu.
mysql> select * from dynamicmenu;
+------+-----------------+--------+-------+-----------+
| SLN | Child | Parent | Level | Reference |
+------+-----------------+--------+-------+-----------+
| 1 | FILE | NULL | 0 | NULL |
| 2 | EDIT | NULL | 0 | NULL |
| 3 | SEARCH | NULL | 0 | NULL |
| 4 | Session Manager | FILE | 1 | 1 |
| 5 | Connect To | FILE | 1 | 1 |
| 6 | DO | FILE | 2 | 5 |
| 7 | Copy | EDIT | 1 | 2 |
| 8 | Paste | EDIT | 1 | 2 |
| 9 | Find Text | SEARCH | 1 | 3 |
| 10 | Cut | EDIT | 2 | 7 |
| 11 | VMS | FILE | 3 | 6 |
+------+-----------------+--------+-------+-----------+
11 rows in set (0.00 sec)
The c# code is as follows.
mysqlConn conn;
private void Form1_Load(object sender, EventArgs e)
{
conn = new mysqlConn();
conn.OpenConnection();
MySqlCommand cmd = new MySqlCommand("Select * from dynamicmenu", conn.connection);
MySqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
if (dr["Parent"].ToString() == "")
{
menuStrip1.Items.Add(dr["Child"].ToString());
}
else if (dr["Parent"].ToString() != "")
{
AddSubMenu(new ToolStripMenuItem(dr["Child"].ToString()), dr["Parent"].ToString());
}
}
dr.Close();
conn.CloseConnection();
}
private void AddSubMenu(ToolStripMenuItem ChildItem, string ParentItem)
{
foreach (ToolStripMenuItem item in menuStrip1.Items)
{
if (ParentItem == item.Name)
{
item.DropDownItems.Add(ChildItem);
}
}
}
Please advise.
Use toString() instead of name.
private void AddSubMenu(ToolStripMenuItem ChildItem, string ParentItem)
{
foreach (ToolStripMenuItem item in menuStrip1.Items)
{
if (ParentItem == item.ToString())
{
item.DropDownItems.Add(ChildItem);
}
}
}

Can't read from database using Entity Framework 5

Im trying to read records from a database using Entity Framework , which I have not used before.
Im trying to run the load rule method:
class Rule
{
private STRATCODE stratCode;
private STRATRULEDEF stratRuleDef;
AREEntities AREDb = new AREEntities();
public Rule(STRATRULEDEF StratRuleDef, STRATCODE StratCode)
{
this.stratRuleDef = StratRuleDef;
this.stratCode = StratCode;
}
public void LoadRule()
{
var query = from stratCode in AREDb.STRATCODES
where stratCode.CODEVALUE == "49300"
select stratCode;
//StratCodeRepository StratCodeRepository = new StratCodeRepository(new AREEntities());
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\user\Desktop\NewText.txt",true))
{
foreach (STRATCODE row in query)
{
file.WriteLine("{0} | {1} | {2} | {3} | {4} | {5}", stratCode.STRATRULEKEY, stratCode.CODETYPE, stratCode.CODEVALUE, stratCode.SYSTEMID, stratCode.CODESETKEY, stratCode.PAYMENTYEAR);
}
}
}
My problem is that everytime I run it, it returns the right number of records but all of the data in the text file is empty and I can find no clues in my output log.
0 | | | | |
0 | | | | |
0 | | | | |
0 | | | | |
0 | | | | |
Any ideas? I dont know how to even start with no clues
Your write is not using the foreach variable:
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\stephen.carmody\Desktop\NewText.txt", true))
{
foreach (var row in query)
{
file.WriteLine("{0} | {1} | {2} | {3} | {4} | {5}",
row.STRATRULEKEY,
row.CODETYPE,
row.CODEVALUE,
row.SYSTEMID,
row.CODESETKEY,
row.PAYMENTYEAR);
}
}

Categories