Printing the output of an if-then statement in another column - excel

This sounds like the most simple thing ever but here I am.
I have a column with positive and negative numbers. I'm trying to script a code that will print either "P" or "N" in column B (or C or D, doesn't matter) depending on the value of the cell.
For example, if cell A2 has the value -32, then cell B2 should be assigned the string "N". Then goes A3/B3, A4/B4, and so on.
My trouble isn't with the if-then-else stament per se, rather HOW I can get the output to be printed where I want it to be.
Sub Negatives()
value = Range("A:A")
If Sgn(value) < 0 Then
//??? N
ElseIf Sgn(value) >= 0 Then
//??? P
End If
End Sub
Should I be using a for-loop instead to iterate through every value in the column?

Short answer yes. You could construct an array and stamp it in all at once but that will still require a loop to make decisions on each cell value.
I'd suggest:
Sub Negatives()
Dim numberRange As Range
Set numberRange = ThisWorkbook.Sheets("Sheet1").UsedRange.Columns("A")
For Each cell In numberRange.Cells
If cell.Value < 0 Then
cell.Offset(0, 1).Value = "N"
ElseIf cell.Value >= 0 Then
cell.Offset(0, 1).Value = "P"
End If
Next
End Sub

Related

Non-English characters: How to get VBA comparison to be consistent with Excel formula comparison?

Beyond ordinary Latin characters, Excel somehow does a pretty good job of sorting strings in various alphabets.
< and > in formulae use that same order.
But < and > in VBA use a different order - probably given by Unicode().
The extract below shows the inconsistency between columns B and C.
How can I compare strings in VBA using the same order that is used for sorting?
I am hoping that while X < Y will not give the relevant result, somefunction(X) < somefunction(Y) will do so.
I have found some articles/postings about how to change the sort order, but that is not the issue here.
Apologies for the above being an image - I can't work out how to get Excel data in to SO.
For replication:
The values in column A are: А Б В Г Ґ Д Е Є Ж З И Stop, starting from A2, which is named "first"
The formula in B2 is =IF(A2<A3,"Less than next","Greater than next")
The formula in D2 is =UNICODE(A2)
Column C is populated by the macro:
Sub Compare()
Range("first").Select
Do Until ActiveCell.Value = "Stop"
If ActiveCell.Value < ActiveCell.Offset(1, 0).Value Then
ActiveCell.Offset(0, 2).Value = "Less than next"
ElseIf ActiveCell.Value > ActiveCell.Offset(1, 0).Value Then
ActiveCell.Offset(0, 2).Value = "Greater than next"
Else
ActiveCell.Offset(0, 2).Value = "Same as next"
End If
ActiveCell.Offset(1).Select
Loop
End Sub
You can force VBA to use a different comparison method when comparing strings.
This can be done for a whole module, putting Option Compare Text at the top of the code - if done, you can use the regular comparison operators like < to > without changing your code (Default setting is Option Compare Binary)
You can also do this indiviually for a single comparison using the function strComp and pass vbTextCompare as third parameter (omitting tge third parameter will let VBA fall back to the defined Option Compare)
StrComp(cell.Value, cell.Offset(1, 0).Value, vbTextCompare)
Note that the text sorting option also will see upper and lower case characters as "equal".
Not 100% sure if those will always get the same results as the Excel compare, but at least for your given examples it did. If you don't trust this, you can fall back to the Evaluate-method that really uses the Excel-engine.
Option Compare Text
Sub Compare()
Dim cell As Range
Set cell = ThisWorkbook.Sheets(1).Range("A2")
Do Until cell.Value = "Stop"
Dim formula As String, res As Variant
formula = """" & cell.Value & """ < """ & cell.Offset(1, 0).Value & """"
res = Application.Evaluate(formula)
cell.Offset(0, 1) = getCmpInfostr(res)
cell.Offset(0, 2) = getCmpInfostr(cell.Value < cell.Offset(1, 0).Value)
cell.Offset(0, 3) = getCmpInfostr(StrComp(cell.Value, cell.Offset(1, 0).Value))
cell.Offset(0, 4) = getCmpInfostr(StrComp(cell.Value, cell.Offset(1, 0).Value, vbTextCompare))
Set cell = cell.Offset(1, 0)
Loop
End Sub
Function getCmpInfoString(c As Variant)
If VarType(c) = vbBoolean Then
c = IIf(c, -1, 1)
End If
If VarType(c) <> vbInteger And VarType(c) <> vbLong Then
getCmpInfostr = "invalid"
ElseIf c < 0 Then
getCmpInfostr = "Less than"
ElseIf c > 0 Then
getCmpInfostr = "Greater than"
Else
getCmpInfostr = "Same"
End If
End Function
Obligatory hint for all VBA programming: avoid Select and ActiveCell - see How to avoid using Select in Excel VBA
The following code shows the different methods - let the code run once with and once without the Option Compare Text option.

