Application-Defined or Object-defined error - Qualifying References Excel - vba

Trying to hammer out bugs in my code. Currently trying to do some very simple, open worksheet, copy and paste data over. Trying to do it all without using .Select or .Activate. Hitting "Application-defined or Object defined error", which, from reading the other threads on the matter, probably means that my statements aren't fully qualified. However, I can't figure out how they're not fully qualified - other posts on the topic seem to be missing a "." somewhere in the code, but my attempts to fix it haven't gotten anywhere. Heavily truncated code as follows (If you don't see it dimmed/defined, it's elsewhere)
Sub CopyPaste()
Dim CitiReportEUR As Workbook
Dim CitiReportPathEUR As String
CitiReportPathEUR = Range("CitiReportPathEUR")
Workbooks.Open Filename:=CitiReportPathEUR
Set CitiReportEUR = ActiveWorkbook
LastRowCiti = CitiReportEUR.Sheets(1).Range("I" & Rows.Count).End(xlUp).Row
Set RngCitiEUR = CitiReportEUR.Sheets(1).Range("A1:CT" & LastRowCiti).SpecialCells(xlCellTypeVisible)
Set CabReport.Sheets("CITI").Range("C1").Resize(RngCitiEUR.Rows.Count).Value = RngCitiEUR.Value
End Sub
Currently the error is occurring when I define the range. I've had problems historically with pasting into the range as well... but that's an issue for when I can actually get the code to run that far!

Rows.Count is implicitly working with the ActiveSheet.
The use of Set when assigning values to the Value property of a Range is inappropriate. Set should only be used when assigning a reference to an object.
The Resize probably needs to cater for the number of columns in the source as well as rows.
This code is more explicit:
Sub CopyPaste()
Dim CitiReportEUR As Workbook
Dim CitiReportPathEUR As String
CitiReportPathEUR = Range("CitiReportPathEUR")
Set CitiReportEUR = Workbooks.Open(Filename:=CitiReportPathEUR)
With CitiReportEUR.Sheets(1)
LastRowCiti = .Range("I" & .Rows.Count).End(xlUp).Row
Set RngCitiEUR = .Range("A1:CT" & LastRowCiti).SpecialCells(xlCellTypeVisible)
End With
CabReport.Sheets("CITI").Range("C1").Resize(RngCitiEUR.Rows.Count, RngCitiEUR.Columns.Count).Value = RngCitiEUR.Value
End Sub

Related

How do I find out why I get an error when writing to an Excel cell with VBA?

