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 & "]"
Related
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")
New to programming, SQL and VBA. I frequently work with decent size data tables and thought it would be helpful to add SQL query execution capability to apply to an existing excel table. Research led me to ADODB connections and found a great base snippet to work from here: https://blog.learningtree.com/excel-as-a-database-how-to-query-economic-data-with-sql/
I seem to running into limits though on how many rows are accessible before the next line of code runs. In my SQL statement source I can return 65k rows, any more in defining the source table size, and I get an Object does not exist error. Can you run ADODB recordset.Open asynchronously to ensure complete return of the object? - Any help would be very much appreciated.
Thanks!
tried to insert a WAIT inline:
rs.Open strSQL, Application.Wait (Now + TimeValue("0:00:30")), cn
but still errors out. See code below
Sub ExcelTbl_SQL()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
strFile = ThisWorkbook.FullName
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
strSQL = "SELECT * FROM [Sheet1$A1:AI146103] WHERE GROUP = 'HIX'"
rs.Open strSQL, cn
Dim ws As Worksheet
Set ws = Application.Sheets.Add
ws.Range("A1").CopyFromRecordset rs
rs.Close
cn.Close
'Debug.Print rs.GetString
End Sub
These are the results I am getting:
Works: strSQL = "SELECT * FROM [Sheet1$A1:AI65000] WHERE GROUP = 'HIX'"
Error: strSQL = "SELECT * FROM [Sheet1$A1:AI65437] WHERE GROUP = 'HIX'"
Run-time error '-2147217865 (80040e37)': The Microsoft Access database
engine could not find the object 'Sheet1$A1:AI65437'.
I think this is because you are calling old version library through this part of connection string:
Provider=Microsoft.ACE.OLEDB.12.0
You should try
Provider=Microsoft.ACE.OLEDB.16.0
Upd: Answer was here Excel as database - query more than 65536 rows? interesting. You cannot mention rows, or you'll get error.
I am trying to do a Select statement from an SQL server using an ADODB connection, within Microsoft Access VBA. The select statement is very complex with calculations and would work better to keep that to try and turn in to a connection with the DB.
I can append the data row by row, but am wondering how I could append as simple as possible as a block of data to save time/vba effort. (Lots of data!)
In order to simplify the example, I have put a basic SQL statement, but if you could review this and let me know if there is a way to append as a recordset block or what would be a better option... The code below works for pasting as a block into excel, and I would think I only need to change that commented out line's method to append in Access...
Option Private Module
Private Const DataServer = "GLSSQLMADPS2"
Private Const sqlconstring = "Driver={SQL Server};Server=" & DataServer & "; Database=PERF_MGMT_BWRSRV_PROD; Trusted_Connection=yes; Connect Timeout = 600"
Sub M2DSQLPull()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
Dim sql As String
sql = "SELECT " & _
"Employee_Token_NR, " & _
"Null as 'Sum_Month', " & _
"1000 AS 'Data_ID', " & _
"DATEADD(m, DATEDIFF(m, 0, MIN(CALL_TS)), 0) AS 'Metric_1' " & _
"FROM PMBSED_PhoneEvaluations " & _
"GROUP BY Employee_Token_NR "
Set cn = New ADODB.Connection
cn.CommandTimeout = 120
cn.Open sqlconstring
Set rs = New ADODB.Recordset
rs.Open SqlString(i), cn, adOpenStatic, adLockReadOnly
'How I would paste in an excel spreadsheet, how do I block paste in an access database?
'ThisWorkbook.Worksheets("RawData").Cells(RowNumber, 1).CopyFromRecordset rs
RowNumber = RowNumber + rs.RecordCount
rs.Close
cn.Close
End Sub
Thank you for any assistance!
-Robert
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 ?
UPDATE 4
Posted solution.
UPDATE 3
Finally managed to find a solution to my problem, will post the answer shortly within the next few days.
UPDATE 2!
Put updates at the top for better readability.
So apparently it's not possible to use a named range from excel directly in the vba code when exporting to access.
After doing some more research I found there is a way around this: changing the dynamic range to a static range first and then using the entirety of the string as a variable.
However my current code down below says it cannot find the range even though I'm sure the syntax is correct, is this because I haven't set the reference to the excel file correctly?
Sub ExportAccess()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strQuery As String
myAddress = Replace(ThisWorkbook.Names("ExportData").RefersToRange.Address, "$", "")
myAddress = "[GWU$" & myAddress & "]"
' [Excel 8.0;HDR=NO;DATABASE=C:\Users\Public\test.xls] < unused code snippet
strQuery = "INSERT INTO Table1" & vbCrLf & _
"SELECT * FROM " & myAddress & ""
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "C:\Users\Public\Database.accdb"
.Open
End With
rs.Open strQuery, cn
cn.Close
rs.Close
Set rs = Nothing
Set cn = Nothing
End Sub
UPDATE!
After racking my brain for a few hours and checking the links I posted for some much needed reference, I came up with the following:
Sub ExportAccess()
Dim cn As ADODB.Connection
Dim strQuery As String
strQuery = "INSERT INTO Table1" & vbCrLf & _
"SELECT * FROM [Excel 8.0;HDR=YES;DATABASE=C:\Users\Public\test.xls].ExportData"
Set cn = New ADODB.Connection
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "C:\Users\Public\Database1.accdb"
.Open
.Execute strQuery
End With
With cn
.Close
End With
End Sub
I haven't been able to test this yet (will do this first thing tomorrow)
However I'm worried about the following code snippets:
"SELECT * FROM [Excel 8.0;HDR=YES;DATABASE=C:\Users\Public\test.xls].ExportData"
This should technically select the 'ExportData' range from the test worksheet based on a different question here on Stackoverflow, I'm just not 100% sure if it will work
.Open
.Execute strQuery
End With
With cn
.Close
End With
Will this actually perform the INSERT INTO? and is closing the the connection really required? (I'd assume so, just would like to know for sure)
Kind regards,
I've been trying to get what I have in my head working for a while now, but to be honest I don't have the required expertise right now. I'm still fairly new to programming so setting up my own variables and arrays that I can actually use is still very hard for me.
Hopefully you can help me out.
The situation:
So in an Excel read-only file I basically have a 10 row by 14 column range where users put their own data into, I want to only export the rows that have actual data that was filled in by these users to an Access 2010 database.
What I tried before: At first I wanted as simple of a solution as possible, I tried doing this by connecting the Excel worksheet to the Access database and then by doing a SQL append query on the rows where data is NOT NULL. (checks if entries in last column are NOT NULL)
However since many people will use the file at the same time I feared that the Access database/Connection to the Excel worksheet might get confused and start doing things it wasn't supposed to. When I tried to Google find out whether this was actually a problem or not my search results came up empty, so I was unsure if I should continue in this direction and ultimately abandoned this solution.
What I'm trying to do now: Basically I figured that I could do the same thing in an Excel macro before exporting, setting up a named range (via name manager) and then cutting out the rows that have no data in them with a simple macro before appending the remaining rows in the named range to the access database.
There are a few examples of people that have tried to do the same after a few google searches (unfortunately I can't post more than 2 links OR post linkbu.ch links):
Search results
However all of these examples seem to use a static range, not a dynamic range. How do I insert a Range from the name manager in VBA code? If anyone has any ideas on a different solution that would also be appreciated.
Kind regards,
FSDT
Use the macro recorder. Simply turn it on and manually go through the steps to export your named range. Then look at the VBA code you generated. The macro recorder is the greatest tool ever bestowed upon mankind. Try it, you'll like it.
All right everyone, as stated before this is the solution I came up with after trial and error:
Sub ExportAccess()
Dim cn As ADODB.Connection
Dim strQuery As String
Dim dbFilepath As String
Dim xlFilepath As String
dbFilepath = "C:\Users\Public\Database1.accdb"
xlFilepath = Application.ActiveWorkbook.FullName
xlFilepath = "[Excel 8.0;HDR=Yes;DATABASE=" & xlFilepath & ";IMEX=1]"
myAddress = Replace(ThisWorkbook.Names("ExportData").RefersToRange.Address, "$", "")
myAddress = "[Sheet1$" & myAddress & "]"
myAddress = "" & xlFilepath & "." & myAddress & ""
STRcn = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & dbFilepath & ";"
strQuery = "INSERT INTO Table1" & vbCrLf & _
"SELECT * FROM " & myAddress & ""
Set cn = CreateObject("ADODB.Connection")
cn.Open STRcn
cn.Execute strQuery
cn.Close
Set cn = Nothing
End Sub