I've been searching for a solution to change apperance of my textbox into red when the entered value is not a number.
Actually, I succeeded with a textbox only but I have 14 textboxes at total. I've tried with the codes below:
Private Sub Justi_num()
Dim i As Integer
For i = 2 To 14
If IsNumeric(Controls("TextBox" & i).Value) Then
Controls("TextBox" & i).BackColor = RGB(255, 255, 255) 'Blanc
Else 'Sinon
Controls("TextBox" & i).BackColor = RGB(247, 205, 201) 'Rouge clair
End If
Next i
End Sub
But it didnt work. Any help? Thanks in advance.
You first need to ensure that your code is called whenever the user enters something. This is done with Event-Routines. Controls (like buttons, checkboxes, textboxes and so on) have different events like change (something was changed), dblClick (there was a double click on the control) and so on.
If you want some code to be executed, you need to put code into that event routine. The name of the event routine is combined by the name of the control and the event name. If the name is not following that rule, the code is not called automatically.
In design mode, go to the form editor and double click onto one of your textboxes: The editor will open the text editor window and create a subroutine with the most common event of that control (for a textbox, that's the Change-event, for a button, it would be the Click-event):
Private Sub TextBox1_Change()
End Sub
You could call your routine Justi_num from this routine:
Private Sub TextBox1_Change()
Justi_num
End Sub
However, you will need to create such an event routine for every of your text boxes, there is no way around that (ok, yes, there is, but it is much too complicated for a beginner).
Private Sub TextBox2_Change()
Justi_num
End Sub
Private Sub TextBox3_Change()
Justi_num
End Sub
and so on...
One thing: Your routine Justi_num handles all textboxes, no matter which textbox was changed. You could change the code so that the event routine passes the information which control was changed and the color changing routine handles only that control:
Private Sub TextBox1_Change()
setTextBoxColor Me.TextBox1
End Sub
Private Sub TextBox2_Change()
setTextBoxColor Me.TextBox2
End Sub
(and so on...)
Private Sub setTextBoxColor(tbox As Control)
If IsNumeric(tbox.Value) Or tbox.Value = "" Then
tbox.BackColor = vbWhite
Else
tbox.BackColor = RGB(247, 205, 201)
End If
End Sub
I'll try to help:
One thing that may fail is that "IsNumeric" gives a boolean result. Try using If IsNumeric(Controls("TextBox" & i).Value) = True Then
It would be something like:
Private Sub Justi_num()
Dim i As Integer
Dim NA As Boolean
NA = False
For i = 2 To 14
NA = IsNumeric(Controls("TextBox" & i).Value)
If NA = True Then
Controls("TextBox" & i).BackColor = RGB(255, 255, 255) 'Blanc
Else 'Sinon
Controls("TextBox" & i).BackColor = RGB(247, 205, 201) 'Rouge clair
End If
Next i
End Sub
Hope it helps!
Related
I want to do something like this. Don't know if it is possible in Excel VBA. On a user form, I have a checkbox and a text box.
When I check the checkbox, the checkbox's caption will be inserted into the text box, when I uncheck the checkbox, the checkbox's caption will be removed from the same text box.
When i write into the text box the caption of the checkbox, inside the text box change event, the checkbox status will be updated. And at the same moment, the checkbox click event is fired and the caption text will be doubled. How can I stop the checkbox click event from firing twice?
Checkbox's click event code:
Private Sub cbSelect_Click()
With TextBox1
.Value = IIf(cbSelect.Value, _
.Value & cbSelect.Caption, _
Replace(.Value, cbSelect.Caption, vbNullString))
End With
End Sub
Text box's change event code:
Private Sub TextBox1_Change()
If InStr(TextBox1.Value, cbSelect.Caption) Then
cbSelect.Value = 1
Else
cbSelect.Value = 0
End If
End Sub
Any idea?
When I tested your code, the checkbox status did not change which I believe is due to the use of binary values (1 / 0) instead of Boolean (True / False)
I changed your Textbox1_Changecode to the following and as soon as I delete part of the checkbox c
Private Sub TextBox1_Change()
If InStr(TextBox1.Value, cbSelect.Caption) Then
cbSelect.Value = True
Else
cbSelect.Value = False
End If
End Sub
I added a Public TextBoxFlag As Boolean at the User_Form module level, and this "flag" is being modifed and checked in both Control's events.
Once the code enters the TextBox1_Change event the flag gets a True value, and when the code reaches the cbSelect_Click event, it doesn't run the code inside if the value of TextBoxFlag = True, only if it's False (didn't came from the TextBox1_Change event, but directly from the CheckBox1 event).
Code
Option Explicit
Public TextBoxFlag As Boolean
Private Sub cbSelect_Click()
' check if event came from the value being modified in the TextBox1_Change event
If TextBoxFlag = False Then
With TextBox1
.Value = IIf(cbSelect.Value, _
.Value & cbSelect.Caption, _
Replace(.Value, cbSelect.Caption, vbNullString))
End With
End If
End Sub
Private Sub TextBox1_Change()
' raise the flag >> came from TextBox change event
TextBoxFlag = True
If InStr(TextBox1.Value, cbSelect.Caption) > 0 Then
cbSelect.Value = True
Else
cbSelect.Value = False
End If
' reset the flag
TextBoxFlag = False
End Sub
your code actually worked for me without the issue you described just substituting:
InStr(Me.TextBox1.Value, Me.cbSelect.Caption)
with :
InStr(Me.TextBox1.Value, Me.cbSelect.Caption) > 0
BTW here's some possibly useful coding advices :
I'd always use Me keyword and refer to Userform controls.
this will also have Intellisense help you in finding UserForm controls names
your cbSelect.Value setting code can be shortened to one line
as a result of all what above:
Private Sub TextBox1_Change()
Me.cbSelect= InStr(Me.TextBox1.Value, Me.cbSelect.Caption) > 0
End Sub
Private Sub cbSelect_Click()
With Me.TextBox1
.Value = IIf(Me.cbSelect, _
.Value & Me.cbSelect.Caption, _
Replace(.Value, Me.cbSelect.Caption, vbNullString))
End With
End Sub
I am looking to edit my current code as it is very long winded but if need be I can stick with it. My current code is simply repeated on each button as it runs through ActiveX buttons (these buttons must stay). Undo action is preferred but changing the colour back using RGB is a viable option.
My coding is as follows:
Private Sub btn3_Click()
Sheet1.Range("A84:J84").Interior.ColorIndex = 16
End Sub
This changes the cell range to a grey colour succesfully, I now need a double click to undo the action or something that will change the colours back to the original colour; I made two attempts.
Using undo function.
Private Sub btn3_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
End Sub
Then I tried a different method and went to change the colour.
Private Sub btn3_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim color_index As Long
color_index = 10
Sheet1.Range("A84:J84").Interior.Color(color_index) = RGB(153, 153, 255)
End Sub
End result was unsuccessful in both attempts.
Neither of these worked and would like a 'work around' or to fix my errors, any ideas accepted but I must keep buttons I cannot use 'Cell Selection'.
EDIT
If possible there my be an array method useable, I am not good with using ActiveX controls so any advice will most likely be very useful.
My workbook explaining what btn3 represents.
http://i.stack.imgur.com/35p2f.png
There's no easy way to do Application.Undo to undo the results of a macro-performed operation. You either need to create a cache/copy of the data and revert to that, or you need to formulate a way to "undo" in a custom function.
In any case, the error in your second method, this line:
Sheet1.Range("A84:J84").Interior.Color(color_index) = RGB(153, 153, 255)
Could eeither be changed to:
Sheet1.Range("A84:J84").Interior.ColorIndex = color_index
Or:
Sheet1.Range("A84:J84").Interior.Color = RGB(153, 153, 153)
Alternatively, you can do a custom undo function, something like this:
'## Module level variable
Dim previousColor As Long
Sub btn3_Click()
'## stores the current ColorIndex property of the range
' (assumes all cells have the same color)
previousColor = Sheet1.Range("A84:J84").Interior.ColorIndex
'## Applies the new color:
Sheet1.Range("A84:J84").Interior.ColorIndex = 16
End Sub
Sub btn3_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Sheet1.Range("A84:J84").Interior.ColorIndex = previousColor
End Sub
Further, you inquire:
as I updated is there a way to do this on a mass scale as I have 60+ 'buttons'...
Yes. Ensure firstly that all of the buttons call the same procedures. Then, modify the procedures for each button like below. NOTE I can't get the double-click to work without also invoking the single-click event, first, which has the undesired effect of not being able to "store" the previous color for the range. You may be able to add some conditional logic, for the time being I've hard-coded so the "undo" function will revert to no color at all:
Dim previousColor As Long '
Private Sub CommandButton1_Click()
Debug.Print "click"
Call changeColor(CommandButton1)
End Sub
Private Sub CommandButton1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "dbl click"
Call undoChangeColor(CommandButton1)
End Sub
Private Sub CommandButton2_Click()
Debug.Print "click"
Call changeColor(CommandButton2)
End Sub
Private Sub CommandButton2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "dbl click"
Call undoChangeColor(CommandButton2)
End Sub
Private Sub changeColor(btn As MSForms.CommandButton)
'Assumes all cells are same color initially
previousColor = -4142 '(none) 'Sheet1.Range("A84:J84").Interior.ColorIndex
'Get the row corresponding with each button:
Dim rng As Range
Set rng = Sheet1.Range("A" & btn.TopLeftCell.Row).Resize(1, 11)
rng.Interior.ColorIndex = 16 'Modify as needed
'you could assign the RGB() here
End Sub
Private Sub undoChangeColor(btn As MSForms.CommandButton)
'Get the row corresponding with each button:
Dim rng As Range
Set rng = Sheet1.Range("A" & btn.TopLeftCell.Row).Resize(1, 11)
rng.Interior.ColorIndex = previousColor
End Sub
I have two forms.
form1 has four text boxes and a button for each textbox.
The button would setfocus on the textbox and bring up form2.
form2 is basicly a number keypad that also has a text box so that the user can select a number. That number will go in form2.textbox, which when changed will put the data in form1.textbox1.
The problem I'm having is how to tell form2.textbox to put data in form1.textbox2.
This is what my code looks like:
Public Sub textbox1_Click()
Me.textbox1.SetFocus
numbfrm.Show
End Sub
Private Sub textbox2_Click()
Me.textbox2.SetFocus
numbfrm.Show
End Sub
Private Sub textbox3_Click()
Me.txtactual.SetFocus
numbfrm.Show
End Sub
This is what is in the number form. It contains all of the numbers 1 to 10, but I just put the first three numbers here.
Private Sub Cmd1_Click()
TxtNumber.Value = TxtNumber.Value & "1"
End Sub
Private Sub Cmd2_Click()
TxtNumber.Value = TxtNumber.Value & "2"
End Sub
Public Sub TxtNumber_Change()
passnumber
End Sub
This is in a module:
Sub passnumber()
form1.textbox1.Value = numbfrm.TxtNumber
End Sub
I've been looking through the web to find an easy way to do that.
I tried puting in the module
Sub passnumber()
If form1.texbox1.foucs =true then
form1.textbox1.Value = numbfrm.TxtNumber
Else If form1.textbox2.foucs = true then
form1.texbox2.value =numbfrm.txtnumber
End sub
I have made a workaround for it, I put toggle buttons next to each box and when button is pressed it would mark it as true, and then I told it if that toggle is true it would use certain text box
Sub passnumber()
If form1.option1.value =true then
form1.textbox1.Value = numbfrm.TxtNumber
else
If form1.option2.value =true then
form1.textbox2.Value = numbfrm.TxtNumber
end if
end if
End sub
I have a textbox on a userform. It is the only textbox on the form. There are three labels and two buttons in addition to this textbox. Basically, I want the focus to remain on this textbox under all scenarios, other than the moment that one of the buttons would be clicked, but then I want the focus to come right back to the text box. Both buttons have "TakeFocusOnClick" and "TabStop" set to False. I was having problems with getting the focus set to the textbox, which is why I changed these two settings.
Once I changed these settings, the Enter key in the textbox stopped having any effect. I have events written for _AfterUpdate and _KeyPress for the textbox, but they don't fire. As you can see in the code, I have commented out the lines to set the focus to this textbox. Since it is now the only object that can take focus, these lines are not needed (theoretically). When I allowed the other objects to take focus, these lines weren't having any effect (focus was switching to the buttons despite these SetFocus lines).
Here is the code. It is very simple, except that the Enter key isn't triggering the event. Can anyone see why? Thanks.
Private Sub btnDone_Click()
Application.Calculation = xlCalculationAutomatic
formMath.Hide
'Clear statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
End Sub
Private Sub btnSubmit_Click()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_AfterUpdate()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = 13 Then
recordAnswer
End If
End Sub
Private Sub UserForm_Initialize()
'Initialize manual calculation
Application.Calculation = xlCalculationManual
Application.Calculate
'Initialize statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
'Initialize first problem
newProblem
End Sub
Sub recordAnswer()
'Update statistics
Dim attempts, correct As Integer
attempts = Range("attempts").Value
correct = Range("correct").Value
Range("results").Offset(attempts, 0).Value = attempts + 1
Range("results").Offset(attempts, 1).Value = lblTopNum.Caption
Range("results").Offset(attempts, 2).Value = lblBotNum.Caption
Range("results").Offset(attempts, 3).Value = lblBop.Caption
Range("results").Offset(attempts, 4).Value = Range("Answer").Value
Range("results").Offset(attempts, 5).Value = txtAnswer.Text
If (Range("Answer").Value = txtAnswer.Text) Then
Range("results").Offset(attempts, 6).Value = 1
Else
Range("results").Offset(attempts, 6).Value = 0
End If
'Update attempts and success
Range("attempts").Value = attempts + 1
Range("correct").Value = correct + 1
newProblem
End Sub
Sub newProblem()
Application.Calculate
formMath.lblTopNum.Caption = Range("TopNum").Value
formMath.lblBotNum.Caption = Range("BotNum").Value
formMath.lblBop.Caption = Range("ProbType").Value
formMath.txtAnswer.Value = ""
'formMath.txtAnswer.SetFocus
End Sub
To start off
You can either in the design mode, set the TabIndex property of the Textbox to 0 or you can set the focus on the textbox in the UserForm_Initialize()
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Similarly after any operation that you perform, simply call the TextBox1.SetFocus to revert to the textbox.
Option Explicit
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Private Sub CommandButton1_Click()
MsgBox "Hello from Button 1"
TextBox1.SetFocus
End Sub
Private Sub CommandButton2_Click()
MsgBox "Hello from Button 2"
TextBox1.SetFocus
End Sub
Let me know if this is not what you want?
I found a way to accomplish this. In the code above I took out the _KeyPress and _AfterUpdate events and replaced them with:
Private Sub txtAnswer_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 13: recordAnswer
End Select
End Sub
Not sure why the other methods didn't work, but this does.
Also not sure why simply setting the focus directly didn't work. I suspect that the focus was being set, but then something else was happening subsequently that was changing the focus off of the textbox. Just a guess.
Thanks for the help. I appreciate it.
I have a form with a number of text boxes for user input (this is in a User Form not on the spreadsheet). I have a few boxes that are related to currency and I need them to show the comma and decimal point as the user enters their criteria into the box. So far I have found a bunch of the same formulas online but when I input my number into the box it goes with 4.00 (if i hit 4 first) and all i can change after that is the second 0. Here is something similar I see online:
textbox1 = format(textbox1, "$#,##0.00")
Also seen some with cDbl
No matter what I try it won't let me enter anything more than the first number I enter. I need help. Thanks!
Formatting as the user types in data gets very tricky. May be better to format after the entry is complete.
Entry can also be validated and old value restored if entry deemed invalid
Dim TextBox1oldValue As String
Private Sub TextBox1_AfterUpdate()
If IsNumeric(TextBox1) Then
TextBox1 = Format(TextBox1, "$#,##0.00")
Else
TextBox1 = TextBox1oldValue
End If
End Sub
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If IsNumeric(TextBox1) Then
TextBox1oldValue = Format(TextBox1, "$#,##0.00")
End If
End Sub
Private Sub UserForm_Initialize()
TextBox1oldValue = "$0.00"
TextBox1 = "$0.00"
End Sub
You need to use the TextBox Change event, like:
Private Sub TextBox1_Change()
If TextBox1 = vbNullString Then Exit Sub
If IsNumeric(TextBox1) Then CurrencyTransform(TextBox1)
End Sub
You then create the CurrencyTransform function to modify what it shows in the TextBox.
Try simply this...
Private sub textbox1_AfterUpdate()
textbox1 = format(textbox1, "$#,##0.00")
end sub
I wrote this inspired by chris' solution. It works while user is typing!
Private waiting As Boolean
Private Sub TextBox1_Change()
If waiting Then Exit Sub
waiting = True
TextBox1 = formatAsCurrency(TextBox1)
waiting = False
End Sub
Private Function formatAsCurrency(v As String)
If v = "" Then
formatAsCurrency = Format(0, "0.00")
Else
Dim vv As Variant
vv = Replace(v, ",", "")
vv = Replace(vv, ".", "")
formatAsCurrency = Format(vv / 100, "#,##0.00")
End If
End Function
Try this:
Private Sub TextBox1_Change()
TextBox1.Value = Format(TextBox1.Value, "$#,##0.00")
End Sub
This worked for me just fine, so it should help you as well.
If you want to do calculations that involve multiple text boxes, don't use .value after the name of the text box. Instead, use val( before the name of the text box while following it with an end parenthesis. I used .value and got weird results. Instead of, for example, $100 for TextBox1.Value + TextBox2.Value where TextBox1.Valueis equal to $25 and TextBox2.Value is equal to $75, I would get "$25$75".