I created an Excel application using C# with MVVM model. In that excel file I created some columns as template columns. For example I am having some columns like Unit, Cost and Quantity. Now I want to find the exact column number of "Quantity" .
How can I get that particular column(Quantity) number?
Please can any one tell me some method to achieve this?
Execute the Select statement and fill the dataset. Now traverse through the column in the table and find the index of column 'Quantity".
Sample code to load the excel file in Dataset:
public static DataSet exceldata(string filelocation)
{
DataSet ds = new DataSet();
OleDbCommand excelCommand = new OleDbCommand(); OleDbDataAdapter excelDataAdapter = new OleDbDataAdapter();
string excelConnStr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + filelocation + "; Extended Properties =Excel 8.0;Hdr=Yes";
OleDbConnection excelConn = new OleDbConnection(excelConnStr);
excelConn.Open();
DataTable dtPatterns = new DataTable(); excelCommand = new OleDbCommand("SELECT `PATTERN` as PATTERN, `PLAN` as PLAN FROM [PATTERNS$] where 1=0", excelConn);
excelDataAdapter.SelectCommand = excelCommand;
excelDataAdapter.Fill(dtPatterns);
"dtPatterns.TableName = Patterns";
ds.Tables.Add(dtPatterns);
return ds;
}
By using this method, you have loaded the table schema in dataset. Now you can store the column name and index in any of the collection variable and get the column index using the key column name in that collection.
Related
I'm using SQL 2014, Visual Studio 2013. I have the following code that's part of a larger script task:
//Load DataTable1 with Source Excel Sheet Data
OleDbCommand oconn = new OleDbCommand("select * from [" + sheetname + "]", cnn);
OleDbDataAdapter adp = new OleDbDataAdapter(oconn);
DataTable dt = new DataTable();
adp.Fill(dt);
What I would like to do next is select a targeted number of columns from datatable1, and fill another datatable. Something like this:
//Load another DataTable with Data from datatable1
OleDbCommand oconn2 = new OleDbCommand("select [column1], [column2] from datatable1", cnn);
OleDbDataAdapter adp2 = new OleDbDataAdapter(oconn2);
DataTable dt2 = new DataTable();
adp2.Fill(dt2);
Is this possible? The reason behind this is complicated, but I don't know another way around it. My source files are Excel. So the data needs to be brought into a datatable. Then the column names need to modified. Then a table can be made with the modified column names. But first, the data needs to be brought into a datatable as is, as I'm not sure I want to modify the source files.
Thank you.
Define the second DataTable using the data types and new names for the columns that will be added to it. Then you can populate this object by using the ordinal position of the columns in the initial DataTable with the Add method as below.
DataTable dt2 = new DataTable();
dt2.Columns.Add("NewColumnName1", typeof(int));
dt2.Columns.Add("NewColumnName2", typeof(string));
//in this example dt is the original DataTable
foreach (DataRow dr in dt.Rows)
{
//add only necessary columns by their
//ordinal position in source DataTable
dt2.Rows.Add(dr[1], dr[0]);
}
I try to import an excel in to my DataTable with condition.
example : - The user have my provided excel import template, with the first row 0 as the column header (ItemCode, QTY, SerialNo, Remarks). But due to the user might accidentally insert few unwanted column name in anywhere of my per-ready column or delete one of my column name.
I try to build a code regardless what happen, the system only detect my standard ready column header (ItemCode, QTY, SerialNo, Remarks). And only will add the column still within the excel and ignore those accidentally delete column name.
What is the best way to code the detection of the column name when is exist before allow to import those specific column into dataTable?
Below is my current excel import code (which i try to add the above condition code)
private DataTable ReadExcelToDataTable(string filePath)
{
tableSalesOrder = new DataTable("dtSO");
string strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text\"", filePath);
using (OleDbConnection dbConnection = new OleDbConnection(strConn))
{
dbConnection.Open();
DataTable dtExcelSchema = dbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string sSheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
dbConnection.Close();
using (OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT DISTINCT * FROM [" + sSheetName + "]", dbConnection)) //rename sheet if required!
dbAdapter.Fill(tableSalesOrder);
}
return tableSalesOrder;
}
I have try to google around, found many hint but still unable to make it work.
Thank you for any advice.
If you just wanted to ignore extra columns, you could use
... new OleDbDataAdapter("Select Distinct ItemCode, QTY, SerialNo, Remarks FROM [" + sSheetName + "] ...
If you need to cope with some of these columns being missing, then it is slightly more complicated. You need to get a list of columns in the excel sheet , eg
DataTable dt = dbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns,
new object[] { null,null, sSheetName, null });
List<string> columnNames = new List<string>();
foreach (DataRow row in dt.Rows)
columnNames.Add(row["Column_name"].ToString());
Then you need to build up your select statement to only include the columns that you want and that exist in the excel sheet.
You could set up your workbooks with named ranges, and extract those. That way it'll work even if they accidentally change the name or insert extra columns. You can select the named range with something like this:
var sql = "SELECT * FROM [Workbook$MyNamedRange]"
using (OleDbDataAdapter dbAdapter = new OleDbDataAdapter(sql, dbConnection));
dbAdapter.Fill(tableSalesOrder);
I solve the issue by using different method, I got the idea from both your guys advise. In fact, after i do some test on my origin code which posted, it only will import according the column name which i define which is ItemCode, Qty, SerialNo & Remakrs at my gridView which my dataTable have assign to it as data source.
The only issue is when one of the column deleted, my import process will be facing problem. This due to the datatable never assign any column name after it created.
I solve it by improve the dataTable set and redefine the column name into It.
if (tableSalesOrder == null)
{
tableSalesOrder = new DataTable("dtSO");
DataColumn colItemCode = new DataColumn("ItemCode",typeof(string));
......
tableSalesOrder.Columns.Add(colItemCode);
......
}
else
{
tableSalesOrder.Clear();
}
Thanks guys for the help. Finally I found where the bugs were.
I do the following:
SqlConnection conn = new SqlConnection("... my connection string ...");
dataAdapter = new SqlDataAdapter();
SqlCommand selectCommand = new SqlCommand("select * from items", conn);
dataAdapter.SelectCommand = selectCommand;
DataTable schemaTable = new DataTable();
dataAdapter.FillSchema(schemaTable, SchemaType.Source);
However, there are no rows in the schemaTable. dataAdapter.Fill() work.
I think you misunderstand what FillSchema does.
It takes the DataTable passed in (with no row and no column) and builds the schema adding the columns with infos about size, type etc... corresponding to the table that will be returned by the SelectCommand.
It doesn't fill the passed in table with records.
Infact, if you look at the Columns count after the call to FillSchema you will find that your schemaTable has been 'built' with columns matching the items table.
So, what is the use for a FillSchema call considering that a Fill call, equally fills the table with its columns names and types? Well, FillSchema is used to prepare the table passed in for the following Fill with some properties that otherwise are not loaded by the Fill call. For example, suppose that your items table has an AutoIncrement column. This property is not available on the the matching DataColumn after the call to Fill. But, if you pass to Fill, the table prepared by FillSchema, that property is available.
If you want just the infos about the columns of your table you need a different approach
using(SqlConnection con = new SqlConnection(.......)
{
con.Open();
DataTable schema = con.GetSchema("Columns", new string[] {null, null, "items"});
foreach(DataRow row in schema.Rows)
Console.WriteLine("TABLE:" + row.Field<string>("TABLE_NAME") +
" COLUMN:" + row.Field<string>("COLUMN_NAME"));
}
or in a more standard way
using(SqlConnection con = new SqlConnection(.......)
{
con.Open();
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='items'
AND TABLE_CATALOG = 'yourDBNameHere'", con);
SqlDataReader reader = cmd.ExecuteReader();
dt.Load(reader);
foreach(DataRow row in dt.Rows)
..... catalog, name, ordinal_position, column_default etc....
}
The FillSchema method retrieves the schema from the database using the SelectCommand. A FillSchema creates a DataTable with the PrimaryKey and Constraints properties, adds the columns to the DataColumnCollection and configures the necessary DataColumn properties. This method doesn't fill the datatable with rows, it only applies the schema. use the Fillmethod to do this.
I'm trying to search for a code entered by the user in a sqlite table if it's found add the row to a dataGridView. the problem is that the code I'm using clears the datagrid every time I add a new row.
Here is the code I'm using
DataTable dt = new DataTable();
String insSQL = "select * from Produtos where codigo =" + txtCodigo.Text;
String strConn = #"Data Source=C:\caixa.sqlite";
SQLiteConnection conn = new SQLiteConnection(strConn);
SQLiteDataAdapter da = new SQLiteDataAdapter(insSQL, strConn);
da.Fill(dt);
dataGridViewProdutos.DataSource = dt.DefaultView;
I tried to change the dataGridViewProdutos.datasource to dataGridViewProdutos.Rows.add(dt); them it adds a row but always empty.
I fixed it removing the DataTable dt = new DataTable(); from the loop. I also changed the dt.DefeulView to only dt as sugested by N4TKD and Im seeing no diference so Im using it.
Also thanks for the links it was very helpfull since I was struggling to make my colums fill the dataGridView space.
I have a listbox and would like to fill it with data from a database, the two must be linked so if i select a value from the listbox i can work with the entry in the database.
I'm using a disconnected database witch connects though a connection string:
conn = new SqlConnection(Properties.Settings.Default.DBConnectionString)
I have read up on dataset's and think i need to create one and use it as my listbox data source, Then to have the data displayed looking neat i need to set the display name.
Could someone show me how to create a dataset that's connected to my table in my database and then show me how to bind it.
Database is called TagCloudDB and table is called Tag and just listbox1.
This is the code i have so far, but it just fills the listbox with System.Data.DataRowView.
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
{
conn.Open();
SqlDataAdapter daTags
= new SqlDataAdapter("Select * From Tag", conn);
DataSet dsTags = new DataSet("TagCloud");
daTags.FillSchema(dsTags, SchemaType.Source, "Tag");
daTags.Fill(dsTags, "Tag");
daTags.MissingSchemaAction = MissingSchemaAction.AddWithKey;
daTags.Fill(dsTags, "Tag");
DataTable tblTag;
tblTag = dsTags.Tables["Tag"];
dplTags.DataSource = dsTags;
dplTags.DataMember = "Tag";
dplTags.DataBind();
}
I did some thing similar in collage with VB and they have a ValueMember and Displaymember, Whats the equivalent in C#
SqlConnection _connection = new Connection(connectionString)
SqlDataAdapter _adapter = new SqlDataAdapter(_connection, "select * from tag")
DataTable _table = new DataTable()
_adapter.Fill(_table)
_connection.Close();
foreach(DataRow _row in _table.Rows)
{
listbox.AddItem(new Item(_row["column1"], _row["column2"])
}
You don't need to mess with datatables. It automatically binds with the sql query.