excel oledb fields truncated at 255 - vb.net

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);

Related

VBA to query field contents in CSV

I'm struggling with ADO connections/recordsets.
My problem statement is: a function that will return the first value of a chosen field, in a chosen .csv file.
I am doing this to identify variably-named .csv files before adding the data to the relevant tables in a database. I am making the assumption that this field is always present and that either it is consistent throughout the file, or only relevant ones are grouped (this is controlled higher up the chain and is certain enough).
My code is being run as part of a module in an MS Access database:
Public Function GetFirstItem(File As Scripting.File, Field As String)
Dim Conn As ADODB.Connection, Recordset As ADODB.Recordset, SQL As String
Set Conn = New ADODB.Connection
Set Recordset = New ADODB.Recordset
'Microsoft.ACE.OLEDB.16.0 / Microsoft.Jet.OLEDB.4.0
Conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=""" & File.ParentFolder & _
"""; Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
SQL = "SELECT " & Field & " FROM """ & File.Name & """ LIMIT 1"
Debug.Print Conn.ConnectionString
Debug.Print SQL
Conn.Open
Recordset.Source = SQL
Recordset.ActiveConnection = Conn.ConnectionString
Recordset.Open
Recordset.MoveFirst
'GetFirstItem = Recordset!Questionnaire
Recordset.Close
Conn.Close
Set Recordset = Nothing
Set Conn = Nothing
End Function
ConnectionString = Provider=Microsoft.ACE.OLEDB.16.0;Data Source="D:\Documents\Jobs\TestPath"; Extended Properties="text;HDR=Yes;FMT=Delimited;";
Field = Questionnaire
SQL = SELECT Questionnaire FROM "test.csv" LIMIT 1
I get an error on Recordset.Open of:
This may be (is probably) down to a complete lack of understanding of how ADO connections/recordsets work. I have tried sans-quotes and it complains about a malformed FROM expression. Additionally, once this hurdle is overcome I am unsure of the syntax of how to return the result of my query. If there is a better way of doing this I am all ears!
Thanks.
In Access you don't need ADO library to query a CSV file:
Public Function GetFirstItem(File As Scripting.File, Field As String) As String
Dim RS As DAO.Recordset, SQL As String
SQL = "SELECT TOP 1 [" & Field & "]" _
& " FROM [" & File.Name & "]" _
& " IN '" & File.ParentFolder & "'[Text;FMT=CSVDelimited;HDR=Yes];"
Debug.Print SQL
Set RS = CurrentDb.OpenRecordset(SQL)
GetFirstItem = RS(0)
RS.Close
Set RS = Nothing
End Function
Usage:
?GetFirstItem(CreateObject("Scripting.FileSystemObject").getfile("c:\path\to\your\file.csv"), "your field")

Automation Error when Attempting to Query Access Database Using VBA

I've made the following ADODB object declarations in code.
Dim OConn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim fld As ADODB.Field
Set OConn = New ADODB.Connection
Set rs = New ADODB.Recordset
I would like to use the following code to read from a table on a MS Access database file and generate a recordset, rs.
'Get the table name from the search results.
tableName = ThisWorkbook.Sheets("PLC Module Data").Cells(2, 9).Value
'Set the SQL string.
strSql = "SELECT Code, Points, Type, Description, Rating " & _
"FROM " & tableName
'Set the connection string and open the connection to the Access DB.
OConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=Q:\AutoCAD Improvements\PLC IO Utility Docs\PLC IO Spreadsheet
App\PLC IO App\ace_plc.mdb"
OConn.Open
'Open the recordset and error out if nothing is returned
Set rs = OConn.Execute(strSql)
If rs.EOF Then
MsgBox "No matching records found."
rs.Close
OConn.Close
Exit Sub
End If
I've checked the query statement within the Access file itself and it works fine. I always get the error
Run-time error'-2147217900 (80040e14)': Automation Error
on the line,
Set rs = OConn.Execute(strSql)
If anyone could take a look over my code and determine why this is happening it would be much appreciated. I've looked at similar examples online and it seems like this should be correct.
I added the brackets around the tableName string and it works now. Thanks for all the feedback.
'Set the SQL string.
strSql = "SELECT Code, Points, Type, Description, Rating " & _
"FROM [" & tableName & "]"

Performing SQL queries on basic Excel 2013 worksheet as table using ADO with VBA triggers Errors

I'm developping modules on a client XLSm with 32-bits 2013 Excel.
I'd like to use datas on worksheet as if it is an Access table.
With a lot of difficulties, I think connection is now OK.
Still, I have error : 3001 Arguments are of wrong type, are out of acceptable range. Error that I cannot understand.
Here excerpts of VBA lines :
In addition, I added 20 lines in data Worksheet below the header line to permit to Excel to interpret for the type of each columns.
varCnxStr = "Data Source=" & G_sWBookREINVOICingFilePath & ";" & "Extended Properties='Excel 12.0 Xml;HDR=YES;IMEX=15';"
With conXLdb
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Mode = adModeShareExclusive
.Open varCnxStr
End With
strSQL = "SELECT * "
strSQL = strSQL & " FROM [ReInvoiceDB$B2B5072] inum "
strSQL = strSQL & " WHERE inum.InvoiceNum LIKE '1712*' "
strSQL = strSQL & ";"
'>> TRIGGERs ERROR with the current Where Clause !!'
adoXLrst.Open strSQL, conXLdb, dbOpenDynamic, adLockReadOnly, adCmdText
If adoXLrst.BOF And adoXLrst.EOF Then
'no records returned'
GoTo Veloma
End If
adoXLrst.MoveFirst
Do While Not adoXLrst.EOF
'Doing stuff with row'
adoXLrst.MoveNext
Loop
sHighestSoFar = adoXLrst(1).Value '> just to try for RecordSet : Codes are not completed...
sPrefixeCURR = Mid(sHighestSoFar, 1, 4)
Highest = CInt(Mid(sHighestSoFar, 5))
'> Increment >'
Highest = Highest + 1
HighestStr = sPrefixeCURR & Format(Highest, "00")
strGSFNumber = HighestStr
adoXLrst.Close
conXLdb.Close
Veloma:
On Error Resume Next
Set adoXLrst = Nothing
Set conXLdb = Nothing
Exit Sub
Etc.
Any idea about what seems be wrong ?
Thank you
Below is an old example I have been using successfully. Note that the sheet name in the book are Sheet1 and Sheet2, but in the query I had to use sheet1$ and sheet2$. I noticed you had $ signs in the middle of your sheet names. perhaps that's the issue ?
Sub SQLUpdateExample()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
con.Open "Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=" & ThisWorkbook.FullName & ";" & _
"DefaultDir=" & ThisWorkbook.FullName & ";ReadOnly=False;"
Set rs = New ADODB.Recordset
Set rs = con.Execute("UPDATE [Sheet1$] inner join [Sheet2$] on [Sheet1$].test1 = [Sheet2$].test1 SET [Sheet1$].test3 = [Sheet2$].test2 ")
Set rs = Nothing
Set con = Nothing
End Sub
To give more details about the whole module to be implemented : it is to perform a Transaction unit.
This transaction will comprise 3 operations : get a max value from a column (Invoice number) to increment it, record the new number inside an Access table (by DAO), the same Excel file (by ADO) and generating document on HDD.
So it is aimed to use the Excel file as a table not as a file manipulated with Windows script or Excel VBA. My end user is disturbed by the pop-uping of an Excel opening file operation. As a developer, I'm feeling more comfortable with using SQL statements as much as possible inside Transaction session. Is that your opinion too ?

Unable to read data from a CSV using ADO due to the driver thinking I am working with integers/number and showing nulls instead of text

I am trying to use the ADO to read in a series of text files into a worksheet. I am running into problems when the majority of the data in a specific column are integers. It will give null values (blank cells) when it reaches a String.
According to microsoft support (Ado mixed data tyes) this is a common thing and the solution is to set the IMEX = 1. I tried this however it didn't work.
I have been searching others threads looking for the answer and came across this answer (other thread) where the author says to change TypeGuessRows to "get the Jet to detect whether a mixed types situation exists and trick the Jet into detecting a certain data type." However, this hasn't worked either.
Below is my VBA code. Any help would be appreciated
Sub query_text_file(WorkingSheet As String, Col As String, Row As Integer, fileName As String, firstOrLast As Integer)
Dim strPath As String
Dim ws As Worksheet
strToolWkbk = fileName
strPath = ThisWorkbook.Path & "\Excel_Barcode_Files"
Set ws = Worksheets(WorkingSheet)
'Need to reference the:
' Microsoft ActiveX Data Objects 2.5 Library
Dim s_rst As ADODB.Recordset
Dim s_cnn As ADODB.Connection 's for sub connection
Dim intRow As Integer
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
Set s_cnn = New ADODB.Connection
s_cnn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath & ";" _
& "Extended Properties=""text;HDR=Yes;IMEX=1;TypeGuessRows=12;FMT=Delimited"";"
s_cnn.Open
Set s_rst = New ADODB.Recordset
strSQL = "SELECT * FROM " & strToolWkbk
s_rst.Open strSQL, _
s_cnn, adOpenStatic, adLockOptimistic, adCmdText
intRow = Row
s_rst.MoveFirst
Do Until s_rst.EOF
ws.Range(Col & intRow) = s_rst(0)
ws.Range(Chr(Asc(Col) + 1) & intRow) = s_rst(1)
intRow = intRow + 1
s_rst.MoveNext
Loop
s_rst.Close
s_cnn.Close
Set s_rst = Nothing
Set s_cnn = Nothing
End Sub
Here is a sample text file. The code reads in everything except the "P"
test test
P,0
1,1
5,2
6,3
Basically, don't rely on the registry entries as explained here on MSDN.
You need to create a Schema.ini file and put it in the same folder as all your text files. In the Schema.ini you specify the type for all columns you may have in your text files - it's just a much safer option to do that explicitly rather than have the driver work out the correct types for columns...
Say you have some txt files on your desktop, open Notepad and copy paste the below - make sure you adjust the [test.txt] part to match the name of your actual txt file and save it as: Schema.ini
[test.txt]
Format=CSVDelimited
Col1=Column1 Text
Col2=Column2 Text
Make sure you add another slash at the end of the parth in the strPath (also indicated in the article)
strPath = ThisWorkbook.Path & "\Excel_Barcode_Files\"
*Keep in mind that I am working in a different location to yours - I am using my Desktop for this example and my text file is named test.txt
Now, that you have a Schema.ini you can modify the connection string and take out some parameters which are not required because they exists in the Schema.ini
So bascially an SSCCE based on the above assumptions would be:
Sub Main()
Cells.ClearContents
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim thePath As String
thePath = "C:\Users\" & Environ("USERNAME") & "\Desktop\"
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & thePath & ";" _
& "Extended Properties=""text;HDR=No;"""
cn.Open
Dim sql As String
sql = "SELECT * FROM test.txt"
' populate the recordset
rs.Open sql, cn, adOpenStatic, adLockOptimistic, &H1
' copy the recordset starting at Range("A1") - assuming there are no headers - see HDR = No;
Range("A1").CopyFromRecordset rs
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Now after running this you should see all the values including the missing P:

