VBA/Excel Find a string in a cell to determine the next cell's value - vba

I need to find a string in a cell, and if that string is found, the cell next to it has to put that string in the next cell. In layman's terms:
IF "Medina" is found in a C3
put "ME" in cell D3;
ELSEIF "Brunswick" is found in C3
put "BR" in D3;
ELSE
put "OTH"in D3;
And this has to go through out the sheet, i.e., C4 & D4, C5 & D5, etc.
Thanks in advance

Sounds like you're looking for the InStr function (see this link: https://msdn.microsoft.com/en-us/library/8460tsh1(v=vs.90).aspx). Basically we want to check if there is a non-zero answer for this, which indicates the string can be found.
So you could do something like below. Note I just put in 40 as your last row arbitrarily, but you can change this as you need.
Dim indStartRow As Integer
Dim indEndRow As Integer
Dim i As Integer
indStartRow = 3
indEndRow = 40
For i = indStartRow To indEndRow
If InStr(Sheets("Sheetname").Range("C" & i).Value, "Medina") > 0 Then
Sheets("Sheetname").Range("D" & i).value = "ME"
ElseIf InStr(Sheets("Sheetname").Range("C" & i).Value, "Brunswick") > 0 Then
Sheets("Sheetname").Range("D" & i).value = "BR"
Else
Sheets("Sheetname").Range("D" & i).value = "OTH"
End If
Next i

I don't think you need VBA for this, Excel Formulas are sufficient. If you want your Selection criteria to be easily extendable, use this:
=IFERROR(INDEX($AB$1:$AB$2,MATCH($A1,$AA$1:$AA$2,0)),"Other")
This Formula is in B1, while A1 contains Medina, Brunswick, etc. AA1:AA2 contain Medina...Brunswick and AAB1:AAB2 ME...BR. It can be moved to a different sheet, and you can extend it by selecting the last cell and inserting whole rows. Later you may want to use named ranges, too.

Related

How to shorten VBA code using repeated SUMIFS function?

