VBA Excel — Insert symbol based on cell value - excel

I need to work with Excel to which I am absolutely new. I am looking for a VBA solution to speed up some daily work. Here is my case: I need to check cells of Column C which has negative, positive and netural values and then insert sysmbols in corresponding cells of Column B.
For instance, if C4 has a positive value (2,345), B4 should have &u& as symbol. If C5 has negative value (-12.98), then B5 should have &d& as a symbol. And if C6 has a netural value (0.000), then B6 should be inserted with &n& as a symbol.
An empty B column already exists and values are all in Column C.

As Kyle says, all you need for this is a simple (well, nested) if-formula:
=IF(C1<0;"&d&";IF(C1>0;"&u&";"&n&"))
The format is pretty straightforward, the if has three parts separated by semicolons. The first is the logical test, what you test for, in this case if the value in C1 is smaller (or larger) than 0. The next is the value you want in the cell if the the statement in the test is true, and finally what to put in if it is false.
In this case, we test again if C1 is not smaller than 0, to see if it is larger than zero, that is why there is another if-statement inside the first one.
To apply the formula to your entire column, just copy it down the entire way, and the cell it refers to should update automatically.

Give this a try:
Sub WhatEver()
Dim C As Range
Set C = Intersect(ActiveSheet.UsedRange, Range("C:C"))
For Each cc In C
ccv = cc.Value
If ccv <> "" Then
If ccv = 0 Then
cc.Offset(0, -1).Value = "&n&"
ElseIf ccv > 0 Then
cc.Offset(0, -1).Value = "&u&"
Else
cc.Offset(0, -1).Value = "&d&"
End If
End If
Next cc
End Sub

Related

How to include another if function within a combined if, vlookup and index function?

My data looks like:
Colums C,D,E,F
Row 1 4,10,40,F
Row 2 4,12,48,F
Row 3 4,14,56,F
Row 4 3,16,48,F
Row 5 1,18,18,F
Row 6 1,20,10,F
Row 7 0,22,0,0
My foucs is on column F. My current array formula in column F is:
=IF(C31=0,VLOOKUP(INDEX($C$30:$C$38,MIN(($C$30:C30*D31)-$E$30:E30)),$C$30:$E$38,1),"F")
In case column C is is equal to 0, I want the formula of column F to return the value of column C,which has the respective minimum difference between column C (allrowsbefore) * column D (currentrow) and E(respective, all rows before). For instance, in row 2 that minimization problem would equal:C1*D2-E1, if C2 would be equal to 0.
However, now i want column F formular to only choose a value of C which is unequal to 0.
Hence, in column F7 i want column F to give me the value 1, as this is a C value which is bigger as 0 and has the respective min difference between (C6*D7)-E6.
(For value 4 of C it would be 32 and for value 3 of C it would be 18).
How and where do i include the if condition, that the value of C chosen has to be bigger as 1, into my existing formula ?
Thanks a lot for helping out, its much appreciated!!! In case i need to split up my existing formula that would be alright, too.
I reread your question more carefully after making my earlier comment, and I think I understand better now. To make sure you get the smallest value greater than 0, you use the following according to this KB article:
=MIN(IF(A1:A10>0,A1:A10))
So your formula in F7 should look like this for the ranges you described:
=IF(C7=0,VLOOKUP(INDEX($C$1:$C$7,MIN((IF($C$1:$C$7>0,$C$1:$C$7)*D6)-$E$1:$E$7)),$C$1:$E$7,1),"F")
EDIT
Okay. I think I finally understand the question. :)
If Cx <> 0, Fx = Cx
If Cx = 0, Fx = the address of the cell in Column C that produces minimum of (C1 * D7 - E1, C2 * D7 - E2, ..., CN * D7 - EN)
From what I know of Excel, I don't think you can do this with a single formula. INDEX and VLOOKUP both look for values in the worksheet, but you're trying to work from the value of a calculation (MIN). Using the array formula to find that value is really smart. But once we get the value (4 in this case), we can't use that to look up the address of the cell in column C that produced that result. I really can't think of any way to do this without a macro. Are you able to do that?
EDIT: Macro Solution
This is a little quick and dirty, but it passed the test. Make sure to save your workbook as a Macro-Enabled workbook. Hit Alt+F11 to open the macro editor. You might need to insert a new module. You can do this by right-clicking the workbook project in the project explorer on the left.
Once you've done this, double-click on the module. You should get a blank white text editor on the right. Paste the following code into that window:
Public Function MinimumC()
Dim rngCurrent As Range
Set rngCurrent = Application.ThisCell
Dim rngMin As Range
Dim minimum As Long
minimum = 100000000
Dim tmp As Long
Dim rngC As Range
Set rngC = ActiveSheet.Range("C1:C" & rngCurrent.Row - 1)
For Each c In rngC.Cells
If c.Value2 <> 0 Then
tmp = c.Value2 * rngCurrent.Offset(0, -2).Value2 - c.Offset(0, 2)
If tmp < minimum Then
minimum = tmp
Set rngMin = c
End If
End If
Next c
MinimumC = rngMin.Value2
End Function
Save the workbook. You can now close the code editor.
Now you can use the following formula in F1 and copy down column F: =IF(C1<>0,C1,MinimumC()).
This will work as long as the value of C1 * Dy - E1 is never greater than 100000000. :)

