How to retrieve data from MS Excel sheet? - c#

I am trying to fetch data from excel using below C# code. I am getting the value from two
columns into single variable(str).
I want that value into different variables.So that i can send that value at runtime for two different statements.
How to bring them into two different variable?
string currentSheet = "Sheet1";
excelApp = new Excel.Application();
//Opening/adding Excel file
excelWorkbook = excelApp.Workbooks.Add(workbookPath);
excelSheets = excelWorkbook.Sheets;
excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
//Gives the used cells in the sheet
range = excelWorksheet.UsedRange;
for (rowCnt = 1; rowCnt <= range.Rows.Count; rowCnt++)
{
for (colCnt = 1; colCnt <= range.Rows.Count;colCnt++)
{
str = (string)(range.Cells[rowCnt,colCnt] as Excel.Range).Value2;
System.Console.WriteLine(str);
}
}

string Connection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
OleDbConnection con = new OleDbConnection(Connection);
OleDbCommand command = new OleDbCommand();
System.Data.DataTable dt = new System.Data.DataTable();
OleDbDataAdapter myCommand = new OleDbDataAdapter("select * from [Sheet1$]", con);
myCommand.Fill(dt);
con.Close();

for (rowCnt = 1; rowCnt <= range.Rows.Count; rowCnt++)
{
string Charity = (string)(range.Cells[rowCnt, 1] as Excel.Range).Value;
string Country = (string)(range.Cells[rowCnt, 2] as Excel.Range).Value;
System.Console.WriteLine(Charity + " --- " + Country);
}

Related

Reading headers into excel sheet , from a list

