Non-functional IF Else VBA - vba

Witless newbie attempting an If Else based on entries made on a user form:
If OptionButtonMed.Value = True Then
pp = pp + 2
ElseIf OptionButtonLarge = True Then
pp = pp + 4
ElseIf OptionButtonXL = True Then
pp = pp + 8
Else: pp
End If
It simply does not work. Suggestions valued.

You get a run-time error, because of your Else statement, you need to give pp a valid value.
If you try pp = pp +1 or whatever value, it will work.
Also, it's good practice to keep .Value after the Control you are trying to test the Critera. (the = True is actually not necessary)
Modify your code to:
If OptionButtonMed.Value Then
pp = pp + 2
ElseIf OptionButtonLarge.Value Then
pp = pp + 4
ElseIf OptionButtonXL.Value Then
pp = pp + 8
Else
pp = pp + 1 ' <-- just for example
End If

Related

VBA Else without if error

I keep getting the " Else without if" error in VBA when I clearly do not have that issue. Does anyone know how to fix it? It takes me to the elseif statement that begins with elseif memb= "platinum"
Below is my code:
ElseIf memb = "Platinum" Then d = 0.01
ElseIf memb = "Black" Then d = 0.03
End If
If st >= min Then cb = st * d Else cb = 0
End If
If cb >= thresh Then MsgBox ("cb is greater than thresh")
End If
tac = st + cb
Range("B5").Value = st
Range("B7").Value = cb
Range("B9").Value = tac
I'm going to assume your first If statement goes something like this:
If memb = "Gold" Then d = 0.005
ElseIf memb = "Platinum" Then d = 0.01
ElseIf memb = "Black" Then d = 0.03
End If
If some processing is performed on the same line as the Then keyword, VBA treats it as a single, non-nested If statement. This means that anything after that will be treated as a new statement and not related to prior If statement.
What you can do is put the processing statement(s) on the next line after each If-Then and ElseIf-Then statements.
Example,
If memb = "Gold" Then
d = 0.005
ElseIf memb = "Platinum" Then
d = 0.01
ElseIf memb = "Black" Then
d = 0.03
End If
With this in mind, you may want to fix the succeeding If-Then-Else statements in your code. The End If part becomes meaningless if your If-Then-Else is in a single line.
Your code seems to have syntax error and error message tells you that.
Or you did not post all code?
Have a look on MS documentation: https://msdn.microsoft.com/de-de/library/752y8abs.aspx
Do you really stick to the syntax?
Without even having MS OFfice this should (be better readable and) work:
If memb = "Platinum" Then
d = 0.01
ElseIf memb = "Black" Then
d = 0.03
End If
If st >= min Then
cb = st * d
Else
cb = 0
End If
If cb >= thresh Then
MsgBox ("cb is greater than thresh")
End If
tac = st + cb
Range("B5").Value = st
Range("B7").Value = cb
Range("B9").Value = tac

More Multidimensional Array Issues

