MSAccess - Invalid use of property? - ms-access

I have a button on a form that grabs the value of the selected column (SFDC_InventoryID) from a subform datasheet located on the MainForm. SFDC_InventoryID is a text string.
When I attempt to pass this value to a function (called "SFDC"), I am seeing the "Invalid use of property" error. VB never gets to my function.
In my code snippet below, the msgbox does show the expected string value. When I point to a simple textbox control on the MainForm itself, I do not see the same error.
Any suggestions to correct?
Private Sub btnSFDCInventory_Click()
'MsgBox just to test...
MsgBox Forms!mainform!InventoryList_subform.Form!SFDC_InventoryID
If Nz(Trim(Forms!mainform!InventoryList_subform.Form!SFDC_InventoryID)) = 0 Then
MsgBox "No SFDC InventoryID to Display"
Else
SFDC Forms!mainform!InventoryList_subform.Form!SFDC_InventoryID '<< this line throws the error
End If
End Sub
Calls this function:
Public Function SFDC(SFDC_ID As String)
Dim strSFDC As String
strSFDC = "https://na79.salesforce.com/" & SFDC_ID
Application.FollowHyperlink strSFDC
End Function

Try this
If Nz(Trim(Forms!mainform!InventoryList_subform.Form!SFDC_InventoryID),"") = "" Then
MsgBox "No SFDC InventoryID to Display"
Else
SFDC Forms!mainform!InventoryList_subform.Form!SFDC_InventoryID
End If

Related

VBA Access Textbox returning Null Value

I have a VBA Access userform. In this useform there is a textbox with the name txtSearch_POBOX. I'm trying to get its value using the code below:
Private Sub txtSearch_FirstName_Change()
MsgBox ([Form_Client List].txtSearch_POBOX.Value)
End Sub
But this is constantly returning NULL. When even when there is a value inside the text box. Any ideas?
Your reference is wrong. It should read:
MsgBox Forms![Client List]!txtSearch_POBOX.Value
As it could be empty, you should use:
MsgBox Nz(Forms![Client List]!txtSearch_POBOX.Value)
remember that if you want to intercept the text box value while digiting, until you "validate" the content change (e.g. losing focus) the .Value property is not updated.
For instance I used a text box to make a running filter of a submask: I wanted to filter the submask while digiting.
To do this you need to use the .Text property.
In the following example I make a running filter of a list of Publishers:
Private Sub txtNameFilter_Change()
On Error Resume Next
Dim strFilter As String
If Not IsNull(Me.txtNameFilter.Text) Then
strFilter = "Publisher LIKE '*" + Me.txtNameFilter.Text + "*'"
Me.Filter = strFilter
Me.FilterOn = True
Me.txtNameFilter.SelStart = Len(Me.txtNameFilter.Text)
End If
End Sub
Bye
Wiz

Dlookup Hyperlinks to display in MsgBox

Im attempting to replace all my path constants in VBA with an administration table in my datatbase so users can change the location of folders and files without having to edit vba code.
the code is as follows
Private Sub Command8_Click()
Debug.Print DLookup("fsFileLink", "tblFileSystem", "fsFileName= 'TEMPLATES'")
MsgBox = DLookup("fsFileLink", "tblFileSystem", "fsFileName= 'TEMPLATES'")
End Sub
debug.print returns
C:\Users\... \templates\
but the msgbox returns the error "left must be variant or object".
How can I get my dlookup value as a string that I can display and edit in a text box?
Thank You
I'm using the below code:
Dim strCOCTemplate As String
strCOCTemplate = Nz(DLookup("fsFileLink", "tblFileSystem", "fsFileName= 'TEMPLATE_COC2'"), "none")
If strCOCTemplate = "none" Then Err.Raise Number:=11001, Description:=ERR_DESC_11001
Set docJobSpec = WordApp.Documents.Add(Template:=strCOCTemplate, NewTemplate:=True)
Dlookup returns a variant, but Template:= can't accept null values and throws an akward error. I compensated for this by using nz() function to return a string, and raised my own custom error to say the table couldn't find data

Use a button to Enable/Disable a text box in VBA

