array entered longer than column - c#

I have a permission form and I want to enter all buttons and MenuStrip to databases.
But when I try to use this function a false message appears
public DataTable loadFormsItemsNameDb(string FormName)
{
var formtype = Assembly.GetExecutingAssembly().GetTypes()
.Where(a => a.BaseType == typeof(Form) && a.GetTypeInfo().Name == FormName)
.FirstOrDefault();
Form f = (Form)Activator.CreateInstance(formtype);
DataTable formsitem = new DataTable();
var ms = f.Controls.OfType<MenuStrip>();
if (ms.Count() > 0)
{
for (int i= 0; i< ms.ElementAt(0).Items.Count; i++)
{
string name = ms.ElementAt(0).Items[i].Name;
string Text = ms.ElementAt(0).Items[i].Text;
string mType = ms.ElementAt(0).Items[i].GetType().ToString();
formsitem.Rows.Add(f.Name, name, Text);
}
}
var BTN = f.Controls.OfType<Button>();
if (BTN.Count() > 0)
{
for (int i = 0; i < BTN.Count(); i++)
{
string name = BTN.ElementAt(i).Name;
string Text = BTN.ElementAt(i).Text;
string mType = BTN.ElementAt(i).GetType().ToString();
formsitem.Rows.Add(f.Name, name, Text, mType);
}
}
return formsitem;
}

After you create a DataTable , you need to define its structure using columns.
for eg.
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Decimal");
column.AllowDBNull = false;
column.Caption = "Price";
column.ColumnName = "Price";
column.DefaultValue = 25;
table.Columns.Add(column);
and then you can add a row to a table. Here you have not specified the columns for the table.

Form f = (Form)Activator.CreateInstance(formType);
DataTable formsItem = new DataTable();
//************
// Add This Columns Name To Solve Problem ( longer than column )
formsItem.Columns.Add("FIFName");
formsItem.Columns.Add("FIName");
formsItem.Columns.Add("FIText");
formsItem.Columns.Add("FImType");
// *******************
var MS = f.Controls.OfType<MenuStrip>();

Related

How to loop through a data table and get the current row/index if the value match with a variable?

My WPF application contains a form which when loaded, obtains two variables which contain a PID (procid) and a processname (procname) of a certain process currently running on the local computer.
I have a data table which contains netstat -ano data outputs in each column. Now i will need to compare either (procid) or (procname) with the associated data contained in the datatable, if both variable matches, store the current index/row number and use that index to get the remote ip address (remoteIp) of the associated datarow to be stored as variables.
How would i achieve this?
Pageone.xaml.cs
public partial class Pageone : Page
{
public Pageone(MainWindow mainWindow)
{
InitializeComponent();
}
private string remoteIp;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//instantiate the MainWindow and assign it to the 'window' variable
var window = (MainWindow)Application.Current.MainWindow;
string procName = window.proc1;
int subprocPid = window.proc2;
string procPID = subprocPid.ToString();
MessageBox.Show(procPID);
using (Process ns = new Process())
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("Protocol"),
new DataColumn("Local Address"),
new DataColumn("Foreign Address"),
new DataColumn("State"),
new DataColumn("PID"),
new DataColumn("Process Name"),
});
ProcessStartInfo psi = new ProcessStartInfo("netstat.exe", "-ano");
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
ns.StartInfo = psi;
// Run it, and read the results
ns.Start();
using (StreamReader r = ns.StandardOutput)
{
string output = r.ReadToEnd();
ns.WaitForExit();
//Parse those results into a DataTable, polling the Process info
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
foreach (string line in lines)
{
string[] elements = line.Split(' ');
if (elements.Length < 5) continue;
if (elements.Contains("Proto")) continue;
DataRow dr = dt.NewRow();
List<string> validElements = new List<string>();
//Weed out empty elements.
foreach (string element in elements)
{
//skip blanks
if (element.Trim() == "") continue;
validElements.Add(element);
}
foreach (string element in validElements)
{
foreach (DataColumn dc in dt.Columns)
{
// fill in the buckets. Note that UDP doesn't have a state
if (dr["Protocol"].ToString() == "UDP" && dc.ColumnName == "State") continue;
if (dr[dc] == DBNull.Value)
{
dr[dc] = element;
break;
}
}
}
dr["Process Name"] = Process.GetProcessById(int.Parse(dr["PID"].ToString())).ProcessName;
dt.Rows.Add(dr);
}
for (int i = 0; i < dt.Rows.Count; i ++)
{
DataRow dr = dt.Rows[i];
///if cellprocPid and procPID matches, get the current index of the row and
///store it in the remoteIp variable
///
}
}
}
MessageBox.Show(remoteIp);
}
}
DataTable has select method, where you can pass fiterexpression to select rows matching filter condition
string expression = "PID= " + procPID.ToString();
var foundRows = table.Select(expression);
// Access rows
for (int i = 0; i < foundRows.Length; i++)
Console.WriteLine(foundRows[i][0]);
Hope it helps.