I am trying ti fill arrays based on conditions, and it seems my sample code is sticking values in the wrong position. I included the position where it is being altered. I tried doing some basic +1/-1 fixes but so far all these efforts have misplaced things or returned various other errors.
to be more clear- the issue is that in the v loop, the value is being stuck in the (o,0) position instead of the (o,v) position (over writing the previous value).
I thought the way I had it structured would for each loop perform o's criteria and then check for v's criteria and in turn when v would loop would enter the value in the v position that is equal to the current value of o?
Im clearly missing something and any pointers in the correct direction would be gladly appreciated
Dim Cbox(9, 1)
For o = LBound(Cbox, 1) To UBound(Cbox, 1)
If LPDif2 = 0 Then
Cbox(o, 0) = 0
ElseIf LPDif2 < 3 And LPDif2 > 0 Then
CCount = CCount + LPDif2
Cbox(o, 0) = LPDif2
Else
CCount = CCount + 3
Cbox(o, 0) = 3
LPDif2 = CNLP - CCount
End If
LPDif2 = CNLP - CCount
If CCount = CNLP Then BCount = BCount + 1
WCount = WCount + CW
If CCount < CNLP And CCount >= Round(CLng(CNLP) / 2 + 0.000001, 0) Then DCount = DCount + 1
If CCount >= CNLP Then DCount = DCount + 2
For v = LBound(Cbox, 2) To UBound(Cbox, 2)
If CCount >= Round(CLng(CNLP) / 2 + 0.000001, 0) And DCount = 1 Then
Cbox(o, v) = "Green"
If CTCombo = "9 W" Then
AXWCount = WCount / 2
WH.Value = Ceiling(AXWCount, 9)
Else
WH.Value = WCount
End If
End If
Next v
Next o
Based on the comments, the code inside of the inner loop should only be running if the value of v is 1. It should be as simple as just eliminating the inner loop entirely and hard coding the value "1":
For o = LBound(Cbox, 1) To UBound(Cbox, 1)
'...
If CCount >= Round(CLng(CNLP) / 2 + 0.000001, 0) And DCount = 1 Then
Cbox(o, 1) = "Green"
If CTCombo = "9 W" Then
AXWCount = WCount / 2
WH.Value = Ceiling(AXWCount, 9)
Else
WH.Value = WCount
End If
End If
Next o

Upper Case in VB 6 text box

