Reading Excel in .NET - some columns are read in as null - vb.net

i am trying to read in some data from an excel:
If (FileUpload1.PostedFile.ContentType = "application/vnd.ms-excel") Then
Dim filename As String = Path.GetFileName(FileUpload1.FileName)
'Session("userid") & "-" & Date.Now()
filepath = "\excel\" & Session("userid") & "_" & Now.Date().ToString("Mdy") & "_" & filename
FileUpload1.SaveAs(Server.MapPath("~/") & filepath)
ReadExcel(filepath)
Else
StatusLabel.Text = "Only Excel file types are accepted"
End If
everything seems to be fine, except when one of the columns sometimes reads in as NULL. seems like that happens if it's of a different type.
i can't figure out what it is. someone help me please....
Sub ReadExcel(ByVal filepath As String)
Dim MyConnection As System.Data.OleDb.OleDbConnection
Dim DtSet As System.Data.DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
MyConnection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & Server.MapPath("~/") & filepath & "';Extended Properties=Excel 8.0;")
DtSet = New System.Data.DataSet
Try
MyCommand.Fill(DtSet)
'gwResults.DataSource = DtSet.Tables(0)
LoopSources(DtSet)
'gwResults.DataBind()
MyConnection.Close()
Catch ex As Exception
StatusLabel.Text = "Import Excel status: The file could not be loaded. The following error occured: <br>" + ex.Message
End Try
End Sub

You need to include Extended Properties="Excel 8.0;IMEX=1;" in your connection string. Excel tries to determine the data type of your columns by reading the first few rows. Once it thinks it knows the data type, anything that doesn't conform to that is coerced to NULL. Very annoying. IMEX=1 tells it to read your data as intermixed and should resolve your problem. If you have a header row, you should also consider including HDR=YES. See this link: http://www.connectionstrings.com/excel for more info.

Probably the type of column is determined incorrectly. By default Jet provider reads 8 first rows to determine the type of column. And if these 8 lines contain something wrong you'll get a problem.
This can be changed by setting TypeGuessRows setting in registry.

Related

Issue with data type importing csv file into sql in vb.net (SqlBulkCopy)

I'm trying to automate the import of csv data into sql. All files, but one are imported ok, so there is no issue with the code. This particular file has a mixed data type column. And when importing data, it loads data as Double, instead of String. As a result, the values that have words, are imported as null. I tried to convert that column into String (ds.Tables(0).Columns(4).DataType), but it makes no difference. When I try to check the type right after the conversion attempt, it shows runtime type, not a string. I have spent a few days researching similar issues and tried everything I could find. Hopefully someone here can offer help on converting the column properly, as it doesn't work for me. Please see the code below. Thanks!
Private Sub ImportIntoSqlBulk(SqlConnString As SqlConnection, ConnStringSql As String, TableNameSql As String, Filenmcsv As String)
SqlConnString.ConnectionString = ConnStringSql
SqlConnString.Open()
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(SqlConnString)
bulkCopy.DestinationTableName = TableNameSql
Try
bulkCopy.WriteToServer(GetCsvData(PathImpt, Filenmcsv))
SqlConnString.Close()
Catch ex As Exception
Email_Subject = "Financial Data Import from Excel Error"
successflag = "N"
Email_Body = "There was an error importing data into " & TableNameSql & " from excel. Error message: " & ex.Message
Send_Email()
SqlConnString.Close()
Exit Sub
End Try
End Using
End Sub
Public Function GetCsvData(ByVal strFolderPath As String, ByVal strFileName As String) As DataTable
Dim strConnString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFolderPath & ";Extended Properties=""Text;HDR=YES;IMEX=1"""
Dim strConnString2 As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFolderPath & ";Extended Properties=""Text;HDR=YES;IMEX=1;MaxScanRows=0"""
Dim conn2 As New OleDbConnection(strConnString2)
Dim conn As New OleDbConnection(strConnString)
Try
conn.Open()
Dim cmd As New OleDbCommand("SELECT * FROM [" & strFileName & "]", conn)
Dim da As New OleDbDataAdapter()
da.SelectCommand = cmd
Dim ds As New DataSet()
da.Fill(ds)
If strFileName = "CheckRegister.csv" Then
Convert.ToString(ds.Tables(0).Columns(4).DataType)
ds.Tables(0).Columns(4).DataType.GetType()
End If
da.Dispose()
Return ds.Tables(0)
Catch ex As Exception
Return Nothing
Finally
conn.Close()
End Try
End Function