How to convert string separated by new line and comma to DataTable in C#

I have a string like this:
"Product,Price,Condition
Cd,13,New
Book,9,Used
"
Which is being passed like this:
"Product,Price,Condition\r\Cd,13,New\r\nBook,9,Used"
How could I convert it to DataTable?
Trying to do it with this helper function:
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split(new string[] { "\r\n" }, StringSplitOptions.None))
{
DataRow dataRow = dataTable.NewRow();
foreach (string cell in row.Split(','))
{
string[] keyValue = cell.Split('~');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(keyValue[0]);
dataTable.Columns.Add(dataColumn);
}
dataRow[keyValue[0]] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
However I don't get that "connecting cells with appropriate columns" part - my cells don't have ~ in string[] keyValue = cell.Split('~'); and I obviously get an IndexOutOfRange at DataColumn dataColumn = new DataColumn(keyValue[0]);
Based on your implementation, I have written the code for you, I have not tested it. But you can use the concept.
DataRow dataRow = dataTable.NewRow();
int i = 0;
foreach (string cell in row.Split(','))
{
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(cell);
dataTable.Columns.Add(dataColumn);
}
else
{
dataRow[i] = cell;
}
i++;
}
if(columnsAdded)
{
dataTable.Rows.Add(dataRow);
}
columnsAdded = true;
You can do that simply with Linq (and actually there is LinqToCSV on Nuget, maybe you would prefer that):
void Main()
{
string data = #"Product,Price,Condition
Cd,13,New
Book,9,Used
";
var table = ToTable(data);
Form f = new Form();
var dgv = new DataGridView { Dock = DockStyle.Fill, DataSource = table };
f.Controls.Add(dgv);
f.Show();
}
private DataTable ToTable(string CSV)
{
DataTable dataTable = new DataTable();
var lines = CSV.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var colname in lines[0].Split(','))
{
dataTable.Columns.Add(new DataColumn(colname));
}
foreach (var row in lines.Where((r, i) => i > 0))
{
dataTable.Rows.Add(row.Split(','));
}
return dataTable;
}
You can split given string into flattened string array in one call. Then you can iterate through the array and populate list of objects.
That part is optional, since you can immediately populate DataTable but I think it's way easier (more maintainable) to work with strongly-typed objects when dealing with DataTable.
string input = "Product,Price,Condition\r\nCd,13,New\r\nBook,9,Used";
string[] deconstructedInput = input.Split(new string[] { "\r\n", "," }, StringSplitOptions.None);
List<Product> products = new List<Product>();
for (int i = 3; i < deconstructedInput.Length; i += 3)
{
products.Add(new Product
{
Name = deconstructedInput[i],
Price = Decimal.Parse(deconstructedInput[i + 1]),
Condition = deconstructedInput[i + 2]
});
}
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Condition { get; set; }
}
So, products collection holds 2 objects which you can easily iterate over and populate your DataTable.
Note: This requires further checks to avoid possible runtime exceptions, also it is not dynamic. That means, if you have differently structured input it won't work.
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn(nameof(Product.Name)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Price)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Condition)));
foreach (var product in products)
{
var row = dataTable.NewRow();
row[nameof(Product.Name)] = product.Name;
row[nameof(Product.Price)] = product.Price;
row[nameof(Product.Condition)] = product.Condition;
dataTable.Rows.Add(row);
}

CSV to GridView than CRUD operations

