Function to determine and pass value in a form control - ms-access

I am trying to create a function that will determine the value held in an active form control and then pass the value for a form criteria as follows:
Public Function fc_id() As Long
fc_id = (Screen.ActiveControl.Caption)
End Function
Public Sub sShowForm()
DoCmd.OpenForm "F_Details", , , "c_id = " & fc_id
End Sub
I then call the function from the form control being clicked:
sShowForm
The details form opens but it's black, and there is not error message.
If I use a numeric value, what would be the equivalence of the
(Screen.ActiveControl.Caption)

Temporarily change your procedure to find out what you're getting from Screen.ActiveControl:
Public Sub sShowForm()
'DoCmd.OpenForm "F_Details", , , "c_id = " & fc_id
MsgBox Screen.ActiveControl.Name
End Sub
You may not be getting what you expect. For example, if you're using a command button to run sShowForm(), the command button is the ActiveControl. Whether or not that is the situation, check to see what you're actually getting.
If the present form (the form where your VBA code is running) includes a text box bound to a c_id field in the form's record source, you can eliminate the function and reference that text box directly in the OpenForm option. For example, if c_id is a numeric field and the text box is named txtc_id ...
DoCmd.OpenForm "F_Details", , , "c_id = " & Me.txtc_id
If c_id is text type, add quotes around the text box value ...
DoCmd.OpenForm "F_Details", , , "c_id = '" & Me.txtc_id & "'"

Related

Microsoft Access - Record Form Load

I am curious whether it is possible that when i load a record in one of my forms and i choose to add a quote for that record selected, so i choose add quote (button) which takes me to my quote page. i would then like the form to auto load the record i had previously selected in the other form.
Client Form:
Quote Form:
Here is the data flow:
Record Selected ("Add Job") > Click "Add Items" button > "Items List" loads > the record i previously selected in "Add Job" is then auto loaded.
the feild that will need loading are "Project ID" & "Client name"
Use OpenArgs argument of the DoCmd.OpenForm method
When you click Add Quotes button to open Quotes form, send the details/linked ID via openArgs parameter.
In Quotes form load event, you can get the details passed using Me.OpenArgs
See below sample code
On Add Quotes button click
Private Sub AddQuotes_Click()
DoCmd.OpenForm "frmQuotes", OpenArgs:=me.ClientID
End Sub
Quotes form
Private Sub Form_Load()
Dim varArgs
varArgs = Me.OpenArgs
'Fill the controls with recordset data
If Not IsNull(varArgs) Then
With CurrentDb.OpenRecordset("SELECT * FROM tblClients WHERE ClientID = " & varArgs, dbOpenForwardOnly )
Me.ClientID = !ClientID
Me.ClientName = !ClientName
Me.ClientAddress = !ClientAddress
Me.ClientPhone = !ClientPhone
Me.ClientEmail = !ClientEmail
.Close
End With
End If
End Sub

MS Access Pass Form Through Function

