(Access VBA touchup) Auto Populating after update based on another textbox - vba

Hello I'm trying my best to piece together a code to have all text boxes on the form update to existing records.
All the textboxes are updating beside
Me.txtSftLvl = myrs!SafteyStockLvl
I am left with the error
Item Cannot Be Found In The Collection (3265)
I have double checked my naming on the table and textbox itself and they are fine...
Hoping someone would know what im doing wrong or a simpler way of accomplishing my goals.
Private Sub txtRcStock_AfterUpdate()
Dim qrystr1 As String
Dim mydb As Database
Dim myrs As DAO.Recordset
DoCmd.OpenQuery "qryPartDesc"
If Me.txtRcStock <> "" Then
Set mydb = CurrentDb
qrystr1 = "SELECT Desc FROM qryPartDesc WHERE [PartNumber] = '" & Me.txtRcStock & "'"
Set myrs = mydb.OpenRecordset(qrystr1)
If myrs.EOF = False Then
Me.txtRcCat = myrs!Desc
End If
qrystr1 = "SELECT Price FROM tblRecLog WHERE [PartNumber] = '" & Me.txtRcStock & "'"
Set myrs = mydb.OpenRecordset(qrystr1)
If myrs.EOF = False Then
Me.txtPrice = myrs!Price
If myrs.EOF = False Then
Me.txtSftLvl = myrs!SafteyStockLvl
End If
End Sub
Anything helps.

Related

Update a record Field from an unbound text box on a form in ms access 2016

I have a form called [ADD_Individual_Info] that pops up when a user scans in with their ID Card and the barcode isn't in the database. However I have learned that some have just gotten new cards and the new barcode number isn't stored in the database. I have a text box [txt_copyEmail] on the form [ADD_Individual_Info] that allows the user to search their email address to find their record in the database. This is so they don't have to retype their info in again. On the same form I another text box [txt_EDIPI] with the newly scanned barcode number. I want to just update the record on my table with the new number from text box [txt_EDIPI]. The Form [ADD_Individual_Info] has a sub form [SubIndividualInfo] on it and its Source [sfrm_User_Item_Info] and its record source is [qry_User_Item_Info] this only displays the users email address and their name. I have on after update event on text box [txt_copyEmail]. That looks like this:
Private Sub txt_copyemail_AfterUpdate()
Call search_email
Me.txt_UserEmail.Value = Me.SubIndividualInfo.Form.[UserEmail]
Me.txt_UserName.Value = Me.SubIndividualInfo.Form.[UserName]
Me.txt_Office.Value = Me.SubIndividualInfo.Form.[Office]
Me.txt_Rank_Title.Value = Me.SubIndividualInfo.Form.[Rank_Title]
Me.txt_PhoneNumber.Value = Me.SubIndividualInfo.Form.[PhoneNumber]
Me.txt_IndividualID.Value = Me.SubIndividualInfo.Form.[EDIPI]
End Sub
my function code:
Function search_email()
Dim SQL As String
SQL = "SELECT tbl_User_Info.UserName, tbl_User_Info.[UserEmail]," _
& "tbl_User_Info.[Office]," _
& "tbl_User_Info.[Rank_Title]," _
& "tbl_User_Info.[EDIPI]," _
& "tbl_User_Info.PhoneNumber FROM tbl_User_Info " _
& "Where [UserEmail] LIKE '*" & Me.txt_copyemail & "*' "
Me.SubIndividualInfo.Form.RecordSource = SQL
Me.SubIndividualInfo.Form.Requery
End Function
This is so the user can verify the info is still accurate and if so they just click a button [btn_SaveandClose]. its code looks like this:
Private Sub Btn_SaveandClose_Click()
Dim db As Database
Dim rec As Recordset
Set db = CurrentDb
Set rec = db.OpenRecordset("Select * from tbl_User_Info")
rec.Edit
rec("UserEmail") = Me.UserEmail
rec("EDIPI") = Me.txt_EDIPI
rec("UserName") = Me.UserName
rec("Office") = Me.Office
rec("Rank_Title") = Me.Rank_Title
rec("PhoneNumber") = Me.PhoneNumber
rec.Update
rec.Close
Set rec = Nothing
Set db = Nothing
Me.txt_UserEmail.Value = ""
Me.txt_UserName.Value = ""
Me.txt_Office.Value = ""
Me.txt_Rank_Title.Value = ""
Me.txt_PhoneNumber.Value = ""
Me.txt_IndividualID.Value = ""
Me.txt_EDIPI.Value = ""
Me.txt_copyemail.Value = ""
Call search_email
End Sub
It is not editing the record that is displayed on the form it just update the first record on the table it comes too with the new number in text box [txt_EDIPI]. any help with my code. Or if there is a better way to make this work I am open to a better way. thanks.
The code i used on my Save and Close Button. this was to add new or just update field. I give credit to User June7 for giving me the helpful hints.
If Me.chkAddNewInfo = True Then
Dim db As Database
Dim rec As Recordset
Set db = CurrentDb
Set rec = db.OpenRecordset("Select * from tbl_User_Info")
rec.AddNew
rec("UserEmail") = Me.txt_UserEmail
rec("EDIPI") = Me.txt_EDIPI
rec("UserName") = Me.txt_UserName
rec("Office") = Me.txt_Office
rec("Rank_Title") = Me.txt_Rank_Title
rec("PhoneNumber") = Me.txt_PhoneNumber
rec.Update
rec.Close
Set rec = Nothing
Set db = Nothing
Else
Me!SubIndividualInfo.Form.EDIPI.Value = Me.txt_EDIPI
DoCmd.RunCommand acCmdSaveRecord
End If
Open recordset with filter criteria that will return only 1 record:
Set rec = db.OpenRecordset("Select * from tbl_User_Info WHERE somefield=" & input)
Or don't open recordset and just run an UPDATE action SQL with criteria for the desired record, example showing text, date, number type fields:
CurrentDb.Execute "UPDATE tablename SET field1 = '" & Me.tbxName1 & "', field2 = #" & Me.tbxName2 & "#, field3 = " & Me.tbxName3 & " WHERE ID=" & input
Or don't do either and just edit record via form. If fields are included in form's RecordSource, simply:
Me!fieldname = "some input"