I'm creating a program to export Excel sheets, and I want to use a list to read in the headers (List<String> lFields) but for some reason it does not work, the DateTime works though.
using (Workbook workbook = new Workbook())
{
Worksheet sht = workbook.Worksheets[0];
try
{
rowcount = 0;
//top headers
sht.Cells[rowcount, 1].Value = DBName;
int cols = lFields.Count() + 3;
sht.Cells[rowcount, cols].Value = Convert.ToString(DateTime.Now);
rowcount++;
//headers
for (int i = 0; i < lFields.Count(); i++)
{
sht.Cells[rowcount, i].Value = lfields[i];
}
//styling
sht.Rows[rowcount].Font.Name = "Calibri";
sht.Rows[rowcount].Font.Size = 10;
sht.Rows[rowcount].Font.Bold = true;
sht.Rows[rowcount].Font.Italic = false;
rowcount++;
sht.FreezeRows(0);
int RowCount = 0;
from Microsfot support :https://support.microsoft.com/en-us/help/306572/how-to-query-and-display-excel-data-by-using-asp-net--ado-net--and-vis
You can query the Excel file as a sql table, and than recover the headers:
// Create connection string variable. Modify the "Data Source"
// parameter as appropriate for your environment.
String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + Server.MapPath("../ExcelData.xls") + ";" +
"Extended Properties=Excel 8.0;";
// Create connection object by using the preceding connection string.
OleDbConnection objConn = new OleDbConnection(sConnectionString);
// Open connection with the database.
objConn.Open();
// The code to follow uses a SQL SELECT command to display the data from the worksheet.
// Create new OleDbCommand to return data from worksheet.
OleDbCommand objCmdSelect =new OleDbCommand("SELECT * FROM myRange1", objConn);
// Create new OleDbDataAdapter that is used to build a DataSet
// based on the preceding SQL SELECT statement.
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
// Pass the Select command to the adapter.
objAdapter1.SelectCommand = objCmdSelect;
// Create new DataSet to hold information from the worksheet.
DataSet objDataset1 = new DataSet();
// Fill the DataSet with the information from the worksheet.
objAdapter1.Fill(objDataset1, "XLData");
// Bind data to DataGrid control.
DataGrid1.DataSource = objDataset1.Tables[0].DefaultView;
DataGrid1.DataBind();
// Clean up objects.
objConn.Close();

Error when i read excel file by C#

I read excel but dataGridView show data than lines excel file, So I can't write datagridview.Rowcount(). I use the below given code to read the excel file.
Code:
filePath = txtExcelFile.Text;
string[] fileSpit = filePath.Split('.');
if (filePath.Length > 1 && fileSpit[1] == "xls")
{
connString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=No'";
}
else
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0;HDR=No'";
}
OleDbCommand cmd = new OleDbCommand(#"Select * from [" +comboBox1.SelectedValue.ToString() + "]", ole);
OleDbDataAdapter oledata = new OleDbDataAdapter();
oledata.SelectCommand = cmd;
DataSet ds = new DataSet();
oledata.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
Either strip out the blank lines from the data table before assigning it to the grid:
private DataTable StripEmptyRows(DataTable dt)
{
List<int> rowIndexesToBeDeleted = new List<int>();
int indexCount = 0;
foreach(var row in dt.Rows)
{
var r = (DataRow)row;
int emptyCount = 0;
int itemArrayCount = r.ItemArray.Length;
foreach(var i in r.ItemArray) if(string.IsNullOrWhiteSpace (i.ToString())) emptyCount++;
if(emptyCount == itemArrayCount) rowIndexesToBeDeleted.Add(indexCount);
indexCount++;
}
int count = 0;
foreach(var i in rowIndexesToBeDeleted)
{
dt.Rows.RemoveAt(i-count);
count++;
}
return dt;
}
Or do your own row count ignoring blank rows.

Faster way of storing Excel worksheet to system.data.datatable using C#

I am trying to find a faster way to read an XML file that can be opened in Excel 2010. I cannot immediately read the XML file using readxml method because it contains Workbook, style, cell, data and other tags. So my approach was to open it in Excel then get the data on sheet 2 only. The sample file contains 9,000+ rows and takes about 2mins 49secs to store in a datatable. The actual file has 25,000+ rows. This is what I have tried:
private void bulkInsert()
{
var s = new Stopwatch();
s.Start();
try
{
KillExcel();
GCollector();
Excel.Application app = null;
app = new Excel.Application();
Excel.Worksheet sheet = null;
Excel.Workbook book = null;
book = app.Workbooks.Open(#"my directory for the file");
sheet = (Worksheet)book.Sheets[2];
sheet.Select(Type.Missing);
var xlRange = (Excel.Range)sheet.Cells[sheet.Rows.Count, 1];
int lastRow = (int)xlRange.get_End(Excel.XlDirection.xlUp).Row;
int newRow = lastRow + 1;
var cellrow = newRow;
int columns = sheet.UsedRange.Columns.Count;
Excel.Range test = sheet.UsedRange;
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("Node_SegmentName");
dt.Columns.Add("Type");
dt.Columns.Add("Sub-Type");
dt.Columns.Add("Description");
dt.Columns.Add("Parameter_DataIdentifier");
dt.Columns.Add("RuntimeValue");
dt.Columns.Add("Category");
dt.Columns.Add("Result");
dt.TableName = "SsmXmlTable";
//slow part
for (i = 0; i < lastRow; i++)
{
DataRow excelRow = dt.NewRow();
for (int j = 0; j < columns; j++)
{
excelRow[j] = test.Cells[i + 2, j + 1].Value2;
}
dt.Rows.Add(excelRow);
}
dataGridView1.DataSource = dt;
DataSet ds = new DataSet();
ds.Tables.Add(dt);
ds.WriteXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));
DataSet reportData = new DataSet();
reportData.ReadXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));
SqlConnection connection = new SqlConnection("Data Source=YOURCOMPUTERNAME\\SQLEXPRESS;Initial Catalog=YOURDATABASE;Integrated Security=True;Connect Timeout=0");
connection.Open();
SqlBulkCopy sbc = new SqlBulkCopy(connection);
sbc.DestinationTableName = "Test";
sbc.WriteToServer(reportData.Tables["SsmXmlTable"]);
connection.Close();
s.Stop();
var duration = s.Elapsed;
MessageBox.Show(duration.ToString() + " bulk insert way");
MessageBox.Show(ds.Tables["SsmXmlTable"].Rows.Count.ToString());//439 rows
}
catch (Exception ex)
{
KillExcel();
GCollector();
MessageBox.Show(ex.ToString() + i.ToString());
}
}
Without the reading from Excel part, the insertion of data using bulk copy only takes a couple of seconds (0.5secs for 449 rows).
For others who are encountering the same issue, what I did was:
save the xml as an xlsx file
use oledb to read the xlsx file
store in dataset using OleDbAdapter (Fill() method)
bulk insert
Here is the code that I used to do this (change the connection string):
Stopwatch s = new Stopwatch();
s.Start();
string sSheetName = null;
string sConnection = null;
System.Data.DataTable sheetData = new System.Data.DataTable();
System.Data.DataTable dtTablesList = default(System.Data.DataTable);
OleDbConnection oleExcelConnection = default(OleDbConnection);
sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + #"C:\Users\YOURUSERNAME\Documents\Visual Studio 2012\Projects\TestXmlParser\TestXmlParser\bin\Debug\ConsolidatedSSMFiles.xlsx" + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
oleExcelConnection = new OleDbConnection(sConnection);
oleExcelConnection.Open();
dtTablesList = oleExcelConnection.GetSchema("Tables");
if (dtTablesList.Rows.Count > 0)
{
sSheetName = dtTablesList.Rows[0]["TABLE_NAME"].ToString();
}
dtTablesList.Clear();
dtTablesList.Dispose();
if (!string.IsNullOrEmpty(sSheetName))
{
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [TEST$]", oleExcelConnection);
sheetAdapter.Fill(sheetData);
} s.Stop();
var duration = s.Elapsed;
oleExcelConnection.Close();
dataGridView1.DataSource = sheetData;
MessageBox.Show(sheetData.Rows.Count.ToString()+"rows - "+ duration.ToString());
This reads 25000+ rows of excel data to a datable in approx. 1.9 to 2.0 seconds.