I have written up a number of SUMIFS in VBA based on the change of a value in cells
E.g. Cell A23 is a drop down menu with Total and UK
If A23 = "Total" Then
Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group")
If A23 = "UK" Then
Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group",
Range(E:E)), "UK")
Based on the example above, the second code is a repeat of the first code but with an additional range included to pick up "UK"
Instead of constantly rewriting it is there a way I can shortern the code so I can simply concatenate any additional range I want to include?
So ideally I could have something like:
Test = Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group"
If A23 = Total Then
A24 = Test)
If A23 = UK Then
A24 = Test &, Range(E:E), "UK")
Is this possible and if so how can I do it?
Could you enter the actual function in the cells, rather than do the worksheetfunction calculation in the vba? (doing worksheetfunction calculations won't actually enter the formula in the cells, just return the output value)
Something like this maybe:
Dim strFormula as String
strFormula = "=SUMIFS(B:B, C:C, ""Year"", D:D, ""Group"")"
'Thats the basic formula
If Result.Range("A23").Value = "UK" Then
strFormula = replace(strFormula, ")", "E:E, ""UK"")")
'that replaces the end bracket with the extra condition
End If
Result.Range("A4").FormulaA1 = strFormula
(this answer posted mainly in response to that second comment with the actual code included - although it looks like the actual operation you're doing is a bit different?)
So, as I said you need to simplify that code out a bit by saving the separate parts in variables
Dim strFormula as String
Dim rngLIC as Range
Dim rngRegion as Range
Dim rngYear as Range
Set rngLIC = Range(rngHeaders.Find(LIC) , rngHeaders.Find(LIC).End(xlDown))
Set rngRegion = Range(rngHeaders.Find(Year), rngHeaders.Find(Year).End(xlDown))
Set rngYear = Range(rngHeaders.Find(Year), rngHeaders.Find(Year).End(xlDown))
'and I think you'll need to add others for the extra bit you wanted to fix, but you get the pattern
strFormula = "=SUMIFS(" & _
rngLIC.Address(xlA1) & "," & _
rngRegion.Address(xlA1) & ", A23," & _
rngYear.Address(xlA1) & ", ""Year 0"")"
'Then add the replace bit I detailed above if necessary to add bits to the formula
That code should hopefully do xsactly the same as the code snippet you put in the comment. Does that help? (please vote up if it does because I'm trying to build my reputation!!)

Excel VBA - Expand range from using just one column to using multiple

I have a working piece of code that looks at a columns value, copies those values, and strips off the 'speed' component string of that value - Turning '200 Mbps' into just '200', etc.
They updated the source data on me and the values are now in three columns - AC, AD, AE instead of just AC now. So values can exist in either column and any row, can be Gbps and Mbps, etc.
At the end of the day, I need the total of the three columns and X number of rows. I have sample data below.
How can I (or can I even) modify this existing code to account for the extra two columns. I am wondering if the Dictionary approach is correct at this point. It was originally added at someone else's suggestion.
Dim Cla As Range
With CreateObject("scripting.dictionary")
For Each Cla In wbFrom.Sheets("Sheet0").Range("AC9", Range("AC" & Rows.Count).End(xlUp))
Cla.Value = Replace(Cla.Value, " Mbps", "")
Cla.Value = Replace(Cla.Value, " Gbps", "")
If Not .exists(Cla.Value) Then
.Add Cla.Value, Nothing
End If
Next Cla
wbTo.Sheets("Sheet1").Range("D13").Resize(.Count).Value = Application.Transpose(.keys)
End With
I don't really understand the If and With loops and how they combine with keys and Transpose like this. ((Thanks TinMan for the info))
I've tried moving this out, but having this outside the loop breaks the code. Is there something in this section that I need to update?
If Not .exists(Cla.Value) Then
.Add Cla.Value, Nothing
End If
Next Cla
Some sample data looks like this: Notice each element is on its own row.
AC AD AE
300
123
72
200
101
The 300 gets paste where it belongs but nothing else adds up or get grabbed I think. Also, when the data looks like THIS, it pastes two values instead of just one:
Notice the 300 and 123 are now on the same line, 300 gets paste into the destination cell and 123 gets paste into two cells below that.
AC AD AE
300 123
72
200
101
Example 1
Use Range.Resize() to extend the number of columns targeted.
For Each Cla In wbFrom.Sheets("Sheet0").Range("AC9", wbFrom.Sheets("Sheet0").Range("AC" & Rows.Count).End(xlUp)).Resize(, 3)
Next
Example 2
Set a helper variable to the Range and use Range.Resize() to extend the number of columns targeted.
Dim Target As Range
With wbFrom.Sheets("Sheet0")
Set Target = .Sheets("Sheet0").Range("AC9", .Range("AC" & Rows.Count).End(xlUp)).Resize(, 3)
Debug.Print Target.Address
End With
Addendum
This will strip away the " Mbps" and " Gbps" as well as insert the sum the a;; the numbers into Range("D13").
With wbFrom.Sheets("Sheet0")
Set Target = .Range("AC9", .Range("AC" & .Rows.Count).End(xlUp)).Resize(, 3)
For Each Cla In Target
Cla.Value = Replace(Cla.Value, " Mbps", "")
Cla.Value = Replace(Cla.Value, " Gbps", "")
Next Cla
.Range("D13").Value = WorksheetFunction.Sum(Target)
End With
I'm not sure that you are describing the problem correctly. Clearly, using the dictionary, get you a list of unique distinct values. But you stated that:
At the end of the day, I need the total of the three columns and X
number of rows.
The existing code leads me to believe that you are going to be doing a count of different speeds...how many 200 Mbps, how many 72 Mpbs, etc.
Either that, or the previous code didn't work as intended.
Assuming that you described the problem correctly and all you want is the total bandwidth then this should do the trick...
Dim LastRow As Long, Value As Long, Sum As Long, Count As Long
' Get the last row, looking at all 3 columns "AC:AE"
LastRow = FindLastRow(wbFrom.Sheets("Sheet0").Range("AC:AE"))
' Iterate through all 3 columns
For Each Cla In wbFrom.Sheets("Sheet0").Range("AC9:AE" & LastRow)
' Use Val() to get just the numeric value and the inline IIF() statment to automatically adjust the speed
Value = Val(Cla.Value) * IIf(InStr(Cla.Value, "Gbps") > 0, 1000, 1)
' Check if there is a Value, if so, Add it to the Sum (and increment the count)
If Value > 0 Then
Sum = Sum + Value
Count = Count + 1
End If
Next Cla
' Write the Sum to the other Workbook (not sure if you need the Count)
wbTo.Sheets("Sheet1").Range("D13") = Sum
And a function to find the last cell in a range (even if the list is filtered)
Public Function FindLastRow(r As Range) As Long
' Works on Filtered Lists/Hidden rows
Const NotFoundResult As Long = 1 ' If all cells are empty (no value, no formula), this value is returned
FindLastRow = r.Worksheet.Evaluate("IFERROR(LARGE(ROW('" & r.Worksheet.Name & "'!" & r.Address & ")*--(NOT(ISBLANK('" & r.Worksheet.Name & "'!" & r.Address & "))),1)," & NotFoundResult & ")")
End Function
From the comments on your question I gather that you want the sum of the original inputs that are contained in columns AC, AD and AE. Such sum you want to store it at cell d13. Since I have limited input, this is the least ugly code I can provide:
nRow1 = ActiveSheet.Cells(ActiveSheet.Rows.Count, "AC").End(xlUp).Row
nRow2 = ActiveSheet.Cells(ActiveSheet.Rows.Count, "AD").End(xlUp).Row
nRow3 = ActiveSheet.Cells(ActiveSheet.Rows.Count, "AE").End(xlUp).Row
nRow = Application.Max(nRow1, nRow2, nRow3)
input_range = Range("AC9:AE" & nRow)
acum = 0
For Each cell In input_range
If Not IsEmpty(cell) Then
temp = Split(cell, " ")
acum = acum + CInt(temp(0))
End If
Next
Range("D13").Value = acum

How to change values in excel acording to different sheet

I have an excelsheet which contains two sheets named respectively 'Sertifika' and 'Egitim Katılım'. in Sertifika i need a button which upgrades value of cells B6, M2 and M3 to next cells from Egitim Katılım.
Example:
B6 ='Eğitim katılım'!C149
and i want to change value of B6 to,
='Eğitim katılım'!C150
how can it be possible?
Assuming you already know how to use a button, include the below code inside the command button,
Sub mac()
Dim str As String, a As String
str = Range("B6").Formula
a = Right(str, (Len(str) - InStr(str, "C")))
a = a + 1
Range("B6").Formula = "='E?itim kat?l?m'!C" & a
End Sub
The code extracts the formula in cell B6, unstrings the row number from the formula, adds +1 to it and updated the formula. I would like you to manipulate this for the other 2 cells.

I have 3 excel formulas that I would like to fill ranges in a spreadsheet with, how can I make sure the cells change with the rows?

=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, " ")
=IF(N2=" ", " ",NETWORKDAYS(H2,TODAY()))
=IF(OR(O2 = " ", O2 <= 0), " ", (O2/N2)*100)
These are the three formulas, I want to make sure that as they are inserted into the worksheet the cell references will still change to match the rows they are on, as they would in a normal spreadsheet. Any advice would be much appreciated! (To clarify, I need to fill the ranges using VBA as the code I'm using clears the worksheet every time it is run.)
you could use FormulaR1C1 property of range object, which uses the "R1C1" notation for range addresses
for instance inserting your first formula in "A1" would be:
Range("A1").FormulaR1C1 = "=IF(AND(RC7<>100,TODAY()>=RC8, TODAY()<=RC9), RC5, "" "")"
where the pure R would assume the current cell row index, while C7 stands for a fixed (not varying with host cell position) 7th column index reference, and so on
If i have interpreted your question correctly, you need something like the below:
Option Explicit
Sub InsertFormula()
Dim i As Long
Dim n As Long
n = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To n
Cells(i, 1).Formula = "=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")"
Next i
End Sub
replace the 1 in n=... with whichever column has the most rows of data
replace for i = 1 to whichever row it must begin form
You will notice i have added extra quotations to the end of the formula, this is needed as quotes in a formula in VBA must be enclosed... in more quotes lol
Apply this concept for the other formulas :)
Instead of absolute references like G2 you can use something along
.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
where R and C reference the offset from the current cell (positive: right or down, negative: up or left).
Use it in a way similar to this:
Dim c
For Each c In Selection
c.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
Next c
Relative References are adjusted when you set the formula to range of cells:
[A1:B2].Formula = "=C$1" ' now the formula in B2 will become "=D$1"
You can also set multiple formulas at once:
Range("K2:M9").Formula = Array("=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")", _
"=IF(N2="" "", "" "",NETWORKDAYS(H2,TODAY()))", _
"=IF(OR(O2 = "" "", O2 <= 0), "" "", (O2/N2)*100)" )
or if each row has different formula:
[A1:Z3] = [{"=1";"=2";"=3"}]

