Prepopulating Access Form - vba

I have a form that we use for data entry, to make it easier I would like to have some of the fields prepopulate based on the EmployeeID field, for example once I put in my employee id then the EmployeeName field would be Auto populate with John Doe, and Gender would be Male and EEOC would be White, etc. Is this at all possible to do? It would be based of the data in another table title EmpData.

In the AfterUpdate event of EmployeeID, you could put something like (untested code, so it needs to be tweaked a bit):
Dim db as DAO.Database
Dim rec as DAO.Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("Select * from EmpData where EmployeeID = " & Me.EmployeeID & "")
Me.EmployeeName = rec("EmployeeName")
Me.Gender = rec("Gender")
Me.EEOC = rec("EEOC")
etc...
Set rec = Nothing
Set db = Nothing
If EmployeeID is a Text field, it will need to be surrounded by single quotes in the "Set rec" line. Like this:
Set rec = db.OpenRecordset("Select * from EmpData where EmployeeID = '" & Me.EmployeeID & "'")

If you create a query that joins the two tables, then Access will do it all for you automatically. Then you should use that query as the DataSource for the form.
SELECT MyDataTable.*, EmpData.*
FROM MyDataTable LEFT JOIN EmpData
ON MyDataTable.EmployeeID = EmpData.EmployeeID;
Doing this, you might want to lock the columns coming from EmpData from being possible to edit.
In your form, you show the fields from the MyDataTable and the relevant fields from EmpData. Any fields in MyDataTable that should be filled in from EmpData should not be shown to the user.
I.e. you show the EmployeeName from EmpData and not from MyTableData.
In the AfterUpdate event on EmployeeID you copy the data from EmpData to MyTableData
Me.RecordSet!MyTableData.EmployeeName = Me.RecordSet!EmpData.EmployeeName

Related

Display Multiple Values in Text Boxes based on a Combo Box Value

I have one table - tblMAIN
I have 4 ID Fields - mainID, FatherID, MotherID and FullName
1 Form - frmMAIN
1 Combo Box - cboMAIN
2 Text Boxes - txtFATHER, txtMOTHER
I am trying to write a SQL statement in VBA that will select a record in the combo box cboMAIN and by doing that selection, two text boxes are populated.
Robert is selected in the cboMAIN, Robert has a MainID of 20
Robert mother is Ruth, she has a MainID of 30
Robert's father's MainID is 40
So in txtFather it will display record 40 / FullName and in txtMother it will display FullName for record MainID30.
I would like to add text fields and show Ruth's mother and Robert's father's father.
Here is an idea I have, but not sure what to do next.
Dim sqlME As String
Dim sqlFATHER As String
Dim db As Database
Dim rs As DAO.Recordset
sqlFATHER = "SELECT * FROM tblMAIN WHERE MainID = " & Forms![MAIN]![cboMAIN] & ";"
'AND NOT SURE WHAT I NEED TO DO HERE!
Set db = CurrentDb
Set rs = db.OpenRecordset(sqlFATHER)
Me.txtFather.Value = rs!FullName
Set rs = Nothing
Set db = Nothing
VBA setting value of UNBOUND textbox will show same value for every record.
This data is recursive in nature and Access SQL doesn't easily manipulate data of recursive nature. Other database platforms have utility to better deal with.
Build a self-join query object named qryAncestors:
SELECT tblMain.mainID, tblMain.FullName, tblMain_1.FullName AS Father,
tblMain_2.FullName AS Mother, tblMain_3.FullName AS PGFather,
tblMain_4.FullName AS PGMother, tblMain_5.FullName AS MGFather, tblMain_6.FullName AS MGMother
FROM tblMain AS tblMain_6
RIGHT JOIN (tblMain AS tblMain_5
RIGHT JOIN (tblMain AS tblMain_4
RIGHT JOIN (tblMain AS tblMain_3
RIGHT JOIN (tblMain AS tblMain_2
RIGHT JOIN (tblMain AS tblMain_1
RIGHT JOIN tblMain
ON tblMain_1.mainID = tblMain.FatherID)
ON tblMain_2.mainID = tblMain.MotherID)
ON tblMain_3.mainID = tblMain_1.FatherID)
ON tblMain_4.mainID = tblMain_1.MotherID)
ON tblMain_5.mainID = tblMain_2.FatherID)
ON tblMain_6.mainID = tblMain_2.MotherID;
Then options to use that query:
reference query as combobobox RowSource then textbox ControlSource references combobox columns by index
=[cboMain].Column(2)
textbox ControlSource uses DLookup() expression, such as:
=DLookUp("Father", "qryAncestors", "mainID=" & mainID)
textbox ControlSource calls VBA custom function to return a value, like:
=GetAncestor(mainID, "Father")
Function GetAncestor(intID As Integer, strAnc As String)
GetAncestor = DLookUp(strAnc, "qryAncestors", "mainID=" & intID)
End Function
If you want to go beyond grandparents to any level, approach would have to be quite different. Recursive procedure is tricky. A function to return FullName of ancestor could be like:
Function GetAncestor(intID As Integer, intGen As Integer, strParent As String)
Dim x As Integer
GetAncestor = intID
For x = 1 To intGen
GetAncestor = DLookup(strParent, "tblMain", "mainID=" & Nz(GetAncestor,0))
Next
GetAncestor = DLookup("FullName", "tblMain", "mainID=" & Nz(GetAncestor,0))
End Function
To get ancestor of specific generation, call function: GetAncestor(mainID, 1, "MotherID")

