I have a DataGridView that contains data which has been successfully imported from a .csv file using the code below. The columns in the DGV can be reordered by the user. I need to export the data to a SQL Server database using the columns' DisplayIndex order rather than the Index order.
private void btn_Upload_Click(object sender, EventArgs e)
{
char colDelimiter = ',';
char rowDelimiter = '\r';
DataTable dataTable = new DataTable();
OpenFileDialog getFile = new OpenFileDialog();
getFile.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*";
getFile.FilterIndex = 1;
if(getFile.ShowDialog() == DialogResult.OK)
{
string fileName = getFile.FileName;
TextReader reader = new StreamReader(getFile.FileName);
string[] columns = reader.ReadLine().Split(colDelimiter);
int x = 0;
foreach(string c in columns)
{
dataTable.Columns.Add(columns[x]);
x += 1;
}
x = 0;
string[] rows = reader.ReadToEnd().Split(rowDelimiter);
foreach (string r in rows)
{
string[] record = r.Split(colDelimiter);
dataTable.Rows.Add(record);
}
this.dataGridView1.DataSource = dataTable;
MessageBox.Show(fileName + " was successfully imported.");
}
Unfortunately this is the best solution I know of: Create a new table based on the dataGridView's displayed table. Then replace the original DataTable with the new one. I'm assuming you have some DataTable called table in this example.
Hope this helps and I wish there was a simpler way, but if you're doing a large Update() command this is the easiest approach I know.
If you're doing something where you manually update each line with a SQL query or something though you can just make sure the update goes based on the DisplayIndex and the DataGridView rather than the DataTable directly.
//Make a new DataTable
DataTable newTable = new DataTable();
//Create Columns based on DataGridView headers
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
newTable.Columns.Add(col.HeaderText);
}
//Add each row of data from DataGridView into new DataTable in the displayed order
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow newRow = newTable.NewRow();
foreach(DataGridViewCell cell in row.Cells)
{
newRow[cell.ColumnIndex] = cell.Value;
}
newTable.Rows.Add(newRow);
}
//Set your original DataTable to the new DataTable with the correct ordering
table = newTable;
Also, as a note, I was looking at how you originally load the .csv...
I have something similar where I'm splitting based on delimiters and I just make sure to include a Schema.ini where my .csv is being loaded from and then use ADO commands to populate the DataTable. This seems to work much faster for me.
See my Schema.ini which splits at commas:
[tempdata.csv]
Format=Delimited(,)
ColNameHeader=True
MaxScanRows=0
Here is the #include command:
using System.Data.OleDb;
Here is the C# code to populate my DataTable using the dataAdapter Fill(), set the binding source to the DataTable, and then set the DataSource for my dataGridView to the binding source:
string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + workingPath + ";Extended Properties=\"text;HDR=YES;FMT=Delimited(|)\"";
using (OleDbConnection conn = new OleDbConnection(connString))
{
using (OleDbCommand cmd = new OleDbCommand("SELECT * FROM " + workingFilename, conn))
{
conn.Open();
OleDbDataAdapter dAdapter = new OleDbDataAdapter(cmd);
originalTable = new DataTable("");
dAdapter.Fill(originalTable);
}
}
Related
I really don't know guys if U can understand my problem but I will try to make it clear as possible, I have a DataGrid view and I don't use Entity framework to fill it with data just I've displayed direct data from my database to fill it like:
private void load()
{
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["UR2k_CS.Properties.Settings.StoreConnectionString"].ConnectionString);
SqlDataAdapter data = new SqlDataAdapter("Select * FROM [dbo].[missingItems]", con);
DataTable table = new DataTable();
data.Fill(table);
dataGridView1.Rows.Clear();
foreach (DataRow item in table.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["RFID"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["name"].ToString();
dataGridView1.Rows[n].Cells[2].Value = item["model"].ToString();
dataGridView1.Rows[n].Cells[3].Value = item["category"].ToString();
dataGridView1.Rows[n].Cells[4].Value = item["prix"].ToString();
dataGridView1.Rows[n].Cells[5].Value = item["ref"].ToString();
}
and I want to export its data into .csv file using Save File Dialog ( to make user select save place) and I found that code on the net:
private void btnExportToExcel_Click(object sender, EventArgs e)
{
var dia = new System.Windows.Forms.SaveFileDialog();
dia.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dia.Filter = "Excel Worksheets (*.xlsx)|*.xlsx|xls file (*.xls)|*.xls|All files (*.*)|*.*";
if(dia.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
{
DataTable data = null;// use the DataSource of the DataGridView here
var excel = new OfficeOpenXml.ExcelPackage();
var ws = excel.Workbook.Worksheets.Add("worksheet-name");
// you can also use LoadFromCollection with an `IEnumerable<SomeType>`
ws.Cells["A1"].LoadFromDataTable(data, true, OfficeOpenXml.Table.TableStyles.Light1);
ws.Cells[ws.Dimension.Address.ToString()].AutoFitColumns();
using(var file = File.Create(dia.FileName))
excel.SaveAs(file);
}
}
but As U see Guys I don't have data source so how to fill it with my grid view data.
You have a datatable...
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["UR2k_CS.Properties.Settings.StoreConnectionString"].ConnectionString);
SqlDataAdapter data = new SqlDataAdapter("Select * FROM [dbo].[missingItems]", con);
DataTable table = new DataTable();
data.Fill(table);
Why dont you use just this table to export to excel?
If your datable doesnt match the columns you want to export, you still would have to manage column mapping...
I'am using listView to import excel file because all of my table is listView.
How to import selected column and rows of excel file to listView? Because it's only working if I make a column in first row or "A1" and if possible can I use where query that will match to their NAMES or ID? Thank you for giving me a hand!
This is my example Excel file that will import to my listView.
my code
string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + txtFileName.Text + ";Extended Properties=Excel 12.0;";
DataTable table = new DataTable();
string excelName = "Sheet1";
string strConnection = string.Format(connStr);
OleDbConnection conn = new OleDbConnection(strConnection);
conn.Open();
OleDbDataAdapter oada = new OleDbDataAdapter("select * from [" + excelName + "$]", strConnection);
table.TableName = "TableInfo";
oada.Fill(table);
conn.Close();
// Clear the ListView control
listView1.Items.Clear();
// Display items in the ListView control
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow drow = table.Rows[i];
// Only row that have not been deleted
if (drow.RowState != DataRowState.Deleted)
{
// Define the list items
ListViewItem lvi = new ListViewItem(drow["1ST"].ToString());
// Add the list items to the ListView
listView1.Items.Add(lvi);
}
}
You would need to get all of the values from the first row, i.e. A1 -> [...]1 and create columns named with those values. Then add all of the rows.
Grab the first row, perhaps like:
foreach (Column c in ExcelColumns)
{
listView.Columns.Add(c.Value);
}
! Note this is not necessarily the correct code, just illustrative.
...then have your code read
for (int i = 1; i < table.Rows.Count; i++)
instead of
for (int i = 0; i < table.Rows.Count; i++)
I have a DataTable called dt which is filled with values from excel.
On line 6 (row) i have my header information
Code i have now
string connString = #"Provider=Microsoft.ACE.OLEDB.16.0;Data Source=C:\Users\thoje\Desktop\stack\forslag.xlsx;" +
#"Extended Properties=""Excel 12.0;HDR=No;""";
DataTable dt = new DataTable();
string sql = #"SELECT * from [Ark1$]";
using (OleDbConnection conn = new OleDbConnection(connString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand(sql, conn))
{
using (OleDbDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
}
}
DataTable dt2 = dt.Clone();
//foreach (DataRow dr in dt.Rows)
//{
for (int i = 5; i <= dt.Rows.Count-1; i++)
{
if (i == 6)
{
DataRow dr = dt2.NewRow();
dr.ItemArray = dt.Rows[i].ItemArray;
dt2.Rows.Add(dr);
}
else if(i >=8)
{
DataRow dr = dt2.NewRow();
dr.ItemArray = dt.Rows[i].ItemArray;
dt2.Rows.Add(dr);
}
}
What i need is:
I want all my data on row 6 to become headers in a new DataTable
All data after line 7 i need to append to this new Datatable with the new headers.
What my code shows:
My code now shows how to do it on a DataTable which is cloned, so therefore i have the wrong headernames.
You don't need to iterate through all rows if you only need 1 of them.
DataTable dtSource = new DataTable();
DataTable dtTarget = new DataTable();
// Get row at index == 6 (7th line as this is a 0-based-index)
var headerRow = dtSource.Rows[6];
// Iterate through all values
foreach(var value in headerRow.ItemArray)
{
// For each value create a column
// and add it to your new dataTable
DataColumn dc = new DataColumn(value.ToString());
dc.Caption = value.ToString();
dtTarget.Columns.Add(dc);
}
using a linq approach might be good:
a pseudo way:
//linq query to select row
var query = from myRow in
myDataTable.AsEnumerable() where myRow.Field<int>("RowNo") == 6
select myRow;
// Create a table from the query DataTable newTable =
query.CopyToDataTable<DataRow>();
Your question is pretty confusing to read, and keeps talking about rows where I'd expect columns etc, but I'll make the following assumptions:
You have an excel file with 5 blank rows and then a row of headers, and then data rows
You've successfully imported this data into a Datatable called dt
You want to end up with a datatable that has the values in row 6 as the column names, and the blank rows removed
Code:
for(int i = 5; i >= 0; i--){
if(i == 5)
{
for(int j = 0; j < dt.Columns.Count; j++)
dt.Columns[j].ColumnName = dt.Rows[i][j].ToString();
}
dt.Rows.RemoveAt(i);
}
You don't need to clone the datatable. Watch out for strings that make for poor column names (containing chars like '[' ) making your life miserable further down the line ..
I'm trying to export data in multiple files to a single datatable. I was able to add data to the dataset but it doesn't provide the output that I need. I guess it should be an error in my loop and I tried in different ways but failed to get the correct output. Given below the output that I receive:
And this is the output I need:
Please refer the coding that I used, and please help me to find where I'm going wrong. Thanks in advance.
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.Multiselect = true;
DataTable dt = new DataTable();
if (thisDialog.ShowDialog() == DialogResult.OK)
{
foreach (string files in thisDialog.FileNames)
{
//each file generates two columns
DataColumn column1 = new DataColumn();
dt.Columns.Add(column1);
DataColumn column2 = new DataColumn();
dt.Columns.Add(column2);
using (System.IO.StreamReader file = new System.IO.StreamReader(files))
{
string line;
while ((line = file.ReadLine()) != null)
{
if (line.Contains("DISKXFER"))
{
string dataLine = line.ToString();
string[] split = dataLine.Split(',');
int result = split.Length;
DataRow row = dt.NewRow();
dt.Rows.Add(split[2], split[3]);
}
}
}
}
dataGridView1.DataSource = dt;
}
You are adding a new row for each DISKXFER line in each file, with only the first two columns populated - dt.rows.add does this.
You should fill in more of the columns in dr, then add dr to the table.
Rather than use the designer I'm trying to populate a DataGridView I've put on my Winform programmatically. When I look in the table under the debugger it has the correct columns and number of rows. The problem is the grid appears as an empty grey box on my form. When I bind the grid to the database via VS 2008 Designer it worked fine. How can I track down the problem?
UPDATE
I pretty much took this from this MSDN Article
UPDATE
Do I have to do anything in the designer other than drop the grid on the Winform?
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SQLite;
using System.Windows.Forms;
namespace CC
{
public partial class Form1 : Form
{
private BindingSource bindingSource1 = new BindingSource();
private SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter();
public Form1()
{
InitializeComponent();
dataGridView1 = new DataGridView();
this.Load += new System.EventHandler(Form1_Load);
this.Text = "Cars";
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = bindingSource1;
GetData("select * from Cars");
}
private void GetData(string selectCommand)
{
string dbPath = "c:\\temp\\cars.db";
try
{
var connectionString = "Data Source=" + dbPath + ";Version=3";
dataAdapter = new SQLiteDataAdapter(selectCommand, connectionString);
SQLiteCommandBuilder commandBuilder = new SQLiteCommandBuilder(dataAdapter);
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
dataAdapter.Fill(table);
bindingSource1.DataSource = table;
// Resize the DataGridView columns to fit the newly loaded content.
dataGridView1.AutoResizeColumns(
DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
}
catch (SqlException)
{
MessageBox.Show("To run this example, replace the value of the " +
"connectionString variable with a connection string that is " +
"valid for your system.");
}
}
}
}
I think you need to specify the DataMember property. And I think you don't require binding source object, directly you can bind DataTable to DataGridView control.
I am attaching a code which helps to bind gridview control with SQL Server database, and it works fine for me.
using(SqlDataAdapter sqlDataAdapter =
new SqlDataAdapter("SELECT * FROM Table1",
"Server=.\\SQLEXPRESS; Integrated Security=SSPI; Database=SampleDb"))
{
using (DataTable dataTable = new DataTable())
{
sqlDataAdapter.Fill(dataTable);
this.dataGridView1.DataSource = dataTable;
}
}
Sorry I don't have SQLite installed :(
basically i dont think u should complicate this! here's an easy way:
string cs = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=your db location;"; //connection string
string sql = "SELECT * FROM table_name"; //sql statment to display all data
OleDbConnection conn = new OleDbConnection(cs); //connectiion
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn); //data adapter object
DataSet ds = new DataSet(); //dataset object to keep data in table
conn.Open(); //open connection
da.Fill(ds, "table_name"); // fill the dataset with table_name through data adapter
conn.Close(); //close connection
dataGridView1.DataSource = ds; //populate the datagridview with dataset
dataGridView1.DataMember = "table_name"; // populate datagridview with table_name
I have has difficulties with sqlite and also binding with linq. Now I have the same issue as above and ended up looping the data table to fill the grid.
I have noticed other minor issues with sqlite when using datatables and also databinding so I guess the problem lies with sqlite.
Here's some code to save time for anyone.
int rowcount = 0;
foreach (DataRow row in dataTable.Rows)
{
dataGrid.Rows.Add();
int column = 0;
foreach (var item in row.ItemArray)
{
dataGrid.Rows[rowcount].Cells[column].Value = item;
column++;
}
rowcount++;
}