Comparing cells using match in vba - vba

I am trying to compare two columns of cells in vba using the match function. I am comparing the second column against values in the first and copying and pasting the values that aren't found to another column. I am doing the same with the second against the first as well. For some reason when I try to run this it says that it cannot get the match property of the worksheet function class and I am really confused as to why I am receiving this error. I have pasted the code below. Any help with this issue would be greatly appreciated.
Set PrevMonth = Sheet13.Range(Range("A2"), Range("A2").End(xlDown))
Set currMonth = Sheet13.Range(Range("B2"), Range("B2").End(xlDown))
Count = 2
For i = 2 To PrevMonth.Rows.Count
match = Application.WorksheetFunction.match(Cells(i, 1), currMonth, 0)
If WorksheetFunction.IsNA(match) = True Then
Sheet13.Cells(i, 1).Cut
Sheet13.Cells(Count, 3).Paste
Count = Count + 1
End If
Next i
For i = 2 To currMonth.Rows.Count
match = WorksheetFunction.match(Cells(i, 1), PrevMonth, 0)
If WorksheetFunction.IsNA(match) = True Then
Sheet13.Cells(i, 1).Cut
Sheet13.Cells(Count, 4).Paste
Count = Count + 1
End If
Next i

Can you try using
Application.Match(Cells(i, 1), currMonth, 0)
I know this should have been a comment...but I'm unable to comment as I'm below 50 Rep...

