how to retrieve data from access to excel using vba? - excel

I am trying to retrieve data from access using excel-vba but the problem is when i want to use an AND in SQL query it throws an error.
This works
SQL = "SELECT " & col_name & " FROM PhoneList WHERE Item LIKE '" & var & "%" & "'"
This doesn't
SQL = "SELECT " & col_name & " FROM PhoneList WHERE Item LIKE '" & item & "%" & "'" & " AND Size Like '" & size & "%" & "'"
even this doesn't work
SQL = "SELECT Standard FROM PhoneList WHERE Item = 'Shank Button' AND Size = '17'"
This throws an
error -2147467259 Method 'open'object' _recordset' failed
from excel where it works fine if I try it in access query
SELECT Standard FROM PhoneList WHERE Item = 'Shank Button' AND Size = '17'
here is my table [PhoneList] structure
ID | Item | Size | Standard | Customized Standard | Premium | Customized Premium
here, the combination of Item and Size makes a record unique.
I assume only AND part is creating the problem or something is wrong with recordset pasting to the excel sheet.
I am trying to retrieve only one value from DB where Item, size and category type (Standard or Customized Standard or Premium) will be taken from excel userform's combobox, and I will show that value in a cell or in a textfield.
Any help will be highly appreciated.
here is my code ...
Option Explicit
Private Sub CommandButton1_Click()
'Declaring the necessary variables.
Dim cnn As ADODB.Connection 'dim the ADO collection class
Dim rs As ADODB.Recordset 'dim the ADO recordset class
Dim dbPath As String
Dim SQL As String
Dim i As Integer
Dim item As String
'add error handling
On Error GoTo errHandler:
'Disable screen flickering.
Application.ScreenUpdating = False
'Clear the old data
Sheet2.Range("A2:G10000").ClearContents
'Variables
dbPath = Sheet1.Range("I3").Value
item = ComboBox1.Text
'Initialise the collection class variable
Set cnn = New ADODB.Connection
'Connection class is equipped with a —method— named Open
'—-4 aguments—- ConnectionString, UserID, Password, Options
'ConnectionString formula—-Key1=Value1;Key2=Value2;Key_n=Value_n;
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
'Create the SQL statement to retrieve the data from table.
Dim col_name As String
Dim Isize As String
Isize = "17"
col_name = ComboBox3.Text
If Sheet2.Range("J2").Value = "Yes" Then
SQL = "SELECT * FROM PhoneList WHERE Item = '" & item & "'"
Else
SQL = "SELECT " & col_name & " FROM PhoneList WHERE Item LIKE '" & item & "%" & "'" & " AND Size LIKE '" & Isize & "%" & "'"
'SQL = "SELECT " & col_name & " FROM PhoneList t WHERE t.Item LIKE '" & item & "*' AND t.Size = " & size
End If
'Create the ADODB recordset object.
Set rs = New ADODB.Recordset 'assign memory to the recordset
'ConnectionString Open '—-5 aguments—-
'Source, ActiveConnection, CursorType, LockType, Options
rs.Open SQL, cnn
'Check if the recordset is empty.
If rs.EOF And rs.BOF Then
'Close the recordet and the connection.
rs.Close
cnn.Close
'clear memory
Set rs = Nothing
Set cnn = Nothing
'Enable the screen.
Application.ScreenUpdating = True
'In case of an empty recordset display an error.
MsgBox "There are no records in the recordset!", vbCritical, "No Records"
Exit Sub
End If
'Write the reocrdset values in the sheet.
Sheet2.Range("a2").CopyFromRecordset rs
'Close the recordset and the connection.
rs.Close
cnn.Close
'clear memory
Set rs = Nothing
Set cnn = Nothing
'Update the worksheet
Application.ScreenUpdating = True
'Inform the user that the macro was executed successfully.
MsgBox "Congratulation the data has been successfully Imported", vbInformation, "Data Imported"
On Error GoTo 0
Exit Sub
errHandler:
'clear memory
Set rs = Nothing
Set cnn = Nothing
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Import_Data"
End Sub
Thanks

There should be a space before the AND:
SQL = "SELECT " & col_name & " FROM PhoneList WHERE Item LIKE '" & item & "%" & "'" & " AND Size Like '" & item & "%" & "'"

There are a few issues here -
MS Access uses the asterisk * as the wildcard character to represent any sequence of characters (or no characters), not the percent symbol % used by some other RDBMS.
size is a reserved word in MS Access and so could potentially cause problems unless enclosed in square brackets or prefixed with the table qualifier.
Assuming the Size field is numerical (as the name would imply), you should not surround the value with single quotes, hence the code might become:
SQL = "SELECT " & col_name & " FROM PhoneList t WHERE t.Item LIKE '" & item & "*' AND t.Size = " & size

