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
Related
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
I am trying to divide all the cells in a selection by 1000 but not cells which have a sum formula.
Criteria:
Cell must have a number.
Cell should not contain the Sum() formula (any other formula is okay).
If both of these criteria are met then divide the cell value by 1000.
For Each cell In Selection.Cells
If IsNumeric(cell) = False Or cell.Address = Left(ActiveCell.Formula, 5) = "=Sum(" Or cell.Address = Left(ActiveCell.Formula, 6) = "=+SUM(" Or cell.Address = Left(ActiveCell.Formula, 6) = "=-SUM(" Then
MsgBox ("Selection either does contain numbers or has only sum formulae")
Else
cell.value = cell.value / 1000
End If
Next
Not sure what you're trying to achieve with
Cell.Address = Left(ActiveCell.Formula,5) = "=Sum(
You can only compare one value with another.
I'm sure the more advanced people here will frown on the way I phrased the if statement but it does the job:
Sub divideBy1000()
Dim formCheck As Variant
For Each ccell In Selection.Cells
Debug.Print (ccell.Formula)
Debug.Print (ccell.Value)
formCheck = InStr(ccell.Formula, "SUM(") 'This checks if SUM is in the formula and returns a value bigger than 0 if so (where it occurs in the string).
If len(trim(ccell.value2))>0 Then
If IsNumeric(ccell.Value) And (formCheck = Null Or formCheck = 0) Then
'You have to use AND so none of the SUM formulas get through, no else needed this way
If Left$(ccell.Formula, 1) = "=" Then 'EDIT to keep your formula
ccell.Formula = "=(" & Right$(ccell.Formula, Len(ccell.Formula) - 1) & ")/1000"
Else
ccell.Value = ccell.Value / 1000
End If
End If
End If
Next ccell
End Sub
Edit:
Added a catch for empty cells so they don't turn to 0 and added Instr to check for the SUM as suggested by #Marcucciboy2
I am trying to make a macro in VBA-Excel that allows me to generate a simple sum (using a + sign) in a specific cell; keeping all the numbers in the formula of the cell. I mean i need that the output formula "hold" the values/adding formulas that are in a certain range. The numbers should be added automatically to the + formula. An special restriction is that in the event that there is no number in a cell of the range, the formula should not incorporate "0".
For example The data shown below are to numbers or sums within a Range (A1:A7):
A1: 5
A2: 7,5 --> =5+2,5
A3:
A4: 1
A5: 1 --> =3-2
A6:
A7: 5,5
Where A2: =5+2,5 and A5: =3-2. The other terms are just numbers.
Range of the example = A1:A7
Formula Output of the macro on B1 (or Cells(1, 2)) should be:
=5 + 5 + 2,5 + 1 + 3 - 2 + 5,5 (20)
The pseudo code should be like:
for i = 1 to 7 -> Cells(1, 2).FormulaLocal = if Cell(i,1) is a number (or an existing adding formula with values), add to the current formula. if its blank or 0, skip to next i (or row).
Output: formula "= Value1(5) + formula2(5+2,5) + Skip0Value3() +
Value4(1) and so on..
I already tried the following code with partially positive results:
Sub summanual()
Dim i As Integer
Dim y As String
For i = 1 To 7
If Cells(i, 1) <> 0 Then
y = Cells(i, 1)
Cells(1, 2).FormulaLocal = Cells(1, 2).FormulaLocal & "+" & y
End If
Next i
If Cells(1, 2) <> 0 Then
Cells(1, 2).FormulaLocal = "=" & Cells(1, 2).FormulaLocal
Else
Cells(1, 2) = ""
End If
End Sub
This works only for positives values. Negatives values are added
like "+-" to the output formula.
The output formula only stores the results of the origin cell. Ex:
A2 is 5+2,5 but it is added like 7,5. It should be split. Same with
A5.
Is fine to declare "y" variable as String in this case?
Any other optimization? Maybe there is a completely different
approach with better and faster result? Just new with vba-excel
Any help would be appreciated
Thanks
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
I have two integer values in 2 columns in excel. I need to retrieve these integers and form a ratio and then compare it with another ratio in another column.
For example, if the numbers are 2 and 3 in columns A1 & B1. I need to retrieve these values and form 2:3 in C1 and should compare if this is same as in D1 (with value 4:1).
How do i do it in VBA ?
I created a formula in C1 as =A1&":"&B1 and got the values in C1. However i am unable to compare this with the value in D1, and I am not sure how do I declare this variable in VBA ?
Kindly help me here.
You can try this ..
Private Sub Worksheet_Change(ByVal Target As Range)
Dim y As Integer
y = Target.Row
Select Case Target.Column
Case 1, 2 ' if col A
If IsEmpty(Cells(y, 1)) Or IsEmpty(Cells(y, 2)) Then
Cells(y, 3) = ""
Exit Sub
End If
Cells(y, 3) = "'" & Cells(y, 1) & ":" & Cells(y, 2)
Case 3 ' then compare
MsgBox IIf(Cells(y, 3) = Cells(y, 4), "Equal", "Not Equal")
End Select
End Sub
This use ' sign to avoid autoconvert value to time and for this you should have in D column with ' too ..
If D1 is formatted in the same way as C1 then a formula of =(D1=C1) would return TRUE or FALSE. In VBA this could be stored in a variable:
Dim blnSame As Boolean
blnSame = (Range("D1").Value = Range("C1").Value)
Based on the OPs further comment, an Excel formula would be:
=IF(Sheet1!C1=Sheet2!D1,"Win","Lose") ' or ,"Lose","Win"
(adjust the cell and sheet references as necessary) which could be copied down the column.
In VBA, a formula could be inserted into a range:
Worksheets("Sheet3").Range("E1:E10").Formula = _
"=IF(Sheet1!C1=Sheet2!D1,""Win"",""Lose"")"
If you want to loop down the column inserting the words "Win" or "Lose" then IMO you should study some VBA.