How to populate a ComboBox with query results

I had a problem populating a ComboBox from query results in access vba. My goal was to query for one column of a table and use every record from the result as an option for the combobox.
There are some things about the properties of ComboBoxes you need to be aware of and assign properly to make this work. Here's my code that seemed to hold the correct information but did not display anything in the dropdown list:
Dim RS As DAO.Recordset
Dim SQL As String
'Clean-up. not sure if it's needed but I'm "clearing" the old data (if there's any) before putting the new in
combox.RowSourceType = "Table/Query"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
combox.RowSource = SQL
This was part of another question I asked but for clearer structure I'm moving this question (and it's answer) to this thread.
Your first attempt is fine, you just need to requery the combo box to actually load in the results of the query.
Dim SQL As String
combox.RowSourceType = "Table/Query"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
combox.RowSource = SQL
combox.requery 'Clears old data, loads new data
After some refactoring and fixing I came to this result which makes the ComboBox behave as I intend:
combox.RowSourceType = "Value List"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
With combox
.RowSource = kombSQL
.ColumnCount = 2
.ColumnWidth = 1
.ColumnWidths = "1.5in."
End With
Set RS = CurrentDb.OpenRecordset(SQL)
RS.MoveLast
RS.MoveFirst
combox.RemoveItem 0
Do Until RS.EOF
Me.combox.AddItem RS.Fields("some_value")
RS.MoveNext
Loop
RS.Close
Set RS = Nothing
Me.combox.BoundColumn = 0
Me.combox.ListIndex = 0

SetFocus is getting ignored - Why?

