I want to be able to compare 2 cells in VBA. The issue i'm having is that it's not making an exact match.
Dim WeekNum2 As Integer
WeekNum2 = Cells(1, 12).Value
Range("F2:F60").Find(WeekNum2).Activate
U = ActiveCell.Row
Range(Cells(U, 7), Cells(U, 7)).Value = GreenCountP4
Range(Cells(U, 8), Cells(U, 8)).Value = YellowCountP4
Range(Cells(U, 9), Cells(U, 9)).Value = RedCountP4
Above is the section of code that isn't working ideally. The value in Cells(1,12) is generated using the =WEEKNUM(K1) formula so depending on the date in K1 it returns a value from 1-52. I want it to take this value and then find the equivalent value in the range F2:F60.
In F2:F60 i have values going in order from "w46"-"w52" and then "w1"-"w52". The issue is that if the value in Cells(1, 12) is 5 for example, it will select the first row that has a 5 in it in the range (w50 in this case).
Is it possible to compare just the numbers in the cell (so not include the "w" with it still being present). If not, how do i make it so it picks up the exact values (So if the value in Cells(1, 12) is 5, then it goes to right 5 instead of the first 5 in the range)
use xlWhole value for lookat argument of Find() method:
Range("F2:F60").Find("W" & WeekNum2, lookat:=xlWhole, LookIn:=xlValues).Activate
U = ActiveCell.Row
furthermore you can avoid Select and directly go like follows:
U = Range("F2:F60").Find("W" & WeekNum2, lookat:=xlWhole, LookIn:=xlValues).Row
I suggest you use an optional argument to the find method, which allows you to insist that the entire cell is matched, and not just some subset of the text inside. You want to use the LookAt argument, and set it to xlWhole. Now nothing will be found for "5", because no cell will match "5" entirely. Cells containing "w5" aren't a match with LookAt:=xlWhole. I know, the naming of arguments is not at all intuitive...
Furthermore, life would be much easier if you simply used a string "w5" in your search. An alternative would be to strip the w's out of the cells in the find (search) range. This can be done with the split method.
You can "cheat" a little, make the value of 5 as "W5" and then find a match for that in your range. Just add another variable, let's call it WeekNum2String and add the "W" as a prefix. Now you can search your range with Range("F2:F60").Find(WeekNum2String).
Dim WeekNum2String As String
WeekNum2String = "W" & Cells(1, 12).Value
Note: you should use the Find method by defining a Range, then setting it to the Find result (and not with Activate) .This method will allow you to trap errors if there is no Find.
Like this:
Dim FindRng As Range
Set FindRng = Range("F2:F60").Find(WeekNum2String)
If Not FindRng Is Nothing Then
U = FindRng.Row
Else
MsgBox "Week number " & Cells(1, 12).Value & " not found in Range"
End If
Related
So I am using the "find" function in VBA and once this value is found, I am wanting to offset 2 cells to the right. I'm not sure if something is right with my logic, but does anyone mind having a look at my code?
Set StationSearchCell = StationLocationRng.Find(what:="*" & ShortenLocationName & "*", LookIn:=xlValues, lookat:=xlWhole)
'If the StationSearchCell returns a value
If Not StationSearchCell Is Nothing Then
projectinfosheet.Range("B23").Value = StationSearchCell.Offset(0, 2).Value
Else
End If
I have to convert this function into VBA and I couldn't understand what the second numbers after the comma inside the ADDRESS() meant. The function is used to calculate time difference between two systems. I know that ADDRESS() can get optional parameters of numbers from 1 to 4, but I don't think this isn't the case here. Can you please help me understand it?
IF(Z44<>"N/R",((INDIRECT(ADDRESS(Y44,1))-INDIRECT(ADDRESS(Z44,1)))*86400)+((INDIRECT(ADDRESS(Y44,6))-INDIRECT(ADDRESS(Z44,6)))*86400),"N/R")
Please, try the next VBA code, able to convert the formula you show. Select a cell and run the code. It will return exactly what the formula does:
Sub testVBAFromFormula()
'=IF(Z44<>"N/R",((INDIRECT(ADDRESS(Y44,1))-INDIRECT(ADDRESS(Z44,1)))*86400)+((INDIRECT(ADDRESS(Y44,6))-INDIRECT(ADDRESS(Z44,6)))*86400),"N/R")
Dim sh As Worksheet, cel As Range
Set sh = ActiveSheet
Set cel = ActiveCell
If sh.Range("Z44").Value <> "N/R" Then
cel.Value = (sh.Range("A" & sh.Range("Y44").Value).Value - sh.Range("A" & sh.Range("Z44").Value).Value) * 86400 + _
(sh.Range("F" & sh.Range("Y44").Value).Value - sh.Range("F" & sh.Range("Z44").Value).Value) * 86400
Else
cel.Value = "N/R"
End If
End Sub
If you split the formula in small pieces you can better understand what happens:
"=ADDRESS(Y44,1)" returns "A" & the number in "Y44", let us imagine 23. "A" is the first column, defined by the second parameter 1.
"=INDIRECT(ADDRESS(Y44,1))" returns the value from "A23".
The same for the second part of the formula, but the second parameter is 16, which means the sixth column: "F".
The rest of the code should now be easily understood, I think...
I am trying to search an entire row for a string that contains "PROFILE". It will always be capitalized, but the format will be, for example "[9]PROFILE001".
Some extra information: I have used the Find command to locate the row that I am searching in for the string. It has its own variable that I am trying to incorporate into the range I am using.
I have searched multiple partial string articles on here, and have not been able to implement it into my code. I have tried using the Like command and the IntStr command to no avail. I believe my issue may be with how im referencing the search range or how i am searching.
Here is a snippet of my current code:
'finding item name row
Set FindRow3 = Range("A1:A100").Find("Item Name", LookIn:=xlValues)
itemnamerow = FindRow3.Row
'The section above is working as intended
'searching for the word profile, the section below is the one I am having issues with
Range("B8:Z100").Style = "Normal"
If ActiveSheet.Range("B" & itemnamerow & ":Z" & itemnamerow) Like "*PROFILE" Then
Range("C1").Value = "it worked"
End If
I am currently experiencing a run time error 13, type mismatch in the "If ActiveSheet..." line. I have not been able to get the correct index to make this correct.
I am trying to use that if the partial string is found, I want do something.
TIA
You need to use the Find method, with MatchCase and LookIn arguments set. And probably LookAt for to ensure it checks actual values and not formula syntax.
Dim profileFound as Range
Set profileFound = ActiveSheet.Range("B" & itemnamerow & ":Z" & itemnamerow).Find("PROFILE",lookIn:=xlValues,MatchCase:=True,lookAt:=xlPart)
If Not profileFound is nothing Then
debug.print profileFound.Value
Range("C1").Value = "it worked"
else
debug.print "no profile found"
End If
The reason your original code is failing is because Excel will not allow you to evaluate a multi-cell range against a single value. You could loop through each cell in the range and check each cell individually, but since Find is available, that is superfluous.
You don't provide enough parameters for the Range.Find operation. Switch to the worksheet's Match to locate Item name then again as a wildcard search to locate profile.
dim m as variant, n as variant
m = application.match("Item Name", range("A1:A100"), 0)
If not iserror(m) then
n = application.match("*profile*", cells(m, "B").resize(1, 25), 0)
If not iserror(n) then
Range("C1").Value = "it worked " & cells(m, n+1).value
end if
end if
I am trying to create a Module that will format an excel spreadsheet for my team at work. There is one column that will contain the word "CPT" and various CPT codes with descriptions.
I need to delete all text (CPT description) after the 5 digit CPT code but alsp keep the word CPT in other cells.
For example: Column S, Row 6 contains only the word "CPT" (not in quotations)
Then Column S, Row 7 contains the text "99217 Observation Care Discharge"
This setup repeats several times throughout Column S.
I would like for Row 6 to stay the same as it is ("CPT") but in Row 7 i only want to keep "99217"
Unfortunately, this is not possible to do by hand as there are several people who will need this macro and our spreadsheets can have this wording repeated hundreds of times in this column with different CPT codes and descriptions.
I have tried various If/Then statements, If/Then/Else
Sub CPTcolumn()
Dim celltxt As String
celltxt = ActiveSheet.Range("S6" & Rows.Count).End(xlUp).Text
Dim LR As Long, i As Long
LR = Range("S6" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If InStr(1, celltxt, "CPT") Then
Next i
Else
With Range("S6" & i)
.Value = Left(.Value, InStr(.Value, " "))
End With
Next i
End If
End Sub
When i try to run it I get Various "Compile Errors"
I would do this differently.
Given:
The cell to be modified will be the cell under a cell that contains CPT
in the algorithm below, we look for CPT all caps and only that contents. Easily modified if that is not the case.
Since you write " a five digit code", we need only extract the first five characters.
IF you might have some cells that contain CPT where the cell underneath does not contain a CPT code, then we'd also have to check the contents of the cell beneath to see if it looked like a CPT code.
So we just use the Range.Find method:
Sub CPT()
Dim WS As Worksheet, R As Range, C As Range
Dim sfirstAddress As String
Set WS = Worksheets("sheet4")
With WS.Cells
Set R = .Find(what:="CPT", LookIn:=xlValues, lookat:=xlWhole, _
MatchCase:=True)
If Not R Is Nothing Then
sfirstAddress = R.Address
Set C = R.Offset(1, 0)
C.Value = Left(C.Value, 5)
Do
Set R = .FindNext(R)
If Not R.Address = sfirstAddress Then
Set C = R.Offset(1, 0)
C.Value = Left(C.Value, 5)
End If
Loop Until R.Address = sfirstAddress
End If
End With
End Sub
If this sequence is guaranteed to only be in Column S, we can change
With WS.Cells
to With WS.Columns(19).Cells
and that might speed things up a bit.
You may also speed things up by adding turning off ScreenUpdating and Calculation while this runs.
Your first error will occur here:
ActiveSheet.Range("S6" & Rows.Count).End(xlUp).Text
Because you're trying to retrieve text from the last used range starting .End(xlUp) at Range("S61048576"), which is roughly 58 times the row limit in Excel. You might change Range("S6" & Rows.Count) to Range("S" & Rows.Count)
Your second error will occur here:
LR = Range("S6" & Rows.Count).End(xlUp).Row
Which will be the same error.
The third error will occur here:
For i = 1 To LR
If InStr(1, celltxt, "CPT") Then
Next i
You cannot nest half of an If-End If block in a For-Next loop, or vice-versa and you've done both. If you want to iterate and perform an If-End If each iteration, you need to contain the If-End If within the For-Next like
For i = 1 To LR
If InStr(1, celltxt, "CPT") Then
'Is the purpose here to do nothing???
Else
With Range("S" & i)
.Value = Left(.Value, InStr(.Value, " "))
End With
End If
Next i
EDIT:
For technical accuracy, your first error would actually be your broken up For-Next and If-End If, as you wouldn't even be able to compile to execute the code to run into the other two errors.
You can simply use the Mid function in the worksheet.
As I understood from your question that you need to separate numbers and put them in other cells, is this true?
To do this, you can write this function in cell R6 like this
=Mid(S6,1,5)
Then press enter and drag the function down and you will find that all the cells containing numbers and texts have been retained numbers in them
I have data stored in three columns of Excel
Column A: Serial Number
Column B: Date
Column C: Value (e.g. Cost)
I need to look for the Value (Column C) associated with a particular Serial Number (Column A) AND Date (Column B).
So for example, in the screenshot below, if I want to look for the Value associated with Serial number (T455) and Date (Dec 13, 2010), the value should be 8.
The only method I can come up with would be computationally inefficient, because I would go through ALL the cells each time I look for a value.
Is there a method, for example, that would limit the search area for a given serial number?
For example, if I am looking for a value for Serial Number T455, how can I limit the code to search for the date in Rows (6-13) and find the corresponding value in Column C, rather than searching the whole table?
Sub FindValue()
Dim S as String
Dim D as Date
Dim V as Integer
S = T455
D = Dec 13, 2010
for i = 1 to Range("A1").End(xldown).Row
If Range("A" & i) = S And Range("B" & i) < Date - 7 And Range("B" & i) < Date + 7 Then
' This way i search a date range rather than a specific date
V = Range("C" & i).Value
End If
End Sub
I thought of While loops, or Lookup functions, but reached a dead end.
Non-VBA Solution that may be a lot easier and less of a headache.
Column A consists of the formula, for A1 = "=B1&C1"
Cell G1 formula can be seen in formula bar.
UPDATE
Here is a VBA solution that will work faster, but there are some notes based on what you wrote that I am unsure of. Also, see some comments to help your code work more like you want it to.
Sub FindValue()
Dim S As String, D As Date, V As Integer, rngFound As Range, cel As Range
S = "T455" 'needs quotes around the string
D = "Dec 13, 2010" 'needs quotes around the date
Dim wks As Worksheet
Set wks = ActiveSheet
With wks
'always better to AutoFilter than Loop when you can!
.UsedRange.AutoFilter 1, S
.UsedRange.AutoFilter 2, ">" & D - 7, xlAnd, "<" & D + 7
Set rngFound = Intersect(.UsedRange, .Columns(3)).SpecialCells(xlCellTypeVisible)
'the only thing here is if you have a date range _
'you may return more than one result _
'in that case, I don't know what you want to do with all the V's
If Not rngFound Is Nothing Then
For Each cel In rngFound
V = cel.Value
Next
End If
.AutoFilterMode = False
End With
End Sub
If you are willing to entertain a non-VBA solution, then you can use this implementation, which basically uses this formula:
=IFERROR(INDEX(List, MATCH(0, COUNTIF(H1:$H$1, List)+
IF(Category2<>Criteria2, 1, 0)+IF(Category1<>Criteria1, 1, 0), 0)), "")
There are several VBA methods, which really depend on how comfortable you are with the language and how efficient you want your solution to be. Off the top of my head:
1) filter the list with both criteria, then return the relevant value in whatever row is visible (if any)
2) sort your data by those two columns (first by serial, then date), then perform searches (you'd probably want to call built-in functions like MATCH)