Excel Import Error in ASP.net - c#

I am trying to import an excel to database from asp.net website through dataset.
Here is my first part.
int xlColCount = 1;
wb = app.Workbooks.Open(FilePath, 0, false, 5, "", "", true, Ex.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
ws = (Ex.Worksheet)wb.ActiveSheet;
xlColCount = ws.Columns.Count;
xlColCount = ws.UsedRange.Columns.Count;
ws.Columns.ClearFormats();
xlColCount = ws.UsedRange.Columns.Count;
//creating datacolumns
for (int i = 0; i < xlColCount; i++)
{
try
{
DSname.Tables[0].Columns.Add(((Ex.Range)ws.Cells[1,strColArr[i]]).Value2.ToString().Trim());
}
catch(Exception ex)
{
//error occured
}
}
First I am creating the column name based on the excel heading into dataset column. here xlColCount=198 (total no.of columns from the excel template and all are filled ) but when reaching 172th column (i=172) it is giving index out of range error.
What could be the reason? I need to create a dataset with column names from all excel column names.

Check your strColArr[i] array capacity..may be initialized with 172 or less in size.

May be you will have better results (and performance) with ADO.NET and System.Data.OleDb :
string filePath = #"C:\Workbook1.xls";
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=\"Excel 8.0\";";
OleDbConnection connection = new OleDbConnection(connectionString);
string cmdText = "SELECT * FROM [Sheet1$]";
OleDbCommand command = new OleDbCommand(cmdText, connection);
command.Connection.Open();
OleDbDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}\t{1}", reader[0].ToString(), reader[1].ToString());
}
}

string filePath = "":
OleDbCommand cmd = new OleDbCommand(); ;
OleDbDataAdapter oleda = new OleDbDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
UserBase loginUser = (UserBase)Session["LoggedUser"];
SearchFilter filter = new SearchFilter();
string action = "ExportDocumentType";
filter.DocumentTypeID = Convert.ToInt32(cmbDocumentType.SelectedValue);
filter.DepartmentID = Convert.ToInt32(cmbDepartment.SelectedValue);
try
{
Logger.Trace("Started Extracting Soft Data", Session["LoggedUserId"].ToString());
// need to pass relative path after deploying on server
oledbConn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +
filePath + ";Extended Properties='Excel 12.0;';");
try
{
oledbConn.Open();
}
catch
{
string con = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filePath + ";" + "Extended Properties=Excel 8.0;HDR=Yes;IMEX=1";
oledbConn = new OleDbConnection(con);
oledbConn.Open();
}
// Get the data table containg the schema guid.
dt = oledbConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
throw new Exception(" No sheets available!");
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
// Add the sheet name to the string array.
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
cmd.Connection = oledbConn;
cmd.CommandType = CommandType.Text;
// Get column names of selected document type
string SelectCommand = getIndexFieldsList();
SelectCommand = "SELECT " + SelectCommand + " FROM [" + excelSheets[0] + "]";
cmd.CommandText = SelectCommand;
oleda = new OleDbDataAdapter(cmd);
try
{
oleda.Fill(ds);
}
catch
{
throw new Exception("Selected file is not matching to " + cmbDocumentType.SelectedItem.Text + ".");//Bug Wrtier DMS ENHSMT 1-1012 M
}
string strXml = string.Empty;
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
// note: Do ur code here.. i prefer to create a insert satement from here using looping it out
}
else
{
throw new Exception(" No data available in uploaded file!");//Bug Wrtier DMS ENHSMT 1-1012 M
}
}
catch (Exception ex)
{
Logger.Trace("Exception:" + ex.Message, Session["LoggedUserId"].ToString());
throw new Exception(ex.Message.ToString());
}
finally
{
// Clean up.
if (oledbConn != null)
{
oledbConn.Close();
oledbConn.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
if (ds != null)
{
ds.Dispose();
}
}
}

Related

No value given for one or more required parameters error - Excel