Searching Excel Document Columns with Visual Basic and Interop

I'm struggling with a problem that involves interop and excel.
Basically, I have excel files with columns that contain "headers" and the rows beneath the columns have the data. For example, the column Age will have 12,14,etc underneath it. I am new to Interop and I'm trying to allow the user to enter the name of the column header they wish to extract data from, so if they enter "Age", it'll find age is colum B for example and then extract all the data from the proceeding rows.
I've Googled extensively and haven't found anything solid, all rather context orientated and being new to Interop makes this a little tricky.
What I've got so far:
Public Sub getExcelData(ByVal directory As String)
Dim excelAppFirstFile As Excel.Application = Nothing
excelAppFirstFile = CreateObject("Excel.Application")
Try
excelAppFirstFile.Workbooks.Open(directory)
Dim excelSheet As Excel.Worksheet = excelAppFirstFile.Worksheets(1)
Catch ex As Exception
MsgBox("There was a problem: " + ex.Message)
End Try
End Sub
I know it isn't much but I've gone in circles with ranges,etc and can't figure out how to get where I need to.
EDIT:
I forgot to add that the Column name being searched for is a variable called field which is set at an earlier stage by the user.
If all you want to do is read data in the Excel file, I suggest you to use OleDb instead of interop (which is much faster):
Dim filePath As String = "C:\Book1.xls"
Dim connectionString As String = (Convert.ToString("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=") & filePath) + ";Extended Properties=""Excel 8.0"";"
Dim connection As New OleDbConnection(connectionString)
Dim cmdText As String = "SELECT * FROM [Sheet1$]"
Dim command As New OleDbCommand(cmdText, connection)
command.Connection.Open()
Dim reader As OleDbDataReader = command.ExecuteReader()
If reader.HasRows Then
While reader.Read()
Console.WriteLine("{0}" & vbTab & "{1}", reader(0).ToString(), reader(1).ToString())
End While
End If

"Could not find installable ISAM" error in VB.NET