Dynamic insert function

It is a requirement that I use Excel to solve this issue.
In col A I have 0s and 1s with various quantities of 0s between the 1s. Every time a 1 appears I want the difference between two numbers given in two columns next to my binary column. However I wish to get the results from this calculation stated next to the previous 1.
I'd cope with different software, but how do I achieve this with Excel?
=IF(A4=1,OFFSET(B4,MATCH(1,A5:A$1000,0),0)-OFFSET(C4,MATCH(1,A5:A$1000,0),),"")
in D4 and copied down to suit seems to work.
Edit:
=(IF(A$=1, ,"") is as in: IF(logical_test,value_if_true,value_if_false) where value if false is (blank), expressed as "".
The value_if_true is the difference between ColumnB and ColumnC values, each ‘located’ from an OFFSET function as in =OFFSET(reference,rows,cols,height,width).
references are to the appropriate column for the row into which the formula is inserted (ie B4 and C4) from which the values required are ‘south’ by a variable amount.
MATCH, as in =MATCH(lookup_value, lookup_array, [match_type]) is to determine the extent of the offset on a case-by-case basis. In reverse order, the parameters here are match_type = 0 (to require an exact match) and lookup_array is as much of ColumnA as required. Initially chosen as up to Row1000 (by A$1000) but can be extended as far as necessary, subject to row limit for the relevant Excel version.
The first parameter lookup_value) is of course 1 since that is the flag for the rows that contain the values to be subtracted.
Without a $ between A and 5 in the MATCH functions the size of the array automatically decreases (top cell row reference increases) as the formula is copied down, hence finds the next instance (rather than the same one over and over again).
With VBA, I'd first set the formulas to show results in same line as the "ones". (Suppose I used the D column for that.)
= if(A1 = 1; B1 - C1; "")
Then, in VBA window, do the following:
Dim i as integer
Dim Filled as Collection
Set Filled = new Colleciton 'this collection will stored filled lines
'store filled lines
for i = 2 to 1000 'use your table limit
if Sheet1.Cells(i, 4).Value <> "" then 'the 4 is for D column, i for the line
Filled.Add i
end if
next
'now fill the E column with displaced values
for i = 1 to Filled.Count - 1
Sheet1.Cells(Filled(i), 5).Value = Sheet1.Cells(Filled(i+1), 5).Value
next
'please note there's a missing line (the last), it's up to you to decide how to fill it
'sorry I cannot debug this code
I'd associate that to some sheet event or to a button.

Excel conditional formatting for the entire row with more than one formula