Export data to excel file 2003, 2007 and Above

I'm using these connection strings, depending on the extension of the file:
For 2003 : Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties='Excel 8.0;
For 2007 : Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties='Excel 12.0;
Here is to get the connection.
string con_excel = "";
switch (Extension.ToLower())
{
case ".xls":
con_excel = ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString;
break;
case ".xlsx":
con_excel = ConfigurationManager.ConnectionStrings["Excel07ConString"].ConnectionString;
break;
}
con_excel = con_excel.Replace("filename", filePath);
The following is the code to generate excel file.
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
oXL = new Excel.Application();
oXL.Visible = false;
oXL.SheetsInNewWorkbook = 1;
oWB = (Excel._Workbook)(oXL.Workbooks.Add());
oSheet = (Excel._Worksheet)oWB.ActiveSheet;
try
{
string[] colNames = new string[dataTable.Columns.Count];
int col = 0;
foreach (DataColumn dc in dataTable.Columns)
colNames[col++] = dc.ColumnName;
char lastColumn = (char)(65 + dataTable.Columns.Count - 1);
oSheet.get_Range("A1", lastColumn + "1").Value2 = colNames;
oSheet.get_Range("A1", lastColumn + "1").Font.Bold = true;
oSheet.get_Range("A1", lastColumn + "1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter;
DataRow[] dr = dataTable.Select();
string[,] rowData = new string[dr.Count<DataRow>(), dataTable.Columns.Count + 1];
int rowCnt = 0;
foreach (DataRow row in dr)
{
for (col = 0; col < dataTable.Columns.Count; col++)
{
rowData[rowCnt, col] = row[col].ToString();
}
rowCnt++;
}
rowCnt++;
oSheet.get_Range("A2", lastColumn + rowCnt.ToString()).Value = rowData;
oXL.Visible = false;
oXL.UserControl = true;
String sNewFolderName = "Report_" + intReportId;
filename = Server.MapPath("Your Report\\" + sNewFolderName + DateTime.Now.ToString("dd-MM-yyyy_hh-mm-ss") + Extension);
oSheet.SaveAs(filename);
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);
oXL.Quit();
Marshal.ReleaseComObject(oSheet);
Marshal.ReleaseComObject(oWB);
Marshal.ReleaseComObject(oXL);
oSheet = null;
oWB = null;
oXL = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
//The excel is created and opened for insert value. We most close this excel using this system
Process[] localByName = Process.GetProcessesByName("EXCEL");
foreach (Process process in localByName)
{
process.Kill();
}
2007 file format is ok.
I tried to upload the 2003(.xls) excel file and then also generate 2003(.xls) format. But when i open that file, i got the following error.
The file you are trying to open "FileName.xls" in a different format than specified file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now?
Is this because of connection string ?
Try this Code upload Excel 2003 and 2007 file
if (filenam.ToString() == ".xls")
{ constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathnam + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\""; }
else if (filenam.ToString() == ".xlsx")
{ constr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + pathnam + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\""; }
else { Response.Write("<script>alert('Load Excel file Only')</script>"); }
string Qry = "SELECT [Customer], [Project], [Contact], [Designation], [Phone], [EmailID],[Region] FROM [Sheet1$]";
OleDbConnection conn = new OleDbConnection(constr);
if (conn.State == ConnectionState.Closed)
{
conn.Open();
OleDbCommand cmd = new OleDbCommand(Qry, conn);
OleDbDataAdapter da = new OleDbDataAdapter();
da.SelectCommand = cmd;
DataTable dt = new DataTable();
da.Fill(dt);
if (dt != null && dt.Rows.Count > 0)
{
gv_upload.DataSource = dt;
gv_upload.DataBind();
}
da.Dispose(); conn.Close(); conn.Dispose();

Empty Excel spreadsheet returning incorrect rowcount

I'm using the code below to read my Excel spreadsheet (Sample.xls, also below).
Sample.xls
[Sheet 1]
Column 0, Row 0 = "Test 1"
Column 0, Row 1 = "Test 2"
Column 0, Row 2 = "Test 3"
[Sheet 2]
All columns/rows are blank and empty
public void importFileButton_Click(object sender, EventArgs e)
{
string sourcefile = "C:\\Sample.xls";
string sqlQuery = null;
if (File.Exists(sourceFile))
{
DataTable fileSheetInfo = null;
OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + sourceFile + ";Extended Properties=\"Excel 8.0;HDR=No;IMEX=1;\"");
connection.Open();
fileSheetInfo = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
int fileSheetCount = fileSheetInfo.Rows.Count;
OleDbCommand command = new OleDbCommand();
String[] sheetNames = new String[fileSheetInfo.Rows.Count];
int i = 0;
foreach (DataRow row in fileSheetInfo.Rows)
{
sheetNames[i] = row["TABLE_NAME"].ToString();
sqlQuery1 = "SELECT * FROM [" + sheetNames[i] + "]";
command.CommandText = sqlQuery1;
OleDbDataAdapter adapter1 = new OleDbDataAdapter(sqlQuery, connection);
DataTable sheetData = new DataTable();
adapter1.Fill(sheetData);
int iRow = sheetData.Rows.Count;
MessageBox.Show("Sheet Name: " + sheetNames[i], "Sheet Name", MessageBoxButtons.OK);
MessageBox.Show("Rows: " + iRow.ToString(), "Row Count", MessageBoxButtons.OK);
i++;
}
}
}
Why does the code return a rowcount of 1 or 2 for the blank sheet (Sheet2)? Why isn't the rowcount displaying as 0 for Sheet 2? I have noticed that the rowcount is 1 if I have the file open in Excel; 2 if the file is closed in Excel.
Thanks for the help!

Categories

Resources