I am trying to create a function that will allow me to use various command buttons without having to recreate the code every time.
To do this I have to pass the form name through a function
Function:
public Function NewRecord(controlForm, focusForm)
focusForm.SetFocus
DoCmd.GoToRecord , , acNewRecord
controlForm.SetFocus
controlForm - This is the main form akin to the Me function
focusForm - This is for not only the main form but when I create subforms I have to have the focus on the subform to have the command work.
To call the function I did the following:
public sub Command19_Click()
Dim controlForm
Dim focusForm
Set controlForm = Forms![frm_Sales_CustomerProfile]
Set focusForm = Forms![frm_Sales_CustomerProfile]
Call NewRecord(controlForm, focusForm)
End Sub
I get this error that States: Compile Error: Invalid Use Of Property.
You got trapped using an already in this context (the form) used identifier and not using a strong name (NameOfLibrary.NameOfFunction).NewRecordis a forms property, soInvalid Use Of Propertymakes sense. If you useMyModulName.NewRecord(frm1,frm2)everything is fine. If you useNewRecordin Module òr Class it works too as there is no property with same name (I assume;-)).
To be honest, I don't use strong names either (except on database or recordset objects, as I got trapped there too, assuming DAO, using ADODB), but the Pros suggest that and now we know why!
Your function should have just one argument as it is sufficent to pass only the subforms reference if you need that form NewRecord(frm as Access.Form) (note the strong name!). You can easy refer to the mainform with Set mfrm = frm.Parent
Your code;
Public Function FrmNewRecord(frm As Access.Form)
frm.Recordset.AddNew
End Function
Public Sub Command19_Click()
FrmNewRecord(Forms![frm_Sales_CustomerProfile]) ' mainform
FrmNewRecord(Forms![frm_Sales_CustomerProfile]!sfrmControl.Form) ' subform
End Sub
You are passing the same form two times in your code, any reason? If Forms[frm_Sales_CustomerProfile] contains Command19 use Me.
I dropped the .SetFocuspart as not necessary or any reason to for setting focus? Why is NewRecord a function? Doesn't return anything.
btw: I am working on aSubForms(frm)function , that returns a collection of all subforms.
Code:
'SubForms(frm As Access.Form) returns a collection of all subform references in frm
Public Function SubForms(frm As Access.Form) As VBA.Collection
Dim ctr As Access.Control
Dim sfrm As Access.Form
Dim col As New VBA.Collection
For Each ctr In frm.Controls
If ctr.ControlType = acSubform Then
On Error Resume Next
Set sfrm = ctr.Form
If Err.Number = 0 Then
col.Add sfrm, sfrm.Name
End If
On Error GoTo 0
End If
Next ctr
Set SubForms = col
End Function
As a general rule to build say custom menu bars, or ribbons, you can write code that is “form” neutral like this:
Public Function MyDelete(strPrompt As String, strTable As String)
Dim strSql As String
Dim f As Form
Set f = Screen.ActiveForm
If MsgBox("Delete this " & strPrompt & " record?", _
vbQuestion + vbYesNoCancel, "Delete?") = vbYes Then
So note how we don’t need to pass the form name at all – the above code simply picks up the active screen as variable “f”.
At that point you can do anything as if the code was inside the form.
So
Me.Refresh (code inside the form)
Becomes
f.Refresh
So the key concept here is that you don’t need to pass the current active form since screenActive form will enable you to get the current form object anyway.
However, for sub forms and “common” type of code the above falls apart because screen.ActiveForm will return the main form, and not the sub form instance.
So as a second recommended approach, simply always pass the current context form object “me” like this:
Call MySub(me)
And you define your sub like:
Sub MySub(f as form)
Now in this code we can reference "anything" by using "f" in place of "me"
f.Refresh
So just pass “me” if you ever use sub forms. Given the above information, then your code becomes:
public sub Command19_Click()
Call NewRecord(me)
End Sub
And NewReocrd becomes:
Sub NewRecord(f as form)
Now in your newreocrd code, you can use “anything” form the object such as:
f.Name ' get name of the form.
or
City = f.City ' get value of city control
So pass the “whole” form context.
And you could say make a routine to display the City value for any form like:
Call ShowCity(me, "City")
And then
Sub ShowCity(f as form, strControlToShow as string)
Msgbox "City value = " & f(strControlToShow)
So OFTEN one will write code that works for any form by simply picking up the current active form as:
Dim f As Form
Set f = Screen.ActiveForm
And note how the above code picks up right away the active form – this is a good idea since then if focus changes, the “f” reference will remain intact for the code that follows in that “general” routine that is called + used from many forms.
However due to the sub form issue, then often it simply better to always pass the “whole” forms instance/object with:
Call MyNewRecord(me)
And then define the sub as:
Sub MyNewReocord(f as form)
DoCmd.GoToRecord acDataForm, f.Name, acNewRec
End Sub
And you could optional add “focus” to above with
f.SetFocus
So for a lot of menu or ribbon code, you don't pass the form object, but simply use screen.ActiveForm, and you can also use Screen.ActiveControl (again great for menu bar or ribbon code to grab what control has focus). However due to sub form limitations, then often passing "me" to the routine will achieve similar results if not better in some cases.

Hyperlink text disappears based on combo box value on continuous form

I'm having a bit of an unusual problem (or at least I think it's unusual). I have a continuous form that shows certain records based on a query that updates after I change the value in a combo box. I have a "View All" hyperlinked text box so that I can switch to seeing all of the records when I want to, but have discovered it only appears when I have selected a combo box value that has records. For example, if I want to find records assigned to Joe Shmo and there is one record assigned to him, the hyperlink appears. If I want to find records assigned to Susie Seashell and she has none assigned to her, it disappears. The catch is that if I click on the area of the screen where the hyperlink should appear, it still works as expected-- there is just nothing visible that would lead you to click there. The text field's visibility is on, and I even tried coding in a txtfield.visible=true and it did nothing. Any help would be appreciated!
Note: The hyperlink control source is ="View All". Not sure if that matters or not.
All of the VBA code used on this form is below:
Option Compare Database
Private Sub cboFindNotice_AfterUpdate()
getSearchResults
End Sub
Private Function getSearchResults()
Dim sql As String
Dim errMsg As String
'== Sets value of string 'sql'
sql = "SELECT tblNotice.ID, tblNotice.noticeSEIFnoticeNumber, tblNotice.noticeJurisdiction, tblNotice.noticeDueDate, tblNotice.noticeTitle, " _
& "tblAnalysts.[analyst_lName] & "", "" & [analyst_fName] AS Expr1, tblNotice.noticeStatus" _
& " FROM tblAnalysts INNER JOIN tblNotice ON tblAnalysts.ID = tblNotice.noticeAnalyst" _
& " WHERE tblNotice.noticeAnalyst LIKE '*" & Me.cboFindNotice & "*'" _
& " ORDER BY tblNotice.noticeDueDate"
'== Displays records based on query
Me.Form.RecordSource = sql
Me.Form.Requery
End Function
Private Sub noticeSEIFnoticeNumber_Click()
DoCmd.OpenForm "frmNoticeDetails"
[Forms]![frmNoticeDetails].Controls("txtControlField").Value = Me.Controls("ID").Value
Call Forms.frmNoticeDetails.txtControlField_AfterUpdate
End Sub
Private Sub txtViewAll_Click()
Me.cboFindNotice.Value = ""
Call cboFindNotice_AfterUpdate
End Sub