How to make first letter in upper case while pressing tab or space in vb 6.0 ?
My code is as follows
txtFirstName.Text = UCase$(txtFirstName.Text)
but it doesn't change after tab or space
It's just simple just do this in the text box keypress events...
Private sub textbox_keypress(KeyAscii As Integer)
KeyAscii = Asc(UCase(Chr(KeyAscii)))
End Sub
Use the LostFocus event
Private Sub yourTextBox_LostFocus()
With yourTextBox
'first letter in upper case, the rest, untouched.
.Text = UCase(Mid(.Text, 1, 1)) & Mid(.Text, 2, Len(.Text))
End With
End Sub
Apply the same logic to the KeyDown event and check if the pressed key is the space key.
Private Sub yourTextBox_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 32 Then
With yourTextBox
'first letter in upper case, the rest, untouched.
.Text = UCase(Mid(.Text, 1, 1)) & Mid(.Text, 2, Len(.Text))
.SelStart = Len(.Text) 'put the cursor at the end of the textbox...
End With
End If
End Sub
StrConv Function
Returns a Variant (String) converted as specified.
Syntax
StrConv(string, conversion, LCID)
The StrConv function syntax has these named arguments:
Part Description
string Required. String expression to be converted.
conversion Required. Integer. The sum of values specifying the type of conversion to perform.
LCID Optional. The LocaleID, if different than the system LocaleID. (The system LocaleID is the default.)
Settings
The conversion argument settings are:
Constant Value Description
vbUpperCase 1 Converts the string to uppercase characters.
vbLowerCase 2 Converts the string to lowercase characters.
vbProperCase 3 Converts the first letter of every word in string to uppercase.
AND THERE IS MORE ...
TO GSERGE
$ means nothing when applied to a function name as opposed to a variable name. VBA uses $ AND B as a suffix to denote similar functionality.
VB6 IS VBA the person who said maybe in VB6 but not in VBA. VB6 program host VBA as their programming language. VB6 on it's own are some app objects and the forms package only - no programming language. It's best to think of VB6 as a VBA host like Office.
If you want to proper case see this WORDBASIC Ver 6 code, (which word 2003 helpfully converted to vba).
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Public Sub MAIN()
Select Case WordBasic.Int(GetModifer)
Case 0
WordBasic.ChangeCase
Case 1
WordBasic.ChangeCase 4
Case 2
WordBasic.ChangeCase 2
Case 3
ProperCase
Case Else
WordBasic.ChangeCase
End Select
End Sub
Private Sub ProperCase()
Dim F
Dim z
Dim a$
Dim P
F = 1
WordBasic.ChangeCase 2
WordBasic.EditBookmark Name:="SerenityChangeCase", SortBy:=0, Add:=1
z = WordBasic.GetSelEndPos()
WordBasic.CharLeft 1
While WordBasic.GetSelEndPos() < z And Not WordBasic.AtEndOfDocument()
WordBasic.SelectCurWord
a$ = WordBasic.[Selection$]()
P = 0
If LCase(a$) = "a" Then
P = 1
ElseIf LCase(a$) = "an" Then
P = 1
ElseIf LCase(a$) = "as" Then
P = 1
ElseIf LCase(a$) = "at" Then
P = 1
ElseIf LCase(a$) = "be" Then
P = 1
ElseIf LCase(a$) = "by" Then
P = 1
ElseIf LCase(a$) = "in" Then
P = 1
ElseIf LCase(a$) = "is" Then
P = 1
ElseIf LCase(a$) = "of" Then
P = 1
ElseIf LCase(a$) = "on" Then
P = 1
ElseIf LCase(a$) = "or" Then
P = 1
ElseIf LCase(a$) = "to" Then
P = 1
ElseIf LCase(a$) = "and" Then
P = 1
ElseIf LCase(a$) = "are" Then
P = 1
ElseIf LCase(a$) = "for" Then
P = 1
ElseIf LCase(a$) = "the" Then
P = 1
ElseIf LCase(a$) = "from" Then
P = 1
ElseIf LCase(a$) = "what" Then
P = 1
ElseIf LCase(a$) = "with" Then
P = 1
End If
If P = 1 And F = 0 Then WordBasic.Insert LCase(a$)
WordBasic.WordRight 1
F = 0
Wend
WordBasic.WW7_EditGoTo Destination:="SerenityChangeCase"
WordBasic.EditBookmark Name:="SerenityChangeCase", SortBy:=0, Delete:=1
End Sub
Private Function GetModifer()
Dim a
Dim B
Dim c
Dim X
a = GetAsyncKeyState(16)
B = GetAsyncKeyState(17)
c = GetAsyncKeyState(18)
X = 0
If a < 0 Then X = X + 1
If B < 0 Then X = X + 2
If c < 0 Then X = X + 4
GetModifer = X
End Function
OK. Yeah txtFirstName is a good indicator of usage here.. So I'd use (sort of) Title Caps And I'd do it on the Validate event.. So
Private Sub txtFirstName_Validate(Cancel As Boolean)
Dim p As Integer ' i doubt we'll use more than 32K for a name....
Dim mName As String
p = 1
' first off lets trim any leading blanks.. assume NOTHING and make sure its all lower case..
mName = LCase(LTrim(txtFirstName))
Do While p > 0 And p <= Len(txtFirstName) ' start with the first non-blank
Mid(mName, p, 1) = UCase(Mid(mName, p, 1))
p = InStr(p, mName, " ")
If p > 0 And p < Len(mName) Then p = p + 1
Loop
Cancel = False
txtFirstName = mName
End Sub
Works every time, and capitalizes each word.. Didn't add any code to to do TRUE title caps but this is close, and short & easy...

Run function for multiple data sets and output results to different cells