Im new to visual basic.. I would like to ask on how to fixed the problem "Could not find installable ISAM.". I used Visual Basic as programming language. I used MS access as the database. My program is to fetch data from access. This would be my code.
Imports System.Data.OleDb
Module Main
Dim mDataPath As String
Sub Main()
GetPupils()
Console.ReadLine()
End Sub
Private Function GetConnection() As OleDb.OleDbConnection
'return a new connection to the database5
Return New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Database Password=oNer00FooR3n0 " & "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb")
End Function
Public Function GetPupils() As DataSet
Dim conn As OleDb.OleDbConnection = GetConnection()
Try
Dim ds As New DataSet 'temporary storage
Dim sql As String = "select * from SESSIONS" 'query
Dim da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sql, conn) 'connection
Try
da.Fill(ds, "SESSIONS") 'fetch data from db
Finally
da.Dispose() 'in case something goes wrong
End Try
Dim startVal = 0 'first record
Dim endVal = ds.Tables(0).Rows.Count 'total number records
For var = startVal To endVal - 1 'display records
Console.WriteLine(ds.Tables(0).Rows(var).Item(0).ToString() + " " + ds.Tables(0).Rows(var).Item(1).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString()) 'code for display id and name
Next
Return ds
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Module
I would like to know what is the cause of the error so that I can proceed to my program.. Thank you so much for the feedback..
You seem to be missing a delimiter after your password attribute.
I think you also need to use Jet OLEDB:Database Password=... instead (if indeed you have an access database protected with a password):
"Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb;" _
& "Jet OLEDB:Database Password=oNer00FooR3n0;"
Missing ; delimiter here:
...Password=oNer00FooR3n0 " & "Data Sourc...
Needs to be
...Password=oNer00FooR3n0 " & ";Data Sourc...
Also just Password instead of Database Password.
Initially, i too got this sort of error, but when i wrote the connection string in a single line (i mean without using [& _] or breaking in 2 lines, then this worked properly.
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\USER1\Desktop\MSaccessDB\MSaccessDB\my_database_file.mdb;Database Password=MyPassword"
Hope this helps.
Mukesh L.

excel oledb fields truncated at 255

I'm reading in an excel file with the following code:
Function Read_Excel(ByVal sFile As String) As ADODB.Recordset
On Error GoTo fix_err
Dim rs As ADODB.Recordset
rs = New ADODB.Recordset
Dim sconn As String
rs.CursorLocation = ADODB.CursorLocationEnum.adUseServer
rs.CursorType = ADODB.CursorTypeEnum.adOpenStatic
rs.LockType = ADODB.LockTypeEnum.adLockReadOnly
sconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & sFile & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
rs.Open("SELECT CStr([RPOCode]), Description FROM [sheet1$]", sconn)
tot += rs.RecordCount
rs.Close()
rs.Open("SELECT Distinct RPOCode, Description FROM [sheet1$] ORDER BY RPOCode", sconn)
Read_Excel = rs
rs = Nothing
Exit Function
fix_err:
Debug.Print(Err.Description + " " + _
Err.Source, vbCritical, "Import")
Err.Clear()
End Function
Cells longer than 255 chars are getting truncated, and I'm not sure if there is a way to stop it easily?
Update: The truncation only seems to happen if I select Distinct. If I leave the Distinct off it shows the full cell.
Memo-type fields (columns) will be truncated if you do anything that changes them to text-type fields with the Jet driver. It may be possible to use a sub-query to get distinct records and avoid Distinct.
This reference is for Access, but it is still Jet, so nearly everything applies: Truncation of Memo fields
My method's a bit different - opening excel files via OleDbAdapter, but I've solved your issue before using it. It's C# but should be easily transposed to vb.net.
Try this OleDBAdapter Excel QA I posted via stack overflow.
I have a worksheet cell (Rows[0][4]) w/ 445 characters and it worked fine...
Add this to the end of the code for the output
// DataSet cell debug/output:
Object row0Col3 = ds.Tables["xlsImport"].Rows[0][2];
Object row0Col4 = ds.Tables["xlsImport"].Rows[0][4];
string rowZeroColumn3 = row0Col3.ToString();
string rowZeroColumn4 = row0Col4.ToString();
Console.WriteLine("Row 0, Col 4 string length: {0} " + Environment.NewLine + "Excel content: {1}", rowZeroColumn4.Length, rowZeroColumn4);

vb.net traversing an xls / xlsx file?

is there a simple way in vb.net to load an excel file and read it? perhaps there is a way to load the file but have it not be visible to the user?
Alex - here is some old code I dug up to query excel. Pretty basic scenario here. Don't pay attention to the poor error handling and lack of the 'Using' construct.
Dim connString As String = "Provider=Microsoft.Jet.OLEDB.4.0" & _
";Data Source=" & ExcelFile & _
";Extended Properties=Excel 8.0;"
Dim conn As OleDbConnection = Nothing
Dim dt As System.Data.DataTable = Nothing
Dim excelDataSet As New DataSet()
Try
conn = New OleDbConnection(connString)
conn.Open()
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
If dt Is Nothing Then
Return Nothing
End If
Dim excelSheets(dt.Rows.Count) As String
Dim i As Integer = 0
For Each row As DataRow In dt.Rows
excelSheets(i) = row("TABLE_NAME").ToString
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
If i = SheetNumber Then
Exit For
End If
Next
Using excelCommand As New OleDbCommand("Select * from [" & excelSheets(SheetNumber - 1) & "]", conn)
Using excelAdapter As New OleDbDataAdapter(excelCommand)
excelAdapter.Fill(excelDataSet)
End Using
End Using
Catch ex As OleDbException
Throw
Catch ex As Exception
Throw
Finally
conn.Close()
If conn IsNot Nothing Then
conn.Dispose()
End If
If dt IsNot Nothing Then
dt.Dispose()
End If
End Try
Return excelDataSet
Work with the Excel Object Model directly from .NET.
You can use ado.net to read from excel spreadsheets via the OLEDB JET 4 provider
This just opens the excel file as a file stream instead of opening the actual excel spreadsheet.
Alternatively you could use com-interop and simply set the application object visible property to false.
See http://www.connectionstrings.com/excel
One gotcha to watch out for when using .net and com interop with any office application is that if you try opening the application as a user who is more of a windows service than an actual human user then you will need to login to windows as that user and open the relevant application as that user so that all the registry entries are correctly updated for certain features of the office application.
If you have a more simple (ie small) excel spreadsheet that does not need to be dynamic, I think you could export it as a comma delimited file and then use a loop and streamreader object to parse each comma seperated value into an array.
Kinda round about though...