Excel - Is it possible to make characters appear as "*" in a range? - vba

Does anyone know if it's possible to make the text that is input into an Excel range appear as "*******"? I want users to be able to enter a password into a range to sign in (without a Userform), but I want the characters to be asterisks (*) when the user types so that it can't be seen.
I'll use a Userform as a last resort, but I'd like to try to do this without a Userform first.
Can anyone offer any help?
Thank you!

Another possibility could be to use text box ActiveX control in the Sheet with PasswordChar property set to e.g. *. Then the text user enters in the text box will be displayed as *. The text box can be formated so it has the same size as the containing cell and it will be sized when containing cell size changes etc. Linked-cell can be used so the password value can be read from this cell.

Doing this without a userform is less than ideal because this code will get run every time something on the sheet changes. strPassword gets dimensioned as a global variable and must be Dim'd at the top of your code.
Dim strPassword As String
Private Sub Worksheet_Change(ByVal Target As Range)
If Sheet1.Cells(1, 1).Value <> "********" Then
strPassword = Sheet1.Cells(1, 1).Value
Sheet1.Cells(1, 1).Value = "********"
End If
MsgBox strPassword
End Sub
If there's room on your sheet, adding this code to a button (ie, Button1_Click event) that would read the password and replace the cell value would prevent the code from running with every change.

Related

Excel VBA userform type mismatch