I have been trying forever to try and figure this out. I have a set of data in a certain sheet in my Excel file. I have written code so that it outputs some of that information to another sheet. I don't know how to get the function to loop through all the different data sets and output them into the "Output" sheet in my excel file on different rows.
This is what I have so far. Can someone please help?
How do I get the function to run through about 6 data sets that include 5 cells in the column until there are 2 blank cells?
How do I output those different results to another sheet? I already have them outputting the first data set and it works fine. I just need to know how to do the other ones.
Thank you!
Sub EstBatch()
'variables
Dim N As String
Dim D As Date
Dim P As Integer
Dim H As Single
Dim NS As Integer
Dim NL As Integer
Dim BP As Currency
Dim OH As Single
Dim OC As Currency
Dim TP As Currency
Dim PPBR As Currency
Dim EHP As Single
Dim batches As Range
'inputs
N = Sheets("Batch Input").Range("A1").Value
D = Sheets("Batch Input").Range("B1").Value
P = Sheets("Batch Input").Range("A2").Value
H = Sheets("Batch Input").Range("A3").Value
PPBR = Sheets("User Form").Range("C22").Value
EHP = Sheets("User Form").Range("C23").Value
Range("A1").Select
'Processes
BP = P * PPBR
OH = H - 5
If P > 120 Or P < 20 Then
MsgBox ("Cannot Accommodate Group")
ElseIf P >= 20 And P <= 25 Then
NS = 1
NL = 0
ElseIf P >= 26 And P <= 50 Then
NS = 2
NL = 0
ElseIf P >= 51 And P <= 60 Then
NS = 0
NL = 1
ElseIf P >= 61 And P <= 85 Then
NS = 1
NL = 1
ElseIf P >= 86 And P <= 120 Then
NS = 0
NL = 2
End If
If OH > 4 Then
OH = 4
OC = BP * OH * EHP
ElseIf 0 < OH <= 4 Then
OC = BP * OH * EHP
ElseIf OH <= 0 Then
OC = 0
End If
TP = BP + OC
'outputs
Sheets("Batch Output").Range("A2").Value = N
Sheets("Batch Output").Range("B2").Value = D
Sheets("Batch Output").Range("C2").Value = P
Sheets("Batch Output").Range("D2").Value = H
Sheets("Batch Output").Range("E2").Value = PPBR
Sheets("Batch Output").Range("F2").Value = EHP
Sheets("Batch Output").Range("G2").Value = NS
Sheets("Batch Output").Range("H2").Value = NL
Sheets("Batch Output").Range("I2").Value = BP
Sheets("Batch Output").Range("J2").Value = OH
Sheets("Batch Output").Range("K2").Value = OC
Sheets("Batch Output").Range("L2").Value = TP
End Sub
Welcome to StackOverflow. Great first question.
I think what you're reaching for is how to use loops in solving a problem like this.
One easy way to do loops is with a counter, as in the examples I've given below. If appropriate, you can also use a range of cells to loop through data, as described in this answer: https://stackoverflow.com/a/19394207/2665195.
Starting with your second question: if you want a separate sheet for each output you can use Sheets.Add and paste into that new sheet. To do this you will want to use a variable naming convention like Sheets("Batch Output" & X).Range. In this way you can Dim X as Integer and loop through the process incrementing the X integer with each loop. Here's some sample code you can adapt for your purpose:
Sub ExampleAddSheets()
Dim intX As Integer
intX = 1
Dim wsBatchOutput As Worksheet
For intX = 1 To 6
Set wsBatchOutput = Worksheets.Add 'adds a worksheet and tags it to a variable
wsBatchOutput.Name = "BatchOutput" & intX 'names the worksheet
wsBatchOutput.Range("A1").Value = "Data here. Example " & intX
Next intX
Set wsBatchOutput = Nothing
End Sub
I don't know what your data source looks like, but hopefully it is set up in a way that you can turn the inputs aquisition into a loop. For example, if the data came into the system in rows (which your example does not seem to do) you could just increment the row number, something like this:
Sub ExampleSetInputs()
'variables
Dim N As String
Dim D As Date
Dim P As Integer
Dim H As Single
Dim PPBR As Currency
Dim EHP As Single
Dim intRow As Integer
intRow = 2
'inputs
For intRow = 2 To 7
N = Sheets("Batch Input").Range("A" & intRow).Value
D = Sheets("Batch Input").Range("B" & intRow).Value
P = Sheets("Batch Input").Range("C" & intRow).Value
H = Sheets("Batch Input").Range("D" & intRow).Value
Next intRow
End Sub
I hope this helps with your challenge.