i am making a Job reporter application, and till now what i did is, imported C.S.V file to grid view and displaying it by saving it in a data table, now what i want is,update and save the record back in the c.s.v file, i am not using any S.Q.L or any type of database, is it possible to do this?
please help me, i have to deliver project in two hours.
The project is C# Win forms.
Also help me in how i can serialize it to upload into ftp server.
THE CODE IS here...
private void openProjectToolStripMenuItem_Click_1(object sender, EventArgs e)
{
// int size = -1;
OpenFileDialog ofd = new OpenFileDialog()
{
Title = "Choose a File",
InitialDirectory = #"c:\dev\",
Filter = "Text Files (.txt)|*.txt|XML Files|*.xml|Word Documents (.docx)|*.docx",
RestoreDirectory = true,
Multiselect = false
};
if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
MessageBox.Show("No file selected!");
return;
}
using (StreamReader oStreamReader = new StreamReader(ofd.FileName))
{
try
{
Application.DoEvents();
DataSet ds = new DataSet("ApplicationData");
//some updates in the Datatable
DataTable JobHeaderDataTable = new DataTable("JobHeaderDataTable");
DataTable JobDate = new DataTable("JobDate");
DataTable JobDateItems = new DataTable("JobDateItems");
ds.Tables.Add(JobHeaderDataTable);
ds.Tables.Add(JobDate);
ds.Tables.Add(JobDateItems);
int rowCount = 0;
string[] columnNames = null;
string[] oStreamDataValues = null;
while (!oStreamReader.EndOfStream)
{
string oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
oStreamDataValues = oStreamRowData.Split('-');
if (rowCount == 0 && oStreamDataValues[0].ToString() == "HDR")
{
rowCount = 1;
columnNames = oStreamDataValues;
for (int i = 1; i < columnNames.Length; i++)
{
DataColumn oDataColumn = new DataColumn(columnNames[i].ToUpper(), typeof(string));
oDataColumn.DefaultValue = string.Empty;
JobHeaderDataTable.Columns.Add(oDataColumn);
}
//// For Slider
//txtCompany.Text = oStreamDataValues.GetValue(1).ToString();
//txtLocation.Text = oStreamDataValues.GetValue(2).ToString();
//txtRigName.Text = oStreamDataValues.GetValue(3).ToString();
//txtState.Text = oStreamDataValues.GetValue(4).ToString();
//txtCounty.Text = oStreamDataValues.GetValue(5).ToString();
//txtWellName.Text = oStreamDataValues.GetValue(6).ToString();
//txtTownship.Text = oStreamDataValues.GetValue(7).ToString();
//txtDescription.Text = oStreamDataValues.GetValue(8).ToString();
//txtBentHstSub.Text = oStreamDataValues.GetValue(9).ToString();
//txtBilToBend.Text = oStreamDataValues.GetValue(10).ToString();
//txtPadOD.Text = oStreamDataValues.GetValue(11).ToString();
//txtNBStab.Text = oStreamDataValues.GetValue(11).ToString();
//txtJob_ID.Text = oStreamDataValues.GetValue(12).ToString();
//// For Header
//txtCompanyHeader.Text = oStreamDataValues.GetValue(1).ToString();
//txtLocationHeader.Text = oStreamDataValues.GetValue(2).ToString();
//txtRigNameHeader.Text = oStreamDataValues.GetValue(3).ToString();
//txtStateHeader.Text = oStreamDataValues.GetValue(4).ToString();
//txtCountyHeader.Text = oStreamDataValues.GetValue(5).ToString();
//txtWellNameHeader.Text = oStreamDataValues.GetValue(6).ToString();
//txtTownshipHeader.Text = oStreamDataValues.GetValue(7).ToString();
//txtDescriptionHeader.Text = oStreamDataValues.GetValue(8).ToString();
//txtBentHstSubHeader.Text = oStreamDataValues.GetValue(9).ToString();
//txtBillToBendHeader.Text = oStreamDataValues.GetValue(10).ToString();
//txtPadODHeader.Text = oStreamDataValues.GetValue(11).ToString();
//txtNBStabHeader.Text = oStreamDataValues.GetValue(11).ToString();
//txtJob_IDHeader.Text = oStreamDataValues.GetValue(12).ToString();
}
else
{
DataRow oDataRow = JobHeaderDataTable.NewRow();
for (int i = 1; i < columnNames.Length; i++)
{
oDataRow[columnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
}
JobHeaderDataTable.Rows.Add(oDataRow);
}
}
}
oStreamReader.Close();
oStreamReader.Dispose();
foreach (DataRow dr in JobHeaderDataTable.Rows)
{
dataGridView2.DataSource = JobHeaderDataTable;
dataGridView4.DataSource = JobDate;
dataGridView5.DataSource = JobDateItems;
}
}
catch (IOException)
{
}
}
}
Save yourself some headache and check out, ClosedXML, and create the csv using this answer is available Can I save an EXCEL worksheet as CSV via ClosedXML?.
System.IO.File.WriteAllLines(csvFileName,
worksheet.RowsUsed().Select(row =>
string.Join(";", row.Cells(1, row.LastCellUsed(false).Address.ColumnNumber)
.Select(cell => cell.GetValue<string>()))
));

