Excel VBA Textbox resets to 0 when i press a button - excel

i have a userform with 2 textboxes, 2 labels and a log in button.
On my excel sheet i have a sort of database with id, name, pin and balance.
the problem is whenever i click the login button my ID textbox resets its value to 0, but my pin textbox works fine!
i will paste my complete code:
Dim ID As Integer
Dim PIN As Integer
Dim PINField As String
Dim Balance As Double
Dim Attempts As Integer
Dim BalanceField As String
Private Sub btnLogin_Click()
txtID.Text = ID
Call SetId
Call Authenticate
End Sub
Sub Authenticate()
If txtPin.Text = PIN Then
Call Welcome
ElseIf Attempts > 3 Then
Call Bye
Else
lblWelcome.Caption = "Wrong Pin"
lblWelcome.ForeColor = RGB(255, 0, 0)
Attempts = Attempts + 1
End If
End Sub
Sub SetId()
PINField = "C" & Str(ID)
PINField = Replace(PINField, " ", "")
MsgBox (PINField)
BalanceField = "D" & Str(ID)
BalanceField = Replace(BalanceField, " ", "")
MsgBox (BalanceField)
End Sub
Sub Welcome()
MsgBox ("Login Successful. Welcome")
End Sub
Sub Bye()
MsgBox ("Max Pin Attempts reached. Contact Your Bank")
Unload frmLogin
End Sub

The reason it does this is because you are using a variable which has no value. Since it is an Integer it returns 0.
I'm guessing you probably actually want to have ID = txtID.Text - that is, take the value of the txtID textbox and store the value in the ID variable.
This will probably error though because the Text property of a textbox is a String. You will need to use ID = CInt(txtID.Text). You should also do some checking to make sure that txtID.Text evaluates to an Integer before assignment.

Please make sure there's no reset for the txtID anywhere in the code that you have not shown here. Looking at your code, it doesn't say anything how you are setting values to either ID or PIN... You said it's working fine for PIN, so it makes me very curious...
It could be the case Nick pointed out given this is a Form with textboxes allowing people to enter ID and PIN.. And then you are comparing it against PIN. But what are you comparing against? As you said you have a database kind of a structure in the sheet. You need to assing ID and PIN using it.
Here is the visualization I have for your Sheet, which is my best blind guess:
User needs to enter a value via the Form into txtID. That number is infact the cell number for column C which contains the relevant PIN. Then you compare that PIN with the txtPIN value. Next return the balance from column D based on that PIN.
Try this:
Private Sub btnLogin_Click()
If txtID.Text <> "" Or txtID.value > 0 or txtPIN.Text <> "" Then
ID = CInt(txtID.Text)
Call SetID
Call Authentication
Else
MsgBox "ID and PIN" can't be empty!"
End If
End Sub
Sub Authenticate()
If CInt(txtPin.Text) = PIN Then '-- here
Call Welcome
'-- idealy Blance can be shown at this point...
ElseIf Attempts > 3 Then
Call Bye
Else
lblWelcome.Caption = "Wrong Pin"
lblWelcome.ForeColor = RGB(255, 0, 0)
Attempts = Attempts + 1
End If
End Sub
Sub SetId()
PIN = CInt(Trim(Sheets(1).Range("C" & ID).value))
'-- NOT sure why you are showing this PIN here since you want to authenticate...?
MsgBox PIN
BalanceField = Sheets(1).Range("D" & ID).value
BalanceField = Trim(BalanceField) '--here
'-- doesn't make sense to show Balance before authentication...
MsgBox BalanceField
End Sub
Trim is clearner and faster than Replace..

Related

How to do if statement that prevents a combo value from being added to a list box when the list box already has the combo value (Duplicate scenario)

I am having trouble finding a way if the combobox value is selected to add to the listbox but if the combobox value is already display in the listbox then a msgbox appears saying "this value is already in the listbox". I am trying to use an if statement then a for loop. For example, if I pick the letter d and then add it to the listbox it will but if I pick d again from the combo box then a message will acquire saying this value is already in the listbox and will not add the letter d again.
I believe I should use an if statement, but I don't know have to formulate it
Private Sub cmdplayer_Click()
Dim ratio As Double
Dim formatratio As String
Dim name As String
Me.listbox.ColumnCount = 2
If cmbComboBox.Value = "" Then
MsgBox "Please Select a Player"
ElseIf cmbComboBox.Value = Me.listbox.List Then
MsgBox cmbComboBox.Value & " has already been added to your team"
Else
name = Me.cmbComboBox.Column(0)
Me.listbox.AddItem name
ratio = Me.cmbComboBox.Column(3)
formatratio = FormatNumber(ratio, 1)
Me.listbox.List(listbox.ListCount - 1, 1) = formatratio
End If
End Sub
try this:
Private Sub cmbComboBox_Change()
Dim duplicate As Boolean
Dim person As String, lName As String
person = Me.cmbComboBox.Column(0)
duplicate = False
For i = 0 To Me.listbox.ListCount - 1
lName = Me.listbox.List(i)
If lName = person Then
duplicate = True
MsgBox "This person is already part of the team."
Exit For
End If
Next i
If Not duplicate Then
Me.listbox.AddItem person
End If
End Sub

