I'm trying to read data from an Excel file to a DataTable. I know that we can assign different DataTypes for a DataColumn when adding columns to a DataTable. So far I have tried the following,
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2]
{
new Datacolumn("column1", typeof(string)),
new DataColumn("column2", typeof(int))
});
And my excel file has data in two columns as follows,
column1------column2
abc----------------230
def----------------230tr
As you can see above, the second row second column has a value of '230tr' which the DataTable should not accept an throw an exception with the invalid data field and row number.
Praveena.
you can try in that way.
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2]
{
new DataColumn("column1", typeof(int)),
new DataColumn("column2", typeof(string))
});
dt.Clear();
try
{
string input = string.Empty;
input = Console.ReadLine();
if (Regex.IsMatch(input, #"^[a-zA-Z]+$"))
{
dt.Rows.Add(1, input);
}
Console.WriteLine(dt.Rows[0]["column2"]);
Console.ReadKey();
}
catch(Exception ex)
{
Console.WriteLine(ex);
Console.ReadKey();
}
In your code, where you are reading the excel values to insert, you should employ the C# function: [Int32.TryParse][1] or float.TryParse;
which will tell you whether the string will convert to a float (or integer) in which case don't insert it.
You can see a detailed example/answer here:
Thank you everyone for their response and I found an easy solution for my question while working with DataTables. My main task was to read data rows from an Excel file sheet and validate each row data before adding it to my database table(using OracleBulkCopy) and notify the user with any invalid data fields in the Excel file sheet.
While I was importing data into the DataTable from the Excel file sheet using oda.Fill(dt); I realized that some of the DataRow fields are empty(null) during the process of data addition to DataTable.
As I have mentioned above in the main question we can assign the DataType for a DataColumn in a DataTable as follows,
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[3]
{
new Datacolumn("column1", typeof(string)),
new DataColumn("column2", typeof(double)),
new DataColumn("column3", typeof(DateTime))
});
And my Excel file sheet would be as follows,
column1-----------------column2----------------------column3
abcd----------------------20000-------------------------20-Dec-2018
efgh-----------------------56500.5----------------------xyz17-Mar-2018
ijklm-----------------------67000------------------------1-Jan-2018
In the above table 3rd row 3rd column RowData is in invalid date type (xyz17-Mar-2018). While performing oda.Fill(dt); for the above table, this data field gets added as a null RowData to the DataTable. It would be the same for other columns if the importing data fields are not in the type of defined DataColumn type. So My final step was to check each row data of DataTable which has a null field and throw the user with an error message mentioning the row number and column name.
int errorRowNumber = 0;
private bool validateDataTableData(DataTable dt, string dtColumnName)
{
Boolean isTrue = false;
foreach (DataRow r in dt.Rows)
{
if(!string.IsNullOrEmpty(r[dtColumnName].ToString()))
{
isTrue = false;
errorRowNumber = dt.Rows.IndexOf(r) + 2;
break;
}
}
return isTrue;
}
Related
My DataTable has many columns more than 35 columns. Among them I want to copy the first column "SYMBOL_QA" data to another new DataTable.
I searched in internet but did not found any suitable approaches. One approach I found was to copy the whole DataTable as it is, then delete the unwanted columns. But I have 35 columns and deleting all of them one by one will not be good approach.
protected void SendDataTable(DataTable dSource)
{
DataTable dTarget = new DataTable();
dTarget.Columns.Add(new DataColumn("SYMBOL_QA_"));
int rowIdx = 0;
dTarget.AsEnumerable().All(row => { row["SYMBOL_QA_"] = dSource.Rows[rowIdx++]["SYMBOL_QA"]; return true; });
}
This code block is not working. How can I do this ?
I think that the easiest method to do what you have requested is through the DataView.ToTable method
DataTable dTarget = dSource.DefaultView.ToTable(false, "SYMBOL_QA");
It is just a single line and it
Creates and returns a new DataTable based on rows in an existing
DataView.
protected DataTable CopyColumn(DataTable sourceTable, string columnName)
{
DataTable result = new DataTable();
result.Columns.Add(new DataColumn(columnName));
foreach(DataRow sourceRow in sourceTable.Rows)
{
var destRow = result.NewRow();
destRow[columnName] = sourceRow[columnName];
result.Rows.Add(destRow);
}
return result;
}
I am trying to get the values from column 18, Test to uppercase after the upload of the excel file but without any succes.
How exactly can I reach the values that are in a DataTable?
This is where I fill the DataTable with the values from the excel file:
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
return dataTable;
}
I would like to have all the values in 18 to be uppercase.
Loop through all rows making the 18th columns data UpperCase:
foreach (DataRow row in dataTable.Rows)
{
row["Test"] = row["Test"].ToString().ToUpper();
}
You can add an Event Handler for the RowChanged event of the DataTable.
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
DataTable dataTable = new DataTable();
dataTable.RowChanged += changedRow;
adapter.Fill(dataTable);
return dataTable;
}
void changedRow(object sender, DataRowChangeEventArgs e)
{
if(e.Action == DataRowAction.Add)
e.Row[17] = e.Row[17].ToString().ToUpper();
}
Probably some check about null values should be planned also.
Of course this avoid a second loop on the data because this event will be called while loading the datatable within the Fill call.
Notice that you should use RowChanged event because RowChanging event doesn't allow to modify the row values. Also I have used a fixed index for the column because I don't know if your connection string contains the configuration to activate column names in the first row of your excel sheet. However if your column name is really named "18" then you could replace the numeric index with the string "18".
I want to copy all rows in old datatable (oldDT) to a new datatable (dt) using ImportRow method. But the new row doesn't have a same column with the old one. Here is my code:
foreach (DataRow dr in oldDT.Rows)
{
MessageBox.Show(dr["tenant_no"].ToString()); //giving a correct result
dt.ImportRow(dr);
MessageBox.Show(dt.Rows[0]["tenant_no"].ToString()); //giving an error Column 'tenant_no' does not belong to table .
}
i try to use the answer C# simple way to copy or clone a DataRow? and here is my new code:
foreach (DataRow dr in oldDT.Rows)
{
MessageBox.Show(dr["tenant_no"].ToString());
DataRow newDR = oldDT.NewRow();
newDR.ItemArray = dr.ItemArray.Clone() as object[];
dt.Rows.Add(newDR); //giving an error "This row already belongs to another table."
MessageBox.Show(dt.Rows[0]["tenant_no"].ToString());
}
Anyone can help me?
Try this... this will work
DataTable dt= new DataTable();
dt= oldDT.Clone();
for (int i=0;i < oldDT.Rows.Count; i++)
{
dt.ImportRow(dataTable.Rows[i]);
}
You could use DataTable.Copy, if you are not locked into using the ImportRow :
Copies both the structure and data for this DataTable.
DataTable dt = oldDt.Copy();
I have a predefined DataGridView that I need to add rows to from a DataTable without data binding. I am trying to use the DataGridView.Rows.Add() method programmatically however, I do not know the column names of the DataTable. The columns in the DataTable are in the same order as the DataGridView but how do I add them to the DataGridView without knowing the column names?
Say your DataGridView exists but has no columns. You can do this:
foreach (DataColumn dc in yourDataTable.Columns) {
yourDataGridView.Columns.Add(new DataGridViewTextBoxColumn());
}
Then add the row data:
foreach(DataRow dr in yourDataTable.Rows) {
yourDataGridView.Rows.Add(dr.ItemArray);
}
Now, if the default textbox column isn't sufficient, you might have to create a column with a different cell template.
it seems that you want to get the column names from the DataTable and add the rows to DataGridView from DataTable rows
DataTable myDataTable = new DataTable();
//adding Columns
myDataTable.Columns.Add("colInt", typeof(int));
myDataTable.Columns.Add("colDate", typeof(DateTime));
myDataTable.Columns.Add("colString", typeof(string));
//adding Rows
myDataTable.Rows.Add(1, DateTime.Now, "Hello World");
//to get columns
foreach (DataColumn col in myDataTable.Columns)
{
var c = new DataGridViewTextBoxColumn() { HeaderText = col.ColumnName }; //Let say that the default column template of DataGridView is DataGridViewTextBoxColumn
dataGridView1.Columns.Add(c);
}
//to get rows
foreach (DataRow row in myDataTable.Rows)
{
dataGridView1.Rows.Add(row[0], row[1], row[2]);
}
anyway there's a shortcut
dataGridView1.DataSource = myDataTable;
if your DataGridView haven’t rows and columns., then just
yourDataGridView.DataSource = yourDataTable
will do all job.
if your DataGridView is already bounded to some datasource(if you using DataTable then I presume DataSource is DataTable),
then you need to edit yourDataTable -> add old rows from old DataTable(or from DataGridView if old DataTable not accessible anymore)
foreach(DataRow dr in oldDataTable.Rows)
{
yourDataTable.Rows.Add(dr);
}
yourDataGridView.DataSource = yourDataTable;
or edit oldDataTable -> add new rows from yourDataTable, something like:
DataTable dtOld = (DataTable)yourDataGridView.DataSource;
foreach(DataRow yourdr in yourDataTable.Rows)
{
dtOld.Rows.Add(yourdr);
}
yourDataGridView.DataSource = dtOld;
I am trying to add data to a row in a dataset but the data is always on a new row?
I need the data to populate under its column. I need something like Ds.Tables[0].Rows[1].add("Item")
This is how i am inserting the data:
DataSet ds = new DataSet();
ds.Tables.Add("Properties");
//GPS
ds.Tables[0].Columns.Add(ArrayProperties[0].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[0].Value);
//Street Num and Name
ds.Tables[0].Columns.Add(ArrayProperties[3].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[3].Value);
//Suburb
ds.Tables[0].Columns.Add(ArrayProperties[6].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[6].Value);
//City
ds.Tables[0].Columns.Add(ArrayProperties[7].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[7].Value);
//Province
ds.Tables[0].Columns.Add(ArrayProperties[8].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[8].Value);
//Locality Map
ds.Tables[0].Columns.Add(ArrayProperties[9].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[9].Value);
//Property Type
ds.Tables[0].Columns.Add(ArrayProperties[10].FormMobiField);
ds.Tables[0].Rows.Add(ArrayProperties[10].Value);
Just get a new Row from the DataTable and then add that row to the table, Use DataTable.NewRow method
DataRow dr = ds.Tables[0].NewRow();
dr["Column1"] = "value";
dr["Column2"] = "value";
dr["Column3"] = "value";
ds.Tables[0].Rows.Add(dr);
You are adding row after adding each column, You may first create your data table's structure by adding all the columns and then you can get the new row using DataTable.NewRow() and later you can add that row to your data table. After adding all the columns you may also try:
ds.Tables[0].Rows.Add(ArrayProperties[0].Value,ArrayProperties[1].Value,ArrayProperties[2].Value,ArrayProperties[3].Value);
The columns collection of a Datatable regards the table structure. In your code you mix adding columns and populating fileds.
You should first create the structure (not tested and syntax errors can occur):
Dataset ds = new Dataset();
Datatable dt = new Datatable();
dt.columns.add(new Column.add(...));
...
dt.columns.add(new Column.add(...));
ds.Tables.add(dt);
And then:
Datarow r = ds.tables[0].NewRow();
r["column1"] = value1;
...
r["columnX"] = valueX;
ds.Tables[0].rows.add(r);
See this msdn article for more details.
Add the columns as you are adding. For populating rows, do the below.
foreach (DataRow row in ds.Tables[0]) // Loop over the rows.
{
row[ArrayProperties[i].FormMobiField]=ArrayProperties[0].Value;
i++;
}
If it doesn't work then let me know,