I have 2 fields - txtTR1_Unit and cmbTR2_Unit. Together, these 2 fields represent the total UNIT.
cmbTR2_Unit has a list of unique values that when selected - txtTR1_Unit automatically gets the related value.
I've created a function called Tier1from2 - that accepts a 'string' and returns the related Tier1 value.
So when I update cmbTR2_Unit in my After_Update event, I'd like to automatically tab to the next field. - Another combo box. I figured that I shouldn't need to set any focus, because it would automatically go to the next field after updating.
txtTR1 gets updated just as expected from my Function, but then it just sits there and won't go to the next field. So I have attempted to 'SetFocus' to the next field after the update.
Still no go. What did I miss??
Private Sub cmbTR2_UNIT_AfterUpdate()
If Len(Me.cmbTR2_UNIT.Value) <> 0 Then
Me.txtTR1_UNIT.Value = Tier1From2(Me.cmbTR2_UNIT.Text)
'cmb_CostCenter.setfocus - 'this doesn't seem necessary - but it doesn't work anyway.
End If
End Sub
As a test I tried removing the function "Tier1From2(Me.cmbTR2_UNIT.text)" simply hard coding the word 'RESULT' in txtTR1_UNIT and it works without a hitch. I know I used to write a more simple function but I haven't touched VBA in awhile - How can I simplify this function:
Private Function Tier1From2(strTier2 As String) As String
Dim qdf As DAO.QueryDef
Dim db As DAO.Database
Dim strQry As String
Dim rs As Recordset
Set db = CurrentDb
Set qdf = db.QueryDefs("qUNIT_HUB")
strQry = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
qdf.SQL = strQry
db.QueryDefs.Refresh
Set rs = db.OpenRecordset(strQry)
Tier1From2 = rs![Tier1_Unit]
Set db = Nothing
Set qdf = Nothing
Set Recordset = Nothing
End Function
It turns out that something in this function was causing the field and form to loose focus. db.QueryDefs.refresh perhaps? The solution was to update my Function as follows
Private Function Tier1From2(strTier2 As String) As String
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
Dim strTier1 As String
Set db = CurrentDb
strSQL = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
strTier1 = rs!Tier1_Unit
Set rs = Nothing
Set db = Nothing
Tier1From2 = strTier1
End Function
This worked without a hitch.

How to set controlsource of a textbox from SQL

I have a subform bound to a SQL statement. Inside the subform, I have a few text boxes bound to the fields of this SQL. However, I have another text box that needs to be bound to a field from a different SQL statement with criteria from the first one. My code looks like below:
Dim subform As Object
Dim formFilter As String
formFilter = "SELECT * FROM my_table_1"
Set subform = Me!my_subform.Form
subform.RecordSource = formFilter
subform.field1.ControlSource = "tb1f1"
subform.field2.ControlSource = "tb1f2"
...
subform.f3.ControlSource = "= SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & [tb1f1] & "' AND tb2f2 = '" & [tb1f2] "' ORDER BY tb2f4"
I cannot use a DLOOKUP function here directly, because I need to sort the table result.
Thanks in advance for your help.
I think I would simply create a little function to go get the result you want. It would probably be best to simply rework DLookup in your own function and add sort but I won't do that here.
First the form code. Notice I am not setting the recordsource, just the value which may not be what you want.
subform.f3 = fGet_tb2f3([tb1f1], [tb1f2])
Then the function code (put in your own error handling)
Public Function fGet_tb2f3(tblf1 as String,tblf2 as String) as String
Dim rst as dao.recordset
Dim db as database
set db = currentdb
set rst = db.openrecordset("SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & tb1f1 & "' AND tb2f2 = '" & tb1f2 "' ORDER BY tb2f4",dbopensnapshot
if not rst is nothing then
if not rst.eof then fGet_tb2f3 = rst!tb2f3
rst.close
set rst = nothing
end if
db.close
set db = nothing
end Function
You can't bind controls on the same form to 2 different recordsets. The only thing you could do is pull data from 2 different recordsets, but that's probably not the best way to do anything.
In order to do that, you'd have to create a second recordset and grab that value in it. Something like:
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & [tb1f1] & "' AND tb2f2 = '" & [tb1f2] "' ORDER BY tb2f4")
Me.MyControlName = rec(0)

Table for priorities?