First time asking a question here, my apologies if my question has already been answered (If it was, I didn't understand it because I am an utter novice). My Excel userform that I use to update quantities of stock supplies used on a particular job is generating a
type mismatch error
It is supposed to add the quantity from the useform to the entry in the appropriate cell on the sheet. I assume that this has something to do with a variable not being declared correctly.
Private Sub SubmitFormButton_Click()
Dim Data_Start As Range
Dim i As Integer
Set Data_Start = ActiveSheet.Cells(6, 6)
For i = 1 To 31
Data_Start.Offset(i, 0) = Data_Start.Offset(i, 0) + AddToform.Controls("TextBox" & i).Value
Next i
Unload AddToform
End Sub
AddToform.Controls("TextBox" & i).Value is making a number of assumptions:
AddToForm was shown with AddToForm.Show. If you're doing this:
With New AddToForm
.Show
'...
End With
...then the code is not referring to the instance that's being displayed, and the .Value of the textbox is very likely not what you expect it to be, since the textbox you're reading from isn't the textbox that the user entered a value in.
There's a control named "TextBox" & i on the form. This means if you ever rename your textboxes to more meaningful names, e.g. FirstNameBox, LastNameBox (or whatever makes sense), then the code breaks. Using control names to hold metadata (e.g. some worksheet row number offset) can work, but it's probably better to iterate the controls on the form (whatever their names are), test if the current control is a TextBox (e.g. If TypeOf ctrl Is MSForms.TextBox Then), and then pull the metadata from the control's Tag property. That way your controls can have meaningful names and renaming them won't break any of the logic.
User input is valid. That's always a bad assumption to make, regardless of the language or technology being used: always protect your code from invalid input. If the user enters "ABC", that loop breaks. One way to do this, is to introduce a local variable, to separate getting the user input from consuming the user input - and validate it on the way:
If IsNumeric(Controls("TextBox" & i).Value) Then
Dim validInput As Double
validInput = CDbl(Controls("TextBox" & i).Value)
Data_Start.Offset(i, 0) = Data_Start.Offset(i, 0) + validInput
End If
And that should fix your bug.

Is it possible set my Excel Userform Combo box to begin narrowing the fields while data is entered?

VBA Newbie here.
I have searched high and low for this answer, and even come across other questions very similar to mine, but cannot get an answer. So I am hoping that this is my lucky day.
I have a Userform in excel that has Four combo boxes. Each combo box has a drop down with several choices. In two of these boxes, there are many business names and a lot of these names are similar. I was wanting to have the feature where are the data was being typed into the box, it would begin to narrow the options. EXAMPLE: if I type "heating and air" it begins to only show items in the list that include that word or phrase.
Is this a properties change in the box, or a code written, or something else?
Please help- I am stumped and no one seems to have the answer.
Very grateful-
Excel Newbie
Yes this is very possible. All you have to do is create a sub that populates that combo box, set it up so that when adding it checks the value of the box for example if it was the basic typing example. basic format. This assumes the possible values are stored in an array. This would add any item that has the string entered in it. (in any position)
For I = 0 to Number of Values
If instr(Value(I), ComboBox.Text) > 0 then
add item
endif
next
I played around a bit and came up with something to get you started. This basically functions as an "auto search". It is not autocomplete because it will search entire terms, not just terms which begin with whatever you've typed in. Basically I assume you have a range of cells (in this example cells A2:A121) that have the date for your drop down in it.
Setup
Add a new generic module (I named mine GlobalVars and add the following code:
Option Explicit
Public IgnoreChange As Boolean
Public RangeOfData As Variant
The Code
Open the code to your UserForm.
Add the following code:
Private Sub UserForm_Initialize()
RangeOfData = Application.WorksheetFunction.Transpose(Sheet1.Range("A2:A121").Value)
IgnoreChange = False
End Sub
Be sure to update A2:A121 and Sheet1 (I am using code name, but Worksheets("Sheet1") would work just as well) to point to the data which contains your combobox choices.
Now, the meat of the job is handled in the Combobox_Change event
Private Sub ComboBox1_Change()
If Me.ComboBox1.Text = vbNullString Then
Me.ComboBox1.Clear
SendKeys ("{Enter}")
End If
If Me.ComboBox1.TextLength > 2 Then
Dim i As Long, j As Long
If IgnoreChange = False Then
Me.ComboBox1.Clear
SendKeys ("{Enter}")
DoEvents 'Bug with NumLock
For i = LBound(RangeOfData) To UBound(RangeOfData)
If UCase(RangeOfData(i)) Like "*" & UCase(Me.ComboBox1.Text) & "*" Then
Me.ComboBox1.AddItem RangeOfData(i)
End If
Next i
Me.ComboBox1.DropDown
End If
End If
IgnoreChange = False
End Sub
Be sure to change ComboBox1 to the name of your combobox control.
Basically, what this does is it handles user input when it reaches two characters or longer. The code will search through your input data range and then return results that match the string as the user is entering it. The results is like a suggestions box.
I should note that with this method, the combobox is NOT pre-populated with data, so users must begin typing something into the combobox.
Additionally, I added the following code to handle the backspace key:
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 8 Then
IgnoreChange = True
End If
End Sub
Again be sure to change ComboBox1 as appropriate.
For my example, I loaded all 120 crayola crayon colors into a spreadsheet (that is what is in Sheet1 from A2:A121).
Here is example output for when I start typing, first I input blu:
As you can see I am getting all values that contain blu, including those that don't start with blu such as Cadet Blue or Midnight blue.
As another example, I will search for flower
So as you can see, instead of being a combobox with 120 static options, it is updated based on what the user types and tied to a list of values in your cells.
I did notice that SendKeys sometimes toggled my NumLock, this is a known issue. The point of that line is to collapse the drop down after the user deletes all of the text or continues texting so as to "refresh" the auto-generated list.

Show picture upon cell selection that matches cell string to picture database in excel

I will attempt to explain to the best of my abilities what I am looking for as far as a final product. I am trying to make a spreadsheet that has a list of strings in a column.
When the strings are hovered over, the string will be used to match to the name of a picture in a database. The database will return the picture and show it as a rollover image.
I have searched for ways on how to do this, but I keep finding people who change it based on the comments and use a static image for each cell. I have a database of around 23000 pictures and can't do it manually one at a time, and the cells have the potential to be variable depending on the opened sheets.
Hover over is not necessary, however. I would be more than happy to do this upon a cell selection.
This is a broad question and covers many parts. Here is a little something to get you started.
Open the VB Editor by pressing Alt+F11. Right click on the sheet you want this functionality to exist on and then click View Code. This code will load a comment with a single image (be sure to change C:\YOUR_IMAGE_FULL_PATH to a valid image) into whichever cell you click into. When you leave the cell it will delete the comment.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.Count = 1 Then
Static cellAddress
Dim sFile As String
Dim cmt As Comment
If cellAddress <> "" Then
Set cmt = Range(cellAddress).Comment
cmt.Delete
Set cmt = Nothing
End If
sFile = "C:\YOUR_IMAGE_FULL_PATH"
Set cmt = Target.AddComment
cmt.Text Text:=""
With cmt.Shape
.Fill.UserPicture sFile
End With
cellAddress = Target.Address
End If
End Sub
When you say
The database will return the picture and show it as a rollover image
Does that mean the image itself is stored in the database? Or is the name of the image returned from the database and we have to search a directory on the HDD for an image with that name?
Without knowing your DBMS or your table schema or anything like that I can't really help much more.

VB, excel macro pause and resume working if possible

I cannot figure out the best way to do the following problem. Basically my macro (excel, VB) is checking several (100+) worksheets for correct values, if wrong value is found, I want it to stop, give me a warning, then I could have a look into the reason why the value is wrong, correct it manually and then I want to resume the macro, or remember the last value checked so if I return, it remembers where to continue (resume).
My current problem is that it finds the wrong value, then I can either make it stop so I check the problem, or it goes through all the sheets and then I have to remember which sheets had the wrong value.
What I thought of is make a list where the name of sheet is added every time a wrong value is found. The problem is that usually there is more than 1 wrong value in the same sheet if there is a wrong value at all and this added the same sheet name several times to the list. Another problem with that is that I cannot correct the values straight away.
I'm very inexperienced with programming and so would appreciate your idea on how to best approach this problem (I don't want to spend a long time on coding something which wouldn't be efficient for such a "simple" problem).
When the error is found (I'm assuming you've already been able to identify this), you can use the Application.InputBox function to prompt you for a new value.
For example, if rng is a Range variable that represents the cell being checked, and you have some logic to determine where the error happens, then you can just do:
rng.Value = Application.InputBox("Please update the value in " & rng.Address, "Error!", rng.Value)
The inputbox function effectively halts execution of the procedure, while waiting for input from the user.
If InputBox isn't robust enough, then you can create a custom UserForm to do the same sort of thing. But for modifying single range values, one at a time, the InputBox is probably the easiest to implement.
I believe you can handle this task by using one or two static local variables in your macro. A variable declared with "static" rather than "dim" will remember its value from the last time that procedure was run. This can hold where you left off so you can resume from there.
One thing that could be a problem with this solution would be if the macro gets recompiled. That would probably cause VBA to clear the value that the static variable was holding. Just doing a data edit in Excel should not cause a recompile, but you will want to watch for this case, just to make sure it doesn't come up. It almost certainly will if you edit any code between executions.
Create a public variable that stores the cell address of the last checked cell and use a conditional statement to see if it's "mid-macro" for want of a better phrase. here is a very crude example...
Public lastCellChecked As String
Sub Check_Someting()
Dim cell As Excel.Range
Dim WS As Excel.Worksheet
If Not lastCellChecked = vbNullString Then Set cell = Evaluate(lastCellChecked)
'// Rest of code...
'// Some loop here I'm assuming...
lastCellChecked = "'" & WS.Name & "'!" & cell.Address
If cell.Value > 10 Then Exit Sub '// Lets assume this is classed as an error
'// Rest of loop here...
lastCellChecked = vbNullString
End Sub
The best way to do this is to create a userform and as mentioned by prior users create a public variable. When the program finds an error store the cell and initiate the userform. Your code will stop on the userform. When you're done checking the problem have a button on the userform that you can click to continue checking. Your loop can be something like the below.
public y as integer
sub temp1 ()
rw1= range("a500000").end(xlup).row 'any method to create a range will do
if y = null then y=1
for x = y to rw1
cells(x,1).select
'check for the problem your looking for
if errorX=true then
userform1.show
y = activecell.row
exit sub
end if
next x
end sub
What about inserting a button (on the sheet or in a menubar) for stopping?
Insert the code below:
'This at the top of the module
Public mStop As Boolean
'This in the module
Sub MyBreak()
mStop = True
End Sub
'This is your macro
Sub YourMacro()
'This at the top of your code
mStop = False
'Your code
'...
'This code where you want to break
DoEvents '<<<< This makes possible the stop
If mStop Then
mCont = MsgBox("Do you want to continue?", vbYesNo)
If mCont = vbNo Then
Exit Sub
Else
mStop = False
End If
End If
'Your code
'...
End Sub
Now you need to create a button and link it to the macro called "MyBreak".

Find cell location based on value then do something- User Forms VBA Excel

i have experience in programing, however, I am new to VBA. I have a user form that i am working on. This form has a Combo Box that has a list initialized to it. What i am trying to do is:
*Get the ID Number value inputted by the user from the ComboBox
*Take the value inputted by the user and find its match using a range of values from a worksheet (i.e. Worksheet.Range("ID_Number_List"))
*Once it obtains it's match get the location of the cell that it matches
* Off set the location of the cell by one column to get the Name that relates to the ID Number(Same Row) to set it to textBoxName.Value
*Off set it two columns to get the telefone number that relates to the ID Number and set it to textboxTele.value
I want this to happen as soon as a value is selected from the Combobox, so my question is does my code go in the combo box or does it go to the next text box? so as soon as the person tabs over to the next text box the code is automatically execute. i would like the code to fully execute without tabing over to the next box.
This code is not complete but here is what i have (i didnt add the off set part i just did a test execution):
Dim ORIValue As String
'get value from combo_box Set
ORIValue = COMBO_ORILIST.Value
Dim cLoc As Range
Dim cORIVal As Range
'worksheet with the ID information Dim ORISheetList As Worksheet
Set ORISheetList = Worksheets("ORI_LIST")
'
For Each cLoc In ORISheetList.Range("ORI_LIST")
'compare the input string from list- considering using Match function for this
If StrComp(cLoc, ORIValue, vbTextCompare) Then TextBAgencyName.Value = "test"
Else: Next cLoc
End If
Let me know what you think. If i have to rewrite everything i will.
Your code doesn't compile.
If you have a userform with a single combobox called ComboBox1, you need to put your cell-finding code in the form code as follows:
Private Sub ComboBox1_Change()
MsgBox "yep, this is where the code should go"
End Sub
I suspect using the rowsource property of the combobox in combination with the index of the selected value you probably don't need to actually perform a search for the selected value. Something like this might work:
Private Sub ComboBox1_Change()
MsgBox Range(ComboBox1.RowSource).Cells(ComboBox1.ListIndex + 1)
End Sub
Hope that helps.