Display current record in MS-Access form - vba

I have a code now that will go to the next record, but in the form it will not display the next record just shows 0. You can see in the table that the code is working and going to the next record seeing that the quantity went down. Another problem is when switched to the next record and that one hits 0, I'm then getting a highlighted error on my .Update when I need it to go to the next one after that. It doesn't say an error, I just assume when it's highlighted then the problem is coming from that. Its basically like the code isn't restarting. Here is my code now:
Private Sub ItemCode_Dirty(Cancel As Integer)
Dim Db As DAO.Database
Dim rs As DAO.Recordset
Set Db = CurrentDb
Set rs = Db.OpenRecordset("Select WrkordNum, ToGo from WorkOrders where ItemCode =" & Me.ItemCode)
With rs
If Not .EOF Then
If !ToGo <= 0 Then
.MoveNext
End If
.Edit
!ToGo = !ToGo - 1
.Update
End If
End With
End Sub
How do I get that next record to display in my form and not just show 0? What can I add in my code to have it restart to the beginning so that I works through the table and not just one record?

You've opened a new recordset. This has no relation to your current form at all. You can do this from outside a form. You can even do this from Excel.
If you want to interact with the form you have to use form methods.
If you just want to go to the next record you would use code like this:
If Me.CurrentRecord < Me.Recordset.RecordCount Then
DoCmd.GoToRecord , , acMoveNext
End If
If you want to move your form to the same record as your new recordset you would do this:
Private Sub ItemCode_Dirty(Cancel As Integer)
Dim Db As DAO.Database
Dim rs As DAO.Recordset
Set Db = CurrentDb
Set rs = Db.OpenRecordset("Select WrkordNum, ToGo from WorkOrders where ItemCode =" & Me.ItemCode)
With rs
If Not .EOF Then
If !ToGo <= 0 Then
.MoveNext
End If
.Edit
!ToGo = !ToGo - 1
.Update
Me.CurrentRecord = rs.AbsolutePosition
End If
End With
End Sub
and finally, if you want to work with the current recordset instead of opening a new one:
Private Sub ItemCode_Dirty(Cancel As Integer)
With Me.Recordset
If Not .EOF Then
If .ToGo <= 0 Then
.MoveNext
End If
.Edit
.ToGo = .ToGo - 1
.Update
End If
End With
End Sub

Related

Facing problems Inserting multiple records in a continuous form in access from a query

I have a continuous form where I need to populate all employees' ID & names to set their yearly target. I don't want to manually add them through a combo box because it can create duplicate records for a single employee. The form contains two fields named EMPID(employee ID) and EmpName(name of the employee). I want all the EMPID and EmpName to auto populate in that continuous form from a Query named "InsertNameTarget". After watching some YouTube videos, I came up with something like the following:
Dim i As Integer
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("InsertNameTarget")
For i = 0 To rs.RecordCount - 1
DoCmd.GoToControl "EMPID"
DoCmd.GoToRecord acDataForm, Me.Name, acNewRec
EMPID = rs.Fields("EMPID")
EmpName = rs.Fields("EmpName")
rs.MoveNext
Next i
rs.Close
Set rs = Nothing
db.Close
It doesn't work as intended. It gives me the following result:
It is giving the first record out of 10 records and doesn't insert the EMPID properly to all records. I don't know what I'm doing wrong here. Can you point me in the right direction?
Continuous forms are difficult to work with. Since each control is only represented once, you can't assign values to it reliably.
Instead, work with the forms recordset:
Dim i As Integer
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim frs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("InsertNameTarget")
Set frs = Me.Recordset
Do While Not rs.EOF
frs.AddNew
frs!EMPID = rs.Fields("EMPID")
frs!EmpName = rs.Fields("EmpName")
frs.Update
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
db.Close

Access VBA Update Form Textbox With Sub Parameter