After 3 hours of searching I still didn't find an answer, here is what I am trying to do:
I am trying to fill with green any row that has WBS in it and with Red any row that has ACT in it and Blue any row that has EPR in it. It works for the first formula then when I try to add the second one every thing get messed up.
what i have understood is that you need to search a keyword in a row and if its found in any cell of that row then color it.
May be we can do it with conditional formatting but i have another idea. We can create a simple search function in Excel VBA. Something like this:
=search_row(A1:F1,"EPR")
The function will return 1 if EPR is found in any cell of specified row. Now if you create two different columns at the end of data columns, name first with WPS and second with EPR and write this function in it. Like
G1 =search_row(A1:F1,"WPS")
H1 =search_row(A1:F1,"EPR")
Drag it to end. Now sort the columns. First for WPS from higher to lower. Then color all rows having 1 in a single select. Similarly do the same with EPR (H1) column.
To use this function you can download the macro file from the following URL:
http://asimishaq.com/myfiles/SearchHighlight.xlsm
Now to run it first of all enable macros, and then re-open your data file and then open this macro file. As long as this macro file is opened you can use this function. Following is the VBA code if you want to create the macro yourself:
Function search_row(sRow As Range, Keyword As String)
Dim i As Integer
Dim Found As Integer
For i = 1 To sRow.Columns.Count
If InStr(1, LCase(sRow.Cells(1, i)), LCase(Keyword)) > 0 Then
search_row = 1
End If
Next
End Function
I had a go at making a function similar to asim-ishaq to determine if your search term exists in the row for fun :) then tried to apply it to highlighting rows, turns out I dont know how to use conditional formatting very well! Figured it out in the end, hopefully I've explained it well enough.
With this you will have to have (one) extra column at the end of your data to contain the result.
It might be possible to not require the extra column by putting the function inside the conditional formatting, however I couldn't get it to work (didn't try very hard). This isn't a great loss as it's much simpler to edit the formula if its on the workbook, instead of having to go through each conditional rule to edit it, should you need to edit it in the future.
To get the formatting to work you will need to create a number of rules (one per keyword)
You want to create a rule of the type shown below, in the formula box you need something along the lines of: =INDIRECT("D" & ROW())=0 where D is the column containing the result of the function below and 0 is the index of the keyword you're highlighting.
In my example, the formula in the D Column is: =SearchRow(An:Cn,"ABS","KBS","JBS") (where n is the row the formula is on)
Set the formatting as desired then press OK, when you return to the rule manager you will need to update the Applies to value, which should be a range that covers all the data you want to highlight. In my example it was $A$1:$C$3
My function below takes 2+ Arguments, The first is the range to search. The second (and any subsequent ones) are search terms.
The function will return a number. -1 for no matches and 0+ for the found search term. The number depends on the position in the arguments.
A1 = "ABS"
B1 = "SBA"
A2 = "SBA"
B2 = "ABS"
A3 = ""
B3 = ""
C1 = "=SearchRow(A1:B1, "ABS", "SBA")"
C2 = "=SearchRow(A2:B2, "ABS", "SBA")"
C3 = "=SearchRow(A3:B3, "ABS", "SBA")"
C1 > 0
C2 > 1
C3 > -1
The function will always return the first result, searching left to right comparing each cell to the Keywords in order. Using my example, if a cell contained "SBA ABS" the result would be 0 (for ABS). I guess your cells will probably only contain one keyword though so this shouldn't be a problem?
Public Function SearchRow(ByVal Row As Range, ParamArray Keyword() As Variant) As Integer
Dim Column As Integer
Dim Value As String
Dim Index As Integer
Dim Result As Integer
For Column = 1 To Row.Columns.Count
Value = LCase(Row.Cells(1, Column))
Result = -1
For Index = LBound(Keyword) To UBound(Keyword)
If InStr(1, Value, LCase(Keyword(Index))) > 0 Then
Result = Index
Exit For
End If
Next Index
If Result > -1 Then
Exit For
End If
Next Column
SearchRow = Result
End Function

If values in Column B = specific text, insert specific text into a value in Column A

