I am using the below code to trim all cells in my DataTable.
The problem is, that I am doing it through a loop, and depending on what I fill the DataTable with, if it has 1500 rows and 20 columns, the loop takes a really, really long time.
DataColumn[] stringColumns = dtDataTable.Columns.Cast<DataColumn>().Where(c => c.DataType == typeof(string)).ToArray();
foreach (DataRow row in dtDataTable.Rows)
{
foreach (DataColumn col in stringColumns)
{
if (row[col] != DBNull.Value)
{
row.SetField<string>(col, row.Field<string>(col).Trim());
}
}
}
And here is how I am importing my Excel sheet to the DataTable:
using (OpenFileDialog ofd = new OpenFileDialog() { Title = "Select File", Filter = "Excel WorkBook|*.xlsx|Excel WorkBook 97-2003|*.xls|All Files(*.*)|*.*", Multiselect = false, ValidateNames = true })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
String PathName = ofd.FileName;
FileName = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName);
strConn = string.Empty;
FileInfo file = new FileInfo(PathName);
if (!file.Exists) { throw new Exception("Error, file doesn't exists!"); }
string extension = file.Extension;
switch (extension)
{
case ".xls":
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PathName + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'";
case ".xlsx":
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + PathName + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'";
default:
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PathName + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'";
}
}
else
{
return;
}
}
using (OleDbConnection cnnxls = new OleDbConnection(strConn))
{
using (OleDbDataAdapter oda = new OleDbDataAdapter(string.Format("select * from [{0}$]", "Sheet1"), cnnxls))
{
oda.Fill(dtDataTableInitial);
}
}
//Clone dtDataTableInitial so that I can have the new DataTable in String Type
dtDataTable = dtDataImportInitial.Clone();
foreach (DataColumn col in dtDataTable.Columns)
{
col.DataType = typeof(string);
}
foreach (DataRow row in dtDataImportInitial.Rows)
{
dtDataTable.ImportRow(row);
}
Is there a more efficient way of accomplishing this?
EDIT: As per JQSOFT's suggestion, I am using OleDbDataReader now, but am still running two issues:
One: SELECT RTRIM(LTRIM(*)) FROM [Sheet1$] doesn't seem to work.
I know that it is possible to select each column one by one, but the number of and header of the columns in the excel sheet is random, and I am not sure how to adjust my SELECT string to account for this.
Two: A column whose rows are mostly populated with numbers, but have a few rows with letters seem to have those rows with letters omitted. For example:
Col1
1
2
3
4
5
6
a
b
Becomes:
Col1
1
2
3
4
5
6
However, I have discovered that if I manually go into the excel sheet and convert the entire table cell format to "Text", this issue is resolved. However, doing this converts any dates in that excel sheet into unrecognizable strings of numbers, so I want to avoid doing this if at all possible.
For example: 7/2/2020 becomes 44014 if converted to "Text".
Here is my new code:
private void Something()
{
if (ofd.ShowDialog() == DialogResult.OK)
{
PathName = ofd.FileName;
FileName = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName);
strConn = string.Empty;
FileInfo file = new FileInfo(PathName);
if (!file.Exists) { throw new Exception("Error, file doesn't exists!"); }
}
using (OleDbConnection cn = new OleDbConnection { ConnectionString = ConnectionString(PathName, "No") })
{
using (OleDbCommand cmd = new OleDbCommand { CommandText = query, Connection = cn })
{
cn.Open();
OleDbDataReader dr = cmd.ExecuteReader();
dtDataTable.Load(dr);
}
}
dataGridView1.DataSource = dtDataTable;
}
public string ConnectionString(string FileName, string Header)
{
OleDbConnectionStringBuilder Builder = new OleDbConnectionStringBuilder();
if (Path.GetExtension(FileName).ToUpper() == ".XLS")
{
Builder.Provider = "Microsoft.Jet.OLEDB.4.0";
Builder.Add("Extended Properties", string.Format("Excel 8.0;IMEX=1;HDR=Yes;", Header));
}
else
{
Builder.Provider = "Microsoft.ACE.OLEDB.12.0";
Builder.Add("Extended Properties", string.Format("Excel 12.0;IMEX=1;HDR=Yes;", Header));
}
Builder.DataSource = FileName;
return Builder.ConnectionString;
}