How can I get the second field, based on the first field, shown in a ListBox

I have a ListBox that is reading data from a SQL Server table. The table has only two fields; the 1st is the report name and the 2nd is the SQL that I want to execute and display in a GridView. My code looks like this.
myItem = ListBox1.SelectedItem
SqlStr = "select ReportSQL from [All_Report_Names] Where ReportName = '" & myItem & "'"
SqlStr = Replace(SqlStr, startDate, VBstartDate)
SqlStr = Replace(SqlStr, endDate, VBendDate)
It almost seems like it would be: myItem = ListBox1.SelectedItem.Offset(0,1)
Of course that doesn't work.
The ListBox points to this SQL Server table.
The first field is shown in the ListBox. When I click on it, I want to read in the seconf column, which has all my SQL scripts. Finally, I do a REPLACE() on the startDate and endDate, and pass those from my Form into the SQL.
The ListBox reads from the SQL Server table below.

How to use a query as a control source for a textbox on a form?

I have a form myForm that's binded to a table tbl in my database. (I don't know if binded is the correct term, but It shows records from tbl on by one.)
In the form:
contact: textbox, binded to tbl.contact.
dailyCount: textbox, should show the amount of contacts entered today.
In the table:
contact
dateEntry
The query I want to use is:
SELECT count(*)
FROM tbl
WHERE contact = currentContact
AND month(dateEntry) = month(now)
AND day(dateEntry) = day(now)
AND ear (dateEntry) = year(now)
Where currentContact is the contact that is showing on the form now.
I tried putting the query in the dailyCount dataSource, but It's not working. When I click on the three dots on datasource to access the wizard, I get a window to build functions and not queries.
How do I get the currentContact showing on the form into the query?
There are multiple ways to do this. For a couple of reasons, I don't like to hardcode queries in the datasource of a specific field, and I mostly build/assign all my queries in VBA. So here's how I would do it.
In the load event of you form :
Private Sub Form_Load()
Dim SQL As String
Dim RST As Recordset
dim theCOntact as string ' Change accordingly
theCOntact = Me.currentContact ' I don't know how your fields are named, so change accordingly
SQL = "SELECT count(*) AS cnt FROM tbl WHERE contact = " & theContact & "' AND month(dateEntry) = month(now) AND day(dateEntry) = day(now) AND Year(dateEntry) = year(now)"
Set RST = CurrentDb.OpenRecordset(RST)
If RST.BOF Then
dailyCount.Value = RST!cnt
Else
dailyCount.Value = 0
End If
End Sub
Assuming your contact field is string, if its a number remove the quotes in the SQL
Probably the simplest approach is to use the DLookup function with an associated query:
Create and save a named query with your SQL code or equivalent. Let's call it "qryDailyCount". Note that it should be modified to look something like this (in particular, name the column and change the record reference to a GROUP BY for now):
SELECT count(*) as DailyCount
FROM tbl
WHERE month(dateEntry) = month(now)
AND day(dateEntry) = day(now)
AND year (dateEntry) = year(now)
GROUP BY contact
In the dailyCount textbox, set the Control Source to something like this:
=DLookUp("Count";"qryDailyCount";"contact = [contact]")
(Note that if the contact field is a text field, you must enclose it with single quotes.)

How to remove period in Middle Initial ms access

