MS Access Nested Subform reference error - vba

I'm having trouble referencing a subform within a subform on a form.
Private Sub Command37_Click()
Dim UMsge As String
Me.Filter = "ID=" & Me.ID
Me.FilterOn = True
UMsge = "Swimmer's Name: " & Forms![Parents]![Swimmers Subform].Form![Memb First Name] & " " & Forms![Parents]![Swimmers Subform].Form![Memb Last Name] & vbCrLf & vbCrLf & "Roster Group: " & Forms![Parents]![Swimmers Subform].Form![Roster Group] & vbCrLf & vbCrLf & "Monthly Fee: " & Format(Forms![Parents]![Swimmers Subform].Form![Parents - Payment subform].Form![GroupMonthlyPrice], "Currency") & vbCrLf & vbCrLf & "Thank You!"
DoCmd.SendObject acSendForm, "Parents", acFormatPDF, Me.Email, , , "Monthly Fees Owed As Of " & DateSerial(Year(Date), Month(Date), Day(Date)), UMsge, True
End Sub
It's only this last piece:
Format(Forms![Parents]![Swimmers Subform].Form![Parents - Payment subform].Form![GroupMonthlyPrice], "Currency")
FormView:

First, it looks like you using a sub datasheet. They are somewhat different then sub forms (in that you cannot name them, they are named automatic for you).
Further, since your button is in the same form, for the top most form, we can use “me” keyword. This will simple your code quite a bit.
Assuming we had 3 nested sub forms, we could use this syntax:
strName = Me.Swimmers_SubForm.Form![memb First Name] & " " & _
Me.Swimmers_SubForm.Form![memb Last Name]
The above will get you the name in the first nested sub form.
However, you next sub form looks VERY much like a Subdatasheet.
Two things:
If this is a sub data sheet (as opposed to sub form, then if this form has never been expanded, then the reference will break (the child form does not exist). This is often the same for if the sub datasheet has no child records.
So you need (should) to trap this error.
Also, if this is a sub data sheet, then you cannot give the sub form control a name – it starts at child0 and that likely is your issue.
Note that the record return will be the highlighted row, and in your example screen shot, I see two rows, and I DO NOT see the column called [GroupMonthlyPrice]. However I will assume that this is the column you wish to reference? Or is do you want the column called [Monthly Fee] ?
So to reference that 3rd nested form, the syntax would be this:
Me.Swimmers_SubForm.Form!Child0.Form![GroupMonthlyPrice]
So to break all this down, I would use this code:
Dim f As Form ' ref to sub form
Dim UMsge As String
Set f = Me.Swimmers_Subform.Form
UMsge = "Swimmer's Name: " & f![Memb First Name] & " " & f![Memb Last Name] & vbCrLf & _
"Roster Group: " & f![Roster Group] & vbCrLf & vbCrLf & _
"Monthly Fee: " & Format(f!Child0.Form![GroupMontlyPrice], "Currency")
The referenced "f" in above is not required, but certainly makes code much more readable.
Note that you might have to replace child0 with the name of the sub form control, but as I stated, this looks like a sub datasheet, and quite sure the first sub datasheet is called Child0.

Related

How to make listbox display search results based on input in form?

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,

VBA at Access - Filter with several criteria, where one criteria can be Null

I got some problems with my vba code.
I got a form at access with a filter.
At the moment the one filter is for start/end date and a Person.
And because i am a noob, there is an other Filter for a cost centre and the start/end date.
I want to combine both, but with the case, cost centre can be Null or not.
My "main" filter looks like this:
Private Sub Befehl51_Click()
If Nz(Me.txtvon, "") = "" Then //StartDate
MsgBox "Bitte Datumsbereich wählen!"
Exit Sub
End If
If Nz(Me.txtbis, "") = "" Then //EndDate
MsgBox "Bitte Datumsbereich wählen!"
Exit Sub
End If
Me.Filter = "[TaetigkeitsDatum] between " & Format(Nz(Me!txtvon, Date),"\#yyyy-mm-dd\#") & "
and " & Format(Nz(Me!txtbis, Date), "\#yyyy-mm-dd\#") & " And " & "[PersonalID] = " & Me.Liste0 & ""
Me.FilterOn = True
End Sub
The syntax for the cost criteria is like:
[TaetigkeitsKostenstellenIDRef] = "Kombinationsfeld145"
Thanks for help!
You're nearly there, there are just some minor SQL syntax errors.
I've written it to separate lines to increase readability and make understanding easier
Me.Filter = "[TaetigkeitsDatum] BETWEEN " & Format(Nz(Me!txtvon, Date),"\#yyyy-mm-dd\#") & " AND " & Format(Nz(Me!txtbis, Date), "\#yyyy-mm-dd\#") & _
" AND [PersonalID] = " & Me.Liste0
If IsNumeric(Me!Kombinationsfeld145) Then
Me.Filter = Me.Filter & " AND [TaetigkeitsKostenstellenIDRef] =" & Me!Kombinationsfeld145
End If
Some of the changes I've made:
Spacing was off. Before every And and variable name, there should be a space.
The " & " between And and a variable name was unnecessary, removed that.
I've only included the comparison on Me!Kombinationsfeld145 if it's numeric. That way, if it's Null or a zero-length string, it's not included in the comparison.

How to create a comment box with time and date stamp in Access using VBA

Completely new to VBA and need help with detailed instructions (dummy version for me).
I have a table with various columns and the following columns, specifically:
ReviewerComments
NewComment
I created a form with both of these fields and need to create an Append Comment button that moves the text from NewComment field and appends it to ReviewerComment field and time/date stamps the comments as they are added. I named this button cmdAppendComment.
I had seen someone else post something and I tried, but as I am completely new to this I know I messed it up. Any help is greatly appreciated.
This is what the VBA code looks like right now:
Private Sub cmdAppendComment_Click()
If (IsNull(NewComment.Value)) Then
MsgBox ("Please provide a comment before clicking" & _
"on the Append Comment button.")
Exit Sub
End If
If (IsNull(ReviewerComments.Value)) Then
ReviewerComments.Value = NewComment.Value & " ~ " & _
VBA.DateTime.Date & " ~ " & VBA.DateTime.Time
Else
ReviewerComments.Value = ReviewerComments.Value & _
vbNewLine & vbNewLine & _
NewComment.Value & " ~ " & _
VBA.DateTime.Date & " ~ " & VBA.DateTime.Time
End If
NewComment.Value = ""
End Sub
I have some suggestions for your code:
1. Do not check if a textbox is null but how many characters your textbox has. You should always do it that way because otherwise you tend to get errors.
If (len(Me.NewComment.Value & "") > 0) Then
MsgBox ("Please provide a comment before clicking" & _
"on the Append Comment button.")
Exit Sub
End If
Here you check the length of the string in your textbox. You need to append "" because otherwise you tend to get null-errors or something similar.
2. You forgot to reference the objects in your form correctly. You have your form and in that form you put your textboxes and also your VBA-code. Your can reference all your objects with "Me.[FormObjects]".
The compiler complains that "NewComment.Value" or "ReviewerComment.Value" is not initialized or in other words not dimensioned. With correct reference this should stop.
Private Sub cmdAppendComment_Click()
If (len(Me.NewComment.Value & "") > 0) Then
MsgBox ("Please provide a comment before clicking" & _
"on the Append Comment button.")
Exit Sub
End If
If (IsNull(Me.ReviewerComments.Value)) Then
Me.ReviewerComments.Value = Me.NewComment.Value & " ~ " & _
VBA.DateTime.Date & " ~ " & VBA.DateTime.Time
Else
Me.ReviewerComments.Value = Me.ReviewerComments.Value & _
vbNewLine & vbNewLine & _
Me.NewComment.Value & " ~ " & _
VBA.DateTime.Date & " ~ " & VBA.DateTime.Time
End If
Me.NewComment.Value = ""
End Sub

Applying vbCrLf to the content of a textbox

I've got a userform within an Excel vba project. At design-time it is empty.
In the form initialize event I've got the following code:
Private Sub UserForm_Initialize()
txtSQL.value = _
"SELECT MyName = ""ColY"" " & vbCrLf & _
"FROM SomeTable " & vbCrLf & _
"GROUP BY Customer " & vbCrLf & _
"ORDER BY Customer DESC"
End Sub
I was hoping for 4 separate lines of text in the textbox but instead have the following:
Am I using the wrong control? Or am I using the right control in the wrong way?
Whoops: maybe I should go to bed...
At design-time set multi-line property to True!

Update Button not updating

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.