I am curious to know if there is a way to make a table based off priorities?
As in you have a form, subform (datasheet), and 2 buttons.
The subform takes data from a query which takes data from a table.
From here, the query shows projects. You can select the project on the subform and click a button to dec priority, which moves it DOWN on the list by 1 project. If you click the inc button, it moves it UP. If it's at the very bottom and you click the decrease button it will pop up saying "This project is already the lowest priority!" same with the increase, but it'll say it's already the highest.
Is this possible? I really don't know any VBA to access a subform's datasheet and modify it, and I'd like to learn.
UPDATE:
I have 1 table, with 5 priority types, and 1 key.
The table is named ProjectsT, the key is named ProjectID and the 5 priorities are:
CuttingPriority, ProjPriority, EngineerPriority, CutplanPriority, HardwarePriority. Each priority is listed as a number datatype.
This is one set of code I have so far for the buttons from an answer below:
Up button:
Dim strSQL As String
Dim intSavePos As Integer
Dim intSavePosMin As Integer
Dim intSavePosMax As Integer
'Save start and end value (It's assumed you start with 1 ! The value 0 (zero) is used for swapping value's)
intSavePosMin = DMin("CuttingPriority", "ProjectsT")
intSavePosMax = DMax("CuttingPriority", "ProjectsT")
'When the subform is linked to a keyfield use that field for a WHERE like:
'intSavePosMin = DMin("sequence", "tblTableNico5038", "Function='" & Me.sfrmFunctionTables.Form.Function & "'")
'intSavePosMax = DMax("sequence", "tblTableNico5038", "Function='" & Me.sfrmFunctionTables.Form.Function & "'")
intSavePos = Me.txtCuttingPriority
'is it the first ? ==> no action
If intSavePos = intSavePosMin Then Exit Sub
'switch positions
DoCmd.SetWarnings False
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = 0 WHERE CuttingPriority=" & intSavePos & ";"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = 0 WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=" & intSavePos & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos & " WHERE CuttingPriority=" & intSavePos - 1 & ";"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = " & intSavePos & " WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=" & intSavePos - 1 & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos - 1 & " WHERE CuttingPriority=0;"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = " & intSavePos - 1 & " WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=0;"
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
Me.Refresh
Me.ProjectsTCuttingSubF.SetFocus
SendKeys ("{up}")
Down button:
Dim strSQL As String
Dim intSavePos As Integer
Dim intSavePosMin As Integer
Dim intSavePosMax As Integer
intSavePosMin = DMin("CuttingPriority", "ProjectsT")
intSavePosMax = DMax("CuttingPriority", "ProjectsT")
intSavePos = Me.txtCuttingPriority
'is it the last ? ==> no action
If intSavePos = intSavePosMax Then Exit Sub
'switch positions
DoCmd.SetWarnings False
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = 0 WHERE CuttingPriority=" & intSavePos & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos & " WHERE CuttingPriority=" & intSavePos + 1 & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos + 1 & " WHERE CuttingPriority=0;"
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
Me.Refresh
Me.ProjectsTCuttingSubF.SetFocus
SendKeys ("{down}")
--
I was curious to see if I could come up with a solution that didn't resort to "SQL glue-up". The result is available for download here (Access 2010 or later).
The key components are a [Managers] table
ID ManagerName
-- --------------
1 Thompson, Gord
2 Elk, Anne
a [Projects] table
ID ManagerID Description Priority
-- --------- -------------------- --------
1 1 buy bacon 1
2 1 wash the car 2
3 1 clean out the garage 3
4 2 test1 1
5 2 test2 2
two saved parameter queries (QueryDefs) to locate the next highest/lowest-priority project
[GetHigherPriorityProject]
PARAMETERS prmManagerID Long, prmCurrentPriority Long;
SELECT TOP 1 Projects.ID, Projects.Priority
FROM Projects
WHERE (((Projects.Priority)<[prmCurrentPriority])
AND ((Projects.ManagerID)=[prmManagerID]))
ORDER BY Projects.Priority DESC , Projects.ID;
[GetLowerPriorityProject]
PARAMETERS prmManagerID Long, prmCurrentPriority Long;
SELECT TOP 1 Projects.ID, Projects.Priority
FROM Projects
WHERE (((Projects.Priority)>[prmCurrentPriority])
AND ((Projects.ManagerID)=[prmManagerID]))
ORDER BY Projects.Priority, Projects.ID;
one more saved parameter query to update the priority of a given project
[SetProjectPriority]
PARAMETERS prmNewPriority Long, prmID Long;
UPDATE Projects SET Projects.Priority = [prmNewPriority]
WHERE (((Projects.ID)=[prmID]));
a dead-simple Class just to hold a couple of Properties
[projectInfo]
Option Compare Database
Option Explicit
Private pID As Long, pPriority As Long
Public Property Get ID() As Long
ID = pID
End Property
Public Property Let ID(Value As Long)
pID = Value
End Property
Public Property Get Priority() As Long
Priority = pPriority
End Property
Public Property Let Priority(Value As Long)
pPriority = Value
End Property
a rudimentary form with a subform
and the code behind that form
Option Compare Database
Option Explicit
Private Sub cmdMoveDown_Click()
AdjustPriority "lower"
End Sub
Private Sub cmdMoveUp_Click()
AdjustPriority "higher"
End Sub
Private Sub AdjustPriority(Direction As String)
Dim cdb As DAO.Database, rst As DAO.Recordset, qdf As DAO.QueryDef
Dim currentProjectID As Long, otherProject As projectInfo
Set rst = Me.ProjectsSubform.Form.RecordsetClone
rst.Bookmark = Me.ProjectsSubform.Form.Recordset.Bookmark
currentProjectID = rst!ID
Set otherProject = GetOtherProject(rst!ManagerID, rst!Priority, Direction)
If otherProject.ID = 0 Then
MsgBox "There is no project with a " & Direction & " priority."
Else
Set cdb = CurrentDb
Set qdf = cdb.QueryDefs("SetProjectPriority")
' swap priorities
qdf!prmNewPriority = rst!Priority
qdf!prmID = otherProject.ID
qdf.Execute
qdf!prmNewPriority = otherProject.Priority
qdf!prmID = currentProjectID
qdf.Execute
Set qdf = Nothing
Set cdb = Nothing
Me.ProjectsSubform.Requery
' now restore the previous current record in the subform
Set rst = Me.ProjectsSubform.Form.RecordsetClone
rst.FindFirst "ID=" & currentProjectID
Me.ProjectsSubform.Form.Recordset.Bookmark = rst.Bookmark
End If
rst.Close
Set rst = Nothing
Set otherProject = Nothing
End Sub
Private Function GetOtherProject(prmManagerID As Long, _
prmCurrentPriority As Long, _
Direction As String) As projectInfo
Dim cdb As DAO.Database, qdf As DAO.QueryDef, rst As DAO.Recordset
Dim rtn As New projectInfo
Set cdb = CurrentDb
If Direction = "higher" Then
Set qdf = cdb.QueryDefs("GetHigherPriorityProject")
Else
Set qdf = cdb.QueryDefs("GetLowerPriorityProject")
End If
qdf!prmManagerID = prmManagerID
qdf!prmCurrentPriority = prmCurrentPriority
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
If rst.EOF Then
rtn.ID = 0
rtn.Priority = 0
Else
rtn.ID = rst!ID
rtn.Priority = rst!Priority
End If
rst.Close
Set rst = Nothing
Set qdf = Nothing
Set cdb = Nothing
Set GetOtherProject = rtn
Set rtn = Nothing
End Function
EDIT re: comment
is there a way to make it automatically add the next priority number on the list if you are adding a record through another form?
Yes. I forgot to mention that in the existing sample solution there is a Before Change Data Macro on the [Projects] table to do just that:
If [IsInsert] Then
If Not IsNull([ManagerID]) Then
SetField
Name Priority
Value = Nz(DMax("Priority", "Projects", "ManagerID=" & [ManagerID]), 0) + 1
End If
End If
Read through the ENTIRE conversation here:
re-order a records sequence using up and down buttons
You're going to need at aleast a mediocre understanding of VBA and how to apply your specific data to a pre-existing example. This person was looking to do almost precisely what your question describes, and the person who was working with him was an Access MVP. I say to read through the entire conversation because there were several iterations and tweaks performed over the course of the solution.
If you have any specific questions after integrating this solution, feel free to come back and ask.
I have a work ticket system in my work place and to create priorities I created two tables: Work_Tickets and Work_Ticket_Criteria. The criteria table has a list of low, low-medium, etc... and a field in Work_Tickets pulls from that 2nd table. Then sort by date.
It doesn't give a single ticket a numerical priority like you are looking for because to do that I believe you would have to create a separate field and then modify the numerical field of each record after every update. Switch 1 with 2, or make the new record 1 and then add 1 to each and every record's priority field to move them down the list.
Or if you start with a number like 1000 then you can make records more or less than 100 in increments of 5, 10, or 20 but then you'll eventually run out of numbers...
Update
If you're willing to go my method of adding another column, then I would just add column and name the field Priority_Numbers or something. Then you would mark each as 1 - whatever but you may want to make check to make sure your number doesn't already exist by making it a key or giving it a check.
Then each time you would want to view your tickets you would use something like:
Dim strSQL As String
Dim myR As Recordset
strSQL = "SELECT * FROM table_name WHERE criteria_here ORDER BY Priority_Numbers ASC"
Set myR = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
And bam you have your prioritized list.
Now to change the priority you would need to select that recordset, do a findfirst to get the record with the value you want replaced, +1 or -1 to each priority number in a While not EOF loop and keep moving next. This will become tedious if your tickets become too high I'm sure.