I am new to automation and I am trying to get data from an Excel sheet using OLEDB, I get an errror saying "OLEDB Exception : Invalid argument" in C#
So, One of the answers to a similar question suggest that I add a key to the app.config file for my test data. Now I am not familiar with the .config files
So, I need help with the key or any other solutions to my problem will do
Here is my code:
{
class ExcelDataAccess
{
public static string TestDataFileConnection()
{
var fileName =
ConfigurationManager.AppSettings[#"Path\DataSet.xlsx"];
var con = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data
Source = {0}; Extended Properties='Excel 12.0 Xml;HDR=YES;'", fileName);
return con;
}
public static UserData GetTestData(string keyName)
{
using (var connection = new
OleDbConnection(TestDataFileConnection()))
{
connection.Open();
var query = string.Format("select * from [DataSet$] where
key='{0}'", keyName);
var value = connection.Query<UserData>
(query).FirstOrDefault();
connection.Close();
return value;
}
}
I use ExcelDataReader - https://github.com/ExcelDataReader/ExcelDataReader
using ExcelDataReader;
using System.Collections.Generic;
using System.IO;
namespace Test.Data.Excel
{
public class Reader
{
public static IEnumerable<object[]> Read(string filePath)
{
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var count = reader.FieldCount;
do
{
var list = new List<object>();
while (reader.Read())
{
list.Add(reader.GetString(0));
}
yield return list.ToArray();
} while (reader.NextResult());
}
}
}
}
}
Try with the following code to import data from Excel sheet.
"openFileDialog1_FileOk" is a Button
Private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
string filePath = openFileDialog1.FileName;
string extension = Path.GetExtension(filePath);
string header = rbHeaderYes.Checked ? "YES" : "NO";
string conStr, sheetName;
conStr = string.Empty;
switch (extension)
{
case ".xls": //Excel 97-03
conStr = string.Format(Excel03ConString, filePath, header);
break;
case ".xlsx": //Excel 07
conStr = string.Format(Excel07ConString, filePath, header);
break;
}
//Get the name of the First Sheet.
using (OleDbConnection con = new OleDbConnection(conStr))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
con.Open();
DataTable dtExcelSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
sheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
con.Close();
}
}
//Read Data from the First Sheet.
using (OleDbConnection con = new OleDbConnection(conStr))
{
using (OleDbCommand cmd = new OleDbCommand())
{
using (OleDbDataAdapter oda = new OleDbDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandText = "SELECT * From [" + sheetName + "]";
cmd.Connection = con;
con.Open();
oda.SelectCommand = cmd;
oda.Fill(dt);
sampleDatatable = dt;
con.Close();
dataGridView1.DataSource = dt;
//dataGridView2.DataSource = Headers;
}
}
}
}
Related
I want to validate column names of uploaded excel sheet with table definition.
Here i get table definition from database and also i get the column names from excel sheet using OLEDB.
i want to validate where all the column from the table is available in excel columns. Here i get both column names (that is from excel and table (DB)).
Here is the code i tried
//for validating column names
public bool ValidateColumnNames(string filename,DataExchangeDefinition dataExchangeDefinition)
{
string extension = Path.GetExtension(filename);
string connstring = string.Empty;
try
{
switch (extension)
{
case ".xls":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString, filename);
break;
case ".xlsx":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel07+ConString"].ConnectionString, filename);
break;
}
using (OleDbConnection connExcel = new OleDbConnection(connstring))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = connExcel;
connExcel.Open();
var dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
connExcel.Close();
string firstSheet = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
cmd.CommandText = "SELECT top 1 * FROM [" + firstSheet + "]";
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
DataTable HeaderColumns = new DataTable();
da.SelectCommand = cmd;
da.Fill(HeaderColumns);
foreach (DataColumn column in HeaderColumns.Columns)
{
//Here i want to validate the column names
dataExchangeDefinition.FieldName = column.Caption.ToString();
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
Here is the answer it works fine for me
//for validating column names
public List<DataExchangeDefinition> ValidateColumnNames(string filename, List<DataExchangeDefinition> dataExchangeDefinitionList)
{
DataExchangeDefinition dt = new DataExchangeDefinition();
//List<DataExchangeDefinition> dataexchangedefinitionList = new List<DataExchangeDefinition>();
string extension = Path.GetExtension(filename);
string connstring = string.Empty;
try
{
switch (extension)
{
case ".xls":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString, filename);
break;
case ".xlsx":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel07+ConString"].ConnectionString, filename);
break;
}
using (OleDbConnection connExcel = new OleDbConnection(connstring))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = connExcel;
connExcel.Open();
var dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); //To get the sheet name
connExcel.Close();
string firstSheet = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
cmd.CommandText = "SELECT top 1 * FROM [" + firstSheet + "]";
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
DataTable HeaderColumns = new DataTable();
da.SelectCommand = cmd;
da.Fill(HeaderColumns);
//List<DataColumn> excelColumn = new List<DataColumn>();
//var excelColumn = new List<DataColumn>();
//foreach (DataColumn column in HeaderColumns.Columns)
//{
// excelColumn.Add(column);
//}
foreach (DataExchangeDefinition data in dataExchangeDefinitionList)
//for(int i=0;i<dataExchangeDefinitionList.Count;i++)
{
dt.IsColumnValid = false;
//var result = from excelColumn in HeaderColumns;
foreach (DataColumn column in HeaderColumns.Columns)
{
if (data.FieldCaption == column.Caption)
{
data.IsColumnValid = true;
break;
}
}
}
return dataExchangeDefinitionList;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
//return isColumnValid;
}
}
}
I am using the below C# code in my program to read excel 97 - 2003 spreadsheet data into a datatable using oledbconnection and ran into the name does not exist in the current context.
DataTable rs = null;
string path = Path.GetFullPath(filePath);
odConnection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';");
odConnection.Open();
OleDbCommand cmd = new OleDbCommand(); ;
OleDbDataAdapter oleda = new OleDbDataAdapter();
DataSet ds = new DataSet();
DataTable dt = odConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string sheetName = string.Empty;
if (dt != null)
{
sheetName = dt.Rows[0]["Sheet_Name"].ToString();
}
cmd.Connection = odConnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
oda = new OleDbDataAdapter(cmd);
oda.Fill(ds, "excelData");
rs = ds.Tables["excelData"];
Here is example how to get all columns and rows from special Sheet from xlsx file. This code takes all data from Sheet2 from xlsx file and fill the DataTable with that values.
Hopefully this will help you.
using System;
using System.Data;
using System.Data.OleDb;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
DataTable rs = new DataTable();
using (var odConnection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Users\IIG\Desktop\test.xlsx;Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';"))
{
odConnection.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = odConnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM [Sheet2$]";
using (OleDbDataAdapter oleda = new OleDbDataAdapter(cmd))
{
oleda.Fill(rs);
}
}
odConnection.Close();
}
foreach(DataRow row in rs.Rows)
{
foreach(object item in row.ItemArray)
{
Console.Write(item +"\t");
}
Console.WriteLine();
}
}
}
}
Below line might be causing the issue -
if (dt != null)
{
sheetName = dt.Rows[0]["Sheet_Name"].ToString();
}
Try using
dt.Rows[0]["Table_name"].ToString();
This should return the name of the sheet.
The data will be first fetched into a DataTable and then the DataTable will be exported to a Text file which can be viewed in Notepad.
But, i dont know how to make the code work for save the work to a specific folder
P.S.I want to give to the file a dynamic name too (YEARmonthDAYhour.txt)
this is my code so far:
protected void ExportTextFile(object sender, EventArgs e)
{
string constr = ConfigurationManager.ConnectionStrings["ConnectionString2"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("Select * from details"))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
string txt = string.Empty;
txt += "#";
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
txt += row[column.ColumnName].ToString() + "$";
}
}
txt += "%";
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=AAAAMM-aaaammddhhmmss.txt");
Response.Charset = "";
Response.ContentType = "application/text";
Response.Output.Write(txt);
Response.Flush();
Response.End();
}
}
}
}
}
expected output:
'#InfofromSQL$InfofromSQl$InfofromSQL$...%' (without " ' ")
data separated by $.
static string connString = #"Server=myServerName;Database=myDbName;Trusted_Connection=True;";
static string fileName = #"C:\CODE\myfile.txt";
public static void WriteFile(string fileName)
{
SqlCommand comm = new SqlCommand();
comm.Connection = new SqlConnection(connString);
String sql = #"select col1, col2 from myTable";
comm.CommandText = sql;
comm.Connection.Open();
SqlDataReader sqlReader = comm.ExecuteReader();
// Change the Encoding to what you need here (UTF8, Unicode, etc)
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(fileName, false, Encoding.UTF8))
{
while (sqlReader.Read())
{
writer.WriteLine(sqlReader["col1"] + "\t" + sqlReader["col2"]);
}
}
sqlReader.Close();
comm.Connection.Close();
}
I did it finally:
StreamWriter file = new StreamWriter(#"C:\test");
file.WriteLine(txt.ToString());
file.Close();
Instead using response. , this works like a charm.
I tried to copy a datatable using this code :
private void button1_Click(object sender, EventArgs e)
{
DataTable dat = dGV.DataSource as DataTable;
DataTable dt = new DataTable();
dt = dat.Copy();
dGV.DataSource = dt;
}
But when I ran it, the first row wasnt copied. The result looks like this :
Before : https://drive.google.com/file/d/0B--Fi4mWsFk5NXlJM0ZRSXhRbjA/view?usp=sharing
After : https://drive.google.com/file/d/0B--Fi4mWsFk5OFptY2ZPRHlNaWc/view?usp=sharing
If I move the cursor into the second row before clicking the button it will copy all data including the first row. The data was imported from excel using this code :
private void importFileDialog_FileOk(object sender, CancelEventArgs e)
{
dGV.DataSource = GetTable();
string path = importFileDialog.FileName;
string ext = Path.GetExtension(path);
if (ext == ".xlsx" | ext == ".xls")
{
try
{
string Excel03ConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;";
string Excel07ConString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=Excel 8.0;";
string conStr, sheetName;
conStr = string.Empty;
switch (ext)
{
case ".xls": //Excel 97-03
conStr = string.Format(Excel03ConString, path);
break;
case ".xlsx": //Excel 07
conStr = string.Format(Excel07ConString, path);
break;
}
//Get the name of the First Sheet.
using (OleDbConnection con = new OleDbConnection(conStr))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
con.Open();
DataTable dtExcelSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
sheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
con.Close();
}
}
//Read Data from the First Sheet.
using (OleDbConnection con = new OleDbConnection(conStr))
{
using (OleDbCommand cmd = new OleDbCommand())
{
using (OleDbDataAdapter oda = new OleDbDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandText = "SELECT * From [" + sheetName + "]";
cmd.Connection = con;
con.Open();
oda.SelectCommand = cmd;
oda.Fill(dt);
con.Close();
//Populate DataGridView.
//dGV.DataSource = dt;
for (int i = 0; i < dt.Rows.Count; ++i)
{
//dGV.RowCount++;
//dGV.Rows[i].HeaderCell.Value = dt.Row[i].;
for (int k = 0; k < dt.Columns.Count; ++k)
{
dGV[k, i].Value = dt.Rows[i].ItemArray[k];
}
}
}
}
}
}
catch
{
MessageBox.Show("Failed to read the file");
}
}
}
If I input the data manually everything works fine.
You can also use clone function try this
private void button1_Click(object sender, EventArgs e)
{
DataTable dat = (DataTable)dGV.DataSource;
DataTable dt = new DataTable();
dt = dat.Clone();
dGV.DataSource = dt;
}
or
DataTable dt = (DataTable)dGV.DataSource;
dGV.DataSource = dt;
Does anyone know how can I read an excel file line by line in c#.
I found this code which will return the data from excel and display a grindview in c#. However, I just was wandering how to possibly read the data line by line on the server side instead?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.OleDb;
using System.IO;
namespace site
{
public partial class pgTest : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnImport_Click(object sender, EventArgs e)
{
string connString = "";
string strFileType = Path.GetExtension(fileuploadExcel.FileName).ToLower();
string path = fileuploadExcel.PostedFile.FileName;
//Connection String to Excel Workbook
if (strFileType.Trim() == ".xls")
{
connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
}
else if (strFileType.Trim() == ".xlsx")
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
}
string query = "SELECT [username],[age],[phone] FROM [Sheet1$]";
OleDbConnection conn = new OleDbConnection(connString);
if (conn.State == ConnectionState.Closed)
conn.Open();
OleDbCommand cmd = new OleDbCommand(query, conn);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
grvExcelData.DataSource = ds.Tables[0];
grvExcelData.DataBind();
da.Dispose();
conn.Close();
conn.Dispose();
}
}
}
Since Excel works with ranges you should first get the range of cells you would want to read. After that you can now browse through them using a for loop. You can see an example below:
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\myexcel.xlsx");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
MessageBox.Show(xlRange.Cells[i, j].Value2.ToString());
}
}
A more detailed explanation on this code block can be found here.
you can use OleDbDataReader as below
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(queryString, connection);
connection.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
var val1= reader[0].ToString();
}
reader.Close();
}
You must try this
string connectionString = "";
string strFileType = "Type";
string path = #"C:\Users\UserName\Downloads\";
string filename = "filename.xls";
if (fielname.Contains(.xls))
{
connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + filename + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
}
else if (fielname.Contains(.xlsx)
{
connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + filename + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
}
string query = "SELECT * FROM [SheetName$]";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(query, connection);
connection.Open();
OleDbDataReader reader = command.ExecuteReader();
var lines = new List<string>();
while (reader.Read())
{
var fieldCount = reader.FieldCount;
var fieldIncrementor = 1;
var fields = new List<string>();
while (fieldCount >= fieldIncrementor)
{
fields.Add(reader[fieldIncrementor - 1].ToString());
fieldIncrementor++;
}
lines.Add(string.Join("\t", fields));
}
reader.Close();
}
I tried the solution with OleDbConnection but it didn't work because I didn't have something installed. Then I found this solution here and it worked like a charm:
https://www.codeproject.com/Tips/801032/Csharp-How-To-Read-xlsx-Excel-File-With-Lines-of
There you can download a small file Excel.dll, add it to your project and browse the excel files cell by cell.
A simple way to convert data table to enumerable of an object is using Json methods.
Per example, with simple method, using only dotnet libraries, you can convert data table to list of especific objects.
using System.Data;
private static IEnumerable<T> ConvertDataTable<T>(DataTable dataTable)
{
if (dataTable is null ||
!dataTable.AsEnumerable().Any())
{
return Enumerable.Empty<T>();
}
var data = dataTable.Rows.OfType<DataRow>()
.Select(row => dataTable.Columns.OfType<DataColumn>()
.ToDictionary(col => col.ColumnName, c => row[c]));
var jsonTextObject = System.Text.Json.JsonSerializer.Serialize(data);
return System.Text.Json.JsonSerializer.Deserialize<IEnumerable<T>>(jsonTextObject)
?? Enumerable.Empty<T>();
}