I am getting data from excel and showing it in DataGridWiew.
I have two textboxes, one is for starting index for first record and other is for last record.
Code works fine. But lets suppose starting record is 1 and ending is 10 when I change 10 to 1 or 2 it gives me an error in this line:
adapter.Fill(dataTable);
Full Code is below:
public DataSet Parse(string fileName)
{
string connectionString = string.Format("provider = Microsoft.Jet.OLEDB.4.0; data source = {0}; Extended Properties = Excel 8.0;", fileName);
DataSet data = new DataSet();
foreach (var sheetName in GetExcelSheetNames(connectionString))
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
string query = "";
var dataTable = new DataTable();
if(tbStarting.Text.Trim()=="" && tbEnding.Text.Trim() == "")
{
query = string.Format("SELECT * FROM [{0}]", sheetName);
}
else
{
query = string.Format("SELECT * FROM [{0}] where SrNo between " + int.Parse(tbStarting.Text.Trim()) + " and " + int.Parse(tbEnding.Text.Trim()) + " order by SrNo", sheetName);
}
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(dataTable);
data.Tables.Add(dataTable);
con.Close();
}
}
return data;
}
static string[] GetExcelSheetNames(string connectionString)
{
OleDbConnection con = null;
DataTable dt = null;
con = new OleDbConnection(connectionString);
con.Open();
dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
String[] excelSheetNames = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheetNames[i] = row["TABLE_NAME"].ToString();
i++;
}
return excelSheetNames;
}
Why this is happening please help me?
Looking at the code, it seems that your procedure is working when you ask to retrieve all the record in each table. But you are not showing which table (Sheet) is actually used afterwars.
Chances are, you are using the first one only.
When you submit some parameters, only one of the tables (Sheets) can fulfill those requirements. The other(s) don't, possibly because a field named [SrNo] is not present.
This causes the More Parameters Required error when trying to apply a filter.
Not related to the error, but worth noting: you don't need to recreate the whole DataSet + DataTables to filter your DataSources.
The DataSet.Tables[N].DefaultView.RowFilter can be used to get the same result without destroying all the objects each time a filter is required.
RowFilter has some limitations in the language (e.g. does not support BETWEEN, Field >= Value1 AND Field <= Value2 must be used), but it's quite effective.
This is a possible setup:
(xDataSet is a placeholder for your actual DataSet)
//Collect the values in the TextBoxes in a string array
private void button1_Click(object sender, EventArgs e)
{
string[] Ranges = new string[] { tbStarting.Text.Trim(), tbEnding.Text.Trim() };
if (xDataSet != null)
FilterDataset(Ranges);
}
private void FilterDataset(string[] Ranges)
{
if (string.IsNullOrEmpty(Ranges[0]) & string.IsNullOrEmpty(Ranges[1]))
xDataSet.Tables[0].DefaultView.RowFilter = null;
else if (string.IsNullOrEmpty(Ranges[0]) | string.IsNullOrEmpty(Ranges[1]))
return;
else if (int.Parse(Ranges[0]) < int.Parse(Ranges[1]))
xDataSet.Tables[0].DefaultView.RowFilter = string.Format("SrNo >= {0} AND SrNo <= {1}", Ranges[0], Ranges[1]);
else
xDataSet.Tables[0].DefaultView.RowFilter = string.Format("SrNo = {0}", Ranges[0]);
this.dataGridView1.Update();
}
I've modified your code you code a bit to handle those requirements.
(I've left here those filters anyway; they're not used, but if you still want them, they are in a working condition)
DataSet xDataSet = new DataSet();
string WorkBookPath = #"[Excel WorkBook Path]";
//Query one Sheet only. More can be added if necessary
string[] WBSheetsNames = new string[] { "Sheet1" };
//Open the Excel document and assign the DataSource to a dataGridView
xDataSet = Parse(WorkBookPath, WBSheetsNames, null);
dataGridView1.DataSource = xDataSet.Tables[0];
dataGridView1.Refresh();
public DataSet Parse(string fileName, string[] WorkSheets, string[] ranges)
{
if (!File.Exists(fileName)) return null;
string connectionString = string.Format("provider = Microsoft.ACE.OLEDB.12.0; " +
"data source = {0}; " +
"Extended Properties = \"Excel 12.0;HDR=YES\"",
fileName);
DataSet data = new DataSet();
string query = string.Empty;
foreach (string sheetName in GetExcelSheetNames(connectionString))
{
foreach (string WorkSheet in WorkSheets)
if (sheetName == (WorkSheet + "$"))
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
DataTable dataTable = new DataTable();
if ((ranges == null) ||
(string.IsNullOrEmpty(ranges[0]) || string.IsNullOrEmpty(ranges[1])) ||
(int.Parse(ranges[0]) > int.Parse(ranges[1])))
query = string.Format("SELECT * FROM [{0}]", sheetName);
else if ((int.Parse(ranges[0]) == int.Parse(ranges[1])))
query = string.Format("SELECT * FROM [{0}] WHERE SrNo = {1}", sheetName, ranges[0]);
else
query = string.Format("SELECT * FROM [{0}] WHERE (SrNo BETWEEN {1} AND {2}) " +
"ORDER BY SrNo", sheetName, ranges[0], ranges[1]);
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(dataTable);
data.Tables.Add(dataTable);
};
}
}
return data;
}
static string[] GetExcelSheetNames(string connectionString)
{
string[] excelSheetNames = null;
using (OleDbConnection con = new OleDbConnection(connectionString))
{
con.Open();
using (DataTable dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null))
{
if (dt != null)
{
excelSheetNames = new string[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
excelSheetNames[i] = dt.Rows[i]["TABLE_NAME"].ToString();
}
}
}
}
return excelSheetNames;
}

