MS Access VBA code - vba

I am new to MS Access and would like to type EmployeeID in the text box 1 (text_in) and after the button is pressed the result query (one unique value e.g. employee first name taken from the table) is printed out in the text box2 (text_out).
So far have the following code:
Private Sub btn_get_data_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
'declaration of database on recordset objects
Dim strSQL As String
Dim a As String
a = text_in.Value
Set db = CurrentDb
Set rs = db.OpenRecordset("Employee")
strSQL = "SELECT Employee.FirstName FROM Employee WHERE Employee.EmployeeId=" & a
Set db = Nothing
Set rs = Nothing
End Sub
I have tried searching for a solution in many places but I cannot understand the structure that is used in MS access VBA to implement query from regular SQL language.
Guys, thank you very much! It took me one more hour to sucessfully implement both solutions into my database file. As I wrote I am completely new to Ms-access I am learning using some tutorials but my level is still low. Thank you very much once again.

Private Sub btn_get_data_Click()
on error goto errorCatch
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb
strSQL = "SELECT Employee.FirstName FROM Employee WHERE Employee.EmployeeId=" & Me.text_in.Value & ";"
Set rs = db.OpenRecordset(strSql, DbOpenDynaset)
If rs.RecordCount > 0 Then
debug.print; rs!FirstName
Me.text_out.Value = rs!FirstName
End if
Cleanup:
Set db = Nothing
Set rs = Nothing
Exit Sub
errorCatch:
debug.print; err.Number
debug.print; Err.Description
GoTo Cleanup
End Sub
I cant tell what youre after is this. You need to be better at utilizing recordsets and how to use a string value as your sql statement.
You also didnt need to create a variable to store the textbox value in- you can use it directly in your sql statement.
Also it is very important to have good error handling as hanging recordset objects can be quite a pain in the ass.
EDIT - Ill expand on other ways to use string sql statements within VBA
DoCmd.RunSQl strSql
Or
DoCmd.Execute strSql
Both of these are great for UPDATE's or INSERT's.
Then, like Gustav pointed out, you have various D functions that are basically compact queries with some limitations. However, they often save you the trouble of having to do all the typing that is involved with opening,utlizing and closing records sets. Even though the D functions seem limited, I have often nested a few to get join results out of. Just a matter of imagination.
Look at this nifty site for function details -
https://www.techonthenet.com/access/functions/index.php

You don't need a query to do this. Just set the ControlSource of text2:
=DLookup("FirstName","Employee","EmployeeId=" & [text_in] & "")

Related

Type Mismatch in VBA SQL expression

I've been out of Access for years, but I've been tasked with a small database function. What I need to do is create a query based on dropdown results, and open that query so that end users can copy/paste what they want from it (or the entire result set).
My code looks like this:
Private Sub btnSubmit_Click()
Dim X As String
Dim Y As String
Dim sSQL As String
Dim MyRs As Recordset
If IsNull(cboReportName.Value) Or IsNull(cboError.Value) Or cboReportName.Value = "" Or cboError.Value = "" Then
MsgBox "One or more of your selections is empty."
Exit Sub
End If
X = cboReportName.Column(2)
Y = cboError.Column(1)
sSQL = "Select * from " & X & " where Error = '" & Y & "'"
Set MyRs = CurrentDb.OpenRecordset(sSQL)
End Sub
I'm getting an error on the Set MyRS line, it's telling me there's a Type Mismatch. Does this have to do with how Access uses Short Text and Long Text? There are NULL results in the query, would that throw this off? Any ideas are appreciated.
It is very unlikely that you get a VBA Type Mismatch error from your query since even if the [Error] column were not Text, it would simply return false when comparing to a string value. (This isn't to discount Erik's comment about multiple query levels causing errors... been there, dealt with that, and I believe this could still be a cause if my answer doesn't help.)
It is more likely that you have referenced an ADO library (from VBA window menu Tools | References...) and placed its priority above the default Access data object libraries. That would cause Dim MyRs As Recordset to interpret this as an ADO recordset, but CurrentDb.OpenRecordset(sSQL) will return a DAO.Recordset.
Update the declaration to
Dim MyRs As DAO.Recordset
or change the priority order of the ADO library in the Tools | References... list.

SQL Query in Access not applying WHERE clause

I am an amateur vba programmer currently struggling with the following:
I wrote a simple SQL Query for my VBA program to extract data from an existing Query (GroupedData) in Access:
Dim strSQL as string
Dim db as dao.database
dim rs as dao.recordset
strSQL = "SELECT GroupedData.EmployeeID, GroupedData.End, GroupedData.LOB, GroupedData.Position, GroupedData.WorkStatus " & _
"FROM GroupedData WHERE (((GroupedData.End) Is Null) AND ((GroupedData.Position)=0) AND ((GroupedData.WorkStatus)=0));"
Set db = OpenDatabase(MY_DB, dbOpenDynaset)
Set rs = db.openrecordset(strSQL, dbOpenSnapshot)
Do While Not rs.EOF
ListBox1.AddItem rs!EmployeeID
rs.MoveNext
Loop
So my problem is that SQL is running smoothly but is not applying any filters (that is where clause - it produces records where workstatus and position contain values above 0)
I have done such queries in the past without having any issues. This time however I am stuck
Any help would be much appreciated!
Thank you
Ok i have fixed the issue. Here is what happened:
I have made a separate function that was retrieving Employee Name based on EmployeeID. But in that function i had recordset and database declared the same way, that is: rs and db. What happened when i ran the query was it was taking the first record filtered but then the rest of them were unfiltered because they were based on the recordset within the function (which is of course all of the employees) Such a silly mistake :) Thanks anyways

VBA queries and cleaning up strings on exit