Simply - if any cell in Column B contains thisvalue then append to the adjoining cell in Column A with sometext.
How is this done?
A simple if statement. For example:
=IF(ISNUMBER(SEARCH(thisvalue, B1)), sometext, "")
EDIT: The ISNUMBER(SEARCH(thisvalue, B1)) searches for thisvalue in B1, and if it finds it, it returns a number (that number being the starting index of thisvalue within B1).
EDIT #2: To append the inserted value to the end of the current value in cell A, use the CONCATENATE formula.
Example:
=CONCATENATE(A1, sometext)
Put this formula in A1, then drag down as necessary:
=IF(B1="thisvalue","sometext","")
EDIT
Using a the Visual Basic Editor, you can update the contents of cell A like this:
Private Sub UpdateColumnA()
Dim x As Long
For x = 1 To 65536
If InStr(1, Sheet1.Range("$B$" & x), "thisvalue") > 0 Then
Sheet1.Range("$A$" & x) = Sheet1.Range("$A$" & x) & "sometext"
End If
Next
End Sub
Repeated runnings of the macro, however, will append the text again; you'll need more validation code if you don't want this to happen.
copy-paste in A1 , considering that you have values in B
=IF(ISNA(VLOOKUP("thisvalue",B:B,1,FALSE)),"",VLOOKUP("thisvalue",B:B,1,FALSE)&"ADDITIONAL VALUE")
it is saying:
if value of vlookup is is empty (if lookup returns nothing) , then show empty value ( double quotes)
but if the value of lookup returns something, then do this lookup and append "ADDITIONAL VALUE" text to found result
I think I have what you are looking for, let me know if you are still interested and if you want me to elaborate further. This formula in cell F2: =IF(ISNUMBER(SEARCH($U$2,E:E)),$V$2,"")&IF(ISNUMBER(SEARCH($U$3,E:E)),$V$3,"")&...
where you are searching for a value that you specify in U2 across all cells in column E:E, if it finds a match it appends the value you specify in V2. To search for multiple words assigning corresponding value simply concatenate as shown as much as you like. I am able to specify hundreds of words (and corresponding values). I hope it helps.

creating a counter cell and static cells in excel

Problem:
I have a counter cell: A1 with a value of =COUNTIF(B:B;"FOO")
This gives me a current "count" of all instances of "FOO" in column B.
I have a value cell C1 with a formula of: =IF(B1="FOO";"FOO_" & A1;)
This gives me a result of FOO_1 if "FOO" only exists once in Column B
Question:
I want to be able to reference the value of A1 at the time I write out the contents to the cell of C1. When A1 updates, I do not want C1 to be modified. C2 should now take the update of A1 (which would now be 2) and C2 would be: FOO_2 for example:
A1 = 1
B1 = FOO
C1 = FOO_1
A1 = 2
B2 = FOO
C2 = FOO_2
C1 still remains FOO_1 based on the value of A1 before a new row was added to column B
Looking for an automated way to create an ID, like an increment value in MySQL, and not looking for a solution that involves a person copy / pasting..
The problem with your approach is that, A1 will always change to reflect the COUNT, you can't use a value that WAS. What else is going into the remaining cells in Column A that you could not use the Count in the adjacent row as #JMax suggests?
If you have to increment with fixed Counts, I would recommend you think of a simple macro on a change event of whichever cell you are wanting. For instance everytime you enter "FOO" or "BAR" or anything, it would do a COUNTIF of the Range in B:B and concatenate the result entering it in the adjacent C.
No reason to depend upon A1 at all, and it possibly changing.
This example may get you started. And the Countif may use a ';' for your version of Excel
It assumes you are doing data entry and then moving to the next cell down. It also checks whether you have already made an entry in the adjacent cell in C so it does not change the count if you revisit a cell.
Which means it will be wrong in that adjacent cell unless you delete the value in C first before making a change. Of Course If you have 4 FOOs and then delete one you will still have FOO_4 and it won't change so if you change the 4th FOO to BAR first delete FOO_4. If the Increment HAS to match actual counts for some other reason, I would not rely upon this for that.
Sub doIncrement()
If ActiveCell.Column = 2 And ActiveCell.Offset(-1, 1) = "" Then
ActiveCell.Offset(-1, 1) = ActiveCell.Offset(-1, 0) & "_" & WorksheetFunction.CountIf(Range("B:B"), (ActiveCell.Offset(-1, 0)))
Else: Exit Sub 'or do something else
End If
End Sub
Then call this in
Private Sub Worksheet_Change(ByVal Target As Range)
Call doIncrement
End Sub
If you want to stick to a formula solution, you can replace the A1 formula by:
=COUNTIF($B$1:B1;"FOO")
That would do the trick when you drag and drop your formula.

Resources