I have a form with a text box named Contract_Applying_for which is disabled on form load, but I want to have a button which allows me to edit the contents of the text box.
When I add a button I get presented with the Command Button Wizard, so I have created a Macro called ToggleEnableButton which has the instruction to
RunCode Function Name "=ToggleEnableButton()"
Then I have written the function
Function ToggleEnableButton()
If Me.Contract_Applying_for.Enabled = True Then
Me.Contract_Applying_for.Enabled = False
Else
Me.Contract_Applying_for.Enabled = True
End If
End Function
This seems to produce the error "Member already exists in an object module from which this object module derives."
The code for the ToggleEnableButton_Click is automatically created by the Command Button Wizard and is
Private Sub ToggleEnableButton_Click()
On Error GoTo Err_ToggleEnableButton_Click
Dim stDocName As String
stDocName = "ToggleEnableMacro"
DoCmd.RunMacro stDocName
Exit_ToggleEnableButton_Click:
Exit Sub
Err_ToggleEnableButton_Click:
MsgBox Err.Description
Resume Exit_ToggleEnableButton_Click
End Sub
Any suggestion of what I am doing wrong or a better way to approach this.
Seems like a very simple thing that I am trying to do, but quite a long winded approach.
As suggested by Peekay in the comments I have tried to use a checkbox instead, I wrote
Private Sub chbToggleEdit_Click()
If Me.chbToggleEdit.Value = False Then
Me.Contract_Applying_for.Enabled = False
Else
Me.Contract_Applying_for.Enabled = True
End If
End Sub
This gives the error: "A problem occurred while Microsoft Access was communication with the OLE server or ActiveX Control."
Can you not simply have:
Private Sub ToggleEnableButton_Click()
On Error GoTo Err_ToggleEnableButton_Click
ToggleEnableButton()
Exit_ToggleEnableButton_Click:
Exit Sub
Err_ToggleEnableButton_Click:
MsgBox Err.Description
Resume Exit_ToggleEnableButton_Click
End Sub
You can declare your function with the code behind your form.
Let me know if that works,
Ash

Microsoft Access: Attempting to detect an insert triggered by a subform within the parent form

Is it at all possible to detect an insert operation performed by a subform while still in the parent form?
To clarify: I have a series of forms for data entry, they each have a button for adding an entry to the appropriate table (using the data provided in the form). I am attempting to set each of them in turn to a subform in a 'wizard' parent form that will cycle through all the data entry forms.
My problem arises when it comes to switching between forms, as it became clear that the AfterInsert event in this parent form was not detecting the insert triggered by the form contained in the subform. I know I could move the trigger for the insert to a button in the parent form; however, to my knowledge, this would require setting the code for the click event for each of the buttons in the data entry forms as public so that they may be called from the parent form's code. I am leery to do this and was thus hoping for other options.
Create a public procedure in the parent form.
Public Sub Listener(ByVal pMsg As String)
MsgBox pMsg
End Sub
Then, in each of your subforms, call that procedure from After Insert.
Private Sub Form_AfterInsert()
Dim strMsg As String
strMsg = Me.Name & " inserted row."
Call Me.Parent.Listener(strMsg)
End Sub
If the subform may also be used stand-alone (without a parent), Me.Parent will throw error #2452, "The expression you entered has an invalid reference to the Parent property." You can create a separate function to check whether the current form has a parent, and base your code on the function's return value.
Private Sub Form_Open(Cancel As Integer)
Dim strPrompt As String
If HaveParentForm(Me) = True Then
strPrompt = "I am a subform to '" & _
Me.Parent.Name & "'."
Else
strPrompt = "I am a top level form."
End If
MsgBox strPrompt
End Sub
The function ...
Public Function HaveParentForm(ByRef frm As Form) As Boolean
Dim blnReturn As Boolean
Dim strMsg As String
On Error GoTo ErrorHandler
blnReturn = (Len(frm.Parent.Name) > 0)
ExitHere:
HaveParentForm = blnReturn
On Error GoTo 0
Exit Function
ErrorHandler:
Select Case Err.Number
Case 2452 ' The expression you entered has an invalid '
' reference to the Parent property. '
Case Else
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure HaveParentForm"
MsgBox strMsg
End Select
blnReturn = False
GoTo ExitHere
End Function

Does it degrade performance to use subforms in MS Access?