In my experience the "cannot get 'X' property of the worksheet function class" error is indicative that a poor argument has been passed to the worksheet function itself. In your case the arguments are: Cells(i, 1), currMonth. This likely means one of those ranges are inaccessible. If I had to guess, you want to be passing sheet13.cells(i,1). I'd recommend a 'with sheet13' statement for this whole segment of code. WorksheetFunction.Match in particular will throw that error if a match can't be found (VB doesn't work with the #N/A return value). Using a WorksheetFunction.CountIf > 0 can ensure there is a viable match within the range.
Also, Range("A2").End(xlDown) will result in the last cell of the column if there is no data after A2. This is generally unfavorable behavior.

Related

Finding the cell value 2 columns away dynamically

I wanted to find the cell value 2 columns away. For example, i have found the closest number at A20, the next value i wanted to find will be at C20. Since the closest number may not always fall on A20. How do i code to find the cell.Value 2 columns away dynamically?
The code below is for I find my closest number
ClosestTime2.Value = Application.WorksheetFunction.VLookup(wsInput4.Value, Range("A5:A805"), 1, False)
I did research about it but i found Range.Offset nut suitable for my case.
Since you know the search range ahead of time, you could use Match instead of VLookup. Match returns the relative position of the matching item in the range. You can calculate the row number by adding the row number of the first row of the search range - 1. In this case, since your search range starts on row 5, you would need to add (5 - 1) = 4 to the offset returned by Match to yield the row number.
Offset = Application.WorksheetFunction.Match(wsInput4.Value, Range("A5:A805"), 0)
RowNum = Offset + 4
NextValue = Cells(RowNum, 3).Value
Sub Test()
'Use your sheet code name for below line.
With Sheet3
Dim foundcel As Range
'Use proper data in according to your need.
Dim output As String
'Use below line for your case
'Set foundcel = .Range("A5:A20").Find(what:=wsInput4.Value)
Set foundcel = .Range("A5:A20").Find(what:="Liza")
If Not foundcel Is Nothing Then
output = .Cells(foundcel.Row, foundcel.Column + 2).Value
'In your case use below line
'ClosestTime2.Value=.Cells(foundcel.Row, foundcel.Column + 2).Value
Else
Debug.Print "Data not match"
End If
Debug.Print output
End With
End Sub
Data in sheet
Run output :

Count Rows Until Finding Specific String

I am trying to use Excel VBA to count the number of rows until I hit a specific string and set a variable equal to it.
Something like:
Dim i as Integer
i = Worksheets("Scope Phase Document").Range("A1", Range("A1").End(xlDown)).Find("FACTS - What are we measuring?").Count
I know this isn't the correct syntax and I'm probably missing other stuff, but just using the different functions I currently know, this is what I would hope would do the trick. I get
Run-time error '91' saying "Object variable or With block variable not
set
I have tried a few different ways of doing it, but can't figure out a way that doesn't result in an error.
So I want to start at A1 and count all the rows down until I reach the specific string "FACTS - What are we measuring?".
Any help would be greatly appreciated!
I prefer MATCH, but if the match is not found it throws an error. So we need to test for that:
Dim i As Long
i = 0
On Error Resume Next
i = Application.WorksheetFunction.Match("FACTS - What are we measuring?", ActiveSheet.Range("A:A"), 0)
On Error GoTo 0
If i > 0 Then
' do you stuff with i
End If
So you basically want MATCH():
=MATCH("FACTS - What are we measuring?",A:A,0)
It returns the row number of matched string.
Your code is fine except you should use the Row property. The Count property as you have used it will return 1 because the Find method returns one cell (the first cell where a match is found).
Dim i as Integer
i = Worksheets("Scope Phase Document").Range("A1", Range("A1").End(xlDown)).Find("FACTS - What are we measuring?").Row
Like Scott mentioned, if your text is not found, Excel will throw an error.
I'd do this:
Sub rowcounter()
Dim i As Integer
Range("A1").Select
i = 0
Do
Selection.Offset(1, 0).Select
i = i + 1
Loop Until Selection.Value = "FACTS - What are we measuring?"
MsgBox "rows count is " & i
End Sub

VBA How to Check if Cell Value is valid and exists?

I have this cell.Offset(0, -2) cell that I need to check if it exists inside my VBA loop.
My idea is that if the cell has an .Offset(0, -2) that does not exist (e.g. say cell = Column B and cell.Offset(0, -2) = Column A-1, cell.Offset(0, -2) is supposed to be invalid), I want to be able to check that it doesn't exist in the if else statement.
Right now when it doesn't exist, I'm getting a “Runtime Error 1004: Application defined or object defined error”.
I've tried IsErr(cell.Offset(0, -2)), cell.Offset(0, -2).Value, If cell.Offset(0, -2) Is Nothing Then, cell.Offset(0, -2) = "", but none of them seem to work... can anyone point me in the right direction? I'm pretty new to VBA and it seems like different variable types have different ways of checking if the value exists.
If you can use your offset amount as a variable, or some method to evaluate against the cell's column, you don't need to defend against errors. Consider below...
Sub IsvalidARea()
Dim OffsetAmount As Integer: OffsetAmount = -2
Dim Cell As Range
If Cell.Column + OffsetAmount < 1 Then
MsgBox "Oh FALSE!"
Else
'EVERYTHING IS OKAY!
End If
End Sub
A solution for this is by using the constantly misused On Error Resume Next, coupled with a If IsError. Here's an example:
On Error Resume Next
If IsError(ActiveCell.Offset(, -2).Select) = True Then
'This is indicative of an error. Meaning you are on Column B, and you ran out of space.
Else
'This means an error did not occur. Meaning you were at least on Column C or above.
End If
There may be a better solution, in fact I am sure there is. But what this will do is allow you to move past the actual 1004 Application error, and you can actually identify, and use the error that was really returned, instead of just forcing your macro/script to end.
To avoid using the error check, you can always check the current column index (B is 2) and make sure whatever you are offsetting by, once subtracted by your index is greater than 0. For example, column B is 2. Your offset is 2. 2 - 2 = 0, so it should not attempt it. Column C is 3, 3 - 2 = 1, which is greater than 0 so it would be valid. Both are explorable methods.

Type mismatch when passing an array

I keep on getting an error when I try and pass this value to an array, essentially I am working with exchange rates, I have the currency in the second dimension of the array ary() and I am looking to retrieve a data point in a table that is 2 cells away from the element stored in the array.
Now I believe the problem has something to do with the value being a number and the array being a variant, however I cannot solve the problem.
Option Explicit
Dim fxary(), y
ws.Select
Set Rng = Sheets("BEXR").Range("C2:C" & Sheets("BEXR").Range("A1").End(xlDown).Row)
For i = 1 To UBound(ary, 2)
If ary(2, i) <> ary(2, UBound(ary, 2)) Then
For Each y In Rng
If Sheets("BEXR").Range(y.Address).Value = ary(2, UBound(ary, 2)) And Sheets("BEXR").Range(y.Address).Offset(0, 1).Value = ary(2, i) Then
fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value ' error occurring here
fxary = ary(1, i)
End If
Next y
End If
Next
Your comments say that I have omitted all the lines not related to this specific problem, therefore I will post an answer based on the assumption that all the lines that are related to the problem have been included in the code in the question.
The following comments should be made about your code:
You have used Option Explicit but nowhere do you declare the size or type of the variables i and ary.
Nowhere do you specify values for the variable ary.
Your line saying fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value is trying to assign a scalar to a vector, and will generate a Type Mismatch error.
Your line saying fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value is immediately followed by a line (fxary = ary(1, i)) replacing the value of fxary with something else, so the first line is redundant.
All your references to Sheets("BEXR").Range(y.Address) can be replaced with y.
You are executing through two loops (from 1 to whatever the second dimension of the undefined variable ary is and, within that loop, through every cell in column C of your sheet), but you are effectively only setting fxary once, i.e. to the value in the undefined variable ary where the first dimension's value is 1 and the second dimension's value is i. (But I haven't been able to wrap my mind around the code enough to be able to work out which value of i that will end up being - I think it's worked out by looking at each row of your sheet that has a different value in column C than in column D, and the value in column C is equal to ary(2, highest value), and then determining the highest value of i such that ary(2, i) will equal the value in column D.)
I believe you need to look at each of the above items before your code will do anything meaningful, but to resolve the specific problem you say you are having:
1) Change your declaration of fxary to
Dim fxary, y
2) Simply remove the line saying
fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value
as that line is redundant (as I said in one of my earlier points).

