First off I am a bit of a novice when its comes to VBA, so everything I do is a bit of hit and miss but normally I eventually figure out the problem.
However this time I have been stuck for days and can't seem to find the issue!
I have the following form and subforms with the below structure. (Access2013)
Main Form [Job Number]
Subform [Out2] (this is where a user scans a barcode into the relevant field)
Subform [DS] (this is where the scanned barcode from [Out2] creates a new record)
Subform [DS] fields : Id, Job No, BarCode, Description, Date, User
What I am trying to achieve with the code below, is in 'The Before Update' event of the [DS] BarCode field, the Dcount function will check the list of Barcodes already entered in the subform container [DS], and if there
is more than one it will undo the duplicate entry. Unfortunately nothing is happening when a duplicate entry is entered.
(not even errors)
P.S. Setting the table (No Duplicates) thing will not work for this DB.
Private Sub BarCode_BeforeUpdate(Cancel As Integer)
Dim BarCode As String
Dim strLinkCriteria As String
Dim rsc As DAO.Recordset
Set rsc = Me.RecordsetClone
BarCode = Me.BarCode.Text
strLinkCriteria = "[Barcode]=" & "'" & Replace(Me![BarCode], "'", "''")
'Check Items Subform for duplicate BarCode
If DCount("BarCode", "Forms![Job Number]![DS]", strLinkCriteria) > 0 Then
'Undo duplicate entry
Me.Undo
'Message box warning of duplication
MsgBox "Warning Item Title " _
& BarCode & " has already been entered." _
& vbCr & vbCr & "You will now been taken to the record.", _
vbInformation, "Duplicate Information"
'Go to record of original Title
rsc.FindFirst strLinkCriteria
Me.Bookmark = rsc.Bookmark
End If
Set rsc = Nothing
End Sub
Here is how to handle this:
Private Sub BarCode_BeforeUpdate(Cancel As Integer)
Dim rsc As DAO.Recordset
Dim BarCode As String
Dim Criteria As String
Set rsc = Me.RecordsetClone
BarCode = Nz(Me!BarCode.Value)
Criteria = "[Barcode] = '" & Replace(BarCode, "'", "''") & "'")
rsc.FindFirst Criteria
Cancel = Not rsc.NoMatch
If Cancel = True Then
' Message box warning of duplication
MsgBox "Warning Item Title " _
& BarCode & " has already been entered." _
& vbCrLf & vbCrLf & "You will now been taken to the record.", _
vbInformation, "Duplicate Information"
' Go to record of original Title
Me.Bookmark = rsc.Bookmark
End If
Set rsc = Nothing
End Sub
Related
I'm trying to create a search box that acts like the navigation search function at the bottom of the page in access. This is so the users of my data base have an easier time navigating the database.
My code currently is
Private Sub cmdSearch_Click()
Dim bkmk As Variant
Dim strField As String
Me.RecordsetClone.MoveFirst
'Find the first record that matches what
'is in the search text box.
Me.RecordsetClone.FindFirst "B3 Like " _
& Chr(34) & Me.txtsearch & "*" & Chr(34) _
& "OR Item Like" _
& Chr(34) & Me.txtsearch & "*" & Chr(34) _
If Me.RecordsetClone.NoMatch Then
MsgBox "No Match"
Else
bkmk = Me.RecordsetClone.Bookmark
Me.Recordset.Bookmark = bkmk
End If
End Sub
When I apply this code to my search function even when I'm testing with an item that is known to be in the database it is returning the "No Match" message box. My end goal is to have a search function that will search multiple fields in the back end table.
I got a table called "dbInventory" with "ID, InvName, InvQuantity, InvType" and a entry form matching these columns.
What I'm trying to achieve is to have the listbox start displaying search results based on the input.
(My ID column contains barcodes, not autonumbers)
So for instance, if I scan a barcode for an item I already put in the table some other time, I would like it to appear on the listbox right away.
How would one go about that?
It seems like you are wanting to deal with two different methods of entry - either by scanning a barcode (which would give you the entire barcode) or by the user typing the barcode in.
I would suggest using two controls in tandem - a text box, where the user can either scan a bar code or else type in the start of the barcode (and delete typed in data), and then a list box where matches are displayed.
You can use the text box's Change event to get the .Text property and use that as the basis of the list box's RowSource:
Private Sub txtSearch_Change()
On Error GoTo E_Handle
If Not (IsNull(Me!txtSearch.Text)) Then
Me!lstInventory.RowSource = "SELECT ID, InvName, InvQuantity, InvType FROM dbInventory WHERE ID LIKE '" & Me!txtSearch.Text & "*' ORDER BY ID ASC;"
Else
Me!lstInventory.RowSource = "SELECT ID, InvName, InvQuantity, InvType FROM dbInventory ORDER BY ID ASC;"
End If
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "frmInventory!txtSearch_Change", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
I'm not sure whether scanning a barcode into the text box will trigger the OnChange event - it should do!!
If you are now using 2 different controls to search (part matching on ID and Name) then you should use a small procedure that creates the RowSource of the ListBox as needed, and then call it from the OnChange event of either text box. Something like the code below should get you started:
Private Sub txtSearchID_Change()
Call sSearchForInventory(Nz(Me!txtSearchID.Text, ""), Nz(Me!txtSearchName.Value, ""))
End Sub
Private Sub txtSearchName_Change()
Call sSearchForInventory(Nz(Me!txtSearchID.Value, ""), Nz(Me!txtSearchName.Text, ""))
End Sub
Sub sSearchForInventory(strID As String, strName As String)
On Error GoTo E_Handle
Dim strSQL As String
If Len(strID) > 0 Then
strSQL = " AND ID LIKE '" & strID & "*' "
End If
If Len(strName) > 0 Then
strSQL = strSQL & " AND InvName LIKE '" & strName & "*' "
End If
If Left(strSQL, 4) = " AND" Then
strSQL = "WHERE " & Mid(strSQL, 6)
End If
Me!lstInventory.RowSource = "SELECT ID, InvName, InvQuantity, InvType FROM dbInventory " & strSQL & " ORDER BY ID ASC;"
Me!lstInventory.Requery
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "sSearchForInventory", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Notice that you need to use the .Text property of the control that is being changed, but the .Value property of the other control.
Regards,
Looking for a way to click on a record in a form and then have it go to another record in the same form.
Example: There's a form that lists Products and associated records along with that product. One of the records is a "Replaced" field. Which will show what past Products it replaced.
I want to be able to click in the Replaced field and have it go to that Product record.
txtProduct: Iphone6
txtReplaced: Iphone5 (click on Iphone5) -> and then shows
txtProduct: Iphone5
txtReplaced: Iphone4
I looked into GoToRecord and FindRecord. Thinking the best way to go about it is to put vba code into the On Click event procedure using one of those for txtReplaced. Just not sure how to do that
EDIT to include attempt using RecordsetClone. It's now giving me the error that it can't find the record when I know it's there. Any insight on what I'm doing wrong?
Private Sub txtSupersedes_DblClick(Cancel As Integer)
Dim rs As Object
Set rs = Me.RecordsetClone
rs.FindFirst "[Model]='" & Me.txtSupersedes.Value & "'"
If rs.NoMatch Then
MsgBox "Sorry, could not find Model '" & txtSupersedes & "' ", vbOKOnly, vbInformation
Else
Me.Bookmark = rs.Bookmark
End If
rs.Close
End Sub
Private Sub txtSupersedes_DblClick(Cancel As Integer)
Dim rs As Object
Dim txtValue As String
txtValue = Me![txtSupersedes].Value
With Me.Parent.Form
Set rs = .RecordsetClone
rs.FindFirst "[Model]= '" & txtValue & "'"
If rs.NoMatch Then
MsgBox "Sorry, could not find Model '" & txtSupersedes & "' ", vbOKOnly, vbInformation
Else
.Bookmark = rs.Bookmark
End If
rs.Close
End With
End Sub
I need a small help dear people. I have a form where I have listbox and with selecting listbox I populate some fields and subform in the form.
What I`m trying to achieve is that the subform should not be with 0 records.
So I have a control where is checking if the recordset is 0 and is pop up a message but exit sub is not helping and user can stil get to the next record.
Private Sub lstRev_BeforeUpdate(Cancel As Integer)
Dim DataConn10 As New ADODB.Recordset
Dim Comm10 As String
Set Conn = CurrentProject.Connection
Comm10 = " SELECT tblLIVE.SID " & _
" FROM tblLIVE " & _
" WHERE tblLIVE.CID = " & Me.txtCID & " And tblLIVE.PID =
" & Me.txtPIDRev & " And tblLIVE.MNumber = '" & Me.txtSMNum & "'"
DataConn10.Open Comm10, Conn, adOpenKeyset, adLockOptimistic
If DataConn10.RecordCount = 0 And Not IsNull(Me.txtMIDRev) Then
Dim x As Integer
x = MsgBox("Are sure that you want to leave the form without adding Line in subform. If you press yes Rev will be deleted. If you press No please enter Line", vbYesNo)
If x = vbYes Then
MsgBox "Delete"
Else
MsgBox "EnterSOV"
'Here I need something to tell him to stay in the same record :(
DataConn10.Close
Exit Sub
End If
End If
End Sub
You can add Cancel=True to prevent the before update method from finishing. Just add this before your Exit Sub.
I have been hammering out the issues of this form for about a week now and have almost come to a solution, but I have hit a brick wall. I have a large form with multiple functions, one of the functions is to edit a subform that houses a list of codes and other various pieces of data. When I click the edit button it auto fills the boxes with the selected data. The function works when I click the update button but when I click the save button it does not actually save the data. The code is:
Private Sub cmdEdit_Click()
'check whether there exists data in list
If Not (Me.TableSub.Form.Recordset.EOF And Me.TableSub.Form.Recordset.BOF) Then
'Get data to text box control
With Me.TableSub.Form.Recordset
Me.text_key = .Fields("KW")
Me.txt_code = .Fields("Code")
Me.combo_source = .Fields("Source")
'Store id of student in tag of text id in case id is modified
Me.txt_code.Tag = .Fields("Code")
'Change caption of button add to Update
Me.cmdAdd.Caption = "Update"
'disable button edit
Me.cmdEdit.Enabled = False
End With
End If
End Sub
This is the code for the save or Add button.
Private Sub cmdAdd_Click()
'when we click on button Add there are two options
'1. For insert
'2. For Update
If Me.txt_code.Tag & "" = "" Then
'this is for insert new
'add data to table
CurrentDb.Execute "INSERT INTO KWTable(KW, Source, Code) " & _
" VALUES('" & Me.text_key & "','" & Me.combo_source & "','" & _
Me.txt_code & "')"
Else
'otherwise (Tag of txtID store the id of student to be modified)
CurrentDb.Execute "UPDATE KWTable " & _
" SET KW='" & Me.text_key & "'" & _
", Code='" & Me.txt_code & "'" & _
", Source='" & Me.combo_source & "'" & _
" WHERE KW='" & Me.text_key & "'"
End If
'clear form
cmdClear_Click
'refresh data in list on form
TableSub.Form.Requery
End Sub
You're only copying values to the fields. They're not bound to the subform's recordset in any way. So, to save them, just reverse the process:
With Me.TableSub.Form.Recordset
.Edit
.Fields("KW") = Me.text_key
.Fields("Code") = Me.txt_code
.Fields("Source") = Me.combo_source
.Fields("Code") = Me.txt_code.Tag
.Update
End With
It sounds to me like you are looking at forcing the current bound form's data to save.
If Me.Dirty Then Me.Dirty = False
This statement essentially says "If there is unsaved data on this form/report - save it"
You can also reference your subform
If subform.Form.Dirty Then subform.Form.Dirty = False
It will do the same thing as Fabio's suggestion but I find it a bit more reliable with bound forms than the recordset approach.