Deleting empty rows and columns from a CSV file - C#

I would like to "clean" a CSV file:
deleting empty rows
deleting empty columns
The rows or columns are not completely empty, they have, for example:
"","","","","","","","","","","","","","",
(in a row form)
OR
"","","","","","","","","","",
(in a row form)
OR
"",
"",
"",
"",
"",
"",
"",
(in a columns form)
These rows or columns can be anywhere in the CSV file.
What I have so far:
private void button1_Click(object sender, EventArgs e)
{
string sourceFile = #"XXXXX.xlsx";
string worksheetName = "Sample";
string targetFile = #"C:\Users\xxxx\xls_test\XXXX.csv";
// Creates the CSV file based on the XLS file
ExcelToCSVCoversion(sourceFile, worksheetName, targetFile);
// Manipulate the CSV: Clean empty rows
DeleteEmptyRoadFromCSV(targetFile);
}
static void ExcelToCSVCoversion(string sourceFile, string worksheetName,
string targetFile)
{
string connectionString = #"Provider =Microsoft.ACE.OLEDB.12.0;Data Source=" + sourceFile
+ #";Extended Properties=""Excel 12.0 Xml;HDR=YES""";
OleDbConnection connection = null;
StreamWriter writer = null;
OleDbCommand command = null;
OleDbDataAdapter dataAdapter = null;
try
{
// Represents an open connection to a data source.
connection = new OleDbConnection(connectionString);
connection.Open();
// Represents a SQL statement or stored procedure to execute
// against a data source.
command = new OleDbCommand("SELECT * FROM [" + worksheetName + "$]",
connection);
// Specifies how a command string is interpreted.
command.CommandType = CommandType.Text;
// Implements a TextWriter for writing characters to the output stream
// in a particular encoding.
writer = new StreamWriter(targetFile);
// Represents a set of data commands and a database connection that are
// used to fill the DataSet and update the data source.
dataAdapter = new OleDbDataAdapter(command);
DataTable dataTable = new DataTable();
dataAdapter.Fill(dataTable);
for (int row = 0; row < dataTable.Rows.Count; row++)
{
string rowString = "";
for (int column = 0; column < dataTable.Columns.Count; column++)
{
rowString += "\"" + dataTable.Rows[row][column].ToString() + "\",";
}
writer.WriteLine(rowString);
}
Console.WriteLine();
Console.WriteLine("The excel file " + sourceFile + " has been converted " +
"into " + targetFile + " (CSV format).");
Console.WriteLine();
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
Console.ReadLine();
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
connection.Dispose();
command.Dispose();
dataAdapter.Dispose();
writer.Close();
writer.Dispose();
}
}
static void DeleteEmptyRoadFromCSV(string fileName)
{
//string nonEmptyLines = #"XXXX.csv";
var nonEmptyLines = File.ReadAllLines(fileName)
.Where(x => !x.Split(',')
.Take(2)
.Any(cell => string.IsNullOrWhiteSpace(cell))
// use `All` if you want to ignore only if both columns are empty.
).ToList();
File.WriteAllLines(fileName, nonEmptyLines);
}
Finally, I tried to use the ideas from:
Remove Blank rows from csv c# . But my ouput is not changing at all.
Any help is welcome!
Thank you.
You could delete columns/rows from table before saving csv.
Method is not tested, but you should get the concept.
static void ExcelToCSVCoversion(string sourceFile, string worksheetName,
string targetFile)
{
string connectionString = #"Provider =Microsoft.ACE.OLEDB.12.0;Data Source=" + sourceFile
+ #";Extended Properties=""Excel 12.0 Xml;HDR=YES""";
OleDbConnection connection = null;
StreamWriter writer = null;
OleDbCommand command = null;
OleDbDataAdapter dataAdapter = null;
try
{
// Represents an open connection to a data source.
connection = new OleDbConnection(connectionString);
connection.Open();
// Represents a SQL statement or stored procedure to execute
// against a data source.
command = new OleDbCommand("SELECT * FROM [" + worksheetName + "$]",
connection);
// Specifies how a command string is interpreted.
command.CommandType = CommandType.Text;
// Implements a TextWriter for writing characters to the output stream
// in a particular encoding.
writer = new StreamWriter(targetFile);
// Represents a set of data commands and a database connection that are
// used to fill the DataSet and update the data source.
dataAdapter = new OleDbDataAdapter(command);
DataTable dataTable = new DataTable();
dataAdapter.Fill(dataTable);
var emptyRows =
dataTable.Select()
.Where(
row =>
dataTable.Columns.Cast<DataColumn>()
.All(column => string.IsNullOrEmpty(row[column].ToString()))).ToArray();
Array.ForEach(emptyRows, x => x.Delete());
var emptyColumns =
dataTable.Columns.Cast<DataColumn>()
.Where(column => dataTable.Select().All(row => string.IsNullOrEmpty(row[column].ToString())))
.ToArray();
Array.ForEach(emptyColumns, column => dataTable.Columns.Remove(column));
dataTable.AcceptChanges();
for (int row = 0; row < dataTable.Rows.Count; row++)
{
string rowString = "";
for (int column = 0; column < dataTable.Columns.Count; column++)
{
rowString += "\"" + dataTable.Rows[row][column].ToString() + "\",";
}
writer.WriteLine(rowString);
}
Console.WriteLine();
Console.WriteLine("The excel file " + sourceFile + " has been converted " +
"into " + targetFile + " (CSV format).");
Console.WriteLine();
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
Console.ReadLine();
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
connection.Dispose();
command.Dispose();
dataAdapter.Dispose();
writer.Close();
writer.Dispose();
}
}
Please check if the following query is working.I am getting all the rows:
var nonEmptyLines = File.ReadAllLines(FileName)
.Where(x => !x.Split(',')
.Take(2)
.Any(cell => string.IsNullOrWhiteSpace(cell))
// use `All` if you want to ignore only if both columns are empty.
).ToList();
I think you can use something as:
var nonEmptyLines = File.ReadAllLines(File).
SkipWhile(cell=>{var arr=cell.Split(',');if(string.IsNullOrWhiteSpace(cell)){
return true;
}
else
{
return false;
}
});

