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.
Related
I am trying to create a user-form that will automatically create x amount of printed out user forums from a data base. I cant figure out how to get the certain value from the data base to be inputted into the certain text.box on my user-form. Right now the code will go through my data base and find all bridges that are "slabs" and then find the corresponding NBI number, but I can't figure out the exact syntax to use it seems like. I have tried using various different methods, but all seem to have some sort of problem. final goal is to fill out a user-form with the text boxes NBI NO.(textbox(1)), Local ID No.(textbox(5)), structure No(textbox(4)), and type(textbox(3)).
Sub word()
Dim i As Integer
Dim feat As String
feat = ("Slab")
Range("O4:O13").Clear
For i = 2 To 23089
If Cells(i, 11) = feat Then
TextBox(1).Text = Cells(i, 11)
Else
End If
Next i
End Sub
Based on what you've indicated in your question and comments, this should fix your issue:
NOTE: The below code is referencing data on 'Sheet1' using a UserForm named 'UserForm1' and a TextBox on that UserForm named 'TextBox1'.
Sub text()
Dim i As Integer
Dim feat As String
feat = ("Slab")
Range("O4:O13").Clear
For i = 2 To 23089
If Cells(i, 11) = feat Then
UserForm1.TextBox1.Text = Sheets(1).Cells(i, 11).Text
Else
End If
Next i
End Sub
The change I've made is in the If...Else statement, I've made reference to the UserForm with UserForm1. Rather than referencing the index of the TextBox, I've referenced it by name TextBox1 and lastly, I've specified the Sheet and what data from the cell I want Sheets(1).Cells(i, 11).Text.
By doing this the code will loop through each row of the sheet between 2 and 23089 checking column 'K' for "Slab". If it's found it will populate TextBox1 with "Slab".
NOTE:
If you are running this code in your UserForm module you should replace the UserForm1. reference with Me..
If you want the TextBox to populate the text from another cell in the Row (as you said in your question), change the column index in the line UserForm1.TextBox1.Text = Sheets(1).Cells(i, 11).Text from 11 to whatever the correct column index is.
Be sure to change the above code to use the correct object names (UserForm1 should be your userforms name, TextBox1 should the the relevant TextBox name etc.) Also don't forget to change the Sheets(1). reference to reference the correct sheet for your workbook.
I'll leave it to you to adjust the code to reference your values correctly.
I have a userform which looks like this
All the textboxes are filled with default values once a user opens this form.
The user then changes the values manually and presses OK which will close the form and will affect the charts linked to the form.
If the user opens the form again, the values in the textboxes revert back to default ones and the charts linked will assume their default positions too.
Is there any way where once the user presses OK, the values in the userform gets saved so when the user opens the form the next time, they are presented with the changed values instead of the default ones??
Thanks!
Have you tried using the Sheet as a place to save the data?
Dim i As Integer
Private Sub UserForm_Initialize()
For i = 1 To 49 'Number of TextBoxes (I counted 49)
Controls("TextBox" & i).Text = Cells(i, 1)
Next i
End Sub
Private Sub CommandButton1_Click() 'Save button
For i = 1 To 49
Cells(i, 1) = Controls("TextBox" & i).Text
Next i
End Sub
This will save the values in the first 49 rows of the first coloumn. If you want to save it to an other Sheet, create a new one and add Worksheets("SheetName").Cells....
Another solution if you don´t have similiar names (but Hungarian Notion like cbTest for a combo box) for the control elements, so you cannot iterate through them with a command like Controls("TextBox" & i)....
If you have a userform (e. g. called ufTest), then you can iterate through all control elements like this:
Dim controlElement as Control
For Each controlElement In ufTest.Controls
MsgBox controlElement.Name
' Check for type of control
If Left(controlElement.Name, 2) = "cb" Then
MsgBox = controlElement.Text
ElseIf Left(controlElement.Name, 3) = "txt" Then
MsgBox = controlElement.Value
End If
Next controlElement
This gets you the name of every control element in your userform, no matter how you´ve called your controls.
P. S.: I´m sure there is a way to get the type of the control without using the Hungarian Notion, but I did not find it in time.
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.
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".
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.