Sincerely in the dark. My Code:
Public Property Get rowCount() As Integer
rowCount = Counter
End Property
Public Property Let rowCount(ByRef inte As Integer)
Counter = inte
End Property
Private Sub Form_Timer() 'Timer
Dim dbs As DAO.Database
Dim rs As DAO.Recordset
Dim Caption As Field, Form As Field, Count As Integer, holder As Integer, item As String
Dim strForms() As String
Set dbs = CurrentDb
Set rs = dbs.OpenRecordset("MainMenu", dbOpenDynaset)
ReDim strForms(1 To rs.RecordCount())
If rs.RecordCount <> 0 Then
For c = 1 To rs.RecordCount() Step 1 '!!!THIS IS THE PROBLEM!!!
MsgBox CStr(c)
MsgBox rs("Caption")
strForms(c) = rs("Caption")
rs.MoveNext
MsgBox rs("Caption")
Next c
End If
rowCount = 1
holder = rowCount()
If holder <= rs.RecordCount() Then
Me.Command10.Caption = strForms(holder)
rowCount = holder + 1
Else
rowCount = 1
Me.Command10.Caption = strForms(holder)
End If
End Sub
I added all those message boxes in my effort to debug. All I need is that counter to go up. No idea why it is not. Why will this thing not increment?!
The best way is to use rs.MoveFirst, rs.MoveNext and rs.EOF to check for end of records. The following VBA will do what you want.
'Open up a recordset on our table
Set dbs = CurrentDb
Set rs = dbs.OpenRecordset("MyTable", dbOpenDynaset)
'Did we find any records?
If rs.RecordCount > 0 Then
'Move to first record
rs.MoveFirst
'Iterate through each record
Do
'Do stuff with the currentrecord
MsgBox ("Next record ID is: " + CStr(rs("ID")))
'Move to next record
rs.MoveNext
'Exit when we hit the end of the recordset
Loop While rs.EOF <> True
End If
'Close the recordset
rs.Close
Using the RecordCount property might be the problem.
It essesntially just counts the number of times rs.MoveNext had been called.
Try switching the code to a loop like this:
Dim L As Long
Do Until rs.EOF
L = L + 1
MsgBox rs.RecordCount
MsgBox L
rs.MoveNext
Loop
Access Recordsets aren't as easy as .NET DataTables but they've been around a lot longer.
http://msdn.microsoft.com/en-us/library/office/bb208624(v=office.12).aspx
Related
Ok I am trying to dynamically get recordCount and pass that to .GetRows but it doesnt work as it only pulls in one records into the array. If I just statically put a number into the .GetRows method it works fine, but this is obviously not ideal.
This Works
Set rs = CurrentDb.OpenRecordset("SELECT * FROM Client", dbOpenDynaset, dbSeeChanges)
aRR = rs.GetRows("random number")
For i = 0 To rs.RecordCount - 1
For j = 0 To rs.Fields.Count - 1
Debug.Print ; aRR(j, i)
Next j
Next i
This does not
Set rs = CurrentDb.OpenRecordset("SELECT * FROM Client", dbOpenDynaset, dbSeeChanges)
With rs
rs.MoveLast
Debug.Print ; rs.RecordCount
Q = rs.RecordCount
aRR = rs.GetRows(Q)
End With
For i = 0 To rs.RecordCount - 1
For j = 0 To rs.Fields.Count - 1
Debug.Print ; aRR(j, i)
Next j
Next i
I have tried multiple things I have found on the web but clearly I must be missing something? Is there an easy approach to this or do i need to requery with a DISTINCT clase, and pass the return value within that record set to a new variable?
GetRows also uses the recordset's pointer. With rs.MoveLast you put that pointer to the last row. That's why only one row gets returned. Addrs.MoveFirst after setting Q to resolve this.
Like Phesago mentioned, Access will only return the recordcount based on which record in the recordset it's looking at. As a general practice when working with recordsets, I always begin with the following template:
Private Sub CreateRecordset()
Dim rs As Recordset
Dim sql As String
sql = "SELCT * FROM tblSomeTable"
Set rs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)
With rs
If Not .EOF And Not .BOF Then
.MoveLast
.MoveFirst
Dim i As Integer
For i = 0 To rs.RecordCount - 1
'do whatever actions desired
Next
End If
End With
End Sub
I have a module with a procedure inside that looks like this:
Public Sub OpenRecordset()
Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs("QOff2")
qdf.Parameters(0).Value = [Forms]![Form]![Text10]
Dim db As Database
Dim rs As Recordset
Dim StrBusinesses As String
Set rs = qdf.OpenRecordset
If rs.EOF And rs.BOF Then
MsgBox ("No businesses exist for this Customer")
Exit Sub
Else
rs.MoveFirst
End If
StrBusinesses = ""
Do While Not rs.EOF
StrBusinesses = StrBusinesses & rs!Fnam & ", "
rs.MoveNext
Loop
rs.Close
StrBusinesses = Left(StrBusinesses, Len(StrBusinesses) - 2)
Forms!Form.Badge = StrBusinesses
Set rs = Nothing
End Sub
I am trying to get this module to input the query results into a textbox (forms!form.badge), but I can't seem to get it to do it like my 5 other dlookup functions. When I open up the module and push the green play button, it shows up on the correct textbox but also shows up on the other records as well. It also doesn't show up automatically, nor does it update as you enter in the parameters. Isn't a module supposed to help autofil numerous variables into a text box in place of dlookup for multiple values?
No. If Forms!Form!Badge is an unbound textbox, a value assigned to it will be shown identically for all records.
To individualize, you will need a lookup function which takes the ID or other unique value of the record as parameter(add to textbox):
=LookupBadges([Forms]![Form]![Text10])
Public Function LookupBadges(ByVal Value As Variant) As Variant
Dim db As Database
Dim qd As QueryDef
Dim rs As Recordset
Dim Businesses As String
Set db = CurrentDb
Set qd = db.QueryDefs("QOff2")
qd.Parameters(0).Value = Nz(Value)
Set rs = qd.OpenRecordset
If rs.RecordCount > 0 Then
rs.MoveFirst
Do While Not rs.EOF
Businesses = Businesses & rs!Fnam.Value & ", "
rs.MoveNext
Loop
End If
rs.Close
Businesses = Left(Businesses, Len(Businesses) - 2)
LookupBadges = Businesses
Set rs = Nothing
Set qd = Nothing
Set db = Nothing
End Function
Im trying to get a recordset loop code working, i have my bellow code which keeps inputing a zero. My second piece of code is identical code but displaying the qty in a message box. The number it is displaying is the number i want to input into my field. I just cant seem to get it to put the number in the field !Qty?
Dim Val As Integer
Dim rs As DAO.Recordset
Set rs = Forms!frmReceive!sfrmReceiveDetailEntry.Form.RecordsetClone
With rs
Do While Not rs.EOF
rs.Edit
Val = Nz(DLookup("[RemainingQty]", "tblQtySoFarTEMP", "[OrderDetailPK]= " & rs! [OrderDetailFK]))
rs!Qty = Val
rs.Update
rs.MoveNext
Loop
End With
Set rs = Nothing
Displaying value in message box
Dim val As Integer
Dim rs As DAO.Recordset
Set rs = Forms!frmReceive!sfrmReceiveDetailEntry.Form.RecordsetClone
With rs
Do While Not rs.EOF
val = Nz(DLookup("[RemainingQty]", "tblQtySoFarTEMP", "[OrderDetailPK]= " & rs! [OrderDetailFK]))
MsgBox val
rs.MoveNext
Loop
End With
Set rs = Nothing
I worked it out in the end, this is my working code!
'If YES then run the following code
AreYouSure = MsgBox("You are about to Receive All of Order" & txtOrderNumber.Value & " , Are you Sure?, The whole order and it's Quantities will be updated?", vbYesNo, "Receive All?")
If (AreYouSure = vbYes) Then
'disable warnings
DoCmd.SetWarnings False
'Create recordsetclone of subform
'loop recordset and lookup remaining qty to receive all
Set rs = Forms!frmReceive!sfrmReceiveDetailEntry.Form.RecordsetClone
With rs
Do While Not rs.EOF
rs.Edit
rs("Qty") = Nz(DLookup("[RemainingQty]", "tblQtySoFarTEMP", "[OrderDetailPK]= " & rs![OrderDetailFK]))
rs.Update
rs.MoveNext
Loop
End With
Set rs = Nothing
Basically I want to flip the line number values in the two records when someone changes them in the subform
so if i have line:
12345 and I rename 5 to 3 I want 5 renumbered to 3 and 3 renumbered to 5 so I would have 12543 but they reshuffle to 12345 but the records switch places correctly
However I get an error (see below) and if I change record 1 it can't find any records
the code I have so far is:
Private Sub OrderLineNumber_AfterUpdate()
Dim rst As DAO.Recordset
Set rst = Me.Recordset
Dim recNum As Integer
Dim recVal As Double
Dim move As Integer
Dim i As Integer
recNum = Me.CurrentRecord
Me.Requery
DoCmd.GoToRecord , , acGoTo, recNum
recVal = rst!OrderLineNumber.Value
rst.MoveFirst
Do Until rst.EOF
i = rst!OrderLineNumber.Value
If i = recVal Then
move = Me.CurrentRecord
End If
rst!OrderLineNumber.Value = recVal #Here
DoCmd.GoToRecord , , acGoTo, recNum
rst!OrderLineNumber.Value = i
rst.MoveNext
Loop
End Sub
and is failing at #Here with error update or cancelupdate without add new or edit
Before changing a value on a DAO record you need to run the Edit method. And then you need to run the Update method after changing it.
Private Sub OrderLineNumber_AfterUpdate()
Dim rst As DAO.Recordset
Set rst = Me.Recordset
Dim recNum As Integer
Dim recVal As Double
Dim move As Integer
Dim i As Integer
recNum = Me.CurrentRecord
Me.Requery
DoCmd.GoToRecord , , acGoTo, recNum
recVal = rst!OrderLineNumber.Value
rst.MoveFirst
Do Until rst.EOF
i = rst!OrderLineNumber.Value
If i = recVal Then
move = Me.CurrentRecord
End If
rst.Edit
rst!OrderLineNumber.Value = recVal #Here
rst.Update
DoCmd.GoToRecord , , acGoTo, recNum
rst.Edit
rst!OrderLineNumber.Value = i
rst.Update
rst.MoveNext
Loop
End Sub
Here's a function I use that does something quite similar. I have a main form with buttons with up and down arrows on them, and a datasheet subform (continuous form would work too). Every row in the subform has a RowOrder field with a value in it starting from 1. These values get assigned as the user adds new records.
When the user wants to change the order of the records in the subform they just use the arrow buttons located on the main form. One thing not in my code here is checks for new record, or checks to see if they have no records entered. Another thing my function does not do is reorder or fix all the rows. It only affects the row in focus and the one above or below it. Here's the code:
Private Sub cmdUp_Click()
'Put an "Up" button on one of your forms and pass the function a correct form object
Call MoveCurrentRecordUpOrDown("Up", Me.subform1.Form)
End Sub
Private Sub cmdDown_Click()
'Put a "Down" button on one of your forms and pass the function a correct form object
Call MoveCurrentRecordUpOrDown("Down", Me.subform1.Form)
End Sub
Public Function MoveCurrentRecordUpOrDown(sDirection As String, frm As Form)
Dim lPos As Integer
Dim iCurRowOrder As Integer
iCurRowOrder = Nz(frm!RowOrder, 0)
'Check to see if the record is already up against one of the ends
Dim iChange As Integer
Select Case sDirection
Case "Up"
If iCurRowOrder = 1 Then Exit Function 'Cannot move record up
iChange = -1
Case "Down"
If iCurRowOrder = frm.Recordset.RecordCount Then Exit Function 'Cannot move record down
iChange = 1
End Select
lPos = frm.Recordset.AbsolutePosition + iChange
Dim rs As DAO.Recordset
Set rs = frm.RecordsetClone
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do Until rs.EOF = True
If rs!RowOrder = iCurRowOrder Then
rs.Edit
rs!RowOrder = iCurRowOrder + iChange
rs.Update
ElseIf rs!RowOrder = (iCurRowOrder + iChange) Then
rs.Edit
rs!RowOrder = iCurRowOrder
rs.Update
End If
rs.MoveNext
Loop
frm.Requery
If lPos > (frm.Recordset.RecordCount - 1) Then
lPos = (frm.Recordset.RecordCount - 1)
End If
frm.Recordset.AbsolutePosition = lPos
End If
rs.Close
Set rs = Nothing
End Function
When there is only one record, this expression gives correct calculation, but when there are more than one record the values of last record calculated is reflected in all Total_Time (unbound text box).I have given on load and on open code of the report. Please help me.
Private Sub Report_Load()
strSQL = "SELECT * FROM [q_1ltduty]"
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL)
rs.MoveFirst
Do While Not rs.EOF
'Assigning values of fields to varia
strtime1 = Op_Time
strtime2 = Cl_Time
'This is a simple expression my code has some more detailed calculations
strhrs = strtime2 - strtime1
strtotalhrs = strhrs
'Printing the variable in Total_Time textbox(unbound)
Me.Total_Time.Value = strtotalhrs
rs.MoveNext
Loop
rs.Close
db.Close
Set db = Nothing
Set rs = Nothing
End Sub
Private Sub Report_Open(Cancel As Integer)
strSQL = "SELECT * FROM [q_1ltduty]"
Me.RecordSource = strSQL
Debug.Print strSQL
Exit Sub
ErrHandler:
MsgBox Err.Description
End Sub
Your variable strtotalhrs contains only the value of strhrs for one record, so each time you go through the loop, the value for the current record erases the value for the previous record. What you should do instead of erasing the value is adding to it.
Before the loop (if it has not already been done):
strtotalhrs = 0
then in the loop, instead of strtotalhrs = strhrs:
strtotalhrs = strtotalhrs + strhrs
and that should give you the sum total instead of the last value.