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

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

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

EXCEL VBA - Object Variable or With Block Variable Not Set

I'm currently developing a function that will search for the row number based on a string input that I have. In the following function however I get the error as stated in the title and i have no idea what to do about this :L
Here is the Find Row Function
Function MPNTRowECU(ByVal ECUVariantName) As Range
Debug.Print ECUVariantName
Dim wsMPNT As Worksheet
Set wsMPNT = Worksheets("Module Part Number Tracker")
MPNTRowECU = wsMPNT.Range("C:C").Find(What:=ECUVariantName, LookIn:=xlValues, SearchOrder:=xlByRows)
End Function
The Debug.Print line is there to make sure that ECUVariantName is indeed a string and it does return the string that i have everytime. At the MPNTRowECU is where I get the error. Any suggestions guys? Fairly new to VBA
Try the Function code below, instead of returning the Range, I modifed your Function to return the Row number (as described in your post).
Also, you need to make sure, that Find is successful , by using the If Not MPNTRng Is Nothing Then criteria.
Code
Function MPNTRowECU(ByVal ECUVariantName) As Long
Dim MPNTRng As Range
Debug.Print ECUVariantName
Dim wsMPNT As Worksheet
Set wsMPNT = Worksheets("Module Part Number Tracker")
Set MPNTRng = wsMPNT.Range("C:C").Find(What:=ECUVariantName, LookIn:=xlValues, SearchOrder:=xlByRows)
If Not MPNTRng Is Nothing Then ' confirm that Find was successful
MPNTRowECU = MPNTRng.Row
Else ' Find failed to find "ECUVariantName"
MPNTRowECU = -10000 ' just put a high negative value to raise an error
End If
End Function

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

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

VBA cannot correctly handle range returned by find method

I have this code:
Private Sub UserForm_Initialize()
Dim Text_Cell As Range
Dim temp As Control
Set Text_Cell = Sheet1.Cells.Find("Text")
Do Until Text_Cell.Offset(1, 0).Value = ""
Set temp = UserForm1.MultiPage(1).Controls.Add("Forms.Commandbutton.1", "h")
Set Text_Cell = text_Cell.Offset(1, 0)
Loop
EDIT: Just a quick clarification - using MsgBoxes, breakpoints, science, magic, etc. I found out the cause of the "Object required" error occurs well before VBA gets to the loop.
I am trying to find a cell in a sheet that has the value of "text" then for each cell with a value below it - create a control on my userform. The problem I am having is that the Find method finds the correct cell, returns and assigns it but for some reason VBA cannot handle the "text_Cell" variable, even though after setting a breakpoint and taking a look at the local variable of "text_Cell" I saw it is assigned to the proper cell. I keep getting "Object Required" error. Getting the cell alone returns nothing, hence trying to reference Offst(1,0) raises the "Object required" error.
I am trying to find a cell in a sheet that has the value of "text" then for each cell with a value below it - create a control on my userform.
Use the following to cycle through all of the non-blank cells beneath the cell with text.
Set Text_Cell = Sheet1.Cells.Find(What:="text", MatchCase:=False, _
LookAt:=xlWhole, LookIn:=xlFormulas)
Do Until Text_Cell.Value = ""
Set temp = UserForm1.MultiPage(1).Controls.Add("Forms.Commandbutton.1", "h")
Set text_Cell = text_Cell.Offset(1, 0)
Loop

Find() results in Object variable or With Block variable not set

Thanks for reading my post. I'm new to Excel VBA and have run into a wall debugging a call to Find(). I've gone through several posts on this site and others but so far each fix I've tried has been unsuccessful.
I am writing code to process elements out of financial reports. Each report contains one or more multi-row & multi-column blocks of cells with details describing a project. The size of each block isn't consistent, but each always begins in the top left with "Client Name". So I want to iterate through these blocks keying off that text, then pulling out needed elements.
There's no while loop here yet, as I'm running into the error just setting up the first condition.
Run-time error '91': Object variable or With block variable not set
Here's the section of code from within the Sub, with the error coming in the final line assigning cursorProject:
' store the next report to process
Dim nextReport As String
Dim sourceSheetName As String
Dim sheetSource As Worksheet
nextReport = rptMedia
' copy the worksheet into rptBurn and get that worksheet's name
sourceSheetName = GetSheet(nextReport)
Set sheetSource = Workbooks(rptBurn).Worksheets(sourceSheetName)
sheetSource.Cells.EntireRow.Hidden = False
sheetSource.Cells.EntireColumn.Hidden = False
Workbooks(rptBurn).Activate
' process the sheetSource into sheetCurrent
' set constants
Const constCursorKey As String = "Client Name"
Const constClientColumn As String = "B"
Const constClientNameOffset As Integer = 2
Const constProjectLeft As Integer = 2
Const constProjectRight As Integer = 52
' get range in Client Name column of project entries
Dim cursorStart As Long
Dim cursorEnd As Long
Dim cursorProject As Range
Dim rangeProject As Range
Dim rangeSearch As Range
cursorStart = sheetSource.Columns(2).Find(constCursorKey).Row + constClientNameOffset
' find the last project entry in the sheet
cursorEnd = sheetSource.Range("B" & Rows.Count).End(xlUp).Row
Set rangeSearch = sheetSource.Range(Cells(cursorStart + 1, constProjectLeft), _
Cells(cursorEnd, constProjectLeft))
cursorProject = rangeSearch.Find(What:=constCursorKey, LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
This is very sloppy currently as parts will be moved out to its own Sub called while iterating over the reports (hence nextReport is hardcoded here to a specific report name). The various constants are fixed parameters of the reports. The unlisted values like "rptBurn" are globals. The GetSheet function works well, but if you want to see it:
Private Function GetSheet(rpt As String) As String
Workbooks.Open rootPath + rpt
ActiveSheet.Copy after:=Workbooks(rptBurn).Sheets(Workbooks(rptBurn).Sheets.Count)
GetSheet = ActiveSheet.Name
Workbooks(rpt).Close
End Function
I've tried several variations on this. The Locals all look promising up to the error. I set the Hidden properties to False based on another post. I've tried simplifying the call down to the basics and using With, like this:
Set rangeSearch = Sheets(3).Range("B:B")
rangeSearch.Select
With rangeSearch
cursorProject = .Find("Client Name")
End With
But I'm always getting an error on cursorProject. There are definitely many "Client Name" entries in the worksheet I'm testing. I put in the Select to verify I'm grabbing the correct range; oddly I find that "B:AX" get highlighted (AX is the rightmost used column in the report) in the simple version, but the selection I expect in the original. Regardless there are "Client Name" instances in either selection--I can select B4 and see "Client Name".
What am I doing wrong?
Cursorproject is an object variable (range). You can't simply assign a value to an object variable, you have to set it.
dim strSomeTextVarible as string
dim rngSomeCellsObjectVariable as range
strSomeTextVarible = "abc"
set rngSomeCellsObjectVariable = range("a1:c3")