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");
}
Related
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")
I am using the following code to open an excel file (XLS) and populate a DataTable with the first worksheet:
var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", filename);
OleDbConnection connExcel = new OleDbConnection(connectionString);
connExcel.Open();
DataTable dtExcelSchema;
dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
connExcel.Close();
var adapter = new OleDbDataAdapter("SELECT * FROM [" + SheetName + "]", connectionString);
var ds = new DataSet();
int count = 0;
adapter.Fill(ds, SheetName);
DataTable dt = ds.Tables[0];
It works only when the file is already open in Ms Excel. Why could that be?
If the file is not open, I get an error message (on line connExcel.Open): External table is not in the expected format.
I'm facing the same problem and accordingly to this site, many developers are struggling for the same:
-When I try read Excel with OLE DB all values are empty
-Can't connect to excel file unless file is already open
Actually I'm using the classic connection string (note that I'm trying to read a 97/2003 file):
Provider=Microsoft.Jet.OLEDB.4.0; Data Source = " + GetFilename(filename) + "; Extended Properties ='Excel 8.0;HDR=NO;IMEX=1'
but the file can be read properly only if:
Is open in Excel or even in Word! (the file of course appears corrupted and unreadable, but then the OleDb procedure can read every line of the file), I didn't try with other Office apps
The file is not in read-only mode
I also tried to lock the file manually or to open it with other non-office applications, but the result is not the same. If I follow the two previous rules (file opened in Word or Excel in not read-only mode) I can see all the cells, otherwise it seems the first column is ignored completely (so F2 became F1, F3 became F2,... and F6, the last one, should became F5 otherwise it throws and out-of-index error).
In order to keep compatibility with OleDb without using 3rd parties libraries I found a very stupid workaround using Microsoft.Office.Interop.Excel assembly.
Excel.Application _app = new Excel.Application();
var workbooks = _app.Workbooks;
workbooks.Open(_filename);
// OleDb Connection
using (OleDbConnection conn = new OleDbConnection(connectionOleDb))
{
try
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = String.Format("SELECT * FROM [{0}$]", tableName);
OleDbDataReader myReader = cmd.ExecuteReader();
int i = 0;
while (myReader.Read())
{
//Here I read through all Excel rows
}
}
catch (Exception E)
{
MessageBox.Show("Error!\n" + E.Message);
}
finally
{
conn.Close();
workbooks.Close();
if (workbooks != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
_app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(_app);
}
}
Essentially the first 3 lines run an Excel instance that lasts exactly the time needed to OleDb to perform its tasks.
The last 4 lines, inside the finally block, let the Excel instance to be closed correctly, immediately after the task and avoid ghost Excel processes.
I repeat it's a very stupid workaround that also requires a 1,5 MB dll (Microsoft.Office.Interop.Excel.dll) to be added to the project.
Anyway seems impossible that OleDb cannot manage by itself the missing data...
I had the same problem. If the file was open the read was ok but if the file was closed... some thing was strange... in my case I received strange data from columns and values.. Debugging I found the name of the first sheet and was strange ["xls _xlnm#_FilterDatabase"] looking on the internet I found that's a name of hidden sheet and a trick to avoid read this sheet (HERE) and so I've implemented a method:
private string getFirstVisibileSheet(DataTable dtSheet, int index = 0)
{
string sheetName = String.Empty;
if (dtSheet.Rows.Count >= (index + 1))
{
sheetName = dtSheet.Rows[index]["TABLE_NAME"].ToString();
if (sheetName.Contains("FilterDatabase"))
{
return getFirstVisibileSheet(dtSheet, ++index);
}
}
return sheetName;
}
To me worked very well.
My complete example code is:
string excelFilePath = String.Empty;
string stringConnection = String.Empty;
using (OpenFileDialog openExcelDialog = new OpenFileDialog())
{
openExcelDialog.Filter = "Excel 2007 (*.xlsx)|*.xlsx|Excel 2003 (*.xls)|*.xls";
openExcelDialog.FilterIndex = 1;
openExcelDialog.RestoreDirectory = true;
DialogResult windowsResult = openExcelDialog.ShowDialog();
if (windowsResult != System.Windows.Forms.DialogResult.OK)
{
return;
}
excelFilePath = openExcelDialog.FileName;
using (DataTable dt = new DataTable())
{
try
{
if (!excelFilePath.Equals(String.Empty))
{
stringConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFilePath + ";Extended Properties='Excel 8.0; HDR=YES;';";
using (OleDbConnection conn = new OleDbConnection(stringConnection))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string sheetName = getFirstVisibileSheet(dtSheet);
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
cmd = null;
conn.Close();
}
}
//Read and Use my DT
foreach (DataRow row in dt.Rows)
{
//On my case I need data on first and second Columns
if ((row.ItemArray.Count() < 2) ||
(row[0] == null || String.IsNullOrWhiteSpace(row[0].ToString()))
||
(row[1] == null ||String.IsNullOrWhiteSpace(row[1].ToString())))
{
continue;
}
//Get the number from the first COL
int colOneNumber = 0;
Int32.TryParse(row[0].ToString(), out colOneNumber);
//Get the string from the second COL
string colTwoString = row[1].ToString();
//Get the string from third COL if is a file path valid
string colThree = (row.ItemArray.Count() >= 3
&& !row.IsNull(2)
&& !String.IsNullOrWhiteSpace(row[2].ToString())
&& File.Exists(row[2].ToString())
) ? row[2].ToString() : String.Empty;
}
}
catch (Exception ex)
{
MessageBox.Show("Import error.\n" + ex.Message, "::ERROR::", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private string getFirstVisibileSheet(DataTable dtSheet, int index = 0)
{
string sheetName = String.Empty;
if (dtSheet.Rows.Count >= (index + 1))
{
sheetName = dtSheet.Rows[index]["TABLE_NAME"].ToString();
if (sheetName.Contains("FilterDatabase"))
{
return getFirstVisibileSheet(dtSheet, ++index);
}
}
return sheetName;
}
Is it failing on ToString(), like here?
Error is "Object reference not set to an instance of an object"
Does Convert.ToString() fix anything?
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'm importing data from an excel sheet into a datatable and I'm having a problem/question about the datatypes. When I create the datatable, I add the columns and their datatypes. After this I import the data from excel and this works fine. When I check the datatype of the columns it says what I expect. However, when I try and pass a value to a function I get the message that I'm trying to pass an object type, instead of the datatype I set.
here's my code (it's a simplified dataset):
public void importData(string _file)
{
DataTable dtTest = new DataTable();
dtTest.Columns.Add("a", typeof(Int32));
dtTest.Columns.Add("b", typeof(Int32));
string connString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", _file);
OleDbConnection conn = new OleDbConnection(connString);
conn.Open();
OleDbDataAdapter objAdapter = new OleDbDataAdapter();
string sheetName = "Sheet1";
string sql = "SELECT * FROM [" + sheetName + "$]";
OleDbCommand objCmdSelect = new OleDbCommand(sql, conn);
objAdapter.SelectCommand = objCmdSelect;
objAdapter.Fill(dtTest);
conn.Close();
form.write(dtTest.Rows[0]["a"]);
}
the function 'form.write()' accepts an integer.
when I check the datatype before I try and pass the value to form.write, it says it's Int32.
if (dtTest.Columns[0].DataType == typeof(Int32))
{
//this is true
}
what am I doing wrong?
the function 'form.write()' accepts an integer.
Since form.Write accepts an integer, you need to cast it from object to int:
int a = dtTest.Rows[0].Field<int>("a");
form.write(a);
Late binding is not allowed in C#, you must use the correct type at compile-time.
If I am understanding your post correctly, you may need to cast the value.
form.write(dtTest.Rows[0]["a"]);
I believe it should be:
form.write(Convert.ToInt32(dtTest.Rows[0]["a"]));
Without the Convert.ToInt32() you are referencing an object type.
User upload the inputs through the Excel file.
I want to find that excel file is empty or else.I check the content length and file size for find empty file..size is vary between empty files(without type and user type data and delete the all data to make an empty)For example content length for emptyfile 8714 but user type any data and delete all the data then the content length is 8104 like that
So I convert the excel file to datatable and check the datatable is null or not.when convert empty file to datatable the datatable have the default column F1.so datatable =null not work.Pls help me
My code:
string dirpath = Server.MapPath("~") + "uploadfile\\";
string LocalFilePath = dirpath + fileName;
fileUpload.PostedFile.SaveAs(LocalFilePath);
string fileType = Path.GetExtension(fileName);
string SourceConstr = string.Empty;
var Inputs = ProjectAttributeMasterService.GetInputAttributes(7);
if (fileType == ".xls" || fileType == ".xlsx")
{
if (fileType == ".xls")
{
SourceConstr = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + LocalFilePath + "';;Extended Properties= 'Excel 8.0;HDR=Yes;IMEX=1'";
}
OleDbConnection con = new OleDbConnection(SourceConstr);
con.ResetState();
con.Open();
System.Data.DataTable dtl = new DataTable();
System.Data.DataTable dts = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
OleDbDataAdapter da = new OleDbDataAdapter("select * from [Sheet1$]", con);
da.Fill(dtl);
if ((dtl.Rows.Count >= 1 || dtl.Columns.Count >= 1) && !dtl.Columns.Contains("F1")){
}
else
{
/empty file
}
dtl.Columns.Contains("F1")..If i use this condition even the Excel contain Data in cell "F1" then return Empty..and F1 is not default column for all server...So Its also not fine.
Use the code as follows:
OleDbDataAdapter da = new OleDbDataAdapter("select * from [Sheet1$]", con);
da.Fill(ds);
if ((ds.Table.Count >= 1)
{
if (ds.Tables[0].Rows.Count > 0)
{
//Excel contains data
}
else
{
//file is empty
}
}
else
{
//file is empty
}