Form event procedure not moving to last record - vba

I am experiencing some odd behavior from a form I am creating in an access database. I have a form called frmSeedling with a subform called frmSeedling detail. frmSeedling gets launched by an event procedure from a command button on a separate form called frmTransect. The OpenArgs passes the primary key of frmTransect called Transect_OID to frmSeedling. Transect_OID is the link field between frmSeedling and frmSeedlingDetail. I have a Form_Current event procedure in frmSeedling to count the number of unique entries on frmSeedling, and create a custom unique id called Seedling_OID. The tables that are the record source for these forms are linked ODBC tables. Below is the code:
Private Sub Form_Current()
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
If Not (rs.EOF) Then
rs.MoveLast
End If
Set rs = Nothing
If IsNull(Seedling_OID) Then
Entry_No = Nz(DCount("Seedling_OID", "rd_Seedling", "Transect_OID = '" & Me.Transect_OID & "'"), 0) + 1
Seedling_OID = Transect_OID & "SD" & Entry_No
End If
End Sub
However, when I launch frmSeedling from frmTransect, I get an error saying I am trying to overwrite the primary key. When I look at the form, this is happening because somehow Access is try to create a new record at the beginning of the form instead of the end of the form, thus thinking that the unique Id I have: created has already been used. Here is a screenshot to show what I mean:
What is curious is that with a separate form called frmDWD with subform frmDWDdetail, I have used this exact setup and it worked fine. Here is the code from frmDWDdetail:
Private Sub Form_Current()
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
If Not (rs.EOF) Then
rs.MoveLast
End If
Set rs = Nothing
If IsNull(DWD_OID) Then
DWD_Piece = Nz(DCount("DWD_OID", "rd_DWD", "Transect_OID = '" & Me.Transect_OID & "'"), 0) + 1
DWD_OID = Transect_OID & "W" & DWD_Piece
End If
End Sub
And here is what that looks like:
Notice how in frmDWD, the record being edited is the last record in the form, while in frmSeedling it is trying to edit the first record in the form. I have set all of the data properties exactly the same in both form and subform, and at least to my eye the code looks identical. Any SQL reasons why I am getting this behavior? Any ideas for fixes? Thanks!!

After hours of playing "Which-of-these-things-is-not-like-the-other" I discovered that the issue was in the property sheet of the subform. I switched "Filter on Empty Master" from "Yes" to "No" and that solved my issue.

You are not using the recordset for anything, so try this reduced code:
Private Sub Form_Current()
Dim Entry_No As Long
If IsNull(Me!Seedling_OID.Value) Then
Entry_No = Nz(DCount("*", "rd_Seedling", "Transect_OID = '" & Me!Transect_OID.Value & "'"), 0) + 1
Me!Seedling_OID.Value = Me!Transect_OID.Value & "SD" & Entry_No
End If
End Sub

Related

prevent duplicates when passing values between two forms (with Args)

