Excel VB: how do I call VLOOKUP if condition is met? - excel

I've got a data set that comes out of Oracle, but a number of the records are missing the GEO data (AMER, EMEA, APAC) in column E and instead show "-". I am formatting and processing this data using VB and I have everything working save for this one piece.
What I want to do is to call a VLOOKUP formula to replace those "-" values with the correct GEO based on the country name shown in column J. All records with GEOs already present should be bypassed. The code I built for this overwrites every record, unfortunately:
For z = 1 To LR
x = Application.VLookup(Cells(z, "J"), Sheets("MasterTerritoryList").Columns("A:F"), 6, False)
If Not (IsError(x)) Then
Cells(z, "E").Value = x
End If
Next z
Can someone help me out by showing me how to read the data in column E and replace only those values that equal "-"?
Many thanks!!

For z = 1 To LR
If Cells(z, "E").text = "-" Then ' <-------- Add this test
X = Application.VLookup(Cells(z, "J"), Sheets("MasterTerritoryList").Columns("A:F"), 6, False)
If Not (IsError(X)) Then Cells(z, "E").Value = X
End If
Next z

Related

Checking if each number in a list is between multiple ranges

I have a list of numbers (that will be changed weekly) and I also have a list of ranges (that also change weekly). I need to check whether each number falls between each range.
Eg. My list of numbers on the left and my list of ranges on the right.
4 1 3
10 67 99
54 120 122
155
So what I need is to return a value if 4 falls between 1-3, then check if it falls between 67-99 and so on. Then return a value if 10 falls between 1-3 or 67-99 etc.
I have tried array and vba but I'm noob and I cant find much in the way of examples for this issue. I have had success with the following nested if;
=IF(OR(AND(G2>$L$2,G2<$M$2),AND(G2>$L$3,G2<$M$3),AND(G2>$L$4,G2<$M$4),G2,"")
=IF(OR(AND(G3>$L$2,G3<$M$2),AND(G3>$L$3,G3<$M$3),AND(G3>$L$4,G3<$M$4),G3,"")
However, once my number of ranges gets above a certain number it says i have too many characters.
Any help would be appreciated.
Regards,
Will.
So what I need is to return a value if 4 falls between 1-3, then check if it falls between 67-99 and so on. Then return a value if 10 falls between 1-3 or 67-99 etc.
If you want to match each value in col G with the list in L and M then, rearrange the G column values in a row as shown below so that you can get the entire view in one go.
Put this formula =(AND($N$1>L2,$N$1<M2)) in N2 and drag it down. Similarly put the formula =(AND($O$1>L2,$O$1<M2)) in O2 and pull it down and so on...
Thanks Siddarth. This works but the number of rows will be changing weekly and your method would be too tedious to do weekly.
Ended up working it out on my own. Pretty simple but took me forever!
Sub Subtract_Start()
Set rng1 = Range(Range("G2"), Range("G2").End(xlDown))
Set rng2 = Range(Range("L2"), Range("L2").End(xlDown))
For i = 2 To rng1.Rows.count
For j = 2 To rng2.Rows.count
If Cells(i, "G").Value > Cells(j, "L").Value Then
If Cells(i, "G").Value < Cells(j, "M").Value Then
Cells(i, "G").Copy Cells(i, "J")
End If
End If
Next j
Next i
End Sub

Removing duplicate lines of text but have exceptions - Excel

I have some lines of text that look as below. As you can see there is a duplicate of "x1". What I want to do in Excel is remove duplicates (eg. x1) but keep the word "Title" as it counts as a duplicate and it will be removed which is something I don't want.
Title
x1
Title
x2
Title
x3
Title
x1
Title
x4
I searched all over the internet about methods some of them including "data validation" or even formulas like the one below but none of these worked. So do you have any ideas on how can this be done?
=IFERROR(LOOKUP(2, 1/((COUNTIF($A$2:$A$20, $A$2:$A$20)>1)*(COUNTIF($E$1:E1, $A$2:$A$20)=0)*(COUNTIF($C$2:$C$3, $A$2:$A$20)<>1)), $A$2:$A$20), "")
There are a few ways to deal with this I suppose but if the "Title" is always the every other row, you could simply use a do loop with a "+ 2" to determine the dups. So for example, let's assume all this data is in column A starting in row 1:
x = 2
Range("C1").Formula = "=Count(A:A)"
y = range("C1")
Cells(x,2).Formula = "=Countifs(A:A, A1)"
Range(Cells(x,2)).Copy
Range(Cells(x + 1, 2), cells(y, 2)).PasteSpecial xlPasteFormulas
Do While x <= y
If Cells(x, 2) > 1 Then
Rows(x).Delete
x = x + 1 'Add 1 since you already deleted 1 row and only need to move to the next row at this point.
Else
x = x + 2 'Add 2 to ensure you don't delete the title row
End If
Loop
I realized after searching a little further that there is no easy way to do this in Excel. And in some cases it is impossible. So I found a workaround with Sublime text which is much easier to do this.
Copy-paste the content from column A to Sublime text.
Then select the repeated content that you don't want to be removed and then ALT + F3. This will select all instances of that content.(HINT: Add one "space" before that text to avoid line merging when proceeding to deleting duplicates.
Inverse the selection to now select all the rest text/content.
Then go Edit > Permute Lines > Unique....
5 . DONE!!

How to group datas in specific condition and how to get minimum data in it

Having a problem with making a code in vba. First, there are numbers and datas on each row d and e, like number 1~14, 20~39, 48~60 and 84~98. These groups change each time(Randomly). What I want to get is a minimum value of each group. This value should be next to the rows with data. Could you help me with this one?
Rowsss = .Cells(Rows.Count, 4).End(3).Row
For i = 10 To Rowsss + 1
If .Cells(i, 4) - .Cells(i - 1, 4) = 1 Then
n = n + 1
next i
if .cells(i,4)-.cells(i-1,4)<>1 then
(I'm stuck in here)
End If
Next
I want to get results like group number and results
ex. 1/14/minimum value

Names having same ID should come in one cell

I have different ids for for different names in excel. Many names having the the same ids. How to get all the names having same id in one cell correspondingly. I need formula. Please help me out
Is this what you're looking for? It'd have been nicer if you had shown your progress so far, but hope to be of help like this.
Option Explicit
Sub Concatenate_Names()
Dim a As Integer
Dim i As Integer
Dim x As Integer
i = 1
x = *[number of items in your list]*
For a = 1 To *[number of unique values in a separate list]*
i = 1
Do While i <= x
'The cell references should be dependent on where your unique value list is,
'as well as where the full list is.
'"a" for the unique values, "i" for the full list - matching IDs
If Cells(a, 8).Value = Cells(i, 1).Value Then
'"a" for the unique values, "i" for the full list - appending names
Cells(a, 9).Value = Cells(a, 9).Value & Cells(i, 2).Value
End If
i = i + 1
Loop
Next
End Sub
If you want to avoid the VBA aproach, you still can use recursive functions :
Add column to store a semantic representation with key / values, in my example, the representation schema is : #Key1:Value11[;Value12...][#Key2:Value21[;Value22...]...]
The formula bellow recursively builds such a representation, the last row will contain the complete representation of pairs key / values :
=IF(IFERROR(FIND("#"&A2&":";C1);-1)=-1;C1&"#"&A2&":"&B2;IF(IFERROR(FIND("#";C1;FIND("#"&A2&":";C1)+1);-2) = -2;LEFT(C1;FIND("#";C1;FIND("#"&A2&":";C1)+1)-1)&";"&B2;LEFT(C1;FIND("#";C1;FIND("#"&A2&":";C1)+1)-1)&";"&B2&RIGHT(C1;LEN(C1)-FIND("#";C1;FIND("#";C1;FIND("#"&A2&":";C1)+1)) + 1)))
Add a second new column to retrieve values associeted to current row / key, the formula uses the last computed representation :
=IFERROR(LEFT(RIGHT(INDEX(C:C;MATCH(REPT("z";255);C:C));LEN(INDEX(C:C;MATCH(REPT("z";255);C:C)))-FIND("#"&A2;INDEX(C:C;MATCH(REPT("z";255);C:C)))-1-LEN(A2));FIND("#";RIGHT(INDEX(C:C;MATCH(REPT("z";255);C:C));LEN(INDEX(C:C;MATCH(REPT("z";255);C:C)))-FIND("#"&A2;INDEX(C:C;MATCH(REPT("z";255);C:C)))-1-LEN(A2));2)-1);RIGHT(INDEX(C:C;MATCH(REPT("z";255);C:C));LEN(INDEX(C:C;MATCH(REPT("z";255);C:C)))-FIND("#"&A2;INDEX(C:C;MATCH(REPT("z";255);C:C)))-1-LEN(A2)))
The result should look like this :
Key Value Representation Values
1 a #1:a a;e;i
2 b #1:a#2:b b;h
3 c #1:a#2:b#3:c c;j
1 e #1:a;e#2:b#3:c a;e;i
5 f #1:a;e#2:b#3:c#5:f f
6 g #1:a;e#2:b#3:c#5:f#6:g g
2 h #1:a;e#2:b;h#3:c#5:f#6:g b;h
1 i #1:a;e;i#2:b;h#3:c#5:f#6:g a;e;i
3 j #1:a;e;i#2:b;h#3:c;j#5:f#6:g c;j

Is there an easy way to change cell references in Excel VBA?

I recently developed a model for work and I am getting requests for adding additional features.
The problem isn't making the additions as most simply involve adding one or two additional columns. However, each time I add a column I must go through my code line by line and change every formula reference e.g. G to H, H to I, I to J etc.
Is there any way for me to automate this process without having to change each formula individually or a best practice that I can keep in mind when building my next model from scratch?
For example, let's say someone asks for an additional calculation that requires I insert a formula into column D. Currently I am going to each column (H, J, K, and L in the example below), and manually updating them to I, K, L, and M, respectively.
'Year 1 ASP formula = (Year 1 Bookings) / (Year 1 Units)
FormulaRange_ASP1 = "H23:H" & NumRows
Range(FormulaRange_ASP1).Value = "=IFERROR(G23/F23,0)"
Range(FormulaRange_ASP1).NumberFormat = "0.00"
Application.ScreenUpdating = False
'Year 2 AR Units formula = (Year 1 Units) * (Vlookup AR Retention Rate for product in column C)
FormulaRange_ARUnits2 = "J23:J" & NumRows
Range(FormulaRange_ARUnits2).Value = "=IF(E23 = 12,VLOOKUP(D23,$B$8:$F$19,4,FALSE),0) * F23 * AR_Opt_In"
Range(FormulaRange_ARUnits2).NumberFormat = "#,##0_)"
Application.ScreenUpdating = False
'Year 2 AR ASP formula = (Vlookup ASP for product in column C)
FormulaRange_AR_ASP2 = "K23:K" & NumRows
Range(FormulaRange_AR_ASP2).Value = "=IFERROR(VLOOKUP(D23,$B$8:$F$19,2,FALSE),0)"
Range(FormulaRange_AR_ASP2).NumberFormat = "0.00"
Application.ScreenUpdating = False
'Year 2 AR Bookings formula = (Year 2 Units) * (Year 2 ASP)
FormulaRange_AR_Bookings2 = "L23:L" & NumRows
Range(FormulaRange_AR_Bookings2).Value = "=J23 * K23"
Range(FormulaRange_AR_Bookings2).NumberFormat = "$#,##0_)"
Application.ScreenUpdating = False
What I usually do is add some constants to the beginning of the module (or a separate module, for bigger projects) with column number references.
Const c_Column1 As Integer = 1
Const c_Column2 As Integer = 2
So, throughout the code, you can do something like:
For i = 2 to 10
ActiveSheet.Cells(i, c_Column1).Value = i
Next i
.. and never have to worry about changing your code, only the constants.
Notice the use of Cells() instead of Range(), because it allows referencing the columns as numbers. To reference a range, you'll have to use the following sintax:
With ActiveSheet
For i = 2 to 10
.Range(.Cells(i, c_Column1), .Cells(i, c_Column2)).Value = i
Next i
End With
You can also declare the constants as String and assign them column letters instead of numbers. It may be easier to reference ranges, but you'll have to use string concatenation everywhere.
One possibility is to use relative R1C1 references.
E.g. instead of specifying a formula in H23 as:
Range(FormulaRange_ASP1).Value = "=IFERROR(G23/F23,0)"
You can specify it as:
Range(FormulaRange_ASP1).FormulaR1C1 = "=IFERROR(R[0]C[-1]/R[0]C[-2],0)"

Resources