I'm trying to import Excel sheet to SQL Server database. The issue happening is with the column mapping.
If the Column Name in Excel Sheet ends with fullstop (eg: 'No.', 'Name.'), C# is throwing an exception
Message=The given ColumnName 'No.' does not match up with any column
in data source.
But if I remove fullstop, it is working absolutely fine.
The source code for mapping in C# is as follows
private void InsertExcelRecords()
{
string FilePath = "C:\\Upload\\" + FileUpload.FileName;
string fileExtension = Path.GetExtension(FileUpload.PostedFile.FileName);
FileUpload.SaveAs("C:\\Upload\\" + FileUpload.FileName);
ExcelConn(FilePath, fileExtension);
Econ.Open();
DataTable dtExcelSheetName = Econ.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string getExcelSheetName = dtExcelSheetName.Rows[0]["Table_Name"].ToString();
Query = string.Format("Select * FROM [{0}]", getExcelSheetName + "A7:I");
OleDbCommand Ecom = new OleDbCommand(Query, Econ);
DataSet ds = new DataSet();
OleDbDataAdapter oda = new OleDbDataAdapter(Query, Econ);
Econ.Close();
oda.Fill(ds);
DataTable Exceldt = ds.Tables[0];
connection();
SqlBulkCopy objbulk = new SqlBulkCopy(con);
objbulk.DestinationTableName = "BankTransaction";
objbulk.ColumnMappings.Add("No", "Number");
con.Open();
objbulk.WriteToServer(Exceldt);
con.Close();
}
Please let me know if you need any more information.
You will not be able to retrieve column names with . from an excel sheet using OLEDB or ODBC. Because it is not a valid or recognizable syntax.
'.' typically we use it to distinguish between two [schema].[table].[column] like that.
OLEDB,ODBC Replace column name '.' char with '#'
So you need to replace your code
objbulk.ColumnMappings.Add("No.", "Number")
with
objbulk.ColumnMappings.Add("No#", "Number")
Related
I faced such a problem. I trying to read Excel file data, all are as a string. I used code bellow.
try
{
var connectionString = string.Format( "Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"", session["FilePath"] );
using (var adapter = new System.Data.OleDb.OleDbDataAdapter( "SELECT * FROM [Sheet1$]", connectionString ))
{
var ds = new DataSet();
adapter.Fill( ds, "workBook" );
workBook = ds.Tables["workBook"];
}
if (workBook == null)
throw new Exception( "Could not load imported spreadsheet!" );
if (workBook.Rows.Count <= 0)
throw new Exception( "You are use an empty spreadsheet!" );
foreach (DataColumn column in workBook.Columns)
column.ColumnName = column.ColumnName.Trim();
}
catch (Exception exc)
{
}
All worked fine, I was getting a datatable with data as a string data type and was parsing them on program level (I just have a mixed data types in one column). But when the cell have a Number format and value of this cell, for example, is 0589, I need to add a leading apostrophe in a cell because 0 must be present in 4-digit number. When I tried read such excel file using a IMEX parameter 1, I have got NULL value from this cell. I don't understand why, I read all data as a string data type.
Change the number format of the cells to "0000" for a number that will always be 4 digits and retain the leading zeros.
As I fixed that, before loading spreadsheet I set the registry key TypeGuessRows to zero on the program level and after loading back to 8 (in case other programs will use it).
string file = "C:\\temp\\Exposure\\UTC.xlsx";
OleDbConnectionStringBuilder connStringBuilder = new OleDbConnectionStringBuilder();
connStringBuilder.DataSource = file;
connStringBuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
connStringBuilder.Add("Extended Properties", "Excel 8.0;HDR=NO;IMEX=1");
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
DbConnection connection = factory.CreateConnection();
connection.ConnectionString = connStringBuilder.ConnectionString;
connection.Open();
// var myTableName = connection.GetSchema("Tables").Rows[0]["TABLE_NAME"];
DbCommand selectCommand = factory.CreateCommand();
string sql = "SELECT * FROM [Daily Monitoring$]";
selectCommand.CommandText = sql;
selectCommand.Connection = connection;
DbDataAdapter adapter = factory.CreateDataAdapter();
adapter.SelectCommand = selectCommand;
DataSet data = new DataSet();
adapter.Fill(data);
DataTable dt = data.Tables[0];
connection.Close();
string ss = dt.Rows[1][1].ToString();
I have a piece of code where I want to extract values from the A column of an Excel sheet. Right now, here is the code I'm using and having an issue with:
m_connString = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source = " + m_source + "; Extended properties = 'Excel 12.0; HDR = NO; IMEX = 1;';";
using (OleDbConnection conn = new OleDbConnection(m_connString))
{
conn.Open();
DataTable dt = conn.GetOleDbSchemaGuid(Tables, null);
DataSet ds = new DataSet();
string defaultSheet = ExcelSheets.Rows[0]["TABLE_NAME"].ToString();
OleDbCommand comm = new OleDbCommand("SELECT * FROM [" + defaultSheet + "]", conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
// Bug appears here
adapter.fill(ds)
// Fill a List<string> with the data found
for (int r = 0; r < ds.Tables[0].Row.Count; r++)
{
m_list.Add(ds.Tables[0].Rows[r][0].ToString();
}
}
What is happening is that, if I have an Excel file with the following content in the A column:
Row1
Row2
Row3
...
RowX
...What I end up getting is all values except for the first value (Row1). It turns out that Row1 is being used as a column name(?) for the DataSet's table. However, I don't want there to be any column names or headers, and I specifically state this in the connection string.
How can I prevent this behavior so I can have all my data placed in the List? Or, failing that, how can I work around this issue and extract Row1 from that DataSet?
Check Microsoft Reference to understand how Extended Properties of the connection HDR=NO works:
Column headings: By default, it is assumed that the first row of your
Excel data source contains columns headings that can be used as field
names. If this is not the case, you must turn this setting off, or
your first row of data "disappears" to be used as field names. This is
done by adding the optional HDR= setting to the Extended Properties of
the connection string. The default, which does not need to be
specified, is HDR=Yes. If you do not have column headings, you need to
specify HDR=No; the provider names your fields F1, F2, etc.
Here is example:
Excel File Data (test.xlsx):
Code:
string m_source = "test.xlsx";
string m_connString = #"Provider = Microsoft.ACE.OLEDB.12.0;
Data Source = " + m_source + #";
Extended properties = 'Excel 12.0;
HDR= NO;
IMEX = 1;';";
using (OleDbConnection conn = new OleDbConnection(m_connString))
{
conn.Open();
string squery = "SELECT f1, f2, f3 FROM [Sheet1$]";
OleDbCommand comm = new OleDbCommand(squery, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
DataSet ds = new DataSet();
adapter.Fill(ds);
}
DataSet Visualizer:
Try this way:
DataTable table = ds.Tables[0];
foreach (DataColumn column in table.Columns)
{
string cName = table.Rows[0][column.ColumnName].ToString();
if (!table.Columns.Contains(cName) && cName != "")
{
column.ColumnName = cName;
}
}
change the sql to something along the lines of this
"SELECT * FROM [" + defaultSheet + "] Except Select Top(1)"
The following codes read an excel sheet and copy all the data into a C# DataTable
string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
conn = new OleDbConnection(strConn);
conn.Open();
string strExcel = "";
OleDbDataAdapter myCommand = null;
DataSet ds = null;
strExcel = "select * from [" + Sheet1$+ "]";
myCommand = new OleDbDataAdapter(strExcel, strConn);
ds = new DataSet();
myCommand.Fill(ds, "table1");
DataTable DT = ds.Tables[0];
When I review the data in DataTable DT, I found that the data in excel which start with apostrophe cannot be read (ex. '0010, '0026, ..., etc), i.e. become empty in DataTable DT.
Any suggested solution to solve it?
This is one of the fun things working with Excel vba.
The only way to see if there is an apostrophe is using this syntax
Dim s As String
Cells(1, 2).Value = "'abc"
s = Cells(1, 2).Formula
s = Cells(1, 2).PrefixCharacter
When you step through this vba code it will only show you the apostrophe if you add the prefixCharacter to your output.
So the only solution I know of is to loop through ALL THE CELLS.... replace the apostrophe with something silly like & #8217; (html apostrophe) and then fix it in your database..
And if you feel like you've been slapped in the face, yes VBA does that to you now and then. This is not OLEDB issue but an excel issue
I have been working on a desktop application and I have a little problem with Excel file imports.
Everything is good but when I read the data from the Excel sheet it does not read all the numbers and Alphabets. For example, if the first cell of the column is numbers then it will not read Alphabets from that column. If I change the type to Text for that column manually then everything is good.
Here is my sample code for importing Excel sheet data.
Any ideas?
public static DataSet exceldata(string filelocation)
{
DataSet ds = new DataSet();
OleDbCommand excelCommand = new OleDbCommand();
OleDbDataAdapter excelDataAdapter = new OleDbDataAdapter();
string excelConnStr = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 4.0;HDR=YES;IMEX=1;Importmixedtypes=text;typeguessrows=0;\"", filelocation);
OleDbConnection excelConn = new OleDbConnection(excelConnStr);
excelConn.Open();
DataTable dtPatterns = new DataTable();
excelCommand = new OleDbCommand("SELECT * FROM [Sheet1$]", excelConn);
excelDataAdapter.SelectCommand = excelCommand;
excelDataAdapter.Fill(dtPatterns);
ds.Tables.Add(dtPatterns);
return ds;
}
System.out.println(cell.toString());//here is the problem
toString() method returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object.
Use cell.getStringCellValue()
instead
cell.toString()
And propor usage needed.
For numeric values you have to use
getNumericCellValue() and put a condition there
if(cell!=null)
{
int type = cell.getCellType();
if (type == HSSFCell.CELL_TYPE_STRING)
System.out.println(cell.getRichStringCellValue().toString());
else if (type == HSSFCell.CELL_TYPE_NUMERIC)
String[] splits = String.valueOf(cell.getNumericCellValue()).split(".");
System.out.println(splits[0]);
else if (type == HSSFCell.CELL_TYPE_BOOLEAN)
System.out.println( cell.getBooleanCellValue());
else if (type == HSSFCell.CELL_TYPE_BLANK)
System.out.println(cell.getColumnIndex() + "] = BLANK CELL");
}
I am using SqlBulkCopy object to write a datatable into an sql server table. However, everytime I recheck my database it remains intact with no changes. A
I have tried to do Google search to determine my problem but i am unable to resolve it.
The datatable came from an .xls file.
public static DataTable dt = new DataTable();
private void ExportToGrid(String path, String filen)
{
int idx = filen.IndexOf(".");
string tf = filen.Remove(idx, 4);
OleDbConnection MyConnection = null;
DataSet DtSet = null;
OleDbDataAdapter MyCommand = null;
MyConnection = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='" + path + "';Extended Properties=Excel 8.0;");
ArrayList TblName = new ArrayList();
MyConnection.Open();
DataTable schemaTable = MyConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow row in schemaTable.Rows)
{
TblName.Add(row["TABLE_NAME"]);
}
MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + TblName[0].ToString() + "]", MyConnection);
DtSet = new System.Data.DataSet();
MyCommand.Fill(DtSet);
MyCommand.FillSchema(DtSet, SchemaType.Source);
DataTable dt = new DataTable();
dt = DtSet.Tables[0];
Session["dt"] = dt;
int x = dt.Rows.Count;
MyConnection.Close();
if (dt.Rows.Count > 0)
{
theGridView.DataSource = dt;
theGridView.DataBind();
}
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
}
This is my writer function
private void StartImport()
{
string servername = server;
string database = database;
string tbl = "dbo.LinkDb";
Stopwatch sw = new Stopwatch();
sw.Start();
SqlBulkCopy bulkCopy = new SqlBulkCopy("Data Source=" + servername + ";Initial Catalog=" + database + ";Integrated Security=SSPI", SqlBulkCopyOptions.TableLock);
bulkCopy.DestinationTableName = tbl;
bulkCopy.WriteToServer(dt);
sw.Stop();
lblResult.Visible = true;
lblResult.Text = (sw.ElapsedMilliseconds / 1000.00).ToString();
}
Below are the screenshot of the tables stored in my sql server. I assure you that I have been complying to Case Sensitive rules.
There was no exception thrown and average time elapsed is 0.018 - 0.020 secs
Appreciate any helps.
Thank you
Based on the code you have posted, you are writing an empty datatable to the database. Your "ExportToGrid" method fills dt, a DataTable declared locally, which loses scope outside of the method. Your write function is calling the static DataTable dt which is a new datatable.
Does dt need to be static? it seems as though this could be declared as
private DataTable dt;
then inside "ExportToGrid" instead of declaring another DataTable just instantiate the already declared dt rather than declaring a new one
dt = new DataTable();
Alternatively you could extract the DataTable straight from the GridView during the write Method:
DataTable dt = (DataTable)theGridView.DataSource;
bulkCopy.WriteToServer(dt);
This removes the need for variables outside of the scope of the method.
Lastly since you are storing your datatable within the session (I am not generally an advocate of storing large amounts of data in session variables but without knowing the specifics of your site I cannot really pass judgement), you could use the following:
DataTable dt = (DataTable)Session["dt"];
bulkCopy.WriteToServer(dt);
I dont see anything obvious compared to my use except for the fact that I explicitly map columns from the data table to the database table.
Using cn As New SqlConnection(DataAccessResource.CONNECTIONSTRING)
cn.Open()
Using copy As New SqlBulkCopy(cn)
copy.BulkCopyTimeout = 300
copy.ColumnMappings.Add(0, 0)
copy.ColumnMappings.Add(1, 1)
copy.ColumnMappings.Add(2, 2)
copy.ColumnMappings.Add(3, 3)
copy.DestinationTableName = "Tablename"
copy.WriteToServer(dataset.datatable)
End Using
End Using
Connection string (sql server 2000!) looks like
"data source=DBSERVERNAME;initial catalog=DBNAME;persist security info=True;user id=USERNAME;password=PASSWORD;packet size=4096"
I doubt the connection string is a problem assuming youve used it elsewhere.
Finally have you checked the data types for the columns in the dataset datatable match the ones in the database. In my experience oledb load from excel does not always produce output you might expect, date fields and columns with mixed text and numbers being perticular problems.