I have a textbox on an access form that I would like to enable for edditing if the textbox is blank. I am new to VBA, and am uncertain of the best way to go about it. Using a double-click event would be fine with me, but I would prefer to do it on load.
I have tried the following code, but can't seem to get it to work. Any help would be appreciated.
Private Sub EmpID_DblClick(Cancel As Integer)
If EmpID.Text = "" Then
Me.EmpID.Enabled = True
End If
End Sub
For things that should happen on a per record basis, you are best off using the current event. Do not use the .Text property for controls. If you must use a property, use .Value. The .Text property is only available when the control has focus and is generally only used in special cases such as the Change event.
Private Sub Form_Current()
If IsNull(EmpID) Then
Me.EmpID.Enabled = True
End If
End Sub
In a normal set-up, there is no chance of the control being equal to a zero-length string ("")
You can cover all bases by saying:
Trim(EmpID & "") = ""
You are running into the Null problem
Null is not the same as ""
Try this instead
If EmpID.Text Is Null Then
Me.EmpID.Enabled = True
End If
Related
I am doing some work for someone that insists on using MS Access. I don't usually use it so I am a bit new to the whole control structure and best practices. What I am trying to achieve is to have a filter textbox on a form which, when a value is entered, it will filter the rows in the detail section. That seems like a straightforward use case. I initially tried the following behaviour as the event handler for the On Change event:
Private Sub FilterGrid()
Me.Text32.SetFocus
If Not IsNull(Me.Text32.Text) And Me.Text32.Text <> "" Then
Me.Filter = "JobNumber LIKE '*" & Me.Text32.Text & "*'"
Me.FilterOn = True
End
Else
Me.FilterOn = False
End If
End Sub
This worked perfectly until I typed something that didn't have any rows matching and the whole thing exploded with this error (and was unrecoverable without closing the form):
Run-time error '2185': You can't reference a property or method for a control unless the control has the focus.
I did some reading around and the general opinion was that .Text should not be used and .Value (or simply the Text32 without a property) should be used. That produced some very strange behaviour. The Text32.Value is ALWAYS null. I have a watch window and I can see that for the normal behaviour, Text32.Text has an actual value, but Text32.Value is NULL.
Obviously I am doing something wrong, but I don't have enough experience with Access to know what it is.
Just as an aside, another suggestion was to do Text32.SetFocus right before accessing the Text property. This doesn't resolve the error I mentioned. It still throws the exact same error.
Is anyone able to point me in the right direction here?
As you found out, the textbox's Value is only set after the control loses focus.
Conversely, the Text property is only accessible while the control has focus.
The Value property is defined as the default member for controls; that means Text32 will be implicitly the same as Text32.Value, however, depending on the context,Text32 can sometimes refer to the control itself, not just its value.
All these discrepancies can sometimes be infuriating.
To go back to the matter at hand: you have 2 ways to handle filtering.
if the list to filter is large, it's probably better that the user type their filter, then press ENTER to validate it.
if your list is not too large, you can implement filter as you type.
First case, wait for user input to be validated by ENTER.
Say your filtering textbox is called txtFilter and is located on a form whose subform is showing a datasheet (or continuous form) that you want to filter.
All you need to do is wire the textbox OnKeyDown events as such:
' We will only perform the filter if the user press the ENTER key
Private Sub txtFilter_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case 13, 9
KeyCode = 0
QuickFilter
End Select
End Sub
' Perform the actual filtering on the subform
Private Sub QuickFilter()
Dim sql As String
Dim filter As String
If txtFilter.Text = vbNullString Then
' Reset the filter if the textbox is emtpy
SubForm.Form.FilterOn = False
Else
'Some common substitutions that users may have already inserted as wildchars
filter = Replace(txtFilter.Text, "%", "*")
filter = Replace("*" & filter & "*", "**", "*")
' We construct the filter SQL
sql = "([JobNumber ] LIKE """ & filter & """)"
sql = sql & " OR ([ProjectCode] LIKE """ & filter & """)"
sql = sql & " OR ([SupplierName] LIKE """ & filter & """)"
'... Add as many columns to filter on as you want
' Assign the filter to the subform
SubForm.Form.filter = sql
SubForm.Form.FilterOn = True
End If
End Sub
Second case, filter as you type
Well, it's fairly easy, we just need to add to the above solution a way to track changes as the user is typing.
This is best done through the OnChange event of the texbox.
Private Sub txtFilter_Change()
QuickFilter
End Sub
That's all you need to add.
dont use .text property
instead use .value property
text3.value=text1.value+text2.value
you dont need setfocus like .text property everytime.
it works perfectly....vba ms access
Can someone help me understand why this code isn't producing expected results?
I have a form with a text box called TxtVendorSearch.
When a user begins typing into this text box, I'd like for it to start filtering the results in the form's subdatasheet.
I am starting with a fully populated datasheet, and I'm not sure why the filter blanks out the whole thing as soon as I start typing a valid filter that should leave results.
Private Sub TxtVendorSearch_KeyPress(KeyAscii As Integer)
Dim str1 As String
str1 = "[VendorID] LIKE '*" & Me.TxtVendorSearch.Value & "*' "
Me!subOrderDS1.Form.Filter = str1
Me!subOrderDS1.Form.FilterOn = True
End Sub
I had a similar problem and i searched the internet for the keyword "find as you type" AND "ms access"
i found this great article. hopefully it will solve your problem.
N.B. this article also contains the source code to use.
Do not use the KeyPress event, you're not going to be able to easily reconstruct the actual input data from within the event handler itself (when the event is triggered, the key just pressed is not yet added to the text of the textbox, meaning you're always short a the last keystroke).
Instead, use the KeyDown event, and use the textbox' .Text property instead of .Value.
.Value is only set once the focus has moved away from the box.
So your code can be simply rewritten as (make sure your KeyDown event is set in the textbox's events on the form):
Private Sub TxtVendorSearch_KeyDown(KeyCode As Integer, Shift As Integer)
' If there is no filter criteria, disable filtering '
If Len(Trim(TxtVendorSearch.Text)) = 0 Then
subOrderDS1.Form.FilterOn = False
Exit Sub
End If
' Do nothing if user hits RETURN or TAB '
If KeyAscii < 32 Then
KeyCode = 0
Exit Sub
End If
Dim str1 As String
str1 = "[VendorID] LIKE '*" & Trim$(TxtVendorSearch.Text) & "*'"
subOrderDS1.Form.Filter = str1
subOrderDS1.Form.FilterOn = True
End Sub
I used Trim() to remove any leading and trailing white-space that the user may have typed.
Last thing: you don't need to use Me. or Me! from within the form's code itself.
Doesn't hurt if you do, but it makes things a bit less legible without adding anything to the code.
My question is fairly straight forward and hopefully simple.
I've got a database that has a long list of part numbers, and some items without part numbers. What i'd like to do is have a command button or Radio button that when activated, hides these null records, and when pressed again, shows them once more.
I can give more detail if needed
Thanks for any help!
Here is an example of using the Filter (same as using of out-of-the-box filtering capability from the Access/Office menu):
Setup:
Table (e.g. Parts):
Form (PartsForm):
Event handler for the Checkbox (OnClick):
Private Sub DisplayAllFilter_Click()
Me.Filter = ""
If Me.DisplayAllFilter.Value = False Then
Me.Filter = "[PartNumber] is not null"
Me.FilterOn = True
Else
Me.FilterOn = False
End If
End Sub
Result would be something like these:
I have multiple fields on a form that have no values associated with them until data is entered into that field. At which point those controls have the #Name? value. All I'm trying to do is hide the fields using a loop as opposed to writing If statements. Here is the code working with a single If statement to hide said field/fields.
If Not Me.txtField.ControlSource = "#Name?" Then
Me.txtField.ColumnHidden = True
End If
I can't seem to figure out how to hide multiple controls that have the #Name? flag. Any help would be appreciated.
Dim ctl As Control
Dim ctlError As String
ctlError = "#Name?"
For Each ctl In Me.Controls
If Not ctl.ItemsSelected(txtField) = ctlError Then
ctl.ColumnHidden = True
End If
Next ctl
EDIT:
On the main form there is a subform with a cross tab query. But the problem is results on the query are populated from a combobox. So I've added fields that are not yet available in the query to the subform and end up with #Name? Attached is a screenshot to better illustrate the issue.
There is a 90% chance I'm going about this process wrong, so it's a learning process right now.
It would be easier to address this question if you described the specific errors that are raised by your code. This answer assumes that the control in question is a TextBox.
"#Name?" means that a control's ControlSource refers to a field that is not in the form's RecordSource. For example, if your query has two fields (ID and BirthDate, for example) and your form has three controls, with ControlSource of "ID", "BirthDate", and "BirthCountry", then the control whose RecordSource is "BirthCountry" will show "#Name?". However, its Value is not "#Name?". Rather, calling the Value property raises error 2424 (with the rather unhelpful message "The expression you entered has a field, control, or property name that Microsoft Office Access can't find").
The only way I know to check for the string "#Name?" is through the control's Text property, which is only available when the control has the focus, so that's not much help. If you retrieve the value of the ControlSource property, you'll get "BirthCountry" (of course). So you could check all ControlSources on your form against the fields of the form's RecordsetClone (add error handling, please):
For Each ctl In Controls
If Not RecordSourceContains(ctl.ControlSource) Then
ctl.Visible = False
End If
Next
Function RecordSourceContains(strFieldName as String) As Boolean
Dim fld As Field
For Each fld In RecordsetClone.Fields
If fld.Name = strFieldName Then
RecordSourceContains = True
Exit For
End If
Next
End Function
You'll probably want to do some other bookkeeping. For example, you'd want to check for expression control sources (which begin with "=") because they won't be in the RecordSource. You'll also either need to handle error 438 (Object doesn't support this property or method) or check each control's type to make sure it has a ControlSource property.
In design view for the form, what does the field say for Control Source? It should be blank, meaning the form is unbound. If it's not, then that explains #Name.
More information: http://www.databasedev.co.uk/unbound-forms-add-data.html
Here is code I use to take care of that:
Sub setControl
'' You can use this in your loop
Call FieldEnable(subFrm, "boxQty", booSellSet)
End Sub
''----------------
Private Sub FieldEnable(subFrm As Access.Form, strCtlName As String, _
booEnableMe As Boolean)
On Error GoTo errHandler
subFrm(strCtlName).Enabled = booEnableMe
subFrm(strCtlName).Visible = booEnableMe
errExit:
Exit Sub
errHandler:
If Err.Number = 2164 Or Err.Number = 2165 Then ''control has the focus
Resume Next
Else
DoCmd.Hourglass False
Screen.Application.Echo True
MsgBox "Problem with control named " & strCtlName
Resume errExit
End If
End Sub
I have to adjust many fields on the form, so this is very reusable. I might be turning them "on" or "off"; this takes care of either. Let me know if you have questions.
It all boils down to this method for hiding the field:
Control.Enabled = False
Control.Visible = False
Delete the field Black from table.
And then make make again the Black field in your table.
Would anybody know how to determine what a forms data entry mode is from within VB.
The reason for doing this is to be able to hide/show controls depending on whether or not the user is adding or editing records eg:
if Me.DataEntry = New then
Me.comboBoxForEdits.Visible = false
end if
Thanks in advance for any help
Cheers
Noel
How about
If Me.NewRecord Then
Me.SomeControl.Visible=false
End If
Private Sub Form_Current()
If Me.AllowAdditions = True Then
' set controls as required.
End If
End Sub
Adding that code to the forms Current event should work.
Another way to write this code could be:
Me!SomeControl.Visible = Not Me.NewRecord
It would be somewhat different from #Remou's code. This would be the equivalent of the above:
If Me.NewRecord Then
Me!SomeControl.Visible = False
Else
Me!SomeControl.Visible = True
End If
Now, it could very well be that you don't want to change the control's .Visible property if it's not a new record, so #Remou's original suggestion may be correct.
Another suggestion is if you are performing this operation on large numbers of controls, you might want to create a custom collection in the form's OnLoad event and have the collection hold pointers to controls you want to operate on. I do this all the time when I need to change the values/appearance/visibility of large numbers of controls in the OnCurrent event.