I have some code below that creates an input box, and I don't want to allow people to type symbols in. Is there something I can do to have a msgBox popup when someone enters a symbol that says not to, or disallow them altogether? Code pasted below. Thanks for any help up front :)
If AnswerYes = vbYes Then
Dim Discount1 As Variant
Discount1 = Application.InputBox("DO NOT ENTER % SIGN", "Product Discount Percentage", "##", Type:=1)
Dim Discount2 As Variant
Discount2 = Application.InputBox("DO NOT ENTER % SIGN", "SNS Discount net Percentage", "##", Type:=1)
This should work. The False response is for cancel. It will reject any text that isn't numeric. If you wanted something more sophisticated consider using ascii code.
Sub makeInput()
makeEntry:
theResponse = Application.InputBox("DO NOT ENTER % SIGN", "Product Discount Percentage", "##", Type:=1)
If theResponse = False Then Exit Sub
Dim i As Long
For i = 1 To Len(theResponse)
If Not (IsNumeric(Mid(theResponse, i, 1))) Then
MsgBox "Invalid Entry"
GoTo makeEntry
End If
Next i
End Sub
Create a userform like this
And then paste this code in the userform code area. The TextBox1_KeyPress will ensure the user doesn't type anything other than numbers and decimal.
Option Explicit
Private Sub UserForm_Initialize()
MyValue = 0: Cancelled = False
End Sub
'~~> OK Button
Private Sub CommandButton1_Click()
If Len(Trim(TextBox1.Text)) = 0 Then
MsgBox Label1.Caption
Exit Sub
End If
MyValue = Val(TextBox1.Text)
Unload Me
End Sub
'~~> CANCEL Button
Private Sub CommandButton2_Click()
Unload Me
Cancelled = True
End Sub
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, vbKeyClear, vbKeyDelete, vbKeyLeft, vbKeyRight, vbKeyUp, vbKeyDown, vbKeyTab
If KeyAscii = 46 Then If InStr(1, TextBox1.Text, ".") Then KeyAscii = 0
Case Else
KeyAscii = 0
Beep
End Select
End Sub
Now you can use it like this. Paste this code in a module
Option Explicit
Public MyValue As Double
Public Cancelled As Boolean
Sub Sample()
Dim frm As New UserForm1
Dim Discount1 As Double
Dim Discount2 As Double
With frm
.Caption = "WhatEver Title"
.Label1.Caption = "Enter Product Discount Percentage"
.Show
End With
If Cancelled = False Then
Discount1 = MyValue
MsgBox Discount1
End If
Set frm = New UserForm1
With frm
.Caption = "WhatEver Title"
.Label1.Caption = "Enter SNS Discount net Percentage"
.Show
End With
If Cancelled = False Then
Discount2 = MyValue
MsgBox Discount2
End If
End Sub
EDIT
If you want, you can create a common function for the module code.
Option Explicit
Public MyValue As Double
Public Cancelled As Boolean
Sub Sample()
Dim Discount1 As Double
Dim Discount2 As Double
Discount1 = ShowInputBox("WhatEver Title", "Enter Product Discount Percentage")
If Cancelled = False Then MsgBox Discount1
Discount2 = ShowInputBox("WhatEver Title", "Enter SNS Discount net Percentage")
If Cancelled = False Then MsgBox Discount2
End Sub
Private Function ShowInputBox(Title As String, Msg As String) As Double
Dim frm As New UserForm1
With frm
.Caption = Title
.Label1.Caption = Msg
.Show
End With
If Cancelled = False Then ShowInputBox = MyValue
End Function
Related
I made a workbook that has a userform thar is used to fill information in a new row, the information in the textboxes should be prefilled by using the information on the row below. This has to be repeated as many times as an input box value.
So far so good, but now I also need the users to be able to view other sheets in the same workbook where the required information is stored while the userform is open.
if I show the userform modeless I can view other sheets but then the code just keeps going and the second time the userform should pop up it doesn't.
I found a solution to that: using DoEvent.
but now the information is not (pre)filled correctly
Private Sub CommandButton2_Click()
Dim myValue As String
myValue = InputBox("How many do you have?")
If StrPtr(myValue) = 0 Then Exit Sub
For i = 1 To myValue
Range("A4").EntireRow.Insert
UserForm1.Show vbModeless
Do While UserForm1.Visible
DoEvents
Loop
Next
End Sub
What happens now is that the information from a row below is used regardless of any changes made by the user.
Does anyone have a solution?
Edit:
I don't think it is immediately required to understand my question but it might help a bit..
The rest of the code from the userform is as follows
Private Sub CommandButton1_Click()
Unload UserForm1
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
Range("A4").EntireRow.delete
End
End If
End Sub
Private Sub TextBox1_Change()
Dim myValue As Variant
myValue = TextBox1
Range("A4").Value = myValue
End Sub
Private Sub UserForm_Initialize()
Me.TextBox1.Value = Format(Range("A2"), "dd/mm/yyyy")
Me.TextBox2.Value = Range("B5").Value
Me.TextBox3.Value = Range("C5").Value
Me.TextBox4.Value = Range("D5").Value
Me.TextBox5.Value = Range("E5").Value
Me.TextBox6.Value = Range("F5").Value
Me.TextBox7.Value = Range("G5").Value
Me.TextBox8.Value = Range("H5").Value
Me.TextBox9.Value = Range("J5").Value
Me.TextBox10.Value = Range("K5").Value
End Sub
Private Sub TextBox10_Change()
Dim myValue As Variant
myValue = TextBox10
Range("K4").Value = myValue
End Sub
Private Sub TextBox11_Change()
End Sub
Private Sub TextBox2_Change()
Dim myValue As Variant
myValue = TextBox2
Range("B4").Value = myValue
End Sub
Private Sub TextBox3_Change()
Dim myValue As Variant
myValue = TextBox3
Range("C4").Value = myValue
End Sub
Private Sub TextBox4_Change()
Dim myValue As Variant
myValue = TextBox4
Range("D4").Value = myValue
End Sub
Private Sub TextBox5_Change()
Dim myValue As Variant
myValue = TextBox5
Range("E4").Value = myValue
End Sub
Private Sub TextBox6_Change()
Dim myValue As Variant
myValue = TextBox6
Range("F4").Value = myValue
End Sub
Private Sub TextBox7_Change()
Dim myValue As Variant
myValue = TextBox7
Range("G4").Value = myValue
End Sub
Private Sub TextBox8_Change()
Dim myValue As Variant
myValue = TextBox8
Range("H4").Value = myValue
End Sub
Private Sub TextBox9_Change()
Dim myValue As Variant
myValue = TextBox9
Range("J4").Value = myValue
End Sub
~~
I figured that it indeed had to do with the fact that your initial code did not retrigger the TextBox#_Change subs as intended. I did it a little differently, and triggered them in CommandButton2_Click. This way, you don't need to reload really. But whatever works; just sharing for comparison. So, I am assuming a UserForm like this:
We will move row 4 down on Confirm Input. On Cancel, we'll clear it and exit. And on Confirm Input, the user will (continuously) be asked whether he wants to submit another entry. If not, we'll clear row 4 and exit as well.
So, I've rewritten these parts:
Private Sub CommandButton1_Click()
Range("A4").EntireRow.ClearContents
Unload UserForm1
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
Range("A4").EntireRow.ClearContents
Range("A4").Resize(1, 11).Interior.Color = vbYellow
End
End If
End Sub
Private Sub CommandButton2_Click()
Range("A4").Resize(1, 11).Interior.Color = vbWhite
Range("A4").Resize(1, 11).Insert
Range("A4").Resize(1, 11).Interior.Color = vbYellow
For i = 1 To 10
myValue = Me.Controls("TextBox" & i).Value
Me.Controls("TextBox" & i).Value = ""
Me.Controls("TextBox" & i).Value = myValue
Next i
answer = MsgBox("Do you wish to add another row?", vbYesNo)
If answer = vbYes Then
Else
Range("A4").EntireRow.ClearContents
Unload UserForm1
End If
End Sub
Private Sub TextBox1_Change()
Dim myValue As Variant
myValue = TextBox1
If myValue = "" Then
Range("A4").Value = myValue
Else
Range("A4").Value = CDate(myValue)
End If
End Sub
You might want to get rid of the color (re)setting bits. But it may be good to realize that the practice of inserting rows all the time may have unintended effects for formatting. Suppose, for whatever reason, you want row 6 to have a red background. As is, the code will keep pushing this formatting one row down each time. This may be what you want, of course... Other than that, the "update" for TextBox1_Change makes sure you export an actual Excel Date, not a string.
Final warning (since we're using vbModeless): be aware that (both in your code and mine) there is no reference to the worksheet. Suppose your user goes into another sheet and clicks Confirm Input there, this will trigger Range("A4").Resize(1, 11).Insert inside the wrong sheet! Seems highly advisable to fix this.
I found a way..
I now changed the sub names of the textbox#_change subs and call them all on "userform unload".
Private Sub CommandButton1_Click() ' this is the command button on the userform
Call TX1
Unload UserForm1
End Sub
I have one sheet ("Settings"), which needs to be hidden most of the time. I have created Settings UserForm which contains various settings buttons and toggle button in there hides/show that hidden sheet (then clicked and password is entered).
Macro for hiding/showing sheet:
Private Sub SettingsTB_Click()
Dim strPassTry As String
Dim strPassword As String
Dim lTries As Long
Dim bSuccess As Boolean
If SettingsTB.Value = True Then
strPassword = "asd"
For lTries = 1 To 3
strPassTry = InputBox("Enter password", "Show Settings sheet")
If strPassTry = vbNullString Then Exit Sub
bSuccess = strPassword = strPassTry
If bSuccess = True Then Exit For
MsgBox "Incorrect password"
Next lTries
If bSuccess = True Then
Worksheets("Settings").Visible = True
End If
Else
Worksheets("Settings").Visible = xlSheetHidden
End If
End Sub
That macro works as intended, problem arises then I open UserForm and "Settings" Sheet is left visible. UserForm_Initialize event triggers SettingsTB_Click event (ask for entering password).
Code in UserForm_initialize used for remembering toggle button position (without it, every time, UserForm is opened, toggle button in FALSE possition):
Private Sub UserForm_Initialize()
If Worksheets("Settings").Visible = True Then
SettingsTB.Value = True
Else
SettingsTB.Value = False
End If
End Sub
Is it possible to stop SettingsTB_Click from triggering on UserForm_Initialize or should I use completely different approach?
Use a public variable or the tag-property to stop the click-event from running.
Private Sub SettingsTB_Click()
Dim strPassTry As String
Dim strPassword As String
Dim lTries As Long
Dim bSuccess As Boolean
If SettingsTB.Tag Then Exit Sub
If SettingsTB.Value = True Then
strPassword = "asd"
For lTries = 1 To 3
strPassTry = InputBox("Enter password", "Show Settings sheet")
If strPassTry = vbNullString Then Exit Sub
bSuccess = strPassword = strPassTry
If bSuccess = True Then Exit For
MsgBox "Incorrect password"
Next lTries
If bSuccess = True Then
Worksheets("Settings").Visible = True
End If
Else
Worksheets("Settings").Visible = xlSheetHidden
End If
End Sub
Private Sub UserForm_Initialize()
SettingsTB.Tag = True
If Worksheets("Settings").Visible = True Then
SettingsTB.Value = True
Else
SettingsTB.Value = False
End If
SettingsTB.Tag = False
End Sub
i tried various methods to select multiple sheets in the list box and returning the selected sheet names into the msgbox. can any one help doing this.
currently i am able to populate the sheet names in the list box.However i am not getting the all selected sheet names in the msgbox.
Public listChoice As String
Private Sub UserForm_Activate()
For n = 1 To ActiveWorkbook.Sheets.Count
With ListBox1
.AddItem ActiveWorkbook.Sheets(n).Name
End With
Next n
End Sub
Private Sub ListBox1_AfterUpdate()
listChoice = ListBox1.Text
End Sub
Private Sub CommandButton1_Click()
MsgBox (listChoice)
End Sub
Getting the selected item in a listbox isn't as straightforward as you'd want it to be:
Private Sub CommandButton1_Click()
Dim Msg As String
Dim i As Integer
Msg = "You selected" & vbNewLine
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
Msg = Msg & ListBox1.List(i) & vbNewLine
End If
Next i
MsgBox Msg
End Sub
credit: http://www.java2s.com/Code/VBA-Excel-Access-Word/Forms/GettheselecteditemsinaListBox.htm
You don't need the ListBox1_AfterUpdate() Sub or the public listChoice variable with this code
This msgbox the selected items in listbox.
Private Sub CommandButton1_Click()
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
Msg = ListBox1.List(i) & vbNewLine
End If
Next i
MsgBox Msg
End Sub
Something like this may assist,
Private strOP As String
Private dicSelections As Scripting.Dictionary
Private Sub ListBox1_Mouseup(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim strSheet As String
strSheet = Me.ListBox1.List(Me.ListBox1.ListIndex)
If Me.ListBox1.Selected(Me.ListBox1.ListIndex) Then
If Not dicSelections.Exists(strSheet) Then
dicSelections.Add strSheet, strSheet
Else
End If
Else
If dicSelections.Exists(strSheet) Then
dicSelections.Remove strSheet
End If
End If
End Sub
Private Sub UserForm_Click()
Me.ListBox1.AddItem "one"
Me.ListBox1.AddItem "two"
Me.ListBox1.AddItem "three"
End Sub
Private Sub UserForm_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "Worksheets selected " & Join(dicSelections.Items(), " & ")
End Sub
Private Sub UserForm_Initialize()
Set dicSelections = New Scripting.Dictionary
End Sub
I need a macro that prevent the excel from closing while I fill in number remotely to a column. Initially I already ask the user to enter the ID. the next step is prevent closing . How can it be done?
below is the code for ID enter and cell selection.
Sub Enter_1()
Dim data_1 As String
Dim sCell As Variant
Dim rslt As Integer
Dim x As Integer
Do
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
data_1 = InputBox(Prompt:="Enter Employee No.", Title:="Employee", Default:="Enter Employee No. here")
If data_1 = "" Then
QuestionToMessageBox = "Exit?"
YesOrNoAnswerToMessageBox = MsgBox(QuestionToMessageBox, vbYesNo, "No")
End If
If YesOrNoAnswerToMessageBox = vbNo Then
data_1 = InputBox(Prompt:="Enter Employee No.", Title:="Employee", Default:="Enter Employee No. here")
Exit sub
End If
If Not IsNumeric(data_1) Or data_1 = "" Then
rslt = 0
Else: rslt = 1
End If
If rslt = 0 Then
MsgBox "You can only enter a number in this field"
Else:
Sheets("Oven After Assay Test").Activate
For x = 6 To 50
If Cells(x, 8).Value = "" Then
Cells(x, 8).Select
cancel = True
Exit For
End If
Next
End If
Loop While rslt = 0
End Sub
You can implement the requested functionality as follows:
Insert the code Module and add the following line:
Public FlagToClose As Boolean
In ThisWorkbook VBA code module add Sub:
Private Sub Workbook_Open()
FlagToClose = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not FlagToClose Then Cancel = True
End Sub
Modify your procedure as followoing:
Sub Enter_1()
FlagToClose = False
'YOUR PROCEDURE
'.....................
FlagToClose = True
End Sub
I have a userform which I wish to pass a range to. I have tried a couple of different ways to do it but does not seem to work.
Here is the sub code:
Option Explicit
Sub Additional_Comments_Normal()
Dim MSG1 As Integer
Dim msg As String
Dim act As Range
On Error GoTo ErrHandler
'Calls userform
MSG1 = MsgBox("Would you like to add comments", vbYesNo, "Add comments")
If MSG1 = vbYes Then
With AddComments
On Error Resume Next
Set act = Application.InputBox(Prompt:="Please choose files you wish to add comments to", Type:=8)
If act Is Nothing Then
Exit Sub
End If
Application.ScreenUpdating = True
.Show
End With
Else
Exit Sub
End If
ErrHandler:
If Err.Number <> 0 Then
msg = "Error # " & Str(Err.Number) & " was generated by " _
& Err.Source & Chr(13) & Err.Description
MsgBox msg, , "Error", Err.HelpFile, Err.HelpContext
End If
End Sub
And the userform code is here:
Public act As Range
Private Sub CommandButton1_Click()
Dim ctl As Control
Dim rng As Range
Dim MSG2 As Integer
Dim sfile As String
If act.Column > 1 Then
MsgBox ("Please choose File name from Column 1")
Exit Sub
End If
If act.Row < 4 Then
MsgBox ("Please choose a valid file")
Exit Sub
End If
If Me.TxtComment.Value = "" Then
MsgBox "Please add comments", vbExclamation, "Additional Comments"
Me.TxtComment.SetFocus
Exit Sub
End If
If Me.TxtName.Value = "" Then
MsgBox "Please add your name", vbExclamation, "Additional Comments"
Me.TxtName.SetFocus
Exit Sub
End If
MSG1 = MsgBox("Add Comments ?", vbYesNo, "Add comments")
If MSG1 = vbNo Then
End If
If MSG1 = vbYes Then
act.Offset(0, 16).Value = act.Offset(0, 16).Text & " " & Me.TxtComment.Value
act.Offset(0, 17).Value = act.Offset(0, 17).Text & " " & Me.TxtName.Value
For Each ctl In Me.Controls
If TypeName(ctl) = "TextBox" Then
ctl.Value = ""
End If
Next ctl
AddComments.Hide
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
End If
End Sub
Private Sub CommandButton2_Click()
End Sub
Private Sub CommandButton3_Click()
Unload Me
End Sub
Private Sub UserForm_Click()
End Sub
I then get an error about the act not being defined variable.
Can anyone shed some light on better process for this?
You have set Option Explicit at the top of your code. That means that all variables need to be defined (which is considered good programming practice). So, you have two options to resolve this:
(1) Remove the line Option Explicitfrom your code or
(2) define all of your variables using the Dim command. In this case you'd have to add Dim act as Range to your Sub CommandButton1_Click on the form.
If you want to pass a variable to another sub then you can do so calling that sub with that variable like so:
Call Additional_Comments_Normal(act)
and the sub header neeeds to change like so:
Sub Additional_Comments_Normal(ByVal act as Range)
'(your code)'
End Sub
If "passing a variable to another sub" is too much trouble then you can also save the range somewhere in your file like so:
SomeHiddenSheet.Range("A1").Value2 = act
and in the other sub you can initiate act again:
act = SomeHiddenSheet.Range("A1").Value2