VBA Access - Checking recordset on subform load - ms-access

I have an On_Load() sub which checks the records present on a subform, record by record. For example, if the subform loads with 12 records on it, I need the sub to start with the first record, run a DCount (it checks if the job number appears on a different table), then move to the next record, and check that one, etc until it reaches the last record. Here's my code at the moment:
Set rst = Me.RecordsetClone
On Error Resume Next
rst.MoveFirst
'Put code to check keyword schedule here. First get job no
Do Until Me.Specific_Job_No.Value = "00"
strSpec = Format(Me.Specific_Job_No.Value, "00")
strJob = Left(Me.Parent.JobRef.Value, 18) + strSpec
'Then check if that job no is in slot 1, then 2, etc
If DCount("*", "tblKeywordsSchedule", "[Slot1] Like ""*" & strJob & "*""") > 0 Then
Me![Added to Schedule] = True
Me![Added to Schedule].Locked = True
Else
Me![Added to Schedule] = False
Me![Added to Schedule].Locked = False
End If
'Then go to next record
rst.MoveNext
Loop
My problem is, it gets stuck on rst.MoveNext and just keeps checking the first record over and over again. What am I doing wrong?

Your problem is that you cannot lock a field individually for each record.
So the [Added to Schedule] may change its locking during the loop but will keep the setting of the last record in the loop.

I have now sorted it out myself. Found TheSmileyCoder's answer on this page:
https://bytes.com/topic/access/answers/942501-looping-through-subform-records
I was referring to a form control (Me!) rather than the recordset clone to update the strSpec and strJob strings - that was all I needed to know.
If rst.RecordCount > 0 Then
With rst
rst.MoveFirst
Do While Not .EOF
strSpec = Format(rst![Specific Job No], "00")
strJob = Left(Me.Parent.JobRef.Value, 18) + strSpec
'Then check if that job no is in slot 1, then 2, etc
If DCount("*", "tblKeywordsSchedule", "[Slot1] Like ""*" & strJob & "*""") > 0 Then
.Edit
rst![Added to Schedule] = True
.Update
Else
.Edit
rst![Added to Schedule] = False
.Update
End If
.MoveNext
Loop
End With
End If

Related

Access 2013, Extract number from field to use in search