VBA loop one cell upward until cell not equal "" and a cell incorporate two IF functions

I'm totally new to VBA, am learning it by myself. Here is the problem:
enter image description here
So for Column E
If B = "S" Then
E = "" // null
If B = "F" Then
E = (Reverse Rank x PREVIOUS Adjusted Rank + no of failure + 1)/(Reverse Rank + 1)
or in formula excel format
E5 = ((D5*E4)+($K$1+1))/(D5+1)
So the problem lies on the PREVIOUS adjusted rank in the formula. Say, to get value of E5 it needs value of E4 BUT if E4 = "" so it has to go one cell upward. If one cell upward is also ="", it has to go one cell upward again until is not equal <> "".
The problem is I'm not sure what function is right to use. I think it would be IF and LOOP but I don't understand how to write the condition. Like I said I'm totally new and time constraints cause me anxiety. Also, if you notice, for Column E there are two IFs function I suppose? One is E is depended on Column B.
If Range("B2:B" & lastRow) = "S" or "F" and one is if E="" or <> ""
How I incorporated with that?
I think you can do this without using VBA. You can use the following to get the previous non-blank value in column E:
E5=INDEX($E:$E,MAX(ROW($E$1:$E4)*(LEN($E$1:$E4)>0)))
This formula looks in column E above cell E5 (i.e. E1:E4) and returns the one cell with the largest row value that is also not blank (length > 0).
From there, your whole formula becomes:
E5=IF($B5="S","",IF($B5="F",($D5*INDEX($E:$E,MAX(ROW($E$1:$E4)*(LEN($E$1:$E4)>0)))+($K$1+1))/($D5+1)))
Note that these are array formulas, so they must be validated using Ctrl+Shift+Enter. Also, the top non-blank value in column E has to be input manually or with a different formula.
What's the first value in column E when you meet the first "F" in
column B? I mean, there is nothing in column E, what is the "PREVIOUS Adjusted Rank". In this case, I just set it 0.
What's "no of failure"?
Here is my solution for you and I set "no of failure" as zero.
Sub test()
Dim i, j As Integer
Dim previous As Single
Dim NoOfFailure As Single
For i = 2 To Cells.CurrentRegion.Rows.Count
If Cells(i, 2).Value = "S" Then
Cells(i, 5).Value = ""
ElseIf Cells(i, 2).Value = "F" Then
previous = 0
NoOfFailure = 0
For j = i To 2 Step -1
If Cells(j, 5).Value <> "" Then
previous = Cells(j, 5).Value
Exit For
End If
Next
Cells(i, 5).Value = (Cells(i, 4).Value * previous + NoOfFailure + 1) / (Cells(i, 4).Value + 1)
End If
Next
End Sub

Changing cell value for a range of cells without multiple if statments