Related

How to populate a text box from a listbox?

I have a listbox with combined Employee Number and Name. so what you see is 0001-John Doe but now when I try and populate a text box with the list box info it does not work.
How I populate my listbox:
Private Sub UserForm_Initialize()
Dim conn As New ADODB.Connection
Dim rsst As New ADODB.Recordset
dbPath = Sheets("Info").Range("a2").Value
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
rsst.Open "SELECT EmpNumber,EmpFirstName,EmpSurname FROM Employees;", _
conn, adOpenStatic
With rsst
.MoveFirst
Do Until .EOF
Me.lbxNextOfKinEmployeeNumber.AddItem rsst.Fields(0).Value & " - " & rsst.Fields(1) & " " & " " & rsst.Fields(2) & " "
rsst.MoveNext
Loop
End With
End Sub
What's in my view button:
Private Sub btnNextOfKinSelect_Click()
Dim CNOK As New ADODB.Connection
Dim RNOK As New ADODB.Recordset
txtNextofKinEmployeeNumber.Enabled = False
'btnEditNextOfKin.Visible = True
If lbxNextOfKinEmployeeNumber.ListIndex = -1 Then
MsgBox "Please Select a Employee Number"
Else
dbPath = Sheets("Info").Range("a2").Value
CNOK.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
RNOK.Open "SELECT * FROM EmployeeNextOfKin Where EmpNumber ='" &
Me.lbxNextOfKinEmployeeNumber & "'", _
CNOK, adOpenStatic
RNOK.MoveFirst
txtNextofKinEmployeeNumber.Value = RNOK("EmpNumber")
txtNextOfKinName.Value = RNOK("NextOfKinName")
txtNextOfKinSurname.Value = RNOK("NextOfKinSurname")
txtContactNumber.Value = RNOK("NextofKinContactNumber")
txtContactAddressLine1.Value = RNOK("NextofKinAddress")
txtNextofKinCity.Value = RNOK("NextofKinCity")
txtCellNumber.Value = RNOK("NextofKinCellNumber")
End If
End Sub
What I want is when I select 0001-John Doe it should get the data from my database and populate my textboxes.
Code is trying to match concatenated string 0001-john doe with EmpNumber field value 0001. Options:
set listbox RowSource as multi-column
Do Until rsst.EOF
With Me.lbxNextOfKinEmployeeNumber
.ColumnCount = 2
.ColumnWidths = "0;2"
.AddItem rsst(0) & ";" & rsst(0) & " - " & rsst(1) & " " & rsst(2)
End With
rsst.MoveNext
Loop
If users would prefer to type name, don't include EmpNumber in concatenated string. Last name first might be more appropriate:
.AddItem rsst(0) & ";" & rsst(2) & ", " & rsst(1)
Might want to sort recordset: ORDER BY EmpSurname
extract EmpNumber from concatenated string
Left(Me.lbxNextOfKinEmployeeNumber, 4)
use LIKE and wildcard
WHERE '" & Me.lbxNextOfKinEmployeeNumber & "' LIKE [EmpNumber] & '*'"

Importing Excel worksheet range to Ms Access Table

