Method 'Range' of object '_Worksheet' failed despite qualifying ranges - excel

I'm running into an issue and I can't figure it out. Questions with the same error seem to have a different issue.
I have the following code:
Option Explicit
Sub Bank_match()
Dim x As Range, y As Range
Dim FirstSheet As Worksheet, SecondSheet As Worksheet
Dim Txn_count_1 As Integer, Txn_count_2 As Integer
Dim i As Integer
Set FirstSheet = Worksheets("Sheet1")
Set SecondSheet = Worksheets("Sheet2")
With FirstSheet
Set x = Cells.Find(What:="Description", After:=Cells(1, 1), LookIn:=xlValues _
, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
Txn_count_1 = Range(x.offset(1, 0), x.offset(1, 0).End(xlDown)).Count
End With
With SecondSheet
Set y = Cells.Find(What:="Description", After:=Cells(1, 1), LookIn:=xlValues _
, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
Txn_count_2 = Range(y.offset(1, 0), y.offset(1, 0).End(xlDown)).Count
End With
For i = 1 To Txn_count_1
If FirstSheet.Range(x).offset(i, 1).Value = SecondSheet.Range(y).offset(i, 2).Value Or _
FirstSheet.Range(x).offset(i, 2).Value = SecondSheet.Range(y).offset(i, 1).Value Then
FirstSheet.Range(x.offset(i, 1)).EntireRow.Interior.ColorIndex = 6
SecondSheet.Range(y.offset(i, 1)).EntireRow.Interior.ColorIndex = 6
End If
Next i
End Sub
Effectively, I'm trying to iterate through bank statements and highlight the rows of transactions that appear on both sheets. My problem is that I get the error on the 'If statement' line.
At first I thought it might be my sheet references, but if I replace 'FirstSheet' and 'SecondSheet' with Worksheets("Sheet1") and Worksheets("Sheet2") respectively, I then get "Application-defined or object-defined error" on the same line. I get the same error if I also qualify the range with 'ThisWorkbook'.
Any thoughts?

Drop the FirstSheet.Range and SecondSheet.Range... x and y are already range objects:
If x.Offset(i, 1).Value = y.offset(i, 2).Value...
Though you need to check if the Find was successful... otherwise x or y might be Nothing... using the following:
If Not x Is Nothing Then ' and similarly for y
And you are missing a period . before Cells and Range
Set x = .Cells
Set y = .Cells
Txn_count_1 = .Range(...
Txn_count_2 = .Range(...

Related

Replace #Ref over within several Ranges

New to coding so sorry if I'm completely ignoring contexts as I'm still trying to learn them.
I have cells that are trying to pull data from several Pivot Tables in another worksheet. If it is unable to pull any information from the pivot tables, it will return #REF. The Macro is supposed to search through in each cell within several ranges to search for the #REF and replace it with a 0. The reason its several ranges instead of the entire worksheet is that some of the equations are trying to add values from a table and since some of those values are #REF, the sum also ends up being #REF. I need to keep those equations there so once the #REF's are replaced, they would get the sum.
Dim Areas(13) As Range
Set Areas(1) = Range("C5:Z7")
Set Areas(2) = Range("C10:Z14")
Set Areas(3) = Range("C27:Z27")
Set Areas(4) = Range("C33:Z45")
Set Areas(5) = Range("C52:Z55")
Set Areas(6) = Range("C58:Z61")
Set Areas(7) = Range("C63:Z66")
Set Areas(8) = Range("C68:Z72")
Set Areas(9) = Range("C74:Z78")
Set Areas(10) = Range("C80:Z84")
Set Areas(11) = Range("C86:Z90")
Set Areas(12) = Range("C92:Z96")
Set Areas(13) = Range("C102:Z112")
For R = 1 To 13
For Each cell In Areas(R) 'Error: For Each may only iterate over a collection object
If cell.Value = CVErr(xlErrName) Then
.Replace What:="#REF!", Replacement:="0", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Else
Next
I made a bunch of notes after my code to try to work off of based on other StackOverflow questions which I listed below. I figured they worked will form a single range but I'm working with several. If none of what I did makes sense then disregard the below and help me start over. (Please?) Let me know if you need any more information.
If IsError(cell.Value) Then
' If cell.Value = CVErr(xlErrName) Then
' ...
' End If
'End If
'Dim nm As Name
' For Each nm In ActiveWorkbook.Names
' If InStr(nm.Value, "#REF!") > 0 Then
' nm.Delete
' End If
'Next nm
' ActiveCell.Replace What:="#REF!", Replacement:="0", LookAt:=xlPart, _
' SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
' ReplaceFormat:=False
'With Range("B11:AP55").SpecialCells(xlCellTypeFormulas)
' .Formula = Replace(.Formula, "#REF", "Master", , , vbTextCompare)
'End With
As an alternative to Find, consider SpecialCells
To remove only #REF errors
Sub Demo1()
Dim rng As Range
Dim rErr As Range
Dim cl As Range
With ActiveSheet 'or specify a specific sheet
Set rng = .Range("C5:Z7,C10:Z14,C27:Z27,C33:Z45,C52:Z55,C58:Z61,C63:Z66,C68:Z72,C74:Z78,C80:Z84,C86:Z90,C92:Z96,C102:Z112")
End With
On Error Resume Next
Set rErr = rng.SpecialCells(xlCellTypeFormulas, xlErrors)
On Error GoTo 0
If Not rErr Is Nothing Then
For Each cl In rErr.Cells
If cl.Value = CVErr(xlErrRef) Then
cl.Offset(0, 1) = 0
End If
Next
End If
End Sub
To remove All errors:
Sub Demo2()
Dim rng As Range
Dim rErr As Range
With ActiveSheet 'or specify a specific sheet
Set rng = .Range("C5:Z7,C10:Z14,C27:Z27,C33:Z45,C52:Z55,C58:Z61,C63:Z66,C68:Z72,C74:Z78,C80:Z84,C86:Z90,C92:Z96,C102:Z112")
End With
On Error Resume Next
Set rErr = rng.SpecialCells(xlCellTypeFormulas, xlErrors)
On Error GoTo 0
If Not rErr Is Nothing Then
rErr = 0
End If
End Sub

Can I breakup the code to executing the .Find method?

I want to break up this line of code, to make it more digestible, in smaller steps, but I am running in problems that I either get compile errors, run time errors, or just plain the wrong response.
As a beginner in coding of VBA, maybe somebody enlightens me, why it is not possible, or if it is possible where I am going wrong with my approach.
This code is functional snippet is below, but the function following is not
Dim WksN As String
Dim res As Object
' Set res = Sheets("Sheet3").Cells(1, 1).EntireRow.Find(What:=name
Set res = Sheets(WksN).Cells(1, 1).EntireRow.Find(What:=name _
, LookIn:=xlValues _
, LookAt:=xlPart _
, SearchOrder:=xlByColumns _
, SearchDirection:=xlPrevious _
, MatchCase:=False)
Public Function GetColumnNumber(ByVal WksN As String, _
ByVal name As String) As Long
Dim wks As Worksheet
Dim rng As Range
Dim res As Object
Dim clmn As Object
' Set wks = ActiveWorkbook.Worksheets(CStr(WksN))
' Set wks = Sheets(CStr(WksN))
' Set wks = Sheets(CStr(WksN)).Activate
' Set wks = ActiveWorkbook.Worksheets(CStr(WksN)).Activate
Set wks = ActiveWorkbook.Worksheets(CStr(WksN)) '
' Set rng = wks.Cells(1, 1).EntireRow.Select ' Run time error
' Set rng = wks.Activate ' Not needed ??
' Set rng = wks.Rows(1).Select ' Compile error
Set rng = wks.Rows(1)
' With wks.Cells(1, 1).EntireRow ' Didn't work
With rng
Set clmn = .Find(What:=name, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
End With
If res Is Nothing Then
GetColumnNumber = 0
Else
GetColumnNumber = clmn.Column
End If
End Function
I would like to set the range of the entire first row and then
search and find the column in which my string is stored.
I am not sure if the statement from above is atomic and can't be broken up,
or how I am not activating or selecting the "right" range, as the return value of this function is zero when the return value of the first code snippet is none zero and correct.
The second question I have that I seem not to select the range when I am using the .Rows(1) statement, which strikes me that I must fundamentally not understand how this is supposed to work.
Set rng = wks.Cells(1, 1).EntireRow.Select ' Run time error
Select does not return a value, so don't use that if you're trying to get a reference to a range
Set rng = wks.Cells(1, 1).EntireRow
This should work:
Public Function GetColumnNumber(ByVal WksN As String, _
ByVal hdr As String) As Long
Dim f As Range
Set f = ActiveWorkbook.Worksheets(WksN).Rows(1).Find( _
what:=hdr, LookIn:=xlValues, lookat:=xlPart)
If f Is Nothing Then
GetColumnNumber = 0
Else
GetColumnNumber = f.Column
End If
End Function

Determining if VBA If Then Statement is necessary to code and how to fix Compile Error

Trying to set a Range ("headers") that is from a cell containing "Period" to cell containing "Agent Split". At the end of the code I select all of these ranges to make sure it's working properly.
I had tweaked the following code that contained a For loop
Sub Rangeheaders_test()
Dim r As Long
Dim endRow As Long
Dim endCell As Range
Dim headers As Range
With ActiveSheet
endRow = 500
For r = 1 To endRow
If .Cells(r, "A").Value = "Period" Then
Set endCell = .Rows(r).Find(What:="Agent Split", LookIn:=xlValues,_
LookAt:=xlPart, After:=.Cells(r, "A"))
Set headers = .Range(.Cells(r, "A"), endCell)
End If
Next r
End With
headers.Select
End Sub
However this code ran through the ranges and only selected the last when I wish to select them ALL in order to test it. So I deleted the loop which left me with the following
With ActiveSheet
endRow = 500
r = 1 To endRow
If .Cells(r, "A").Value = "Period" Then
Set endCell = .Rows(r).Find(What:="Agent Split", LookIn:=xlValues,_
LookAt:=xlPart, After:=.Cells(r, "A"))
Set headers = .Range(.Cells(r, "A"), endCell)
End If
End With
headers.Select
But now I'm either getting a Syntax Error or Compile error for Unexpected With or If close and I'm stuck. Do I need to define the Then condition? Is the If Then statement even necessary? Is there another way i can set the conditions?
I realized from #Jun 's insightful comment that i was trying to store multiple ranges in one variable and that's where i was going wrong.
After some research i found the Union method where I'm able to combine my ranges after i specify them -- which i did using the .Findnext method
Sub findheader()
Dim startcell As Range
Dim rng As Range
Set rng = Range("A1:A500")
Set startcell = rng.Find(what:="Period", LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
Dim header1, header2, header3 As Range
Set header1 = Range(startcell, startcell.End(xlToRight))
Set startcell = rng.FindNext(startcell)
Set header2 = Range(startcell, startcell.End(xlToRight))
Set startcell = rng.FindNext(startcell)
Set header3 = Range(startcell, startcell.End(xlToRight))
Dim headers As Range
Set headers = Union(header1, header2, header3)
headers.Select
End Sub

Mismatch or Range error

The code below gives either Mismatch or Range error in Excel 2008. How do I fix it?
Sub PEC()
Dim PEC As String, result As Integer
PEC = Range("AE2:AE26848").Value
If PEC = "A.06" Then result = 1
Range("AO2:AO26848").Value = result
End Sub
Sub PEC()
For x = 2 to 26848
If Range("AE" & x) = "A.06" Then Range("AO" & x) = 1
Next x
End Sub
I recommend using the following code. It might seem more complicated, but it certainly does a better and more robust job. It is simply assigning your input and output ranges as SrcRng and DstRng. FIND method for ranges is a good way to check for specific values.
Sub PEC()
Dim SrcRng As Range
Dim DstRng As Range
Dim rcell As Range
Set SrcRng = Range ("AE2:AE26848")
Set DstRng = Range("AO2:AO26848")
Set rcell = SrcRng.Find(what:="A.06", after:=SrcRng.Cells(1, 1), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not rcell Is Nothing Then
DstRng.Value = 1
End If
End Sub

Set VBA Range with Variable End

I'm kind of new to VBA and am struggling to understand some of the syntax.
I have a range from a3:c13, for example, and I'd like to set it as a variable so I can pass it to vlookup later as a the table array. However, the range is defined by user input in terms of its size. It will always start in A3, it will always include columns A:C, but I don't know how far down it would go. In that case, I think I'd set it as:
With range("a3")
table_array = range(.cells(0,0), .End(xlDown).End(xlToRight)).Select
End With
However, that doesn't seem to work. I get a runtime error:
Run-time Error '1004': Method '_Default' of object 'Range' failed.
Assuming cols A, B, and C have the same number of rows:
Sub Macro1()
Set r = Range("A3")
Set table_array = Range(r, r.End(xlDown)).Resize(, 3)
End Sub
You can find the last row in Col A:C and then construct your range?
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long
Dim Rng As Range
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Range("A:C").Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
If Not LastRow < 3 Then
Set Rng = .Range("A3:C" & LastRow)
Debug.Print Rng.Address
Else
MsgBox "No Data found beyond A3"
End If
End With
End Sub

Resources