I'm having an issue with figuring out how to update my forms textbox with the value I ended with in the procedure. If a messagebox is used the output is fine. However, I want the user to be able to click the button and the textbox on that form be updated with the answer.
Private Sub btnTotalGuests_Click()
Call CalculateTotalGuestsForEachService
End Sub
Here is the procedure
Public Sub CalculateTotalGuestsForEachService()
'Declare variables
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim intTotalParty As Integer
Dim intID As Integer
'Set the current database
Set db = CurrentDb
'Set the recordset
intID = InputBox("Enter the Service ID (1-6)", "Service ID")
Set rst = db.OpenRecordset("Select Orders.* From Orders Where ServiceID =" & intID)
'Cycle through the records
Do While Not rst.EOF
If Not IsNull(rst!NoInParty) Then
intTotalParty = intTotalParty + rst!NoInParty
End If
rst.MoveNext
Loop
'Display total amount
txtTotalGuests.Text = intTotalParty 'Wondering how to display this in the textbox on the form.
'Close the recordset
rst.Close
Set rst = Nothing
Set db = Nothing
End Sub
Don't use Text property. You want Value property and since Value is default, don't even need to explicitly reference. Presume CalculateTotalGuestsForEachService is in the form module so can use Me.txtTotalGuests.
Consider domain aggregate function instead of looping recordset.
Dim intID As Integer
intID = InputBox("Enter the Service ID (1-6)", "Service ID")
Me.txtTotalGuests = DSum("NoInParty", "Order", "ServiceID =" & intID)

MS ACCESS VBA Run-time error '3021'; with .MoveNext

this is my code
Dim Reloc, RelocPrev1, RelocPrev2 As String
Dim Blk, Blk2, Lt, Lt2, PrevDate As String
Dim LotComp, BlockComp As Integer
Dim DB As Database
Dim RS As Recordset
Private Sub SearchBtn_Click()
Reloc = Me.RArea.Value
Set DB = CurrentDb()
Set RS = DB.OpenRecordset(Reloc, dbOpenDynaset)
Blk = RS!Block
Lt = RS!Lot
Blk2 = Me.BlockTxt
Lt2 = Me.LotTxt
BlockComp = StrComp(Blk, Blk2, 1)
LotComp = StrComp(Lt, Lt2, 1)
RS.MoveFirst
Do Until BlockComp = LotComp
RS.MoveNext
Loop
Call RetrieveData
End Sub
RS!Block and RS!Lot works fine, only RS.Movenext and RS.Edit which I tried doesn't work.
My table is populated with more than 50 rows.
First item in the table can be pulled just fine, I just can't move to the next row with RS.MoveNext
Any ideas to make this work?
You apparently expect only 1 record to match criteria. It would be best to apply filter criteria to recordset SQL so only desired records are pulled then test if recordset is empty.
To go to a single record that meets criteria, instead of looping recordset use FindFirst and NoMatch.
RS.FindFirst "Block='" & Blk2 & "' AND Lot='" & Lt2 & "'"
If Not RS.NoMatch Then

changing sql string based on active userform

I have a SQL query that I'm calling from a couple of different forms using the ctrl as object method. It works fine, but when I run it from a click event it will also open whichever form isn't currently loaded. The query returns the results I want, it just does it to both forms at the same time regardless of which is loaded.
Only one form is loaded at a time. A drop down list called Team exists on both forms. The query passes the currently selected item from that drop down list to return a list of agents assigned to that team.
I know that part of the issue is my query using an or statement that refers to values on both forms, but I'm not sure how to change it to reference the active form.
Attendance and reporting are the names of the two UserForms currently calling this query. Both of them have combobox controls named Team. I've tried activeform, etc. But I can't seem to find a way to make it work.
Sub agents(ctrl As Object)
database_connect
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim Counter As Long
SQLStr="select distinct[Agentname] from dbo.[Attendance] Where [Team]='" & _
attendance.Team.Value & "' or [Team] ='" & Reporting.Team.Value & "'"
If appconn.State = 0 Then
Call database_connect
End If
rs.Open SQLStr, appconn, adOpenStatic
With ctrl
Do
.AddItem rs![Agentname]
rs.MoveNext
Loop Until rs.EOF
End With
rs.Close
database_Disconnect
Set rs = Nothing
Exit Sub
End Sub
1) Well first off to refer to controls you have to have the form loaded.
2) Youre referring to controls in the oddest way. Review AND save this URL http://access.mvps.org/access/forms/frm0031.htm
3) If one form is closed your query might always return nothing. Is this a desired output?
For anyone who may find this looking for something similar, this is the solution I used.
I used a Function to test if a userform is loaded or not.
Public Function IsLoaded(formName As String) As Boolean
Dim frm As Object
For Each frm In VBA.UserForms
If frm.Name = formName Then
IsLoaded = True
Exit Function
End If
Next frm
IsLoaded = False
End Function
Then adjusted my above code like so
database_connect
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim Counter As Long
If IsLoaded("Attendance") Then
SQLStr = "select distinct[Agentname] from dbo.[Attendance] Where [Team] ='" & attendance.Team.value & "'"
ElseIf IsLoaded("Reporting") Then
SQLStr = "select distinct[Agentname] from dbo.[Attendance] Where [Team] ='" & Reporting.Team.value & "'"
End If
If appconn.State = 0 Then
Call database_connect
End If
rs.Open SQLStr, appconn, adOpenStatic
With ctrl
Do
.AddItem rs![Agentname]
rs.MoveNext
Loop Until rs.EOF
End With
rs.Close
database_Disconnect
Set rs = Nothing
Exit Sub
now it works like a charm!