Autofilter not working as intended

I'm trying to delete all rows that contain a specific value in column with autofilter. For some reason, it doesn't work as intended and only deletes some of the rows with the specified value, and I'm determined to find out WHY
My code is as simple as this:
Function GetRowRange(sheet, column, value) As Range
'check for a valid section column
sheet.AutoFilterMode = False
sheet.UsedRange.AutoFilter Field:=column, Criteria1:=value
Set GetRowRange = sheet.AutoFilter.Range.SpecialCells(xlCellTypeVisible)
sheet.AutoFilterMode = False
End Function
With GetRowRange(importsheet, importsheet.UsedRange.Find("stato_4").column, "0")
.Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Delete
End With
Update
it makes no sense. I try to change my delete function to:
For Each Row In GetRowRange(importsheet, importsheet.UsedRange.Find("stato_4").column, "0").Offset(1, 0).Rows
Row.EntireRow.Delete
iront = iront + 1
Next
MsgBox iront
and it will recognize that there are 42 rows in the range (iront = 42), but none of them get deleted
I think if you have less than 8192 rows (pre Excel 2010), you could delete them using Special Cells?
Add a formula column that throws an error if the row contains the value you want to test for.
TRY THIS:
' Now, this formula will put an #N/A in each row where the column matches the criteria.
Range("C1:C" & Range("A1").End(xlDown).Row).FormulaR1C1 = "=IF(C[-2]=criteria,NA(),"""")"
'Then use SpecialCells with Error code xlErrors to return the range containing the rows to be deleted.
Range("C1:C" & Range("A1").end(xldown).row).SpecialCells(xlCellTypeFormulas,xlErrors).entirerow.delete
There is more on that on Oxgrid
HTH
Philip
Not sure UsedRange is reliable. Try using something like Range("A1").CurrentRegion