Unable to read Excel sheet on Server Machine

I am unable to read my Excel sheet on server..when i run this code on Local it works fine...but unable to run this method on server...
the Error shows "Object Reference not set to an Instance"
public DataTable GetRead_Excel(string strExcelFile)
{
System.Data.OleDb.OleDbConnection OledbCon = new System.Data.OleDb.OleDbConnection();
System.Data.OleDb.OleDbCommand OledbCmd = new System.Data.OleDb.OleDbCommand();
System.Data.OleDb.OleDbDataAdapter OledbDAdapter = new System.Data.OleDb.OleDbDataAdapter();
DataTable dt_1 = new DataTable();
dt_1.Columns.Add("ID", typeof(int));
dt_1.Rows.Add(25);
OledbCon.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source= " + strExcelFile.Trim() + " ;Extended Properties=\"Excel 8.0;HDR=NO\"";
OledbCon.ConnectionString = "Provider=Microsoft.Jet.OLEDB.12.0; Data Source= " + strExcelFile.Trim() + " ;Extended Properties=\"Excel 8.0;HDR=NO\"";
if (System.IO.File.Exists(strExcelFile.Trim()) == false)
{
strErrorCode = "Invalid Excel Data file / File dose not exists";
return null;
}
try
{
OledbCon.Open();
OledbCmd.Connection = OledbCon;
OledbCmd.CommandTimeout = pSQL_CommandTimeOut;
OledbCmd.CommandType = CommandType.Text;
OledbCmd.CommandText = "SELECT * FROM [Sheet1$]";
OledbDAdapter.SelectCommand = OledbCmd;
OledbDAdapter.Fill(dt_1);
OledbDAdapter.Dispose();
OledbCmd.Dispose();
OledbCon.Close();
}
catch (Exception ex)
{
strErrorCode = Get_ErrorString(ex.Message);
return null;
}
return dt_1;
}