Have a sales proposal access database for work that has a field that you can put a earlier corresponding proposal number as a reference. If you click on a button under that field it will take you directly to that earlier record. There are times we have a prefix in front of the number A-12345, E-12345 or it might just be 12345.
I need to be able to grab just the number without the letter and - for the search to work correctly. Thanks
Here is the image of my screen
Assuming you have a table with columns Proposal and Reference and a single form with controls txtReference and txtProposal, put this code to the On_Click event of your form button (I'm using DAO):
Dim strProposal As String
Dim i As Integer
Dim rs As DAO.Recordset
If Len(Nz(Me.txtReference, "")) < 1 Then
MsgBox "No reference number entered"
Else
For i = 1 To Len(Me.txtReference)
If IsNumeric(Mid(Me.txtReference, i, 1)) Then
strProposal = strProposal & Mid(Me.txtReference, i, 1)
End If
Next
End If
Set rs = Me.RecordsetClone
rs.MoveFirst
rs.FindFirst "Proposal = '" & StrProposal & "'"
If rs.NoMatch Then
MsgBox "Original proposal not found"
Else
Me.Bookmark = rs.Bookmark
Me.txtProposal.SetFocus
End If
rs.Close
Set rs = Nothing

Find DAO Record

Is it possible to use DoCmd.GoToRecord or DoCmd.FindRecord in order to quickly find a record in a table, edit the record and get the focus on that record (I want to start looping from that record later)?
I believe such method (if applicable) would be faster than looping through the entire recordset (especially with a large recordset).
Assuming the Primary key is 9999 (Fields(0) = 9999), I have tried:
Dim rs as DAO.Recordset
Set rs = CurrentDb.OpenRecordset("Tbltest")
DoCmd.FindRecord "9999", acEntire, True, acSearchAll, True
Debug.Print rs.Fields(0)
I get "1"; the method failed.
With a DAO.Recordset, you use the rs.FindFirst and rs.FindNext methods.
Set rs = CurrentDb.OpenRecordset("Tbltest", dbOpenDynaset)
lngValue = 9999
rs.FindFirst "myPrimaryKey = " & lngValue
' start loop from there
If Not rs.NoMatch Then
Do While Not rs.EOF
Debug.Print rs(0)
rs.MoveNext
Loop
End If
If it's a local table, there is also the rs.Seek method, but if there is a chance that the table will some day be linked from a backend or server database, I suggest sticking with the Find methods.

Access VBA Loop (Not Responding)

I am looping through a recordset to carry out some basic functions or edits.
Usually with recordsets with more than 50 records, access will stop responding.
I have me.repaint before the loop command but the window always freezes and the access title bar shows: ...(Not Responding).
Any idea how to get around this?
Thanks.
Dave.
EDIT: Added Loop Code
If Me.Dirty = True Then Me.Dirty = False
Dim rs As DAO.Recordset
Set rs = Me.Guardians_Subform1.Form.Recordset
Dim strFirstName, strLastName As String
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do Until rs.EOF = True
rs.Edit
strFirstName = Trim(StrConv(rs!FirstName, 3))
strLastName = Trim(StrConv(rs!LastName, 3))
If rs!FirstName <> strFirstName Then
rs!FirstName = strFirstName
End If
If rs!LastName <> strLastName Then
rs!LastName = strLastName
End If
rs.Update
rs.MoveNext
Me.Repaint
Loop
Else
MsgBox "There are no records in the recordset."
End If
Set rs = Nothing
You need to call the DoEvents-Function within the loop to pass control to the operating system to redraw your Access-GUI and to process any other Window-Messages that might need processing. By that the application will not be marked as "Not responding" in the Task Manager and the Title Bar.
Do Until rs.EOF = True
[...]
rs.MoveNext
DoEvents
Loop
There is a small performance trade off. If not calling DoEvents, the total execution time for the loop will be a little shorter, but Access will do nothing else then process your loop. Therefore it seems to be not responding.
As others have pointed out you can use the DoEvents to release your processor to do other actions before continuing. When I use the DoEvents in a loop I use a counter.
Dim iCounter as Integer
Do Until
' some code here
iCounter=iCounter+1
If iCounter = 100 then
DoEvents
iCounter=0
End if
Loop
This keeps the DoEvents from firing too often and causing your overall code to slow. Adjust the counter to whatever iteration you find appropriate.
It is not the best approach to do such edits with a recordset loop. An UPDATE query is much more efficient.
e.g.
UPDATE tblGuardians
SET FirstName = Trim(StrConv(FirstName, 3))
WHERE StrComp(FirstName, Trim(StrConv(FirstName, 3)), 0) <> 0
and the same for LastName.
This uses StrComp instead of a simple <> comparison, because the latter is case-insensitive. The third parameter 0 = vbBinaryCompare.

VBA code to check the status field of all records

I just ran into a problem with my one part of my code. I have a command button that when it is pressed it determines what day of the week it is. On a certain day it is supposed to check the status field and for each record that is labeled "Needs Ordered" a query is run and is opened. This works fine unless the last record that was opened is marked different (OK or Ordered). I need it to run no matter how the last record opened was labeled.
VBA Code to change font and size in an email from access
If Weekday(Now()) = vbSunday Then
If Forms![Admin Box List].Status.Value = "Needs Ordered" Then
DoCmd.OpenForm "OrderForm"
End If
End If
Then just leave out that condition:
Dim rs As DAO.Recordset
If Weekday(Date) = vbSunday Then
Set rs = Me.RecordsetClone
rs.FindFirst "Status = '" & "Needs Ordered" & "'"
If rs.NoMatch = False Then
DoCmd.OpenForm "OrderForm"
End If
End If
Set rs = Nothing

How to fix "out of stack space" error?

I have code which takes a table, and rearranges the table to form a new table. It worked with a small amount of data, but now that I tried to run the same code with over 1,000 records, it is getting Error 28 which is "Out of stack space". I will not copy all of my code here because it would be way too much and I think unnecessary, unless you think otherwise. I think it is a problem with my recursion of the sub. I need this because a DONOR_CONTACT_ID can only have 4 recipients, if it has more, then it must create a new record with the same DONOR_CONTACT_ID and populate the recipients.
Here is the sub routine which is getting the error:
Sub NextDonor()
With rstOutput
.FindNext "[DONOR_CONTACT_ID] = " & strDonor2
'Find the next record in T_OUTPUT with that DONOR_CONTACT_ID
If .NoMatch Then
'If there are no more records with that DONOR_CONTACT_ID, add a new one
.AddNew
!DONOR_CONTACT_ID = strDonor1
!RECIPIENT_1 = strRecip1
!ORDER_NUMBER = strOrderNum1
.Update
Else
'A second DONOR_CONTACT_ID in T_OUTPUT exists. Check to see if all fields are filled.
If !DONOR_CONTACT_ID = strDonor2 Then
If IsNull(!RECIPIENT_2) And Not (IsNull(!RECIPIENT_1)) Then
'RECIPIENT_2 is empty, so populate it
.Edit
!RECIPIENT_2 = strRecip1
.Update
ElseIf IsNull(!RECIPIENT_3) And Not (IsNull(!RECIPIENT_2)) Then
'RECIPIENT_3 is empty, so populate it
.Edit
!RECIPIENT_3 = strRecip1
.Update
ElseIf IsNull(!RECIPIENT_4) And Not (IsNull(!RECIPIENT_3)) Then
'RECIPIENT_4 is empty, so populate it
.Edit
!RECIPIENT_4 = strRecip1
.Update
ElseIf Not IsNull(!RECIPIENT_4) Then
'RECIPIENT_4 is filled, so run this function again
Call NextDonor
End If
End If
End If
End With
End Sub
The error is in the line where it says "Call NextDonor", probably because of the recursion. If you need me to clarify what my code is trying to do, or if you want me to copy other parts of my code, just let me know.
Try this to avoid recursion ...
Sub NextDonor(byref Again as Boolean)
With rstOutput
DoItAgain :
.FindNext "[DONOR_CONTACT_ID] = " & strDonor2
If ....
....
ElseIf Not IsNull(!RECIPIENT_4) Then
'RECIPIENT_4 is filled, so run this function again
Goto DoItAgain
End If
End Sub
Actually your recursive code and 1st answer both skip past the recipient if the 4th slot is full, you iterate with another Find and you lose the current recipient! This also eliminates the recursion.
instead:
If .NoMatch or (not isnull(!recipient_4)Then
'If there are no more records with that DONOR_CONTACT_ID, add a new one
' or current record is full
.AddNew
!DONOR_CONTACT_ID = strDonor1
!RECIPIENT_1 = strRecip1
!ORDER_NUMBER = strOrderNum1
.Update
Else