Good Afternoon,
I have created a Macro that uploads data to a access database ( both on my desktop). The problem is it I keep getting errors when I try to expand the range.
I presumed it would be something simple but seems to be something I am overlooking.
here is the code - basically I would like to include the column or set it to a dynamic range? can you please help?
Sub AccessCode()
Application.ScreenUpdating = False
Dim db As Database
Dim rs As DAO.Recordset
Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
Set rs = db.OpenRecordset("Fact Table", dbOpenTable)
rs.AddNew
rs.Fields("GUID") = Range("g2").Value
rs.Fields("StageID") = Range("h2").Value
rs.Fields("Sync Date") = Range("i2").Value
rs.Fields("Forecast HP") = Range("j2").Value
rs.Fields("Owner Id") = Range("k2").Value
rs.Fields("Recent Modified Flag") = Range("L2").Value
rs.Fields("Upload Date") = Range("M2").Value
rs.Update
rs.Close
db.Close
Application.ScreenUpdating = True
MsgBox " Upload To PMO Database Successful."
End Sub
You can use a query instead of iterating through a recordset:
Sub AccessCode()
Application.ScreenUpdating = False
Dim db As Database
Dim rs As DAO.Recordset
Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
db.Execute "INSERT INTO [Fact Table] ([GUID], [StageID], etc) " & _
"SELECT * FROM [SheetName$G:M] " & _
"IN """ & ActiveWorkbook.FullName & """'Excel 12.0 Macro;HDR=No;'"
End Sub
This has numerous advantages, such as often being faster because you don't have to iterate through all the fields.
If you would trigger the import from Access instead of Excel, you wouldn't even need VBA to execute the query.
Change the rs section to this one:
With rs
.addnew
!GUID = Range("g2").Value
!StageID = Range("h2").Value
'...etc
.Update
End With
MSDN source
Use the AddNew method to create and add a new record in the Recordset object named by recordset. This method sets the fields to default values, and if no default values are specified, it sets the fields to Null (the default values specified for a table-type Recordset).
After you modify the new record, use the Update method to save the changes and add the record to the Recordset. No changes occur in the database until you use the Update method.
Edit:
This is how your code should look like, when you change the rs section with the code above:
Sub AccessCode()
Application.ScreenUpdating = False
Dim db As Database
Dim rs As DAO.Recordset
Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
Set rs = db.OpenRecordset("Fact Table", dbOpenTable)
With rs
.addnew
!GUID = Range("g2").Value
!StageID = Range("h2").Value
'...etc
.Update
.Close
End With
Application.ScreenUpdating = True
MsgBox " Upload To PMO Database Successful."
End Sub
Just thought I'd add in an alternative to #Erik von Asmuth's excellent answer. I use something like this in a real project. It's a little more robust for importing a dynamic range.
Public Sub ImportFromWorksheet(sht As Worksheet)
Dim strFile As String, strCon As String
strFile = sht.Parent.FullName
strCon = "Excel 12.0;HDR=Yes;Database=" & strFile
Dim strSql As String, sqlTransferFromExcel As String
Dim row As Long
row = sht.Range("A3").End(xlDown).row
Dim rng As Range
sqlTransferFromExcel = " Insert into YourTable( " & _
" [GUID] " & _
" ,StageID " & _
" ,[sync Date] " & _
" ,[etc...] " & _
" ) " & _
" SELECT [GUID] " & _
" ,StageID " & _
" ,[sync Date] " & _
" ,[etc...] " & _
" FROM [{{connString}}].[{{sheetName}}$G2:M{{lastRow}}]"
sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{lastRow}}", row)
sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{connString}}", strCon)
sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{sheetName}}", sht.Name)
CurrentDb.Execute sqlTransferFromExcel
End Sub

ADO ACE OLEDB 12.0 Excel Front end with VBA troubleshooting

I am using Excel 2013 as a front end application written w/ VBA.
I've linked a XLSX file inside an Access 2013 database in order to use SQL simply for example to read MAX Value of a column of which datas are filtered with a Where Clause.
I cannot understand why a SQL statement for retrieving MAX value does not work whereas the same statement is OK via SQL Querying in Access.
Hereafter VBA code excerpt :
varCnxStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" &
G_sWBookREINVOICingFilePath & ";Mode="
With conXLdb
'*
'.Provider = "Microsoft.ACE.OLEDB.12.0"
'.ConnectionString = "Data Source=" & G_sWBookREINVOICingFilePath & ";"
& "Extended Properties='Excel 12.0;HDR = YES'"
'.Mode = adModeShareExclusive
.Open varCnxStr & adModeShareExclusive
'*
End With
Debug.Print varCnxStr & adModeShareExclusive
strSQL = "SELECT MAX(InvoiceNum) as LastNumInvoice"
strSQL = strSQL & " FROM ReInvoiceDB "
strSQL = strSQL & " WHERE InvoiceNum > " & strYMPrefix_p & "000"
strSQL = strSQL & ";"
Debug.Print strSQL
adoXLrst.Open Source:=strSQL, ActiveConnection:=conXLdb,
CursorType:=adOpenStatic, LockType:=adLockOptimistic, Options:=adCmdText
adoXLrst.MoveFirst
'Set adoXLrst = conXLdb.Execute(strSQL)
HighestStr = adoXLrst![LastNumInvoice]
adoXLrst.Close
strGSFNumber = HighestStr '>> byref returning value
conXLdb.Close
Veloma:
'>>
On Error Resume Next
Set adoXLrst = Nothing
Set conXLdb = Nothing
Exit Sub
'>>
Diso:
Beep
Beep
'>>
strGSFNumber = "ERR"
'>>
sMsg = "pG_getNEXTInvoiceValueXLasDB-ERR ::" & Err.Number & ":: - " &
Err.Description
MsgBox sMsg, vbOKOnly + vbCritical
sRet = sMsg
Resume Veloma
End Sub
It returns Null value in variable HighestStr whereas it should receive a double value ...
Any help or any clue on misfunctionning ?
Regards.

Using 'Insert Into' SQL Statement with column names on Excel Worksheet with ACE OLEDB fails

So, I want to get disciplined in how I store data to worksheets and was wanting to use the SQL OLEDB Provide for Excel and standard SQL statements. Insert into with column names does not work, yet, for me at least. Some code demonstrates the problem. Expecting both forms shown here to work W3 Schools SQL INSERT INTO Statement
Option Explicit
Sub MinimalCompleteVerifiableExample()
'Tools->References "Microsoft ActiveX Data Objects 2.8 Library"
Dim wsNew As Excel.Worksheet
Set wsNew = ThisWorkbook.Worksheets.Add
wsNew.Cells(1, 1) = "TimeStamp"
wsNew.Cells(1, 2) = "Path"
Dim oConn As ADODB.Connection
Set oConn = New ADODB.Connection
Debug.Assert UBound(Split(ThisWorkbook.Name, ".")) > 0 '* Workbook needs to be saved
oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties='Excel 12.0 Macro'"
Dim rsTestRead As ADODB.Recordset
Set rsTestRead = New ADODB.Recordset
rsTestRead.Open "Select * from [" & wsNew.Name & "$] AS P", oConn, adOpenStatic
Debug.Assert oConn.Errors.Count = 0
Debug.Assert rsTestRead.Fields.Item(0).Name = "TimeStamp"
Debug.Assert rsTestRead.Fields.Item(1).Name = "Path"
Dim sSQL As String
sSQL = "insert into [" & wsNew.Name & "$] (TimeStamp,Path) VALUES ('31-Dec-2015','C:\temp');" 'DOES NOT WORK
'sSQL = "insert into [" & wsNew.Name & "$] values ('25-Dec-2015','C:\temp')" 'works
Stop
oConn.Execute sSQL
Debug.Assert oConn.Errors.Count = 0
Stop
End Sub
On gets an error message of "Syntax error in INSERT INTO statement."
Ah.
It seems one adds square brackets around the column names
Dim sSQL As String
sSQL = "insert into [" & wsNew.Name & "$] ([TimeStamp],[Path]) VALUES ('31-Dec-2015','C:\temp');"

Lookup Cell Value from Excel in Access and Return Data from Access

I am trying to use a function to look up in an Access table a value from an Excel cell and to return a value from a column in the matched row in the Access table.
I am using the code below, but it just keeps returning #value even though I get an exact match in the Access db.
Dim adoCN As ADODB.Connection
Dim strSQL As String
Const DatabasePath As String = "\\aur\hobo_data\Corporate\Corporate\3DOCK2
\D_IMA\Teams\Data Architecture and Management\Projects\Payments Transformation\02 -
Documents\23 - Data Architecture Deliverables\11 - ODS & Data Mart Model\04 Fundtech
Data Provision\Payments Transformation.mdb"
'Function argument descriptions
'LookupFieldName - the field you wish to search
'LookupValue - the value in LookupFieldName you're searching for
'ReturnField - the matching field containing the value you wish to return
Public Function DBVLookUp(TableName As String, _
LookUpFieldName As Long, _
LookupValue As String, _
ReturnField As String) As Variant
Dim adoRS As ADODB.Recordset
If adoCN Is Nothing Then SetUpConnection
Set adoRS = New ADODB.Recordset
strSQL = "SELECT [" & LookUpFieldName & "], [" & ReturnField & _
"] FROM [" & TableName & _
"] WHERE [" & LookUpFieldName & "]='" & LookupValue & "';"
'If lookup value is a number, then remove the two
adoRS.Open strSQL, adoCN, adOpenForwardOnly, adLockReadOnly
If adoRS.BOF And adoRS.EOF Then
DBVLookUp = "Value not Found"
Else
DBVLookUp = adoRS.Fields(ReturnField).Value
End If
adoRS.Close
End Function
Sub SetUpConnection()
On Error GoTo ErrHandler
Set adoCN = New Connection
adoCN.Provider = "Microsoft.Jet.OLEDB.4.0" 'Change to 3.51 for Access 97
adoCN.ConnectionString = DatabasePath
adoCN.Open
Exit Sub
ErrHandler:
MsgBox Err.Description, vbExclamation, "An error occurred"
End Sub

Resources