I am working on a Microsoft Access Database (Office 2010) and I have a tab control on the bottom of my form that displays equipment information based on the type of equipment you select. I am trying to make it dynamically display and hide tabs as determined by the name of the tabs.
To accomplish this I have used the following naming convention for my tabs.
Tab_Static_Description
Tab_Static_Comments
Tab_Static_Maintenance
Tab_Config_Computer1
Tab_Config_Computer2
Tab_Config_Printer1
Tab_Config_Scanner1
Tab_Config_Telephone1
Tab_Config_Display1
My TabControl is called "Tabs"
I have set the form to execute the function below(the function i need help with) on form load and onchange of the equipment drop down menu.
To call the function i use the following code.
DisplayTab
Here is the code to far. I have been googling this a bit and I have yet to find someone doing something similar to me and have found myself a little lost on this one. Any help would be greatly appreciated.
Function DisplayTab(EquipmentType As String)
Dim Ctl As Control
For Each Ctl In Me.Tabs
If Ctl.Name.contains("Tab_Static_") Then
Me.Tabs.Pages.Item(Ctl).Visible = True
ElseIf Ctl.Name.contains("Tab_Config_") Then
If Ctl.Name.contains("Tab_Congig_" & EquipmentType) Then
Me.Tabs.Pages.Item(Ctl).Visible = True
Else
Me.Tabs.Pages.Item(Ctl).Visible = False
End If
Else
MsgBox "There is an unusually named tab. Please contact the database adminsitrator."
End If
Next Ctl
End Function
The error I am getting is "Invalid qualifier" but after googling that message it doesn't exactly make sense.
If Ctl.Name.contains("Tab_Static_") Then
is not valid VBA syntax. You are probably thinking of some similar method that might be availabe in VB.NET. In VBA you would do something like
If InStr(Ctl.Name, "Tab_Static_") > 0 Then
Related
strong textNeed help to identify the error which is occurring while I'm referencing a Checkbox value inside a if statement in Form's OnLoad event Code. Basically checkbox name is "chkEditFinalized" and is placed in diff Form named "Settings" Under 3rd tab "ActionTriggers". Below is the event code.
Private Sub Form_Load()
Dim YorN As Boolean
If ([Forms]![Settings]![chkEditFinalized].Value = True) Then
'Codes to execute
Else
'Codes to execute
End If
End Sub
On the error message window it says "RunTime Error 2450, Application cannot find the referenced from settings"
Can somebody tell me what i have done wrong?
Edit----: As I know that my intention is not possible to implement(as explained by Wolfgang Kais), Can somebody advice me on how to make a global variable and make it accessible from all forms which I've tried and failed(Error:" Variable not defined" While running a sub function even the variable was declared in a Separate module). I know I may sound like a stupid because I'm no expert in this. If I can do this it will fulfill my requirement.
Expecting your valuable advice.
Thanks..
What I'm trying to do is, whenever a user opens a form (and the sub-form that opens by default), I want to search through all the columns (controls?) on the form, check to see if they are currently set to aggregate (sum, count etc.) with Access' built-in Totals row, and if so, set them to not aggregate.
The reason for this is there are several millions records that are stored, so when someone queries it down to 3-4 and turns on Sum, then closes it, when the next person opens it, it tries to sum millions of numbers and freezes up. The form displays the queried results from a table which is populated via SQL (I think, if that sentence makes sense). Here's what I have so far:
Private Sub Form_Load()
'this form_load is in the UserApxSub sub-form, for reference
Call De_Aggregate
End Sub
Private Sub De_Aggregate()
Dim frm As Form, con As Control
Set frm = Forms!UserAPX!UserApxSub.Form!
For Each con In frm.Controls
If con.ControlType = acTextBox Then
If con.Properties("AggregateType").Value <> -1 Then
'crashes on following line
con.Properties("AggregateType").Value = -1
End If
End If
Next con
End Sub
I have not so much experience in Access VBA (usually work in Excel VBA) so please forgive me if I'm entirely off the mark here. The command con.Properties("AggregateType").Value = -1 doesn't throw an error, but Access just straight-up crashes when reaching that line specifically.
I've tried a number of variations in the syntax with no success, and I've also tried looping through other elements of the file (tabledefs, querydefs, recordsets, etc.) as well to see if I'm trying to change the wrong value, but the controls on this subform are the only things in the entire .mdb file that results when I search for elements with the AggregateType property.
I switched out the line that errors with Debug.Print con.Name & " - " & con.Properties("AggregateType").Value and I can check, have nothing return anything other than -1, turn on aggregation in some column manually, and have it return the correct result (0 for sum for example), so I think I'm looking in the right place, just missing some key factor.
I've been working on this for a couple weeks with no success. Any way to fix what I have or point me toward the right direction would be greatly appreciated!
This is not necessarily the answer but I don't have enough reputation
to give a "comment"...
I tried your scenario and verified can change the property value as you are however I did not iterate through all controls and simply used an onDoubleClick event on a column to simulate.
I would suggest trying to fire your sub with Form_Open or Form_Current to see if the property is getting reset after your code has been called for some reason.
UPDATE:
You are referencing the "Subform" Object of your main Form:
Set frm = Forms!UserAPX!UserApxSub.Form!
Try referencing the actual UserApxSub FORM explicitly.
Something like Set frm = Forms!UserApxSub! (assuming UserApxSub is the name of the form)
then stick in the Form_Open of your main form:
Private Sub Form_Open(Cancel As Integer)
'// the following would set a single control only. You can add your loop through all controls
Me!{your control name}.Properties("AggregateType").Value = -1 '// set control in your main form
Form_UserApxSub!{your control name}.Properties("AggregateType").Value = -1 '// set control in your "sub" form
End Sub
This is kind of a follow up question to this post: Access VBA recordset string comparison not working with wildcard but I don't have the rep to answer/comment on it to ask it in house. What I'm curious about is this line of code specifically:
If ![ACOD] = "*_X" Then '"$ICP_X" works
Debug.Print ![ACOD] 'For testing
'.Delete
End If
I want to know if this can be modified so that on a button click, it looks at all fields in a form with the field name of *_New (with the hope to catch all fields where the name ends in _New) and if they are not Null then confirm that the user wanted to make a the change indicated in the field. I was thinking of something along the lines like this:
If Not isNull(*_New.value) Then
If Msgbox ("Do you want to make these changes?",vbOKCancel, "Confirm Changes") = 1 Then
'### Do something with the record ###
End If
End If
EDIT
As of posting the above information, I did not have the Microsoft VBScript Regular Expressions Reference installed, currently I have version 5.5 (it was the latest version). With that installed (referenced?) and seeing the information from this site MS Access with VBA Regex, I'm wondering if it's better to do something like this:
Dim re As RegExp
Set re = New RegExp
re.IgnoreCase = True
re.Global = True
re.Pattern = "*_New"
If ##Not sure on syntax to match all fields## Then
Msgbox(##Same stuff as above MsgBox##)
End If
EDIT 2
Here's a sample case for my form I'm working on. Each of the fields to the right have names that end in _New. What I want to do is on the button click, to check and see what fields on the right have been filled in and ask the user if they want to confirm the changes to the record.
Not sure what you are trying to achieve but there is a way to access the control collection in a form. Here is a public function where you can loop through all controls and check its name.
Public Function FN_CONFIRM_CHANGES(iSender As Form)
Dim mCtl As control
For Each mCtl In iSender
If VBA.Right(mCtl.name, 4) = "_New" Then
Debug.Print mCtl.name & " is a match and its a " & VBA.TypeName(mCtl)
End If
Next mCtl
End Function
Call this function like
FN_CONFIRM_CHANGES Me 'Where me is referencing the form you are in.
You can modify the above code to return a boolean value to stop further execution if user decided not to save your changes or whatever logic you are trying to implement.
This is one of the stranger issues I have seen in MS Access. I have the following code in a continuous form:
Private Sub thisForm_BeforeUpdate(Cancel As Integer)
If Not Cancel Then
Debug.Print "pre-logging data changes..."
' here we need to doublecheck to see if any values changed.
' we simply iterate through the whole list, re-setting oldValue
' and newValue.
For Each control In thisForm.Section(acDetail).controls
If control.ControlType = acTextBox Or _
control.ControlType = acComboBox Or _
control.ControlType = acListBox Or _
control.ControlType = acOptionGroup Or _
control.ControlType = acCheckBox Then
Debug.Print control.Name
oldValues(control.Name) = control.oldValue
newValues(control.Name) = control.value
End If
Next
End If
End Sub
oldValues and newValues are Dictionary objects (although likely not related to the issue).
My form has 3 textbox controls, and a checkbox control. One of the text box controls is disabled, and is populated via the results of a simple inner join (to get the human readable name associated with a foreign key). The data source comes from the form's recordsource (no DLookup or anything is used).
If I edit one of the other two textbox controls, this code runs absolutely fine. HOWEVER, if I toggle the checkbox on the form, i get a runtime error 3251. In the watches window, I get the error again when i try to view the properties of "control". It shows the value of oldValue for the disabled control to be "Reserved Error".
If it did this consistently, I would think it was due to the control being disabled; but since it works without a problem when the other textboxes receive edits, and only breaks when the checkbox is toggled; I am stumped. I'm almost inclined to believe I found a bug in access, but I could use some extra input.
Anyone else every encounter an issue like this?
EDIT: Upon digging further, I found that in actuality only one of the 3 editable fields will not trigger this error. It holds string data. The other two controls hold a date value, and a yes/no value. Now I am even more confused.
i've got two ideas to that issue.
First one: If the RecordSource of your Form is an ODBC-Table thats linked to a SQL-Server then you should set a standard value for the CheckBox-Column. Otherwise it will try to set NULL to False and throw an error saying that somebody else edited the current record.
Second idea: Sometimes Access just has a little "hiccup" when it compiles the code. You could make a backup of your database and then try to decompile it using "C:\Program Files\Microsoft Office 2007\Office12\MSACCESS.EXE" "C:\yourFolder\yourDatabase.accdb" /decompile in the Run... Window (of course you have to insert the Path as it is on your machine). That often helps solving strange Problems.
Preface
I have a need to create multiple copies of a search form (in Access 2010) that returns a value to the calling (which is also the form that created the instance of the form).
As mentioned these forms could and will have multiple copies running at the same time for example a user could want to add a company to something so they:
Click "select company" and open an instance of the company search screen
Then open the company editor (leaving the original company search/selection screen open) as they notice the company has a parent company that hasn't been added yet.
They then click the "Select Parent Company" button that opens ANOTHER instance of the search and select screen
They find the parent company
Select it which closes the second search screen and the parent company is added to the first company.
The user then selects the modified company using the original search screen which again closes the original search screen and returns the selected company to what ever form they originally initialised the first search...
This all allows the users to update and correct data as and when they find error which reduces the likelihood of them forgetting and makes it much quicker!
MOST of this is fine now but I have had a lot of problems with instances of a form not being able to open as a "acDialog" thus stopping the calling code running until the search was done (see this question for more info) and the solution I have gone with is to simulate the pausing of the calling code by using a endless loop and checking if the search screen instant is still visible. Then when the user selects something on the search screen instant it puts the value in a hidden field in the search screen and hides it's self (not closed). The calling function then sees it's hidden grabs the value from the hidden field and unloads the instant.
Problem
I can check if the form is hidden using FormInstant.Visable but if the user closes the form this causes an error and the code I would normally use to check if the form exists requires a form name and as it's an instant of a form all the forms have the same name! I do have a reference to the form as it is stored in a local "form" object... The code I would normally use is:
CurrentProject.AllForms("FormName").IsLoaded
So how can I check for a instant of a form being loaded still?
An old question but here's what experience taught me: If One, Two, ... instances of FormDefn opened then user closes One (Master which is the only one that can be designed), Forms(FormName) gives an error, Forms(Form) gives wrong object,
but Forms(NumberIndex) does still exist with .Name = FormName!
OpenForm creates the Forms(FormName) object. Once closed Forms(FormName) gives an error. Any "Set xForm = New Form_xxx" creates forms in the forms collection that can only be accessed by the collection number index, and cant be designed.
So to later find a multi-instance form use something like:
Dim FormIdx As Integer
Dim lForm As Access.Form
For FormIdx = 0 To Application.Forms.Count - 1
Set lForm = AccessFunc.Appl.Forms(FormIdx)
If lForm.Name = pFormName Then
IsFormOpened = True
Set rForm = lForm
GoTo IsFormOpened_Exit
End If
Next
LOL I just realised while re-reading my msg that I can likely trap the error to work out if the form is open or not!
I have quickly written this and it seems to work fine:
Public Function IsFormLoaded(ByRef FormToTest As Form, _
Optional ByRef bIsVisable As Boolean = False) As Boolean
Dim lErrorNum As Long
bIsVisable = False
On Error Resume Next
bIsVisable = NewFormClone.Visible
lErrorNum = Err.Number
On Error GoTo 0
If (lErrorNum = 0) Then
IsFormLoaded = True
Else
IsFormLoaded = False
End If
End Function
Guess it doesn't really mater who answers the question as long as it is answered and the next guy/gal can use it! :)
I will leave this open for a bit and if nobody finds a better answer I will mark this as it...
I like your answer. As for the loop/wait idea? A better way is to always include a reference in each form. I useally declare form module variable called frmPrevious.
Create instance of form
Instance.frmPrevious = me
So now we have the form "call" some code when the form is closed in place of some "visible" + looping code setting.
So in the close code of the form we have:
frmPrevious.FunctionCodeToRun
The above solves a good many issues, but one is you don't need dialog (which as you note cannot use) And you also dump the need for writing "loop + wait" code from the calling code.
This does however mean that your code continues in a new function in the calling form. I thus usually place that function right below the calling code in the calling form. I also tend to use a standard name for that function. I find this trade off worth it as opposed to loop/wait and continuing in the same code routine (I do agree this "continue" in code is often preferable, but then again having to write looping and wait code is not really that clean).
Try this also
Function IsLoaded(strFrmName As String) As Boolean
' Determines if a form is loaded.
Const conFormDesign = 0
Dim intX As Integer
IsLoaded = False
For intX = 0 To Forms.Count - 1
If Forms(intX).FormName = strFrmName Then
If Forms(intX).CurrentView <> conFormDesign Then
IsLoaded = True
Exit Function ' Quit function once form has been found.
End If
End If
Next
End Function
You can call the above function it in your project like so
If Not isLoaded("MyForm") Then
MsgBox "MyForm is Not Loaded"
End If