I have two forms: transfert Form with its subform and intransfert Form. I am using
DoCmd.OpenForm "intransfert", , , , acFormAdd, acDialog, Me!Text83
(where text83 is =[transfertasubform].[Form]![transfertadetailid] under
Private Sub Command78_Click()
in transfet form and
Private Sub Form_Load()
On Error Resume Next
If Me.NewRecord Then Me!trnrin = Me.OpenArgs
in intransfet form. intransfert form is based in transfertdetailquery. i wont to prevent passing text83 value more then one time
i tried to explain my problem and expect a help to prevent duplicates when used Arge
assuming trnrin is the name of a variable in your record source. assuming you mean that you want to avoid adding two records where trnrin has the same value and the user sent the same open args twice. assuming trnrin is also the name of a control in the detail section of the intransfert form.
'form load only runs when the form is opened so you have to close the form to pass new args
'but you can just move the same code to a button or whatever
Private Sub IntransferForm_Load()
If Len(Me.OpenArgs) > 0 Then
Me.txtBoxintheHeader = Me.OpenArgs 'the load event is the right place to set controls
'most of this code is to check if there is already an instance where trnrin = the OpenArgs in the record source
Dim lookedupArgs As String
lookedupArgs = Nz(lookedupArgs = DLookup("trnrin", "MyTable", "trnrin = " & "'" & Me.OpenArgs & "'"), "ValuethatisneveranArg")
If lookedupArgs = "ValuethatisneveranArg" Then
'Debug.Print "trnrin = '" & Me.OpenArgs & "'" 'note the string delimiters
'Me.trnrin = Me.OpenArgs 'this surprisingly works but will break easily and doesn't handle complex cases
Dim rs As Recordset
Set rs = Me.Recordset 'if recordset is bound to a table then table will also be updated.
'you can also bind to the table directly but you may need to call me.requery to show the changes
rs.AddNew
rs!trnrin = Me.OpenArgs
rs.Update
End If
End If
End Sub

Access VBA - AfterUpdate() Recordset edit leads to "No current Record 3021" even if Record exists

I have an issue where I was not able to find a solution by tinkering and searching similiar problems already solved on the web.
First:
Im'using a form to enter a component ID (CID). After entering the Number in the Field I'm making use of the AfterUpdate() function to use the CID to look up a corresponding Prod ID in another Table. The Matching Prod ID from the other Table will then be entered automaticaly into the field. The field is a multivalued Field.
Here is the code:
Private Sub Form_AfterUpdate()
Dim rst As DAO.Recordset
Dim rstChld As DAO.Recordset2
Dim tmpVar
If Me.Dirty Then
Me.Dirty = False
End If
If StrComp(Me.Part, "Device") = 0 Then
tmpVar = DLookup("[Device Prod]", "subLookTblCIDDevice", "[CID Device] = '" & Me.CIDDevice & "'")
Set rst = Me.Recordset
If Me.Recordset.RecordCount = 0 Then
rst.MoveFirst
End If
If Not (rst.BOF And rst.EOF) Then
If rst.Updatable Then
rst.Edit
Set rstChld = rst!Prod.Value
rstChld.AddNew
rstChld.Fields(0) = tmpVar
rstChld.Update
rst.Update
Me.Bookmark = rst.LastModified
Set rst = Nothing
Set rstChld = Nothing
End If
End If
End If
End Sub
If the record exists and im Changing the CID - Everything is working fine the corresponding field gets its correct coresponding ID.
But if it is a new Record and the first of the recordset I got the error message
No Current Record - 3021
It can be mitigated by adding
If Me.Recordset.RecordCount = 0 Then
rst.MoveFirst
End If
But if its a new Record and not the first record it changes the previous record.
I have tried to use .AddNew instead of .Edit. This will create a new record after the one which has been updated.
I would be really glad if someone could have a look at it. I dont understand whats going on. why it is jumping before or after the record.
Thx and Cheers

Access add Record issue with autonumber

I'm having an issue with my code generating an autonumber for my UserID field.
I am trying to generate my UserID through VBA since Access's autonumber doesn't actually go sequentially.
For some reason my code will not fill in the Autonumber but instead UserID always ends up as 0 which is the default value. Not sure what I'm missing.
Any help would be greatly appreciated!!
Private Sub RegistrationBtn_Click()
Dim db As Database
Dim rst As DAO.Recordset
Dim strMember As String
strMember = "" & Me!CallSign
Autonumber = Nz(DMax("[UserID]", "[Memberstbl]"), 0) + 1
If Len(strMember) = 0 Then Exit Sub
Set db = CurrentDb
Set rst = db.OpenRecordset("Memberstbl", dbOpenDynaset)
With rst
.FindFirst "CallSign = '" & strMember & "'"
If .NoMatch Then
.AddNew
!UserID = Autonumber
!CallSign = strMember
MsgBox "Welcome to the UNCC"
DoCmd.OpenForm "Logonfrm"
DoCmd.Close acForm, "Registration"
Else
MsgBox "That Call Sign is already in use!"
End If
.Close
End With
Set rst = Nothing
Set db = Nothing
End Sub
I think that the problem that you are having is that you don't finish the adding of the record using .Update. Try:
If .NoMatch Then
.AddNew
!UserID = Autonumber
!CallSign = strMember
.Update 'Needed to "commit" the adding of the new record
Ok, lets back the truck up here a bit.
User enters a call sign.
Check if call sign exists - if yes, then don't proceed.
If call sign does not exist, generate new number AND ALSO NEW record.
Then launch form to the NEW record for additonal information to fill out.
In other words, we can't, and don't launch the 2nd form in "add mode", else you get two records (that explains your other issue - two records). So we can't and don't want to launch the 2nd form to a new record, since we ARE going to assume we created that record already, right??
so, first bit of code - check for existing call sign - lets do that 100% separate and not attempt to combine that operation if we have a green light to add the call sign record (along with a new generated number).
So, first bit of code should look like this:
Dim strTable As String
Dim strMember As String
strTable = "Memberstbl"
If Nz(Me.CallSign, "") = "" Then
MsgBox "Please enter a call sign", vbCritical, "Enter Call sign"
Exit Sub
End If
' get here, user entered a call sign.
' check if exists.
Dim strWhere As String
strWhere = "CallSign = '" & Me.CallSign & "'"
If Nz(DLookup("CallSign", strTable, strWhere), "") <> "" Then
MsgBox "That call sign is already in use, try another", vbInformation, "In use"
Exit Sub
End If
' if we reach here, then user entered a call sign, and it not in use.
' create new reocrd, new UserID, and then launch form to this record.
Dim NewUserID As Long
NewUserID = Nz(DMax("UserID", strTable), 0) + 1
Dim rstMember As DAO.Recordset
Set rstMember = CurrentDb.OpenRecordset(strTable)
With rstMember
.AddNew
!UserId = NewUserID
!CalSign = Me.CallSign
.Update
.Close
End With
' now launch form to this new record
DoCmd.OpenForm "Logonfrm", , , "UserID = " & NewUserID
DoCmd.Close acForm, Me.Name
Do make sure that Logonfrm is set with data entry = "no".
(if you set yes, then the form can ONLY add records - but we already did that in code).
see June 7th's comments but if you want to continue try these things. Make sure UserID is not still an autonumber and make sure that UserID has the same datatype as the foreign key. I've seen both those cases. Then make sure UserID is still the primary key for the UsersTable. At that point you can set up relationships but there are issues with cascading updates. My copy of Access 2016 refused to cascade updates but would allow cascading deletes. I can't see any problems with this except for the error message as access already makes changing primary keys difficult. see here: https://support.microsoft.com/en-us/office/guide-to-table-relationships-30446197-4fbe-457b-b992-2f6fb812b58f#:~:text=When%20you%20enforce%20referential%20integrity,that%20reference%20the%20primary%20key.

How to stop records from being overwritten on close

When I close the form, the current record overwrites the first record in the table. If I include "Me.Undo" just before closing the form then the data on the form is changed but not in the underlying table. How can I stop both of these from happening?
Private Sub Form_Load()
Dim strSelect As String
strSelect = "SELECT * FROM tblData ORDER BY tblData.txtName;"
Set dbs = CurrentDb()
Set rst = dbs.OpenRecordset(strSelect, dbOpenDynaset)
rst.MoveFirst
Me.txtName = rst!txtName
Private Sub btnClose_Click()
'Me.Undo
MsgBox " "
DoCmd.Close acForm, "frmdata", acSaveNo
I would like to form to just close without displaying another record and without overwriting another record in the table.
It is quite possible that your Form has it's DataSource property set to 'tblData'.
So after you Form loads, the Form_Load() event fires, and you modify the first Record of the Table that is set in the Form's DataSource property.
This is the line that modify's the Form data: Me.txtName = rst!txtName

MS Access vba save button error 3021

For various reasons, I want to set up a custom button on my forms to save the current record. I use a navigation form and want to trigger the same process (integrity-checks, user input etc.) whenever the entry is saved, thus whenever the user presses the "save"-button or switches to another form. The user will conditionally be asked to confirm the process and is thus able to cancel it as well.
Everything is running smoothly with one really odd and annoying exception: Whenever I click the save button on a new record and prompt a message within the "BeforeUpdate" event, I receive
RTE 3021 ("no current record")
Without the MsgBox, everything is fine. Even more strange:
When I trigger the save process by switching to another form using the navigation form (or simply press "outside" the form used for data entry), everything is fine as well.
Here is a minimalistic example (similar results with DoCmd.Save, Requery or acCmdSaveRecord):
Private Sub vt_save_Click()
Me.Dirty = False
End Sub
Private Form_BeforeUpdate(Cancel As Integer)
Cancel = True
MsgBox "Test"
End Sub
Any ideas? I simply can't wrap my head around that error.
You could maybe try to run a query using the values in the form while checking if the record exists or not.
Is there a primary key on the table? if so, the primary key will be your focal point.
Private Sub vt_Save_Click()
dim rst as DAO>Recordset
Dim strSQL as String
Dim strID as string
strID = me.YourPrimaryKeyField
strSQL = "SELECT * " & _
"FROM YourTableName " & _
"WHERE (((YourTableName.YourFieldName) =" & me.PrimaryKeyField & "));"
set rst = currentdb.openrecordset(strsql)
if rst.recordcount = 0 then
currentdb.execute "INSERT INTO YourTableName ( List All Fields to Add ) " & _
"SELECT List All Field controls with values to add;"
End IF
'Anything else you want the code to do from here
EndCode:
If not rst is nothing then
rst.close
set rst = nothing
End IF
End Sub
Repeat this process for the Form_LostFocus() event. If you want to make it easier, make this code a module and call within both event triggers on your form.
If this doesn't work please let me know and I will be happy to further assist.
The most straight forward and reasonable solution is to use an Error Handler - which I ignored so far tenaciously.
Private Sub save_Click()
On Error GoTo Err_Handler
Me.Dirty = False
Exit_Here:
Exit Sub
Err_Handler:
If Err.Number = 2101 Then
'ignore or message
Else
MsgBox Err.Description
End If
Resume Exit_Here
End Sub