I'm trying to populate the data extracted from SQL Server into Excel 2010. The code below works fine, but the difficulty is that I don't create an Excel spreadsheet programmatically, it is aleady exists and I make a request for data via plugin in Excel written in C#.
Even though I set the cursor to A10 cell, Excel starts filling-out the data from the very first cell and overwrites the header (that is already exists). Please help to fix.
Code:
OdbcConnection cnn;
cnn = new OdbcConnection(azureConn);
using (OdbcCommand command = cnn.CreateCommand())
{
command.CommandText = "{call sp_Get_Excel_Data(?,?,?,?,?,?,?,?)}";
command.Parameters.AddWithValue("#StartDate", startDate);
command.Parameters.AddWithValue("#EndDate", endDate);
command.Parameters.AddWithValue("#startTime", startTime);
command.Parameters.AddWithValue("#endTime", endTime);
command.Parameters.AddWithValue("#smp", smp);
command.Parameters.AddWithValue("#Reg", reg);
command.Parameters.AddWithValue("#event", events);
command.Parameters.AddWithValue("#userId", userId);
cnn.Open();
//DataTable
OdbcDataAdapter adapter = new OdbcDataAdapter(command);
//DataSet
DataSet ds = new DataSet();
adapter.Fill(ds);
//Cast to DataTable
DataTable dataTable = ds.Tables[0];
string[] colNames = new string[dataTable.Columns.Count];
int col = 0;
foreach (DataColumn dc in dataTable.Columns)
colNames[col++] = dc.ColumnName;
w = this.Application.ActiveWorkbook;
ws = (Worksheet)w.ActiveSheet;
Range hdrRow = (Range)ws.Rows[9];
hdrRow.Value = colNames;
hdrRow.Font.Bold = true;
hdrRow.VerticalAlignment = XlVAlign.xlVAlignCenter;
//Position the cursor
var range = ws.get_Range("A10");
range.Select();
//Inserting the Column and Values into Excel file
string data = null;
int i = 0;
int j = 0;
for (i = 0; i <= dataTable.Rows.Count - 1; i++)
{
for (j = 0; j <= dataTable.Columns.Count - 1; j++)
{
data = dataTable.Rows[i].ItemArray[j].ToString();
ws.Cells[i + 2, j + 1] = data;
}
}
Hate to answer my own questions, but here is the solution (with optimized performance):
int column = 1;
foreach (DataColumn c in dataTable.Columns)
{
//Ninth row, starting from the first cell
ws.Cells[10, column] = c.ColumnName;
column++;
}
// Create a 2D array with the data from the data table
int i = 0;
string[,] data = new string[dataTable.Rows.Count, dataTable.Columns.Count];
foreach (DataRow row in dataTable.Rows)
{
int j = 0;
foreach (DataColumn c in dataTable.Columns)
{
data[i, j] = row[c].ToString();
j++;
}
i++;
}
// Set the range value to the 2D array in Excel (10th row, starting from 1st cell)
ws.Range[ws.Cells[11, 1], ws.Cells[dataTable.Rows.Count + 11, dataTable.Columns.Count]].Value = data;
Related
I'm making a desktop application using the windows form with C#, I stored uploaded csv data with data grid view, then I make a transpose feature in the application, but did not work well, because the row of index or row 0 does not included in transpose output file.
Picture 1
So, I decided to add a empty row inside csv file at the top of data with this code
DataRow dr1 = dt.NewRow();
dt.Rows.InsertAt(dr1, 0);
I tried manually by insert empty row in csv and the application look like this
Picture 2
How should I code to make application insert an empty data row at 0 and store it in data grid view looks like a picture above? so my transpose feature works well
here I wrote to store the data in data grid
public DataSet ConnectCSV()
{
DataSet ds = new DataSet();
string fileName = openFileDialogCSVFilePath.FileName;
CsvReader reader = new CsvReader(fileName);
ds = reader.RowEnumerator;
dGridCSVdata.DataSource = ds;
dGridCSVdata.DataMember = "TheData";
return ds;
}
private void dGridCSVdata_Navigate(object sender, NavigateEventArgs ne)
{
}
here I wrote to read the data
public DataSet RowEnumerator
{
get
{
if (null == __reader)
throw new System.ApplicationException("I can't start reading without CSV input.");
__rowno = 0;
string sLine;
string sNextLine;
DataSet ds = new DataSet();
DataTable dt = ds.Tables.Add("TheData");
DataRow dr1 = dt.NewRow();
dt.Rows.InsertAt(dr1, 0);
while (null != (sLine = __reader.ReadLine()))
{
while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
sLine += "\n" + sNextLine;
__rowno++;
DataRow dr = dt.NewRow();
string[] values = rexCsvSplitter.Split(sLine);
for (int i = 0; i < values.Length; i++)
{
values[i] = Csv.Unescape(values[i]);
if (__rowno == 1)
{
dt.Columns.Add(values[i].Trim());
}
else
{
if (Csv.CharNotAllowes(values[i]))
{
dr[i] = values[i].Trim();
}
}
}
if (__rowno != 1)
{
dt.Rows.Add(dr);
}
ds.Tables.Add(Transposer.Transpose(dt));
// transpose code
StringBuilder sb = new StringBuilder();
for (int u = 0; u < dt.Columns.Count; u++)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
sb.Append(dt.Rows[i][u].ToString());
if (i < dt.Rows.Count - 1)
{
sb.Append(',');
}
}
sb.AppendLine();
}
File.WriteAllText("C:\\Users\\Desktop\\Output.csv", sb.ToString());
}
__reader.Close();
return ds;
}
}
The data in InvtID already match with "3" column once I import an Excel file, but the problem is as shown in the photo why the data column (InvtID) filled in datatable after the last row data? How am I able to fix the position to match with "3" column. I already position the InvtID column at 0. Is there any single line code to start position the row at 1?:
public void filldatagridview(ExcelWorksheet workSheet)
{
DataTable dt = new DataTable();
//Create the data column
for (int col = workSheet.Dimension.Start.Column;
col <= workSheet.Dimension.End.Column; col++)
{
dt.Columns.Add(col.ToString());
}
for (int row = 12; row <= 26; row++)
{
DataRow newRow = dt.NewRow(); //Create a row
int i = 0;
for (int col = workSheet.Dimension.Start.Column;
col <= workSheet.Dimension.End.Column; col++)
{
newRow[i++] = workSheet.Cells[row, col].Text;
}
dt.Rows.Add(newRow);
}
dt.Columns.RemoveAt(0); //remove No
dt.Columns.RemoveAt(0); //remove article
//Get BookCode
var barCodes = dt.AsEnumerable().Select(r => r.Field<string>("3"))
.ToArray(); //EAN column
var barCodesstring = string.Format("'{0}'", string.Join("','", barCodes));
SqlCommand cmd = new SqlCommand("SELECT InvtID FROM InventoryCustomer WHERE
Barcode IN (" + barCodesstring + ")", conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
dt.Columns["InvtID"].SetOrdinal(0);
dataGridView2.DataSource = dt;
conn.Close();
}
This code always adds a new row DataRow newRow = dt.NewRow();, so your rows are not matched:
for (int row = 12; row <= 26; row++)
{
DataRow newRow = dt.NewRow(); //Create a row
//...
dt.Rows.Add(newRow);
}
But if I understood correctly, you want to set data into specific data cells. Then you should find existing row and set the cell value:
DataRow dr = dt.Rows[yourRowNumber];
dr[3] = "Your New Value";
My program able to read excel into datatable using epplus C# and there's a barcode column with data. I need to add & get bookcode data column from SQL Server based on data in barcode column. How will the SQL query be able to get each cell data row from the barcode column? I am confused to get the data by column or row.
I managed to get the SQL Server connection and 1 bookcode so far. I think I have to do looping to get all the bookcode for all the barcode column data but I'm not sure with the sequence in my coding and SQL connection. I believe I almost there to get it, hope you guys can assists me as this is my first project in C# :)
public void filldatagridview(ExcelWorksheet workSheet)
{
DataTable dt = new DataTable();
// Create the data column
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
dt.Columns.Add(col.ToString());
}
// for (int row = workSheet.Dimension.Start.Row; row <= workSheet.Dimension.End.Row; row++)
for (int row = 12; row <= 26; row++)
{
DataRow newRow = dt.NewRow(); //Create a row
int i = 0;
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
newRow[i++] = workSheet.Cells[row, col].Text;
}
dt.Rows.Add(newRow);
}
dt.Columns.RemoveAt(0); //remove No
dt.Columns.RemoveAt(0); //remove article
//Get BookCode
SqlConnection conn = new SqlConnection("Server=10.0.0.10;Database=;UserID=;Trusted_Connection=False");
string query = "SELECT BookCode FROM Inventory WHERE Barcode='" + dt.Rows[1]["3"].ToString().Trim() + "'"; //3 is column for barcode
// looping logic here?
for (int i = 0; i < dt.Rows.Count; i++)
{
}
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
dataGridView2.DataSource = dt;
conn.Close();
da.Dispose();
}
UPDATED:
Able to get data from sql server based on barcode column in "3" as attached in the following image:
Currently facing problem with the order I receive from database in BOOKCODE column. Where supposedly it should follow like in this image:
I have a program that are able to import an excel file to datatable binding with datagridview. Currently I need to add another column name InvtID and get that InvtID data from sql server based on Barcode column (column '3' as header) that I have been imported.
How am I able to achieve this one as right now my coding are able to get the data AFTER import an excel, so the InvtID column data are not in side-by-side with Barcode column. This is the only problem I encounter to finish this task, please assist me. Thank you
Here how my datatable looks like
public void filldatagridview(ExcelWorksheet workSheet)
{
DataTable dt = new DataTable();
//Create the data column
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
dt.Columns.Add(col.ToString());
}
for (int row = 12; row <= 26; row++)
{
DataRow newRow = dt.NewRow(); //Create a row
int i = 0;
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
newRow[i++] = workSheet.Cells[row, col].Text;
}
dt.Rows.Add(newRow);
}
dt.Columns.RemoveAt(0); //remove No
dt.Columns.RemoveAt(0); //remove article
//Get BookCode
using (SqlConnection conn = new SqlConnection("Server"))
using (SqlCommand cmd = new SqlCommand(null, conn))
{
StringBuilder sb = new StringBuilder("WITH cte AS(SELECT case WHEN InvtID IS NULL OR InvtID='' THEN 'No Bookcode Found' ELSE InvtID END AS InvtID,Barcode,ROW_NUMBER() OVER(PARTITION BY Barcode ORDER BY InvtID Asc) rid FROM InventoryCustomer) SELECT InvtID AS BOOKCODE FROM cte WHERE rid=1 and Barcode In (");
for (int i = 0; i < dt.Rows.Count; i++)
{
if (i != 0) sb.Append(",");
string name = "#P" + i;
cmd.Parameters.AddWithValue(name, dt.Rows[i]["3"]); //"3" is barcode column
sb.Append(name);
}
sb.Append(")");
cmd.CommandText = sb.ToString();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
dt.Columns["BOOKCODE"].SetOrdinal(0);
dataGridView2.DataSource = dt;
}
}
I am not sure if this is work.
Avoid adding new row when row is already exists.
Add column first from your dt DataTable
Just take a look at this code:
public void filldatagridview(ExcelWorksheet workSheet)
{
DataTable dt = new DataTable();
DataTable dtInvtID = new DataTable();
dt.Columns.Add("dtInvtID"); //ADDING NEW COLUMN FIRST FOR YOUR dtInvtID
//Create the data column
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
dt.Columns.Add(col.ToString());
}
for (int row = 12; row <= 26; row++)
{
DataRow newRow = dt.NewRow(); //Create a row
int i = 0;
for (int col = workSheet.Dimension.Start.Column; col <= workSheet.Dimension.End.Column; col++)
{
newRow[i++] = workSheet.Cells[row, col].Text;
}
dt.Rows.Add(newRow);
}
dt.Columns.RemoveAt(0); //remove No
dt.Columns.RemoveAt(0); //remove article
//Get BookCode
using (SqlConnection conn = new SqlConnection("Server"))
using (SqlCommand cmd = new SqlCommand(null, conn))
{
StringBuilder sb = new StringBuilder("WITH cte AS(SELECT case WHEN InvtID IS NULL OR InvtID='' THEN 'No Bookcode Found' ELSE InvtID END AS InvtID,Barcode,ROW_NUMBER() OVER(PARTITION BY Barcode ORDER BY InvtID Asc) rid FROM InventoryCustomer) SELECT InvtID AS BOOKCODE FROM cte WHERE rid=1 and Barcode In (");
for (int i = 0; i < dt.Rows.Count; i++)
{
if (i != 0) sb.Append(",");
string name = "#P" + i;
cmd.Parameters.AddWithValue(name, dt.Rows[i]["3"]); //"3" is barcode column
sb.Append(name);
}
sb.Append(")");
cmd.CommandText = sb.ToString();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dtInvtID);
dt.Columns["BOOKCODE"].SetOrdinal(0);
}
int dtctr = 0;
int ctr = 0;
foreach (DataRow dr in dt.Rows)//inserting the value of your InvtID to dt.Rows
{
dtctr += 1;
ctr = 1;
foreach (DataRow InvtID in dtInvtID.Rows) //Getting the value of dtInvtID from database
{
if (ctr == dtctr)//Condition when the row position is equal (dt.Rows==dtInvtID.Rows) IF THIS NOT RETURN A REAL POSITION THEN YOU CAN RUN IT IN DEBUG MODE T CHECK
{
dr["dtInvtID"] = InvtID[0];
ctr += 1;
break;
}
ctr += 1;
}
}
dataGridView2.DataSource = dt;
}
Reminders:
This code has not tested yet. Any wrong result you can check it and run in Debug Mode.
I've seen some interesting problem:
for (int i = 0; i < dt.Rows.Count; i++)
{
if (i != 0) sb.Append(",");
string name = "#P" + i;
cmd.Parameters.AddWithValue(name, dt.Rows[i]["3"]); //"3" is barcode column
sb.Append(name);
}
sb.Append(")");
Try to Modify it because my answer from above is getting the value of your database. It may cause a redundancy.
you are first inserting new rows into data table with this code.
dt.Rows.Add(newRow);
the second time you are using an adapter to fill the same data table with below code.
da.Fill(dt);
which insert the rows at the end instead of updating the existing rows in the data table.
To align the data into the data table you need to first fill another data table with an adapter then write code using for loop and matching data to update existing or original data table.
I am trying to export data from datagridview to csv from mysql. I want to some additional information to every row .
mysql query:
select vehicleregistration from wlist
my csv output :
YV07WMU
I need the output like
YV07WMU; GBR; 20/08/2014; -- here I need to add GBR; and today's date; at the end of each row.
this is my code: I don't where I am going wrong.
MySqlCommand myCommand = new MySqlCommand();
myCommand.Connection = conn;
myCommand.CommandText = "select VehicleRegistration from blacklist";
//myCommand.Connection = myConn;
DataTable data = new DataTable();
MySqlDataAdapter myAdapter = new MySqlDataAdapter(myCommand);
//myAdapter.SelectCommand = myCommand;
myAdapter.Fill(data);
dataGridView1.DataSource = data;
this.dataGridView1.Refresh();
if (dataGridView1.RowCount > 0)
{
string value = "";
DataGridViewRow dr = new DataGridViewRow();
StreamWriter swOut = new StreamWriter("C:/a/blist.csv");
//write header rows to csv
for (int i = 0; i <= dataGridView1.Columns.Count - 1; i++)
{
if (i > 0)
{
// swOut.Write(",");
}
// swOut.Write(dataGridView1.Columns[i].HeaderText);
}
swOut.WriteLine();
//write DataGridView rows to csv
for (int j = 0; j <= dataGridView1.Rows.Count - 1; j++)
{
if (j > 0)
{
swOut.WriteLine(" ");
}
dr = dataGridView1.Rows[j];
for (int i = 0; i <= dataGridView1.Columns.Count - 1; i++)
{
if (i > 0)
{
swOut.WriteLine(",");
}
value = dr.Cells[i].Value.ToString();
//replace comma's with spaces
value = value.Replace(',', ' ');
//replace embedded newlines with spaces
value = value.Replace(Environment.NewLine, " ");
swOut.Write(value);
}
}
swOut.Close();
}
conn.Close();
}