How I get the index of a DataTable Row with two calues of two other Column Values?

To My Application:
I have two DataTables and I want to filter out the first DataTable to the second. For this I get the columns user and modul from the first DataTable and if it not exist in the second I add a new row.
This is the structure from my second DataTable:
User | Modul | Time | Department | Status
and I want to check two Columns (User and Modul) whether the row with this values in the second DataTable exist. If the Entry Exist I need the row index. How I can do this with Linq?
The name of my second DataTable is analyse_table.
here my code:
private static DataTable FilterDataTable(DataTable nofilter_datatable)
{
DataTable analyse_table = new DataTable("Filter_Analyse");
DataColumn User = new DataColumn("User", typeof(string));
DataColumn Modul = new DataColumn("Modul", typeof(string));
DataColumn TIME = new DataColumn("TIME", typeof(string));
DataColumn Department = new DataColumn("Department", typeof(string));
DataColumn Status = new DataColumn("Status", typeof(string));
analyse_table.Columns.Add(User);
analyse_table.Columns.Add(Modul);
analyse_table.Columns.Add(TIME);
analyse_table.Columns.Add(Department);
analyse_table.Columns.Add(Status);
foreach (DataRow nf_row in nofilter_datatable.Rows)
{
string user = nf_row["User"].ToString();
string modul = nf_row["Modul"].ToString();
string OUT = nf_row["OUT"].ToString();
string IN = nf_row["IN"].ToString();
bool contains_user = analyse_table.AsEnumerable()
.Any(row => user == row.Field<string>("User"));
bool contains_modul = analyse_table.AsEnumerable()
.Any(Row => modul == Row.Field<string>("Modul"));
if (!contains_user || !contains_modul)
{
try
{
DataRow row = analyse_table.NewRow();
row["User"] = user;
row["Modul"] = modul;
if (OUT != string.Empty)
{
row["TIME"] = OUT;
row["Status"] = "OUT";
}
else if (IN != string.Empty)
{
row["TIME"] = IN;
row["Status"] = "IN";
}
string[] userSpli = user.Split('#');
row["Department"] = GetActiveDirectoryAttribute(userSpli[0], "Department", domaincontroller);
analyse_table.Rows.Add(row);
}
catch (Exception)
{
}
}
if (contains_user && contains_modul)
{
//index??
//string status = analyse_table.Rows[0]["Status"].ToString();
}
}
return analyse_table;
}
I need help.
There is no need to know the index in the analyse_table, using FirstOrDefault should allow you to find directly the row required
var rowUser = analyse_table.AsEnumerable()
.FirstOrDefault(row => user == row.Field<string>("User"));
var rowModul = analyse_table.AsEnumerable()
.FirstOrDefault(Row => modul == Row.Field<string>("Modul"));
if (rowUser == null || rowModul == null)
{
// Not exist so I add a new row
}
if (rowUser != null && rowModul != null)
{
string statusUser = rowUser["Status"].ToString();
string statusModul = rowModul["Status"].ToString();
}
However, having executed two different queries to search for your rows, we have no guarantees that the two rows are the same. So perhaps you need to change your code to search for both user and modul in the same row
var rowResult = analyse_table.AsEnumerable()
.FirstOrDefault(row => (user == row.Field<string>("User") &&
modul == row.Field<string>("Modul"));
if(rowResult == null)
// add new
else
// read status
I assume you want to add all missing rows that are in the first table but not in the second, the rows are identified via two columns User + Modul.
You could use a "LEFT OUTER JOIN" to link both tables on an anonymous type containing these columns. This is much more efficient.
var newRowsInFirst = from r1 in first_table.AsEnumerable()
join r2 in analyse_table.AsEnumerable()
on new { User=r1.Field<string>("User"), Modul=r1.Field<string>("Modul") }
equals new { User=r2.Field<string>("User"), Modul=r2.Field<string>("Modul") }
into gj from g2 in gj.DefaultIfEmpty()
where g2 == null
select r1;
Then use a simple foreach-loop to add these rows.
foreach(var newRow in newRowsInFirst)
{
analyse_table.ImportRow(newRow);
// or:
//DataRow addedRow = analyse_table.Rows.Add();
//addedRow.ItemArray = newRow.ItemArray;
}

compare two datatable in c#

what would be the best way to compare two data table. i populate two data table reading two different xml and now i need to compare and return the difference in terms of datatable.my compare logic was
private DataTable CompareDataTables(DataTable dtFirst, DataTable dtSecond)
{
int result = 0;
bool flag = false;
DataTable dtNoRows = new DataTable();
dtNoRows.Columns.Add("Result");
DataTable dtDiff = new DataTable();
dtDiff.Columns.Add("Field Name");
dtDiff.Columns.Add("Old Value");
dtDiff.Columns.Add("New Value");
DataRow dr = null;
if (dtFirst.Columns.Count == dtSecond.Columns.Count)
{
for (int i = 0; i <= dtFirst.Columns.Count - 1; i++)
{
try
{
DateTime.Parse(dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString().Trim());
flag = true;
}
catch (Exception ex)
{
flag = false;
}
if (!flag)
{
if (dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString().Trim().ToUpper() != dtSecond.Rows[0][dtSecond.Columns[i].ColumnName.ToString()].ToString().Trim().ToUpper())
{
dr = dtDiff.NewRow();
dr["Field Name"] = dtFirst.Columns[i].ColumnName.ToString();
dr["Old Value"] = dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString().Trim();
dr["New Value"] = dtSecond.Rows[0][dtSecond.Columns[i].ColumnName.ToString()].ToString().Trim();
dtDiff.Rows.Add(dr);
}
}
else
{
result = DateTime.Compare(DateTime.Parse(dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString()), DateTime.Parse(dtSecond.Rows[0][dtSecond.Columns[i].ColumnName.ToString()].ToString()));
if (result != 0)
{
dr = dtDiff.NewRow();
dr["Field Name"] = dtFirst.Columns[i].ColumnName.ToString();
dr["Old Value"] = DateTime.Parse(dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString().Trim()).ToString("MM/dd/yyyy") + " - " + DateTime.Parse(dtFirst.Rows[0][dtFirst.Columns[i].ColumnName.ToString()].ToString().Trim()).ToString("hh:mm:ss");
dr["New Value"] = DateTime.Parse(dtSecond.Rows[0][dtSecond.Columns[i].ColumnName.ToString()].ToString().Trim()).ToString("MM/dd/yyyy") + " - " + DateTime.Parse(dtSecond.Rows[0][dtSecond.Columns[i].ColumnName.ToString()].ToString().Trim()).ToString("hh:mm:ss");
dtDiff.Rows.Add(dr);
}
flag = false;
}
}
}
return dtDiff;
}
my code is working fine but i need to the is there any best way out. please guide me.
you can use LINQ to comparing tables values(two table must have the same structure)
bool flag = false;
if (dtFirst.Columns.Count == dtSecond.Columns.Count)
{
for (int i = 0; i <= dtFirst.Columns.Count - 1; i++)
{
String colName = dtFirst.Columns[i].ColumnName;
var colDataType = dtFirst.Columns[i].DataType.GetType();
var colValue = dtFirst.Columns[i];
flag = dtSecond.AsEnumerable().Any(T => typeof(T).GetProperty(colName).GetValue(T, typeof(colDataType)) == colValue);
}
}
var qry1 = dtDuplicate.AsEnumerable().Select(a => new { SchoolID = a["SchoolMID"].ToString()});
var qry2 = dsValadateSchoolInfo.Tables[1].AsEnumerable().Select(b => new { SchoolID = ["SchoolMID"].ToString() });
var exceptAB = qry1.Except(qry2);
DataTable dtMisMatch = (from a in dtDuplicate.AsEnumerable()
join ab in exceptAB on a["SchoolMID"].ToString() equals ab.SchoolID
select a).CopyToDataTable();

Categories