Access transactions

I have two pieces of code in my form constructor. They are equal for a 95%, but I really don't know how to simplify it (VB newbie, came from PHP/C/C++/other non-script languages). Can someone help me with it? How to make a template, or just make a shared class or just some globals to use it? :-o
Pieces are:
Private Sub AddOne_Click()
If isNull(Forms![Constructor]!FieldOne.value) Then
MsgBox ("Please, fill the field one")
Else
Dim workspace As DAO.workspace
Dim recordset As DAO.recordset
Set workspace = DBEngine.Workspaces(0) 'The current database
workspace.BeginTrans 'Start the transaction buffer
Set recordset = CurrentDb.OpenRecordset("One", dbOpenDynaset)
With recordset
.AddNew
!One = Forms![Constructor]!FieldOne.value
.Update
End With
workspace.CommitTrans 'Commit the transaction to dataset
MsgBox ("New '" + Forms![Constructor]!FieldOne.value + "' added successfully")
Forms![Constructor]!FieldOne.value = Null
End If
End Sub
Private Sub AddTwo_Click()
If isNull(Forms![Constructor]!FieldTwo.value) Then
MsgBox ("Please, fill the field two")
Else
Dim workspace As DAO.workspace
Dim recordset As DAO.recordset
Set workspace = DBEngine.Workspaces(0) 'The current database
workspace.BeginTrans 'Start the transaction buffer
Set recordset = CurrentDb.OpenRecordset("Two", dbOpenDynaset)
With recordset
.AddNew
!Two = Forms![Constructor]!FieldTwo.value
.Update
End With
workspace.CommitTrans 'Commit the transaction to dataset
MsgBox ("New '" + Forms![Constructor]!FieldTwo.value + "' added successfully")
Forms![Constructor]!FieldTwo.value = Null
End If
End Sub
Not sure why you've tagged this 'vbscript' - looks like Access to me (OTOH it's impossible to type a variable in VBScript, and OTH you've used the 'bang' operator). Anyhow:
1) Add a standard module.
2) Add the following helper routine to the module:
Function Add(RecordsetName As String, FieldName As String)
If isNull(Forms![Constructor].Fields(FieldName).value) Then
MsgBox ("Please, fill " + FieldName)
Else
Dim workspace As DAO.workspace
Dim recordset As DAO.recordset
Set workspace = DBEngine.Workspaces(0) 'The current database
workspace.BeginTrans 'Start the transaction buffer
Set recordset = CurrentDb.OpenRecordset(RecordsetName, dbOpenDynaset)
With recordset
.AddNew
.Fields(FieldName).Value = Forms![Constructor].FieldName(FieldName).value
.Update
End With
workspace.CommitTrans 'Commit the transaction to dataset
MsgBox ("New '" + Forms![Constructor].Fields(FieldName).value + "' added successfully")
Forms![Constructor].Fields(FieldName).value = Null
End If
End Sub
3) The existing OnClick handlers can now be replaced with
=Add("One", "FieldOne")
and
=Add("Two", "FieldTwo")
in the Properties pane and the current method handlers deleted from the form module.