I am considering the use of a tab control on a parent form for which I would like to have around 20 tabs. Each tab I am considering the use of one or two separate sub forms. Each sub form will have varied complexity in coded logic. By taking this approach will I severally reduce the performance of my application? I am currently using this in MS Access 2003. I will expect an average of 15 users at any given time on the various forms.
Thoughts?
Yes, performance will be degraded slightly for each subform. One or three isn't too bad but twenty is definitely going to cause you performance issues.
Once you have the subform working to your satisfaction either save the Record Source as a query and give it a name or save the query SQL string. Then either paste the query name or the query SQL string in the VBA code in the tab control change event.
Private Sub TabCtl_Change()
On Error GoTo TabCtl_Change_Error
Select Case Me.TabCtl.Value
Case Me.pagPartsConsumed.PageIndex
If Me.PartsConsumedsbf.Form.RecordSource <> "Equipment - Parts Consumed sbf" Then _
Me.PartsConsumedsbf.Form.RecordSource = "Equipment - Parts Consumed sbf"
....
Now just to ensure that I don't accidentally leave some subform recordsources filled in slowing down the app on startup I check to see if the file the code is running is an MDB (instead of an MDE. The function is below) then display a message telling me I have to remove the recordsource.
If Not tt_IsThisAnMDE Then
If Me.PartsConsumedsbf.Form.RecordSource <> "" Then _
MsgBox "Record source of Equipment - Parts Consumed sbf not empty"
...
End If
Public Function tt_IsThisAnMDE()
On Error GoTo tagError
Dim dbs As Database
Set dbs = CurrentDb
Dim strMDE As String
On Error Resume Next
strMDE = dbs.Properties("MDE")
If Err = 0 And strMDE = "T" Then
' This is an MDE database.
tt_IsThisAnMDE = True
Else
tt_IsThisAnMDE = False
End If
Exit Function
tagError:
Call LogError(Application.CurrentObjectName, "")
Exit Function
End Function
Also in the form unload event I clear the Recourd Source as well.
Private Sub Form_Unload(Cancel As Integer)
On Error GoTo Form_Unload_Error
Me.PartsConsumedsbf.Form.RecordSource = ""
....
BTW I almost always would put each subform on a seperate tab. Also that many tab entries gets visusally unwieldy. When I had a similar question my fellow Access MVPs suggested using a listbox along the left hand side to control which subform is viewable.
Also each combo box and list box will also slightly degrade the performance. So if you have those on a subform then consider similar logic.
In addition to adding recordsets at runtime, I would generally only use one or two tabs and a number of controls to load various subforms into a subform control.
The text for the On Click event of the control might be:
=WhichPage([Form],"lblLocations")
Where WhichPage is a function with the following lines, amongst others:
Function WhichPage(frm, Optional LabelName = "")
<..>
Select Case LabelName
Case "lblLocations"
frm("sfrmAll").SourceObject = "sfrmLocations"
<...>
If necessary, the link child and link master fields can be changed at runtime. The link master field is best set to the name of a control, rather than a field, to avoid errors.
Me.sfrmAll.LinkChildFields = "LocationKey"
Me.sfrmAll.LinkMasterFields = "txtLocationKey"
To expand on Remou's answer...here is a sub I wrote that dynamically loads a form into a subform control. You pass in the name of the form in the call and it will load it into the subform of the Main form. The arguments map to the arguments of Docmd.OpenForm method of Access. If the main form that is hosting the subform control is not open...it just does a regular open of the form. Otherwise it loads it into the subform control. If a where clause was passed in it is used to filter the subform.
Public Sub MyOpenForm(FormName As String, _
Optional View As AcFormView = acNormal, _
Optional FilterName As String = vbNullString, _
Optional WhereCondition As String = vbNullString, _
Optional DataMode As AcFormOpenDataMode, _
Optional WindowMode As AcWindowMode, _
Optional OpenArgs As String)
On Error GoTo PROC_ERR
Dim frm As Form
Dim strNewForm As String
Dim strCurrentForm As String
Dim strNewTable As String
Dim fDoNotFilter As Boolean
Dim strActionText As String
Dim strID As String
If Not IsLoaded("frmMain") Then
DoCmd.OpenForm FormName:=FormName, View:=View, FilterName:=FilterName, WhereCondition:=WhereCondition, DataMode:=DataMode, WindowMode:=WindowMode, OpenArgs:=OpenArgs
Else
strCurrentForm = Forms![frmMain]![sfrMyForm].SourceObject
If strCurrentForm <> FormName Then
Forms![frmMain]![sfrMyForm].SourceObject = vbNullString
Forms![frmMain]![sfrMyForm].SourceObject = FormName
End If
If WhereCondition <> vbNullString Then
Forms![frmMain]![sfrMyForm].Form.Filter = WhereCondition
Forms![frmMain]![sfrMyForm].Form.FilterOn = True
End If
End If
PROC_EXIT:
Exit Sub
PROC_ERR:
MsgBox Err.Description
Resume PROC_EXIT
End Sub