If I have a query that I have created using VBA:
dim SQL as string
dim rs as recordset
dim db as database
SQL = "SELECT ... FROM ..."
Set db = CurrentDb
Set rs = db.OpenRecordset(SQL, dbOpenDynaset)
At the end of my sub I would always do the following:
rs.close
set rs = nothing
My question is, do I need to SQL ="" or something of that like? I think my confusion originally came from the fact that I haven't used set SQL in my code.
and if I do clear these strings, then, is there a 'best' way?
Since you're not opening a connection to either CurrentDb or the SQL string, there's no need to close them. However, you are opening a recordset, so that should be closed. It wouldn't harm anything to set SQL = "", but it's not going to actually do anything constructive.
As far as a "best way", I think you've already got it. At the end of your sub, or before any code that might prematurely exit it, just put:
rs.close
set rs = nothing

How to view a recordset in an access table by means of vba?

With help of the embedded access vb editor i've written a small code to analyse the field values of my database, and want to finally view the recordsets in a table inside the opened access. As a newbie i can only use Debug.Print to display the field names. Could anyone of you tell me with which statements/commands i can execute my SQL String in order to view the result recordset with values?
Debug.Print FinalSQLString
Here is the basic recipe:
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT * FROM myTable")
Know that you are using Jet Data Access Objects (DAO) with Access - google that for details.
Expression (rs.BOF and rs.EOF) = True indicates there were no rows.
Use rs.MoveFirst, rs.MoveNext to go to the first and next rows. Test rs.EOF after rs.MoveNext; when True, last row was already processed.
rs(FieldName) returns the value of the column named FieldName (a string expression).
rs(1) returns the value of the second column.
When done, rs.Close.
There is no way to hand Access the RecordSet and have it displayed in a Datasheet view. Instead, you will have to create a QueryDef object and use it to perform the query and display the Datasheet view of the results:
Dim qd As QueryDef
On Error Resume Next
CurrentDb.QueryDefs.Delete "temp"
On Error GoTo 0
Set qd = db.CreateQueryDef("temp", "SELECT * FROM myTable")
DoCmd.OpenQuery "temp", acViewNormal, acEdit
As far as I know, there is no way to display a datasheet containing a VBA instance of a recordset. If the source of your recordset is strQSL, you could however create a table with your results, and open that one, or more elegantly, create queryDef and open it:
Sub ShowQd(strQdName As String, strSql As String)
'creates queryDef and display it in a datasheet'
Dim qd As DAO.QueryDef
Set qd = CurrentDb.CreateQueryDef(strQdName)
With qd
.ReturnsRecords = True
.SQL = strSql
End With
DoCmd.OpenQuery strQdName
End Sub
If you focus on displaying things, you could also put a ListBox in a form, set its Number of columns to the number of fields returned by your query (qd.Fields.Count), and set your strSql as the RowSource of the ListBox. AND... if you put all your related code in that form, you now have a form that you can import in any db to quickly display what you want :)
Good luck !

Rookie SQL inside of VB question - MSAccess 2003

Hey guys, can anyone help me with a simple question. I have this SQL statement below in a sub in VB within access from a button click, and I am new to this.
Here is what I typed:
Private Sub Command0_Click()
Dim rs As Recordset
Dim sql As String
Dim db As Database
Set db = CurrentDb
sql = "SELECT * FROM Transactions"
Set rs = db.OpenRecordset(sql)
Do Until rs.EOF
rs.MoveNext
Loop
If Not rs.EOF Then
MsgBox "test"
End If
End Sub
Ok, so how do I populate this?? Essentially I am justing starting out with this, so I am wondering how do I take this simple code, and run it like a query so that the resulting recordset opens.
Thanks!
some other remarks and advices:
1) Always indicate which type of recordset you are using. Here it seems to be a DAO recordset, so go for a complete declaration like:
Dim rs as DAO.recordset
Runing on another computer, and depending on the declaration order of ADODB and DAO libraries, the very same code can generate a bug.
2) To avoid any disturbing error message if no record is available, you can add an extra test, something like
if rs.recordcount = 0 then
Else
rs.moveFirst
....
3) To browse the complete recordset with debug.print, you could do it this way. Just ad a 'm_debugLine' as string, and a 'fld' as DAO.Field in your declarations.
rs.MoveFirst
do while not rs.eof
m_debugLine = ""
for each fld in rs.fields
m_debugLine = m_debugLine + vbTab + fld.value
next fld
debug.print m_debugLine
rs.movenext
loop
4) you could even add a debug.print line to print out the field names before printing the data. I guess you'll find this one
Depending on what you are trying to do, you may be over-complicating this. A better approach would be to set the recordsource of the form (in the property sheet) to the transactions table then drop the fields you want on the form using the visual designer.
HOWEVER, If you really must do it this way, here is the code that will replace what you have and open a spreadsheet like view of the data in the transactions table.
Private Sub Command0_Click()
docmd.Opentable "transactions"
End Sub
If you want to limit the results to a query, then first build the query and save it then use the following code.
Private Sub Command0_Click()
docmd.OpenQuery "MyQueryName"
End Sub
To be extremely literal, your original code DID populate a recordset (in the rs object). You can access the fields by name using code in your while loop such as
debug.print rs("Field1")
You put your code inside the Do..Loop. This code will be evaluated for each record that is encountered.
Do Until rs.EOF
Msgbox "The value for MyField is " & rst!MyField
rs.MoveNext
Loop
you get at the columns of the record for the recordset like rs(0) or rs("columnname")....
if your transactions table has three columns named a, b, c you could get to it like:
rs(0)
rs(1)
rs(2)
or
rs("a")
rs("b")
rs("c")