Missing First Columns and First Row in Excel C#

I am trying to read an excel file in excel, but for some reason sometime, the first column is missing and first row is missing from the data.
When I open the file in excel and save it without any changes, the files are read correctly.
Any ideas about how this might happen?
Below is the code i am using to read the file:
string xlConn = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source="
+ txt_InputFile.Text
+ ";Extended Properties=Excel 8.0;";
using (OleDbConnection dbConnection = new OleDbConnection(xlConn))
{
dbConnection.Open();
// Get the name of the first worksheet:
DataTable dbSchema = dbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dbSchema == null || dbSchema.Rows.Count < 1)
{
//"Error: Could not determine the name of the first worksheet."
throw new Exception(Program.lm_GetMethodLanguage(this.GetType().Name, "wp_InputFile_CloseFromNext", 5) );
}
string firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();
using (
OleDbDataAdapter dbCommand = new OleDbDataAdapter("SELECT * FROM [" + firstSheetName + "]",
dbConnection))
{
using (DataSet myDataSet = new DataSet())
{
dbCommand.Fill(myDataSet);
inputData = myDataSet.Tables[0];
}
}
}
Use this.This will retrieve all the sheets in excel sheet.
private String[] GetExcelSheetNames(string excelFile)
{
try
{
excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ""yoursourcepath"+ ";Extended Properties=Excel 12.0;Persist Security Info=False";
excelConnection = new OleDbConnection(excelConnectionString);
excelConnection.Open();
dt = excelConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
return excelSheets;
}
catch (Exception ex)
{
return null;
}
finally
{
if (excelConnection != null)
{
excelConnection.Close();
excelConnection.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
}
}

Best /Fastest way to read an Excel Sheet into a DataTable?

I'm hoping someone here can point me in the right direction - I'm trying to create a fairly robust utility program to read the data from an Excel sheet (may be .xls OR .xlsx) into a DataTable as quickly and leanly as possible.
I came up with this routine in VB (although I'd be just as happy with a good C# answer):
Public Shared Function ReadExcelIntoDataTable(ByVal FileName As String, ByVal SheetName As String) As DataTable
Dim RetVal As New DataTable
Dim strConnString As String
strConnString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" & FileName & ";"
Dim strSQL As String
strSQL = "SELECT * FROM [" & SheetName & "$]"
Dim y As New Odbc.OdbcDataAdapter(strSQL, strConnString)
y.Fill(RetVal)
Return RetVal
End Function
I'm wondering if this is the best way to do it or if there are better / more efficent ways (or just more intelligent ways - Maybe Linq / native .Net providers) to use instead?
ALSO, just a quick and silly additional question - Do I need to include code such as y.Dispose() and y = Nothing or will that be taken care of since the variable should die at the end of the routine, right??
Thanks!!
If you want to do the same thing in C# based on CiarĂ¡n Answer
string sSheetName = null;
string sConnection = null;
DataTable dtTablesList = default(DataTable);
OleDbCommand oleExcelCommand = default(OleDbCommand);
OleDbDataReader oleExcelReader = default(OleDbDataReader);
OleDbConnection oleExcelConnection = default(OleDbConnection);
sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Test.xls;Extended Properties=\"Excel 12.0;HDR=No;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)) {
oleExcelCommand = oleExcelConnection.CreateCommand();
oleExcelCommand.CommandText = "Select * From [" + sSheetName + "]";
oleExcelCommand.CommandType = CommandType.Text;
oleExcelReader = oleExcelCommand.ExecuteReader();
nOutputRow = 0;
while (oleExcelReader.Read())
{
}
oleExcelReader.Close();
}
oleExcelConnection.Close();
here is another way read Excel into a DataTable without using OLEDB
very quick
Keep in mind that the file ext would have to be .CSV for this to work properly
private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
{
csvData = new DataTable(defaultTableName);
try
{
using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[]
{
tableDelim
});
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == string.Empty)
{
fieldData[i] = string.Empty; //fieldData[i] = null
}
//Skip rows that have any csv header information or blank rows in them
if (fieldData[0].Contains("Disclaimer") || string.IsNullOrEmpty(fieldData[0]))
{
continue;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
}
return csvData;
}
I have always used OLEDB for this, something like...
Dim sSheetName As String
Dim sConnection As String
Dim dtTablesList As DataTable
Dim oleExcelCommand As OleDbCommand
Dim oleExcelReader As OleDbDataReader
Dim oleExcelConnection As OleDbConnection
sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test.xls;Extended Properties=""Excel 12.0;HDR=No;IMEX=1"""
oleExcelConnection = New OleDbConnection(sConnection)
oleExcelConnection.Open()
dtTablesList = oleExcelConnection.GetSchema("Tables")
If dtTablesList.Rows.Count > 0 Then
sSheetName = dtTablesList.Rows(0)("TABLE_NAME").ToString
End If
dtTablesList.Clear()
dtTablesList.Dispose()
If sSheetName <> "" Then
oleExcelCommand = oleExcelConnection.CreateCommand()
oleExcelCommand.CommandText = "Select * From [" & sSheetName & "]"
oleExcelCommand.CommandType = CommandType.Text
oleExcelReader = oleExcelCommand.ExecuteReader
nOutputRow = 0
While oleExcelReader.Read
End While
oleExcelReader.Close()
End If
oleExcelConnection.Close()
The ACE.OLEDB provider will read both .xls and .xlsx files and I have always found the speed quite good.
public DataTable ImportExceltoDatatable(string filepath)
{
// string sqlquery= "Select * From [SheetName$] Where YourCondition";
string sqlquery = "Select * From [SheetName$] Where Id='ID_007'";
DataSet ds = new DataSet();
string constring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath + ";Extended Properties=\"Excel 12.0;HDR=YES;\"";
OleDbConnection con = new OleDbConnection(constring + "");
OleDbDataAdapter da = new OleDbDataAdapter(sqlquery, con);
da.Fill(ds);
DataTable dt = ds.Tables[0];
return dt;
}
This seemed to work pretty well for me.
private DataTable ReadExcelFile(string sheetName, string path)
{
using (OleDbConnection conn = new OleDbConnection())
{
DataTable dt = new DataTable();
string Import_FileName = path;
string fileExtension = Path.GetExtension(Import_FileName);
if (fileExtension == ".xls")
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Import_FileName + ";" + "Extended Properties='Excel 8.0;HDR=YES;'";
if (fileExtension == ".xlsx")
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Import_FileName + ";" + "Extended Properties='Excel 12.0 Xml;HDR=YES;'";
using (OleDbCommand comm = new OleDbCommand())
{
comm.CommandText = "Select * from [" + sheetName + "$]";
comm.Connection = conn;
using (OleDbDataAdapter da = new OleDbDataAdapter())
{
da.SelectCommand = comm;
da.Fill(dt);
return dt;
}
}
}
}
You can use OpenXml SDK for *.xlsx files. It works very quickly. I made simple C# IDataReader implementation for this sdk. See here. Now you can easy read excel file to DataTable and you can import excel file to sql server database (use SqlBulkCopy). ExcelDataReader reads very fast. On my machine 10000 records less 3 sec and 60000 less 8 sec.
Read to DataTable example:
class Program
{
static void Main(string[] args)
{
var dt = new DataTable();
using (var reader = new ExcelDataReader(#"data.xlsx"))
dt.Load(reader);
Console.WriteLine("done: " + dt.Rows.Count);
Console.ReadKey();
}
}
I found it pretty easy like this
using System;
using System.Data;
using System.IO;
using Excel;
public DataTable ExcelToDataTableUsingExcelDataReader(string storePath)
{
FileStream stream = File.Open(storePath, FileMode.Open, FileAccess.Read);
string fileExtension = Path.GetExtension(storePath);
IExcelDataReader excelReader = null;
if (fileExtension == ".xls")
{
excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (fileExtension == ".xlsx")
{
excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
var test = result.Tables[0];
return result.Tables[0];
}
Note: you need to install SharpZipLib package for this
Install-Package SharpZipLib
neat and clean! ;)
This is the way to read from excel oledb
try
{
System.Data.OleDb.OleDbConnection MyConnection;
System.Data.DataSet DtSet;
System.Data.OleDb.OleDbDataAdapter MyCommand;
string strHeader7 = "";
strHeader7 = (hdr7) ? "Yes" : "No";
MyConnection = new System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fn + ";Extended Properties=\"Excel 12.0;HDR=" + strHeader7 + ";IMEX=1\"");
MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + wks + "$]", MyConnection);
MyCommand.TableMappings.Add("Table", "TestTable");
DtSet = new System.Data.DataSet();
MyCommand.Fill(DtSet);
dgv7.DataSource = DtSet.Tables[0];
MyConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
The below code is tested by myself and is very simple, understandable, usable and fast.
This code, initially takes all sheet names, then puts all tables of that excel file in a DataSet.
public static DataSet ToDataSet(string exceladdress, int startRecord = 0, int maxRecord = -1, string condition = "")
{
DataSet result = new DataSet();
using (OleDbConnection connection = new OleDbConnection(
(exceladdress.TrimEnd().ToLower().EndsWith("x"))
? "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + exceladdress + "';" + "Extended Properties='Excel 12.0 Xml;HDR=YES;'"
: "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + exceladdress + "';Extended Properties=Excel 8.0;"))
try
{
connection.Open();
DataTable schema = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
foreach (DataRow drSheet in schema.Rows)
if (drSheet["TABLE_NAME"].ToString().Contains("$"))
{
string s = drSheet["TABLE_NAME"].ToString();
if (s.StartsWith("'")) s = s.Substring(1, s.Length - 2);
System.Data.OleDb.OleDbDataAdapter command =
new System.Data.OleDb.OleDbDataAdapter(string.Join("", "SELECT * FROM [", s, "] ", condition), connection);
DataTable dt = new DataTable();
if (maxRecord > -1 && startRecord > -1) command.Fill(startRecord, maxRecord, dt);
else command.Fill(dt);
result.Tables.Add(dt);
}
return result;
}
catch (Exception ex) { return null; }
finally { connection.Close(); }
}
Enjoy...
''' <summary>
''' ReadToDataTable reads the given Excel file to a datatable.
''' </summary>
''' <param name="table">The table to be populated.</param>
''' <param name="incomingFileName">The file to attempt to read to.</param>
''' <returns>TRUE if success, FALSE otherwise.</returns>
''' <remarks></remarks>
Public Function ReadToDataTable(ByRef table As DataTable,
incomingFileName As String) As Boolean
Dim returnValue As Boolean = False
Try
Dim sheetName As String = ""
Dim connectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & incomingFileName & ";Extended Properties=""Excel 12.0;HDR=No;IMEX=1"""
Dim tablesInFile As DataTable
Dim oleExcelCommand As OleDbCommand
Dim oleExcelReader As OleDbDataReader
Dim oleExcelConnection As OleDbConnection
oleExcelConnection = New OleDbConnection(connectionString)
oleExcelConnection.Open()
tablesInFile = oleExcelConnection.GetSchema("Tables")
If tablesInFile.Rows.Count > 0 Then
sheetName = tablesInFile.Rows(0)("TABLE_NAME").ToString
End If
If sheetName <> "" Then
oleExcelCommand = oleExcelConnection.CreateCommand()
oleExcelCommand.CommandText = "Select * From [" & sheetName & "]"
oleExcelCommand.CommandType = CommandType.Text
oleExcelReader = oleExcelCommand.ExecuteReader
'Determine what row of the Excel file we are on
Dim currentRowIndex As Integer = 0
While oleExcelReader.Read
'If we are on the First Row, then add the item as Columns in the DataTable
If currentRowIndex = 0 Then
For currentFieldIndex As Integer = 0 To (oleExcelReader.VisibleFieldCount - 1)
Dim currentColumnName As String = oleExcelReader.Item(currentFieldIndex).ToString
table.Columns.Add(currentColumnName, GetType(String))
table.AcceptChanges()
Next
End If
'If we are on a Row with Data, add the data to the SheetTable
If currentRowIndex > 0 Then
Dim newRow As DataRow = table.NewRow
For currentFieldIndex As Integer = 0 To (oleExcelReader.VisibleFieldCount - 1)
Dim currentColumnName As String = table.Columns(currentFieldIndex).ColumnName
newRow(currentColumnName) = oleExcelReader.Item(currentFieldIndex)
If IsDBNull(newRow(currentFieldIndex)) Then
newRow(currentFieldIndex) = ""
End If
Next
table.Rows.Add(newRow)
table.AcceptChanges()
End If
'Increment the CurrentRowIndex
currentRowIndex += 1
End While
oleExcelReader.Close()
End If
oleExcelConnection.Close()
returnValue = True
Catch ex As Exception
'LastError = ex.ToString
Return False
End Try
Return returnValue
End Function
Use the below snippet it will be helpfull.
string POCpath = #"G:\Althaf\abc.xlsx";
string POCConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + POCpath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
OleDbConnection POCcon = new OleDbConnection(POCConnection);
OleDbCommand POCcommand = new OleDbCommand();
DataTable dt = new DataTable();
OleDbDataAdapter POCCommand = new OleDbDataAdapter("select * from [Sheet1$] ", POCcon);
POCCommand.Fill(dt);
Console.WriteLine(dt.Rows.Count);
I've used this method and for me, it is so efficient and fast.
// Step 1. Download NuGet source of Generic Parsing by Andrew Rissing
// Step 2. Reference this to your project
// Step 3. Reference Microsoft.Office.Interop.Excel to your project
// Step 4. Follow the logic below
public static DataTable ExcelSheetToDataTable(string filePath) {
// Save a copy of the Excel file as CSV
var xlApp = new XL.Application();
var xlWbk = xlApp.Workbooks.Open(filePath);
var tempPath =
Path.Combine(Environment
.GetFolderPath(Environment.SpecialFolder.UserProfile)
, "AppData"
, "Local",
, "Temp"
, Path.GetFileNameWithoutExtension(filePath) + ".csv");
xlApp.DisplayAlerts = false;
xlWbk.SaveAs(tempPath, XL.XlFileFormat.xlCSV);
xlWbk.Close(SaveChanges: false);
xlApp.Quit();
// The actual parsing
using (var parser = new GenericParserAdapter(tempPath)) {
parser.FirstRowHasHeader = true;
return parser.GetDataTable();
}
}
Generic Parsing by Andrew Rissing
Here is another way of doing it
public DataSet CreateTable(string source)
{
using (var connection = new OleDbConnection(GetConnectionString(source, true)))
{
var dataSet = new DataSet();
connection.Open();
var schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (schemaTable == null)
return dataSet;
var sheetName = "";
foreach (DataRow row in schemaTable.Rows)
{
sheetName = row["TABLE_NAME"].ToString();
break;
}
var command = string.Format("SELECT * FROM [{0}$]", sheetName);
var adapter = new OleDbDataAdapter(command, connection);
adapter.TableMappings.Add("TABLE", "TestTable");
adapter.Fill(dataSet);
connection.Close();
return dataSet;
}
}
//
private string GetConnectionString(string source, bool hasHeader)
{
return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};
Extended Properties=\"Excel 12.0;HDR={1};IMEX=1\"", source, (hasHeader ? "YES" : "NO"));
}

Categories

Resources