VBA Excel: Concatenate a range of cells

I am trying to concatenate a range of cells along a single row. This group of cells has a defined start but a variable end. I tried doing this, but it didn't work. I'm still learning the Syntax of VBA but I haven't seen anything that says this WON'T work. Any help is appreciated.
Dim hexVal As String
For i = 4 To N + 3
Cells(3, i) = Application.WorksheetFunction.Dec2Hex(Cells(2, i), 2) & " "
Next i
hexVal = CONCATENATE(Range(Cells(3,i),Cells(3,N+3))
End Sub
You do not need Concatenate(), but using & instead:
for i = 4 to N + 3
hexVal = hexVal & cells(3,i)
next i
That is in case you are just concatenate the strings and you do know the range needs to be concatenate.
HEre's your problem:
CONCATENATE(Range(Cells(3,i),Cells(3,N+3))
The Cells method returns a range object, the default property of which is the .Value property. So, this is equivalent to:
CONCATENATE(Range(Cells(3,i).Value,Cells(3,N+3).Value)
As such, it will ALWAYS FAIL unless those cells contain a valid address string.
Solution ... just use the built-in concatenator
hexVal = Range(Cells(3,i) & Cells(3,N+3))
Or:
hexVal = CONCATENATE(Range(Cells(3,i).Value,Cells(3,N+3).Value))