I'm still fairly new to VBA and struggling with its limitations (and mine!). Here's my code:
Sub updateCache(CacheKey As String, CacheValue As Variant)
Dim DataCacheWorksheet As Worksheet, CacheRange As Range, Found As Variant, RowNum As Integer
Set DataCacheWorksheet = ThisWorkbook.Worksheets("DataCache")
Set CacheRange = DataCacheWorksheet.Range("A1:B999")
Set Found = CacheRange.Find(What:=CacheKey)
If Found Is Nothing Then
RowNum = CacheRange.Cells(Rows.Count, 2).End(xlUp).Row
DataCache.Add CacheKey, CacheValue
On Error Resume Next
DataCacheWorksheet.Cells(1, 1).Value = CacheKey
DataCacheWorksheet.Cells(1, 2).Value = CacheValue
Else
'Do other things
End If
End Sub
When I step through the code, Excel simply exits the sub at the line DataCacheWorksheet.Cells(1, 1).Value = CacheKey, with no error. So, two questions:
What's the bug that's preventing the value from being updated?
Why does Excel ignore my On Error command?
Edit: If I run the line in the IDE's "Immediate" box, I get the error "Run-time error '1004' Application-defined or object-defined error. I get the same error regardless of the value of CacheKey (I tried Empty, 1234 and "Hello").
Edit 2: If I modify the sub so that CacheKey and CacheValue are hardcoded and the reference to DataCache is removed, and then I run the sub standalone it works. So why doesn't it work when called from another function? Is it possible that Excel is locking cells while doing calculations?
Not sure if this applies, but you mentioned you were calling this macro from another function. If you are calling it from a function, depending on how you are calling it, that would explain your problem. For example, a worksheet function entered into a cell cannot modify another cell on the worksheet. And the attempt to do so will result in the macro merely exiting at that point, without throwing a VBA error.
How to work around this depends on specifics you have yet to share. Sometimes, worksheet event code can be useful.
Ok, wasn't about to write an answer, but there are 3 things you should modify in your code:
Found As Range and not As Variant
RowNum As Long in case it's a row after ~32K
To trap errors usually On Error Resume Next won't help you, it will just jump one line of code. You need to handle the error situation.
Modified Code
Sub updateCache(CacheKey As String, CacheValue As Variant)
Dim DataCacheWorksheet As Worksheet, CacheRange As Range, Found As Range, RowNum As Long ' < use Long instead of Integer
Set DataCacheWorksheet = ThisWorkbook.Worksheets("DataCache")
Set CacheRange = DataCacheWorksheet.Range("A1:B999")
Set Found = CacheRange.Find(What:=CacheKey)
If Found Is Nothing Then ' check if not found in cache (*Edit 1)
RowNum = CacheRange.Cells(Rows.Count, 2).End(xlUp).Row
DataCache.Add CacheKey, CacheValue ' I assume you have a `Dictionary somewhere
' On Error Resume Next <-- Remove this, not recommended to use
DataCacheWorksheet.Cells(1, 1).Value = CacheKey
DataCacheWorksheet.Cells(1, 2).Value = CacheValue
Else
'Do other things
End If
End Sub

How to iterate over a range of cells in Excel/VBA?