I have two table that 1 table need to find a match on the other table.
Say I have table1 and Masterfiles table. Table1 has a name field the same with Masterfiles.
But table1 name field has different value because it has only middle initial while Masterfiles has middle name.
Now I want to get the other field value from Masterfiles called "Gender", since table1 has no value on gender field.
The table look like this:
Table1 Masterfiles
Name Gender Name Gender
Smith, John E. Smith, John Estaw M
Canard, Donald R Canard, Donald Reever M
Since I have a lot of records in table1 that need to get the value of gender field I need to do it programmatically.
Currently I have the following code:
Dim db As Database
Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb
Set rs = db.OpenRecordset("Table1")
Do While Not rs.EOF
strSQL = "SELECT [Name], Gender FROM Masterfiles WHERE [Name] Like '%" & Me!txtName & "%'"
Set rs2 = db.OpenRecordset(strSQL)
If rs2.RecordCount > 0 Then
rs!Gender = rs2!Gender
End If
Loop
But this code will not get any result because some of the value of Name field in table1 has a period in the middle initial while other row has no period. Please refer to the sample data above. The middle initial of "Smith, John" has period while "Canard, Donald" has no period.
So how can I query Masterfiles and get the value of Gender field and put it in table1 gender field?
strSQL = "SELECT [Name], Gender FROM Masterfiles WHERE [Name] Like '%" & replace(Me!txtName,".","") & "%'"
You have the name in VB; it is best just to use VB to remove any . from the end of the name before searching:
Dim searchName as String
If Me!txtName.Substring(Me!txtName.Length - 1,1) = '.' Then
searchName = Me!txtName.Substring(0,Me!txtName.Length - 1)
Else
searchName = Me!txtName
End If
strSQL = "SELECT [Name] FROM Masterfiles WHERE [Name] Like '%" & searchName & "%'"
However, in the long term you should probably fix your design:
Give each person a numeric ID that is the same in all tables.
Split the name into first, middle, and last fields.
Use a single table to store all information that is unique to the person. Then link it to other tables using the ID.

MS access SELECT INTO in vba

I'm having some issues with some functionality of my application. There is a particular instance where I have an instance of a 'pending class' on a form for an administrator to review. The form is populated with students associated with this pending class. After their grades are finished, I have a button at the footer that will delete this class from my 'pending' table and add the grades to all of the students. This works.
However, I want to essentially copy this pending class, which just has the class name, date, and teacher to a completed class table before it's deleted from pending. Since no data about this class other than the primary key(class number) persists throughout this form, I can't populate the other fields(class name, date) of the row into my completed class table.
I am trying a "SELECT INTO" operation in VBA to get these values. It's going like this:
dim cname as String
dim classdate as Date
dim pid as integer
dim teacher as String
dim qry as String
pid = [Forms]![frmClasses]![txtID]
qry = "Select className INTO cname FROM tblPending WHERE tblPending.id = " & " ' " & pid & " ' " & ";"
db.execute qry
debug.print qry
debug.print cname
From here, I do the same operations for each other variable, build my INSERT query, and execute it. The problem is-- my select into's are not working. Debug.print shows that the local variables were never initialized from the SELECT INTO statement. Any thoughts?
First, having all classes in one table and just setting a "NotPending" or "Completed" column would be better.
Having two identical tables for classes and moving values from one into the other to indicate status changes is bad database design.
If you really need to do this by using two tables and copying rows, then you need an INSERT INTO query (and not SELECT INTO), as already mentioned by Remou in the comments, because SELECT INTO creates a new table (or overwrites an existing one with the same name, if already there).
The syntax for INSERT INTO looks like this:
INSERT INTO CompletedClassTable (ClassName, Teacher)
SELECT ClassName, Teacher FROM tblPending WHERE id = 123
And finally, you asked this in a comment:
So SELECT INTO is completely different in Access than Oracle? In Oracle and PL/SQL, you can select a row into a variable OR a table. In Access can you not select into a variable?
To load a row into a variable, you need to use a Recordset.
Example code to load your query into a Recordset and output the ClassName field:
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset("SELECT * FROM tblPending WHERE id = 123")
If Not RS.EOF Then
Debug.Print RS("classname")
End If
RS.Close
Set RS = Nothing
Seems you want to retrieve a text value, className, from tblPending where tblPending.id matches the value found in your text box, txtID, and store that text value in a string variable named cname.
If that interpretation is correct, you needn't bother with a query and recordset. Just use the DLookup Function to retrieve the value, similar to this untested code sample.
Dim cname As String
Dim pid As Integer
Dim strCriteria As String
pid = [Forms]![frmClasses]![txtID]
strCriteria = "id = " & pid
cname = Nz(DLookup("className", "tblPending", strCriteria), vbNullString)
Debug.Print "cname: '" & cname & "'"
Notes:
I assumed the data type of the id field in tblPending is numeric. If it is actually text data type, change strCriteria like this:
strCriteria = "id = '" & pid & "'"
DLookup() returns Null if no match found. Since we are assigning the function's return value to a string variable, I used Nz() to convert Null to an empty string. Alternatively, you could declare cname As Variant (so that it can accept a Null value) and get rid of Nz().