Cast a data type with the odbc excel driver

I'm using the Microsoft Excel Driver to import an Excel document into a adodb.recordset so that I can remove duplicate rows and put it into the SQL Server database.
The first column has values like 192, 13U, JJJ, etc. but for some reason the query casts it as a double value, and any rows with alpha values get converted to Null. From what I can tell this is because the Majority type is numeric instead of text.
I tried casting it, but got an error.
Here's my function:
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.adUseClient
rs.CursorType = ADODB.CursorTypeEnum.adOpenKeyset
rs.LockType = ADODB.LockTypeEnum.adLockBatchOptimistic
sconn = "DRIVER=Microsoft Excel Driver (*.xls); ImportMixedTypes=Text; " & "DBQ=" & sFile & ";Extended Properties='Excel 8.0;HDR=No;IMEX=1';"
rs.Open("SELECT Code, Description FROM [sheet1$]", sconn)
tot += rs.RecordCount
rs.Close()
rs.Open("SELECT Distinct * FROM [sheet1$]", sconn)
Read_Excel = rs
rs = Nothing
Exit Function
fix_err:
Debug.Print(Err.Description + " " + _
Err.Source, vbCritical, "Import")
Err.Clear()
End Function
Is there a way to get the first column as text easily?
EDIT: When I try to "SELECT cast(RPOCode as varchar(10)), Description FROM [sheet1$]" I get this error
"[Microsoft][ODBC Excel Driver] Syntax error (missing operator) in query expression 'cast(Code as varchar)'. Microsoft OLE DB Provider for ODBC Drivers"
I've tried varchar, varchar(10) and text as the casting types with the same result.
Try:
rs.Open("SELECT CStr([Code]), Description FROM [sheet1$]", sconn)
Cast is not available in Jet/ACE SQL.
I ended up trying the ACE connection string instead of the one for Microsoft Excel Driver.
sconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & sFile & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
and made sure that the IMEX=1 part was in there. I don't think that the Microsoft Excel Driver was using the Extended Properties correctly.