How to click out of Combobox?

I have a combobox with the properties MatchEntry 1-fmMatchEntryCompleteand MatchRequired True.
I need it true to prevent any invalid entry in the combobox. I dont want to make this a Style 2-fmStyleDropDownList but rather keep it a Style 0-fmStyleDropDownCombo because I have about 1000 items to choose from.
This setup works, except if you accidentally click in the combobox, and try to click out of it. You keep getting
Invalid Property Value
Is there anyway I could code the invalid entries so I don't have to assign the property to True?
Figured it out if anyone has this problem in the future. All I did was keep the properties above, and add this code to my userform for the combobox1.
Private Sub ComboBox1_Change()
If Me.ComboBox1.Value = "" Then
'Match not required if zero lenght string
Me.ComboBox1.MatchRequired = False
Else
'Match is required if other than zero length string
Me.ComboBox1.MatchRequired = True
End If
End Sub
You can use the combo LostFocus event. It will check if the value matches one of the combo entries, send a message in case of not, and delete the combo value. Or it can do something else, if my suggestion is not good enough:
Private Sub ComboBox1_LostFocus()
If ComboBox1.Value = "" Then Exit Sub
Dim cbVal As Variant, boolFound As Boolean, i As Long
cbVal = ComboBox1.Value
For i = 0 To ComboBox1.ListCount - 1
If cbVal = ComboBox1.list(i) Then boolFound = True: Exit For
Next i
If Not boolFound Then _
MsgBox "The value """ & cbVal & """ does not exist between the combo items" & vbCrLf & _
"It will be deleted", vbInformation, "Illegal entry": ComboBox1.Value = ""
End Sub
MatchRequired should remain False (default)...

Excel VBA: delete row after specific password is entered

I have a sheet filled with booking numbers and associated data. In VBA I already have the code ready to delete a booking number with its associated row.
Some of these booking numbers shouldn't be allowed to be removed and I would like a password (tied to this booking) to be used in order to remove it.
Here is the delete code I have:
Private Sub btn_verwijderen_Click()
' try to retrieve the product by ID
Dim rngIdList As Range, rngId As Range
Set rngIdList = ActiveSheet.Range([B2], [B2].End(xlDown))
Set rngId = rngIdList.Find(Me.txtBookingnr, LookIn:=xlValues)
If rngId Is Nothing Then
' bookingnumber is not found
Exit Sub
Else
If MsgBox("you are about to delete: " & "Booking:" & Me.txtBookingnr & ". Are you sure?", vbYesNo) = vbYes Then
If MsgBox("You can't undo this process. Sure to delete?", vbYesNo) = vbYes Then
Sheets("Invoer").Range("Tabel133").Find(Me.txtBookingnr.Value).Delete
Sheets("Gastenlijst_vertrekkers").Columns(2).Find(Me.txtBookingnr, , , , 1).EntireRow.Delete
Sheets("Gastenlijst").Columns(2).Find(Me.txtBookingnr, , , , 1).EntireRow.Delete
MsgBox "Booking is deleted. Refresh update now (automatically)"
Call updatePlanning_Click
Call btn_cancel_Click
Else
MsgBox "Nothing changed"
End If
End If
End If
End Sub
Now, this code works for the rows that the user IS allowed to delete. But for the numbers the user CANNOT delete, should be protected by a password they need to fill in, in order to officially delete the row.
So for example:
Column B = Booking#
Column C = Initials
Column D = Surname
Column E = Checkin date
Column F = Checkout date
etc. etc. etc.
Let's say that Booking number: 1800123 is canceled and need to be removed from the list. I hit the button: Remove (btn_verwijderen) and I will get the first MsgBox. After hitting YES, there should be a new message asking for a password. After entering the correct password, the booking should be removed. BUT the password is tied to a specific booking.
Hopefully, some of you guys know how to achieve this.
Thanks in advance for your help.
Here is some pseudo code that illustrates one approach. In your main sub, you need to state what booking you want to delete. You then need to check to see if that booking requires a password.
The function Password will return either TRUE (okay to delete) or FALSE (not okay to delete) to your sub. Therefore, your delete test needs to be based around the output of this function, which is illustrated in Sub Example.
The Function Password output possibilities are as follows:
TRUE: If booking number to delete does not exist in the array var (no password required)
TRUE: If booking number to delete does exist in the array and the correct password is entered
FALSE: If booking number to delete does exist in the array and the wrong password is entered
I recomend you test this code out as is to understand how it works. Then build it into your main sub. You should really only need to modify the array values in the function. The bulk of the work will be building your delete statements around the result of this function
Notice I am passing the booking number 2 into the function manually. You need to swap the 2 for your variable booking number.
Option Explicit
Sub Example()
If Password(2) Then 'If function returns TRUE
MsgBox "Add Delete Code Here"
Else 'If function returns FALSE
MsgBox "Incorrect Password"
End If
End Sub
Private Function Password(Booking As Long) As Boolean
Dim var As Variant, i As Long, PW As String
var = [{1, 2, 3, 4, 5; "Password1", "Password2", "Password3", "Password4", "Password5"}]
For i = LBound(var, 1) To UBound(var, 2)
If Booking = var(1, i) Then
PW = Application.InputBox("Password required to delete booking: " & Booking, "Password Protected", Type:=2)
If PW = var(2, i) Then
Password = True
Exit Function
Else
Password = False
Exit Function
End If
End If
Next i
Password = True
End Function
Disclaimer
Anyone with VBA knowledge will be able to view any passwords you store using this method. You can tighten the security by password protecting your VBA Project, however, this is still not 100% dummy proof. There are ways, which can be found on this site, that go into great detail about how to break these passwords.

How to dynamically obtain numeric part of userform control name - VBA

I have 2 small lists of combo boxes. The first list is labled Type(1-5). The second list is labled Products(1-5). I want to populate each PRODUCT box pending on the selection made in the corresponding TYPE box. I am currently doing the following...
Private Sub Type1_Change()
NavComboPropChange
End Sub
Sub NavComboPropChange()
If BaseActiveControl.Name = "AVM" Then
= Worksheets("Setup").Range("AVM").Value
ElseIf BaseActiveControl.Name = "Appraisal" Then
= Worksheets("Setup").Range("APPRAISAL").Value
Else
= Worksheets("Setup").Range("TITLES").Value
End If
End Sub
BaseActiveControl.name grabs the root control element currently selected. Before the equal sign in the IF, ElseIf, Else sequence would be the product name and the corresponding value.
To restate my question though, I want to know how I can grab the numeric part of the control name to use in conjunction with the product box name.
I found the solution using this route.
Sub NavComboPropChange()
Dim myString As String
myString = Right(BaseActiveControl.Name, Len(BaseActiveControl.Name) - 4)
If BaseActiveControl.Value = "AVM" Then
Controls("Products" & myString).List = Worksheets("Setup").Range("AVM").Value
ElseIf BaseActiveControl.Value = "Appraisal" Then
Controls("Products" & myString).List = Worksheets("Setup").Range("APPRAISAL").Value
Else
Controls("Products" & myString).List = Worksheets("Setup").Range("TITLES").Value
End If
End Sub

Is it possible to increase the 256 character limit in excel validation drop down boxes?

I am creating the validation dynamically and have hit a 256 character limit. My validation looks something like this:
Level 1, Level 2, Level 3, Level 4.....
Is there any way to get around the character limit other then pointing at a range?
The validation is already being produced in VBA. Increasing the limit is the easiest way to avoid any impact on how the sheet currently works.
I'm pretty sure there is no way around the 256 character limit, Joel Spolsky explains why here: http://www.joelonsoftware.com/printerFriendly/articles/fog0000000319.html.
You could however use VBA to get close to replicating the functionality of the built in validation by coding the Worksheet_Change event. Here's a mock up to give you the idea. You will probably want to refactor it to cache the ValidValues, handle changes to ranges of cells, etc...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ValidationRange As Excel.Range
Dim ValidValues(1 To 100) As String
Dim Index As Integer
Dim Valid As Boolean
Dim Msg As String
Dim WhatToDo As VbMsgBoxResult
'Initialise ValidationRange
Set ValidationRange = Sheet1.Range("A:A")
' Check if change is in a cell we need to validate
If Not Intersect(Target, ValidationRange) Is Nothing Then
' Populate ValidValues array
For Index = 1 To 100
ValidValues(Index) = "Level " & Index
Next
' do the validation, permit blank values
If IsEmpty(Target) Then
Valid = True
Else
Valid = False
For Index = 1 To 100
If Target.Value = ValidValues(Index) Then
' found match to valid value
Valid = True
Exit For
End If
Next
End If
If Not Valid Then
Target.Select
' tell user value isn't valid
Msg = _
"The value you entered is not valid" & vbCrLf & vbCrLf & _
"A user has restricted values that can be entered into this cell."
WhatToDo = MsgBox(Msg, vbRetryCancel + vbCritical, "Microsoft Excel")
Target.Value = ""
If WhatToDo = vbRetry Then
Application.SendKeys "{F2}"
End If
End If
End If
End Sub

Resources