I would like to change the color of a cell based on the value of an adjacent cell. The following code is working properly for a single cell, but I would like it to apply to a range of cells, currently it looks at the value of S5 and changes to color of T5, I would like this to iterate for a range of cells (S5 to S100 matching with T5 to T100). How can I do this without needing to make an if statement for 100 cells?
If LCase(Sheets(1).Range("S5").Value) = "yes" Then
Sheets(1).Range("T5").Interior.ColorIndex = 33
ElseIf Sheets(1).Range("S5").Value <> "" Then
Sheets(1).Range("T5").Interior.ColorIndex = 19
Else
Sheets(1).Range("T5").Interior.ColorIndex = 0
End If
To elaborate on my comment, you could do something like this:
For i = 5 to 100
If LCase(Sheets(1).Range("S"&i).Value) = "yes" Then
Sheets(1).Range("T"&i).Interior.ColorIndex = 33
ElseIf Sheets(1).Range("S"&i).Value <> "" Then
Sheets(1).Range("T"&i).Interior.ColorIndex = 19
Else
Sheets(1).Range("T"&i).Interior.ColorIndex = 0
End If
Next i
Note how instead of referring directly to "S5", instead the code refers to Si [for whatever number i is, starting at 5 and going row by row up to 100].
Conditional formatting in EXCEL would probably be the best way to handle this:
Conditional Formatting
Grade 'Eh' Bacon gave a good solution for doing this, and it is acceptable. Here is another solution that should work fine and allows some different math based Column/Row solutions if you need to make these actions more modular.
Set myRange = Range("S5:S100")
For Each cell in myRange
If LCase(cell.Value) = "yes" Then
cell.Offset(0, 1).Interior.ColorIndex = 33
ElseIf LCase(cell.Value) = "no" Then
cell.Offset(0, 1).Interior.ColorIndex = 19
Else
cell.Offset(0, 1).Interior.ColorIndex = 0
End If
Next
Range Offset Information
Here is an interesting way to do this:
Const FORMULA = "CHOOSE(MMULT(--(~>{""yerz"",""""}),{1;1})+1,0,19,33)"
With [t5:t100]
v = Evaluate(Replace(FORMULA, "~", .Address))
For i = 1 To .Count
.Item(i, 2).Interior.ColorIndex = v(i, 1)
Next
End With
This small solution packs a lot of learning opportunities that can be leveraged far beyond this question.
Notice that your color numbers can be edited at the end of the first line.
Here is what is happening.
We use the Evaluate function to evaluate a formula that takes your range of values T5:T100 and produces an array of color numbers.
We then assign each value in the array to the ColorIndex of the cell to the right.
The challenging part is creating the formula that will result in the appropriate array of color numbers. :)

Beginner to VBA: Greater than

I have numerical values entered in Row 1 from columns A to IA. I want to create a loop that compares one cell with the cell before it (aka Cell B1 to A1 or cell F to E). Let's use B1 and A1 as the example. It looks at the Value in Cell B1 and sees if it is greater then the value of the cell in A1. If it is greater then I want a + to be entered in the Cell B2. Also if B1 is < A1 put a - into Cell B2. I want the program to be able to loop this process so it does it for all the columns A-AI. Below is what I want want the program to do (not including the dashes and teh paranthesis around the positive and negative signs of course).
A B C D F
1 33.12 34.52 34.92 35.19 34.97
2 (+) (+) (+) (-)
I realize this task is easily performed in excel (not using VBA) but I am trying to learn VBA so I can perform much more complex tasks. I have written the basic code to do the simple task but I am not sure how to loop it so it will do this for all my cells!
Sub EnterFormula()
Dim x As Integer
Dim y As Integer
x = Worksheets("Sheet2").Range("C2").Value
y = Worksheets("Sheet2").Range("B2").Value
If x > y Then
Worksheets("Sheet2").Range("C4") = "+"
End If
End Sub
Ok So for the next part of My Program. It gets a touch more complicated. We move onto row 3. Row 3 is going to either have a U (for Up) or a D (for down) or nothing.
Let's Start at Column C. Column C1 has a value of 34.92, and C2 was given a + (as 34.92 was larger then the day before which was 33.02). Now we go to the first previous "+" WITH AT LEAST one opposite sign (in this case "-") in between. So in this case that is row A (one "-" inbetween under row B). Now if the Numerical Value in C1 (34.92) is larger then the numerical value in A (33.12) then we designate a "U" in C3. If it was NOT larger we would leave an empty cell in C3.
Let's move onto column D. Column D1 has a value of 35.19 which is greater then the C1 value of 34.92 and this is why D2 has a "+". Next we go to the first previous "+" WITH AT LEAST one opposite sign (in this case "-") in between. So in this case that is row A again. Since the numerical value in D1 (39.19) is greater then the numerical value in A1 (33.12) then D3 gets a U.
Moving onto Column F (32.97)...Note:I changed the value a little from the original F. 32.97 is LESS then 35.19 (D1) which is why F2 is a "-". Next we go to the first previous "-" WITH AT LEAST one opposite sign (in this case "+") in between. So in this case this is Row B (with two "+" signs in between). Now because we are dealing with "-" signs this time we look and see if the numerical value in F1 is LESS then the numerical value in B1...which it is, so a "D" is entered in F3. If F1 was larger then B1 then the cell would be left empty.
Onto Column G (35.21). This is greater then 32.97 (F1) and therefore gets a "+" in G2. Next we go to the first previous "+" WITH AT LEAST one opposite sign in between (in this case "-"). So in this case this is Row D (with one "-" in between). Since the numerical value of G1 is greater then that of D1 we designate a "U". If it was not greater we would leave the cell empty.
A B C D F G H I
1 33.12 33.02 34.92 35.19 32.97 35.21 35.60 35.90
2 (+) (-) (+) (+) (-) (+) (+) (+)
3 U U D U U U
Here is my code so far for this. I have added to my original code which was creating the "+" signs and "-" signs.
Sub Comparison()
Dim targetCell As Range
Dim targetSignCell As Range
Dim currentSign As String
Dim currentNumericalCell As Currency
' Find out what sign (+ or -) the current Cell has in it
currentSign = Worksheets("Sheet2").Range("H3").Value
'Variable to associate the numerical number above the current Cell
currentNumericalCell = Worksheets("Sheet2").Range("H2").Value
' Here we iterate through each cell in a specified range
' Since you know you want to start at B1 and go until E1,
' you can ues the following syntax to go through each cell
For Each Cell In Range("B2:H2")
' Get the value of the current cell with the .Value property
currentValue = Cell.Value
' Now get the value of the cell that is before it (column-wise)
previousValue = Cell.Offset(0, -1).Value
' Create a variable for our target cell
Set targetCell = Cell.Offset(1, 0)
' Here are the basic comparisons
If currentValue > previousValue Then
targetCell.Value = "+"
ElseIf currentValue < previousValue Then
targetCell.Value = "-"
ElseIf currentValue = previousValue Then
targetCell.Value = "="
Else
' Not sure how it would happen, but this
' is your catch-all in case the comparisons fail
targetCell.Value = "???"
End If
' Now go to the next cell in the range
Next Cell
'Alex starting to code
For Each Cell In Range("H3:B3")
' Find out what the sign is in the cell before it
previousSign = Cell.Offset(0, -1).Value
'Variable used to find the first cell with an
'Opposite sign as the current cell
oppositeSign = Cell.Offset(0, -2).Value
'Variable to associate the numberical number above the first Opposite Sign Cell
oppositeNumericalCell = Cell.Offset(-1, -2).Value
' Create a Variable for Target Cell
Set targetSignCell = Cell.Offset(1, 0)
If currentSign.Value = "+" And currentSign.Value <> previousSign.Value And oppositeSign.Value = currentSign.Value And currentNumericalCell.Value > oppositeNumericalCell.Value Then
targetSignCell = "U"
ElseIf currentSign.Value = "-" And currentSign.Value <> previousSign.Value And oppositeSign.Value = currentSign.Value And currentNumericalCell.Value < oppositeNumericalCell.Value Then
targetSignCell = "D"
Else
End If
Next Cell
End Sub
I agree with #JohnBustos that a formula would be much more efficient, however if this is indeed a learning exercise then here is a simple example that would do what you want:
Sub Comparison()
Dim targetCell As Range
' Here we iterate through each cell in a specified range
' Since you know you want to start at B1 and go until E1,
' you can ues the following syntax to go through each cell
For Each cell In Range("B1:E1")
' Get the value of the current cell with the .Value property
currentValue = cell.Value
' Now get the value of the cell that is before it (column-wise)
previousValue = cell.Offset(0, -1).Value
' Create a variable for our target cell
Set targetCell = cell.Offset(1, 0)
' Here are the basic comparisons
If currentValue > previousValue Then
targetCell.Value = "+"
ElseIf currentValue < previousValue Then
targetCell.Value = "-"
ElseIf currentValue = previousValue Then
targetCell.Value = "="
Else
' Not sure how it would happen, but this
' is your catch-all in case the comparisons fail
targetCell.Value = "???"
End If
' Now go to the next cell in the range
Next cell
End Sub
And if you were to do it as a formula, it could be something like this (entered into B2 and copied to the end of the range):
=IF(B1>A1,"+",IF(B1<A1,"-","="))
This compares the cell above the formula and the cell to the left of that cell and adds the appropriate symbol.
Assuming there are no empty cells in the range you want to work in, you could do it like this:
Range("b2").Select
Do Until IsEmpty(ActiveCell.Offset(-1, 0))
If ActiveCell.Offset(-1, 0).Value > ActiveCell.Offset(-1, 1).Value Then
ActiveCell.Formula = "+"
End If
If ActiveCell.Offset(-1, 0).Value < ActiveCell.Offset(-1, 1).Value Then
ActiveCell.Formula = "-"
End If
ActiveCell.Offset(0, 1).Select
Loop
If there are empty cells in the range then instead of 'do until' use
dim I
for I = 1 to ..
next I

How to print the output value of a column by fixing a particular corresponding reference value in another column

A B C
x=value at C corresponding to A at 0.5
0 5655 0
0.25 6757 545
0.5 7856 5776
0.75 9866 5644
please help me to print the value (say 'x') at somewhere in column B (say B2). It should select the value of column C always corresponding to 0.5 at column A and the 0.5 value will be fluctuating from 1 place to another depending on the input steps given. so whatever it may be, the final output must always be the value corresponding to 0.5
It sounds like you're looking for a VLOOKUP formula. In short, it does exactly what you want - matches a value in one column and returns the value in a column to the right. In this case, assuming your formula is in cell D2, try this:
=VLOOKUP(0.5, A:C, 3, FALSE)
This will look for the value 0.5 in column A and return the corresponding value in column C. Note that it will return the first match if there are multiple 0.5's.
Do like this:
Sub UseSelection()
Dim r As Long
r = ActiveSheet.UsedRange.Rows.Count
Range("A1").Select
Do Until Selection.Row > r
If Selection.Value = 0.5 Then
Range("B2") = Range("C" & Selection.Row).Value
End If
Selection.Offset(1, 0).Select
Loop
End Sub
Or using Vlookup:
Sub UseVlookup()
Range("B2") = Application.WorksheetFunction.Vlookup(0.5, Range("A:C"), 3, False)
End Sub
Or,
Sub Another()
Range("B2") = "=VLOOKUP(0.5,A:C,3,FALSE)"
End Sub
Or put the formula in the cell itself (not flexible)
=VLOOKUP(0.5,A:C,3,FALSE)

Resources