Implementing a Variable in a Label Name in VB?

I currently have a huge IF statement and want to minimize it as much as possible.
I have a datagrid that i am populating from a SQL query and then from this datagrid i am passing the values into seperate labels.
I am able to create a For Each Loop in which i cycle through the variables looking until a counter reaches 7. However the problem arises when i need to incremente the Label name values by one. Each time, so essentially i need to add a counter variable into the Label name.
The code that i need to minimize is:
result73 = DataGridView1.Rows(0).Cells(0).Value.ToString
result74 = DataGridView1.Rows(0).Cells(1).Value.ToString
result75 = DataGridView1.Rows(1).Cells(0).Value.ToString
result76 = DataGridView1.Rows(1).Cells(1).Value.ToString
result77 = DataGridView1.Rows(2).Cells(0).Value.ToString
result78 = DataGridView1.Rows(2).Cells(1).Value.ToString
result79 = DataGridView1.Rows(3).Cells(0).Value.ToString
result80 = DataGridView1.Rows(3).Cells(1).Value.ToString
result81 = DataGridView1.Rows(4).Cells(0).Value.ToString
result82 = DataGridView1.Rows(4).Cells(1).Value.ToString
result83 = DataGridView1.Rows(5).Cells(0).Value.ToString
result84 = DataGridView1.Rows(5).Cells(1).Value.ToString
result85 = DataGridView1.Rows(6).Cells(0).Value.ToString
result86 = DataGridView1.Rows(6).Cells(1).Value.ToString
result87 = DataGridView1.Rows(7).Cells(0).Value.ToString
result88 = DataGridView1.Rows(7).Cells(1).Value.ToString
If result73 = "Monday" Then
DaySalesLbl1.Text = result74
ElseIf result73 = "Tuesday" Then
DaySalesLbl2.Text = result74
ElseIf result73 = "Wednesday" Then
DaySalesLbl3.Text = result74
ElseIf result73 = "Thursday" Then
DaySalesLbl4.Text = result74
ElseIf result73 = "Friday" Then
DaySalesLbl5.Text = result74
ElseIf result73 = "Saturday" Then
DaySalesLbl6.Text = result74
ElseIf result73 = "Sunday" Then
DaySalesLbl7.Text = result74
End If
This If Statement goes on for each variable that is declared above.
The Loop I have created looks something like this:
Dim cou As Integer
Dim n As Integer
cou = 0
n = 1
Do Until result74 <> ""
If result73 = cou Then
DaySalesLbl +n = result74
End If
cou = cou + 1
n = n + 1
Loop
But the section DaySalesLbl +n = result74 brings an Error because it looks for a generated method.
If, as I suspect, this is a WinForm project, then you can access the controls by name using the Form.Controls collection, like this:
Dim cou As Integer
Dim n As Integer
cou = 0
n = 1
Do Until result74 <> ""
If result73 = cou Then
Dim l As Label = CType(Me.Controls("DaySalesLbl" & n), Label)
l.Text = result74
End If
cou = cou + 1
n = n + 1
Loop
The Controls collection contains all the controls that are direct children of the form. You can access them by index (e.g. Me.Controls(0)), or by name (e.g. Me.Controls("DaySalesLbl6")). However, the collection stores the list as the base Control type, so you have to cast it to a the specific type before accessing the specific properties. That is why the CType(..., Label) is there in the example.
I would write code as follows:
For i as Integer = 0 to 7
Select Case DataGridView1.Rows(i).Cells(1).Value.ToString
Case "Monday"
Me.Controls("DaySalesLbl" & i+1).Text = DataGridView1.Rows(i).Cells(2).Value.ToString
Case "Tuesday"
Me.Controls("DaySalesLbl" & i+2).Text = DataGridView1.Rows(i).Cells(2).Value.ToString
... etc ...
I did this without the IDE, so I hope I didn't mess anything up, but I hope this sets you in the right direction and helps.