I am trying to import an xlsx file data into a DataTable. I want to read the 2nd row as columns row or maybe 4th row as columns. currently I am using the below code which is working fine, wanted to know is there any other way to read the excel data from 2nd/4th rows?
public static DataTable GetDataTableFromSecondRow(string filePath,string sheetName)
{
var oleDbConnection = new ExcelToDb(filePath).GetOleDbConnection();
using (OleDbCommand oleDbCommand = new OleDbCommand(String.Format("select * from [{0}${1}]", sheetName, "A2:end"), oleDbConnection))
{
oleDbCommand.ExecuteNonQuery();
using (OleDbDataReader reader = oleDbCommand.ExecuteReader())
{
DataTable dataTable = new DataTable();
dataTable.Load(reader);
return dataTable;
}
}
}
The issue with the code is when I am trying to read the excel file to the end by using "A2:end" it is leaving the data after few blank rows which is not a correct way.
can we use something like "dt1.AsEnumerable.Skip(3)" which skips not just the rows but also the first row default column?
Example picture - would like to read my data as second table by skipping first 2-3 lines.
Try use NPOI to read excel, it can easily use rowNumber and colNumber to get cell value, see this post:
sheet.GetRow(rowNumber).GetCell(colNumber).StringCellValue))
NPOI can add by Nuget.
update:
Select * From [SheetName$] may work, it can select all data on sheet including middle empty cell, then it can use datatable.Rows[rowNum][colNum] to get any cell value, reference post.
Related
I wrote the following code in order to copy a DataTable content into a MS Access table.
The problem is that the data set is very huge, it takes a long time (more than 10mns), and stops when the file reaches 2GB. I know entire set of data is about 785Mo in RAM for about 820000 rows.
public static bool InsertmyDataTableDAO(string filePathName, DataTable myDataTable)
{
string connectionString = string.Format(ConnectionParameters.MsAccessConnectionStringOledb, filePathName);
DBEngine dbEngine = new DBEngine();
Database db = dbEngine.OpenDatabase(filePathName);
db.Execute("DELETE FROM " + myDataTable.TableName);
Recordset rs = db.OpenRecordset(myDataTable.TableName);
Field[] tableFields = new Field[myDataTable.Columns.Count];
foreach(DataColumn column in myDataTable.Columns)
{
tableFields[column.Ordinal] = rs.Fields[column.ColumnName];
}
foreach(DataRow row in myDataTable.Rows)
{
rs.AddNew();
foreach(DataColumn col in row.Table.Columns)
{
tableFields[col.Ordinal].Value = row[col.Ordinal];
}
rs.Update();
}
rs.Close();
db.Close();
return true;
}
Is there a faster way to copy data set from datatable to MS Access DB?
The max db size for access is 2GB, you can't bypass this limit :
https://support.office.com/en-us/article/access-specifications-0cf3c66f-9cf2-4e32-9568-98c1025bb47c?ui=en-US&rs=en-US&ad=US
I see you're using a DELETE statement to remove the rows beforehand. DELETE doesn't necessarily recover free space. Here's what I'd do...
Use your existing code to delete the data in the table.
Next, use Microsoft.Interop.Access to compact/repair the database
Finally, run your above code to insert the DataTable.
I'd also add that you could probably use Microsoft.Interop.Access to import the datatable too... Perhaps save it to a CSV file first... then import it that way rather than using INSERT statements.
I searched the web and Stack Overflow and found lots of descriptions on how to fill a DataGridView with the content of a DataTable. But still it does not work for me. My DataGridView shows the correct number of columns and rows, but they appear empty.
I use following method:
public void ShowDataInGrid(ref DataTable table)
{
BindingSource sBind = new BindingSource();
dbView.Columns.Clear();
dbView.AutoGenerateColumns = false;
sBind.DataSource = table;
dbView.DataSource = sBind; //Add table to DataGridView
dbView.Columns.Add("Date", "Date");
}
Before this I created a DataGridView of name "dbView" via the designer. I am not even sure, whether I need sBind. Without it I can bind the table directly to dbView, with the same bad result.
I suspect my table is the problem. It origins from a database (SQLite) and has several columns and rows (one of the columns has the name "Date"). It is definately filled with readable data.
I mainly read the table in using following commands (after this I manipulate the data in several different steps, like changing strings and adding numbers...):
string sql = "select * from Bank";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
table.Load(reader);
reader.Close();
table.AcceptChanges();
I think the problem might be, that the table entries are stored as objects and not as string, and hence can't be shown. That's why I tried to force the content to be strings with the following change to my table:
DataTable dbTableClone = new DataTable();
dbTableClone.Load(reader);
SQLiteDataReader reader.Close();
dbTableClone.AcceptChanges();
string[] dBHeader = new string[dbTableClone.Columns.Count];
dBHeader = ReadHeaderFromDataTable(dbTableClone); //own funktion, which reads the header
DataTable table;
table.Clear();
//will first create dbTable as empty clone, so I can set DataTyp of each Column
table = dbTableClone.Clone();
for (int col = 0; col > dBHeader.Length; col++) //first set all columns as string
{
dbTable.Columns[col].DataType = typeof(string);
}
foreach (DataRow Row in dbTableClone.Rows)
{
dbTable.ImportRow(Row);
}
This did not help me neither.
Another idea: I found some comments on similar problems, where it got apparently solved with quote: "I designed columns in the VS datagridview designer. Not the column name, but the column DataPropertyName must match with fields in database." Unfortunately I don't seem to be able to do/understand this.
Following you see one row of my input table.
Try fetching and setting to GridView this way
SqlLiteConnection con = new SqlLiteConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename=DB.mdf;Integrated Security=True");
con.Open();
SqlLiteDataAdapter adap = new SqlLiteDataAdapter("select * from Bank", con);
DataSet ds = new System.Data.DataSet();
adap.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
Comment everything you've done so far, try this and let me know if this works for you or not. Change connection according to your DB.
I solved the problem.
The DataTable was fine. The problem was the setup of my DataGridView dbView. I set up dbView in the designer and somehow gave it a datasource. Now I set the datasource to "none" (In "DataGridView Tasks") and my data appears as intended.
Thanks to M Adeel Khalid for looking at my stuff. Him assuring to me that my code for the link was right, made me find the solution eventually.
At the end I really only needed to use a single line:
dbView.DataSource = table;
How to update datatable values through datagridview which will be stored in excel sheet... so that the changes will updated in datagridview when loading excel file next time
If you are talking about "Taking data from GridView and storing that data in DataTable in asp.net", then try this
DataTable yourDT = new DataTable();
yourDT.Columns.Add("content");
// Add your columns here
foreach (GridViewRow row in gvParent.Rows)
{
string Content = row.Cells[0].Text; // If you are using databound columns
string ContentFromLabel = ((Label)row.Cells[0].FindControl("YourLabel")).Text;// If you are using Template column
// get more columns like this that you have added
yourDT.Rows.Add(new object[] { Content, .... other data });
}
Using the code below (from a console app I've cobbled together), I add seven columns to my datatable. Once this is done, how can I set the data type for each column? For instance, column 1 of the datatable will have the header "ItemNum" and I want to set it to be an Int. I've looked at some examples on thet 'net, but most all of them show creating the column header and column data type at once, like this:
loadDT.Columns.Add("ItemNum", typeof(Int));
At this point in my program, the column already has a name. I just want to do something like this (not actual code):
loadDT.Column[1].ChangeType(typeof(int));
Here's my code so far (that gives the columns their name):
// get column headings for datatable by reading first line of csv file.
StreamReader sr = new StreamReader(#"c:\load_forecast.csv");
headers = sr.ReadLine().Split(',');
foreach (string header in headers)
{
loadDT.Columns.Add(header);
}
Obviously, I'm pretty new at this, but trying very hard to learn. Can someone point me in the right direction? Thanks!
You should be able to assign the column's data type property so long as there is no data stored in that column yet:
CODE:
loadDT.Column[1].DataType = typeof(int);
visual studio not allows to change type of a column has some data,
u must create a new column with ur ideal type and copy data from specified column to new column
DataTable DT = new DataTable();
DT = somsdata ;
DT.columns.Add("newcol",object);
foreach(datarow dr in DT.rows)
dr.itemarray["newcolumn"] = dr.itemarray["oldColumn"];
I have some Excel file reading code that uses the OLEDB (Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;) which works well but I keep encountering an issue whereby certain dates are returned as DBNull.
In the original XLS document, the format of dates that work (en-GB locale) are:
"02/04/2009 17:00:00" // returned as a System.DateTime
And the following style fails:
"08/Jan/09 11:24 AM" // returned as DBNull
Excel knows they're both dates (although I can't force them to style correctly) as the following correctly shows a date:
=DATE(YEAR(c),MONTH(c),DAY(c)) // where c = cell reference.
Is there a way, without altering the auto-generated original, to get the data?
EDIT for reference, here is my read-data method (assuming a dbAdapter is set up already -- note the DBNull doesn't come from the catch which isn't fired at all):
public List<List<string>> GetData(string tableName, int maxColumns)
{
List<List<string>> rows = new List<List<string>>();
DataSet ExcelDataSet = new DataSet();
dbCommand.CommandText = #"SELECT * FROM [" + tableName + "]";
dbAdapter.Fill(ExcelDataSet);
DataTable table = ExcelDataSet.Tables[0];
foreach (DataRow row in table.Rows)
{
List<string> data = new List<string>();
for (int column = 0; column < maxColumns; column++)
{
try
{
data.Add(row[column].ToString());
}
catch (Exception)
{
data.Add(null);
}
}
// Stop processing at first blank row
if ( string.IsNullOrEmpty(data[0]) ) break;
rows.Add(data);
}
return rows;
}
I don't know if this will be helpful or not, but I have run into issues with Excel OLEDB code returning NULLs where I expected data and it almost always came back to a data type inference issue. Excel determines the datatype of a column based on the first x rows of data (I think x=10, could be wrong). I know you don't want to alter the file, but it might be worth trying to put the problem date style in the first 10 rows and see if it alters the behavior of your application.
Obviously if it does fix it, then that doesn't solve your problem. The only fixes in that case that I know of are to alter the file (put something in the first 10 rows that forces it to use the correct datatype). Sorry I can't offer a better solution, but hopefully at least I am helping you figure out what's causing your issue.