Form not working unless underyling query re-saved

I'm a newcomer to Access trying to cobble things together from helpful information I've found here.
I have a form that needs to populate the fields based on a combo box selection in the form header. The form is based on an underlying query with the following criteria for field "StudID" [Forms]![frmStudConsentUpdate]![cmbStud] where cmbStud is my combo box. The combo box pulls in StudID, StudFN, StudLN with StudID as the bound columnn. The after update event requeries the form (Me.Requery). This works beautifully, but only if I first open the form in design view, open the Record Source, and save it. I don't make any changes at all, but once I've done this the form works. Otherwise, nothing happens when I select a student in the combo box. Any thoughts on what I need to do to make this work without having to re-save the underlying query?
This is old bug in MS Access, I have no idea why they still didn't fix it:
If underlying form's query has in criteria form's control and the form was filtered once (at start or manually/using VBA), it doesn't accept new values from form's control and uses old value.
Workaround: create public function, which returns control's value and use it in criteria instead of [Forms]![frmStudConsentUpdate]![cmbStud]. You will need to create function for each control or use this function:
Public Function GetControlValue(strFormName As String, strControlName As String, Optional strSubFormControlName As Variant, Optional varDefault As Variant) As Variant
' Returns : Variant, value of control in form/subform
' Comments:
' Params :
' strFormName
' strControlName
' strSubFormControlName
' varDefault - value returned if control is not accessible
'----------------------------------------------------------------------------
On Error GoTo ErrorHandler
If IsMissing(strSubFormControlName) Or Nz(strSubFormControlName, "") = "" Then
GetControlValue = Forms(strFormName).Controls(strControlName).Value
Else
GetControlValue = Forms(strFormName).Controls(strSubFormControlName).Form.Controls(strControlName).Value
End If
ExitHere:
On Error Resume Next
Exit Function
ErrorHandler:
If Not IsMissing(varDefault) Then
GetControlValue = varDefault
End If
Resume ExitHere
End Function
In criteria use function call GetControlValue("frmStudConsentUpdate","cmbStud") instead of [Forms]![frmStudConsentUpdate]![cmbStud]
In your afterupdate for your cmbStud combobox, create code that refreshes the recordsource to
me.recordsource = "SELECT * FROM {yourQueryName} WHERE StudID = '" & me!cmbStud & "'"

how to filter on load in MS access?

when double clicking on a value i need to open a form. the value gets passed to the opened form. I want the form to directly filter on that value instead of pushing on a button first. i tried filtering on change and on load but it doesn't work. when loading it doesn't know the value because it gets added after it opened the form.
this is the code for passing the value:
DoCmd.OpenForm "SubmenuRubrieken", acNormal
Forms!SubmenuRubrieken.Tv_rubrieknaam.Value = Me.Tekst14.Value
this is the code for filtering on that value in Tv_rubrieknaam:
Dim filter As String
filter = ""
If Not IsNull(Tv_rubrieknaam) Then filter = filter & " AND rubrieknaam = '" & Tv_rubrieknaam.Value & "'"
Me.filter = Right(filter, Len(filter) - 5)
Me.FilterOn = True
for some reason it doesn't trigger the filter on changing the value of Tv_rubrieknaam. how do i need to solve this?
I guess, the Form_Load() event is finished before you set the value (OpenForm is performed before value is set), so you would have to do the filtering in the OnChange() event of the Textfield or similar.
Better: pass the Me.Text14.Value with the DoCmd.OpenForm command either as a prepared whereCondition OR as OpenArgs with filtering option in the On_Load event.
A basic example:
I have a Form1 with a TextBox called Text0 on it. Text0 has a value of 2.
I have a Form2 with a Table called Table1 as Recordsource. Table1 has a column called Field1 containing numbers between 1 and 3
All I need to do is add the following code into the module of the Form1 and the moment I click on Text0 Form2 will be openend filtered down to rows with Field1 = 2
Private Sub Text0_Click()
DoCmd.OpenForm "Form2", acFormDS, , "Field1 = " & Nz(Me!Text0, 0)
End Sub