Dim works As Worksheet
Set works = ThisWorkbook.Sheets("Sheet1")
Dim txt As Variant
myrange = works.Range("C1:C9")
For Each txt In myrange
If InStr(1, txt, "£", vbTextCompare) > 0 Then
Debug.Print txt.Value '<..Object required err
Debug.Print works.Range("C" & txt).Value '<..Object required err
Debug.Print works.Cells(txt, 1).Value '<..Object required err
Debug.Print txt.Offset(0, 1).Value '<..Object required err
End If
Next txt
I'm trying to get the value of the cell that contains the "£" and then delete it . I'm getting `the object defined error in any case. I've tried 3 different options and still getting the error. I'm new to VBA and still learning. How can I fix this, and why am I getting the error?
One problem is the line myrange = works.Range("C1:C9"). It should have Set before it, like:
Set myrange = works.Range("C1:C9")
This way you ensure you are making a reference assignment, instead of a value assignment. Without it, you're telling VBA that you want the value of the cells to go in your variable. With it, you're telling VBA that you want your variable to point to that range.
Since you did not explicitly declare myrange as a Range object, VBA implicitly declared it Variant and treated it as a String. So, in the loop, txt was a String too, not a Range as you expected. Hence your error.
If you had Dim myrange As Range in the beginning, your assignment without Set would have failed and you'd have fixed it immediately.
But there's a simple habit that prevents this kind of error: in the top of your module, insert Option Explicit. This way, you have to explicitly declare ALL your variables, which means VBA won't assume they're Variant.
You can even make that automatic by checking the relevant option in Tools > Options.

Error runtime 91 and 429

This code feels like Schrodinger is executing it. If I open the project and run the code, I won't get any errors at all. If I view the code to edit or add anything, the first time I run the code, I get 'Run-time error 91'. If I try to run it a second time, making no changes, I get 'Run-time error 429' (ActiveX component can't create object).
What I'm trying to achieve is to find the row (BuildSel) in a range on worksheet (Ref) that has the same value as what's selected in a list on a userform (BuildList). Then once the row is found, to take data from that row and columns A and B, and put them in textbox's on my userform. Is my code right and ActiveX making the error? I apologize for terrible coding too.
EDIT: The listbox is on a multipage on my userform. I first noticed the issue today when I tried adding another listbox on a different page.
Private Sub BuildList_Click()
Dim Ref As Worksheet, BuildSel As Long
Set Ref = ThisWorkbook.Sheets("Ref")
BuildSel = Ref.Range("B2", Ref.Range("B" & Rows.Count).End(xlUp)).Find(BuildList.Value, lookat:=xlPart).Row
BuilderText.Value = Ref.Range("A" & BuildSel).Value
CompNameText.Value = Ref.Range("B" & BuildSel).Value
End Sub
Not sure why altering 'BuildSel' to variant makes it work, but the code as it stands has no error checking for when there is no matching list item to be found
The following code should be better suited for usage:
Private Sub BuildList_Click()
Dim Ref As Worksheet: Set Ref = ThisWorkbook.Sheets("Ref")
Dim BuildSel As Range
With Ref
Set BuildSel = .Range("B2", .Range("B" & Rows.Count).End(xlUp)).Find _
(BuildList.Value, lookat:=xlPart)
If Not BuildSel Is Nothing Then
BuilderText.Value = .Range("A" & BuildSel.Row).Value
CompNameText.Value = .Range("B" & BuildSel.Row).Value
Else
BuilderText.Value = ""
CompNameText.Value = ""
End If
End With
End Sub

Building a Vlookup between separate workbooks

I am new to VBA coding and am attempting to build a Vlookup to connect two seperate workbooks. Provided belwo is my coding which is currently producing a Run-Time 1004 Method 'Range' of Object'_Global' Failed error on the vlookup line.
Sub dataEntry(agent As Integer, month As Integer)
Dim lookupReturn As Integer
Dim i As Integer
Dim lookupValue As String
Dim lookupBook As String
i = 1
'set excel book to preform vlookup within
lookupBook = sheetName & "-Daily Report Daily-Monthly Grid.xlsx"
'Preforms a Vlookup to fill in data points
Do While Workbooks("Cumulative Agent Ranking Template").Sheets(sheetName).Cells(i, 1).Value <> ""
lookupValue = Workbooks("Cumulative Agent Ranking Template").Sheets(sheetName).Cells(i, 10).Value
lookupReturn = Sheets(sheetName).WorksheetFunction.VLookup(Range("C2"), [lookupBook] & sheet33 & Range("!$A$2" & ":$C" & agent), 2, False)
Workbooks("Cumulative Agent Ranking Template").Sheets(sheetName).Cells(i, 11).Value = lookupReturn
i = i + 1
lookupValue = ""
lookupReturn = 0
Loop
I think there are probably a lot of things going wrong here.
Let's start with the most obvious source of 1004 error, which is unqualified range objects.
Example: in a standard module, Range("C2") always refers to the Active sheet. In a sheet module, it always refers to the parent sheet.
To Resolve: fully qualify your range variables, e.g., Workbooks(_name_).Worksheets(_sheetname_).Range("C2")
Another potential problem I notice is the way you're calling the Vlookup.
Sheets(sheetName).WorksheetFunction...
There is no such method WorksheetFunction of a worksheet object. This is an application-level method, so invoke it like:
WorksheetFunction.Vlookup...
Additional problems or potential problems
Undeclared variables: sheetname (maybe this is a public or module-level variable?)
Unused variables: lookupValue You've declared this, and you've assigned to it, but you haven't done anything to it or used it anywhere else in the code. is this the value you're trying to search for?
The rest of your formula is also pretty gnarly and I'm not even going to try and fix it in its current state. If you use better-defined object variables, your code will be easier to read and understand. You will also benefit from intellisense if the variables are strongly typed in declaration.
Here is an example, which I will leave up to you to work out for your own needs:
Dim lookupBook as Workbook
Dim lookupRange as Range
Dim lookupValue as String
Set lookupBook = Workbooks("some other file.xlsx")
Set lookupRange = lookupBook.Worksheets("some worksheet").Range("A1:B50")
lookupValue = "cat"
Range("A1").Value = WorksheetFunction.Vlookup(lookupValue, lookupRange, 2, False)

VBA for Excel throws "Object variable or with block variable not set" when there is no Object

In my code, I have declared these variables:
Dim Field_Name, Datatype, row As Integer
Then, inside a For loop, I have this code:
Field_Name = Worksheets(i).UsedRange.Find("Field Name").Column
Datatype = Worksheets(i).UsedRange.Find("Datatype").Column
row = Worksheets(i).UsedRange.Find("Field Name").row + 1
However, that code throws the "Object variable or with block variable not set" run-time error. According to the API, the Range.Column and Range.row property is a read-only Long. I have tried making the datatype of my variables to Long, but with no success. It would appear that VBA expecting me to do
Set Field_Name = Worksheets(i).UsedRange.Find("Field Name").Column
Set Datatype = Worksheets(i).UsedRange.Find("Datatype").Column
Set row = Worksheets(i).UsedRange.Find("Field Name").row + 1
However, said variables are not objects, so doing that throws the "Object required" compile error.
Any help with this would be greatly appreciated. If you're not sure about how to fix it, then any workarounds or alternative ways to get the column number and row number of a cell would be greatly appreciated.
Even though this is an old question, I'd like to say something too.
I had the same problem to get this error while using the .Find method. I came to this question and so others will do the same.
I found a simple solution to the problem:
When Find does not find the specified string it returns Nothing. Calling anything directly after Find will lead to this error. So, your .Column or .row will throw an error.
In my case I wanted an Offset of the found cell and solved it this way:
Set result = Worksheets(i).Range("A:A").Find(string)
If result Is Nothing Then
'some code here
ElseIf IsEmpty(result.Offset(0, 2)) Then
'some code here
Else
'some code here
End If
Simplified answer:
Your .Find call is throwing the error.
Simply adding "Set " to that line will address the problem. i.e...
Set Datatype = Worksheets(i).UsedRange.Find("Datatype").Column
Without "Set," you are attempting to assign "nothing" to a variable. "Nothing" can only be assigned to an object.
You can stop reading here unless you would like to understand what all the other (valid, worthwhile) fuss was about your code.
To paraphrase all of the (warranted) code critiquing, your Dim statement is bad. The first two variables are not being "typed" and end up as variants. Ironically, this is why the solution I just described works.
If you do decide to clean up that Dim statement, declare DataType as a variant...
Dim DataType as variant
What about the below code:
For i = 1 to 1 ' change to the number of sheets in the workbook
Set oLookin1 = Worksheets(i).UsedRange
sLookFor1 = "Field Name"
Set oFound1 = oLookin1.Find(What:=sLookFor1, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not oFound1 Is Nothing Then
Field_Name = oFound1.Column
RRow = oFound1.Row +1
' code goes here
Else
Msgbox "Field Name was not found in Sheet #" & i
End If
Set oLookin2 = Worksheets(i).UsedRange
sLookFor2 = "Datatype"
Set oFound2 = oLookin2.Find(What:=sLookFor2, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not oFound2 Is Nothing Then
DataType = oFound2.Column
' code goes here
Else
Msgbox "Datatype was not found in Sheet #" & i
End If
Next i
This is an old old post - but I ran across it when I was having trouble figuring out why I suddenly could not import a PDF export into my excel sheet.
For me the problem was a row I was trying to match on was merged - did a simple unmerge for the entire sheet first and it worked like a charm.
'////// Select and open file
FieldFileName = Application.GetOpenFilename(FileFilter:="Excel Files,*.xl*;*.xm*") 'pick the file
Set frBook = Workbooks.Open(FieldFileName, UpdateLinks:=0, ReadOnly:=True, AddToMru:=False)
For Each mySheet In frBook.Worksheets
mySheet.Cells.UnMerge
Next mySheet