I'm trying to find the location of a specific string in vba.
The following code gives me the error: Run-time error 91: Object Variable or with block variable not set.
With Range("A2:A62")
Position = .Find("Unplanned").Address
End With
So I tried setting the variable with the following code which gave me the error: compile error type mismatch
With Range("A2:A62")
Dim Position As Range
Set Position = .Find("Unplanned").Address
End With
So then I randomly tried this which gave me compile error:object required
With Range("A2:A62")
Set Position = .Find("Unplanned ").Address
End With
Is there a certain type I should be using or way of writing this that would work better? - I'm very new and self taught with VBA.
Related
I am trying to create multiple instances of the same modeless UserForm in excel-VBA, with parameters, through a Sub.
I can make it work with two of the three parameters I want to assign, but the third one keeps returning me
"Run-time Error '91': Object variable or With block variable not set"
and I can't figure out why.
It may be an obvious typo that I didn't see, but I really can't point out the problem.
Here is my code:
Sub AskToClose(targetWksht As Worksheet, targetRow As Integer, test As String)
Dim newInstanceOfMe As Object
Set newInstanceOfMe = UserForms.Add("MOVE_TO_CLOSED") 'MOVE_TO_CLOSED is the name of my UserForm
newInstanceOfMe.targetWksht = targetWksht 'If I comment this line it works just fine, otherwise Run-time error 91
newInstanceOfMe.targetRow = targetRow
newInstanceOfMe.test = test
newInstanceOfMe.Show vbModeless
End Sub
_____________________________________________________________________
Sub test()
Dim openWksht As Worksheet
Set openWksht = Worksheets("OPEN WO") 'The worksheet exists and works just fine everywhere else
Call AskToClose(openWksht, 2, "test 2")
Call AskToClose(openWksht, 3, "test 3")
Call AskToClose(openWksht, 4, "test 4")
Set openWksht = Nothing 'I tried to comment this line just in case, same result...
End Sub
_____________________________________________________________________
'My MOVE_TO_CLOSED UserForm parameters
Public targetWksht As Worksheet
Public targetRow As Integer
Public test As String
newInstanceOfMe.targetWksht = targetWksht
This statement produces an error-level code quality inspection result for Value Required inspection in Rubberduck (an open-source VBIDE add-in project I manage). The inspection explains the situation as follows:
Object used where a value is required
The VBA compiler does not raise an error if an object is used in a place that requires a value type and the object's declared type does not have a suitable default member. Under almost all circumstances, this leads to a run-time error 91 'Object or With block variable not set' or 438 'Object doesn't support this property or method' depending on whether the object has the value 'Nothing' or not, which is harder to detect and indicates a bug.
There are two types of assignments in VBA: value assignment (Let), and reference assignment (Set). The Let keyword is redundant/optional/obsolete for value assignments:
Dim foo As Long
foo = 2 + 2
Let foo = 2 + 2 '<~ exactly equivalent to the above
So unless the Set keyword is present, VBA attempts to make a value assignment. If the object has a default member, that might just work - the VBA specs define how let-coercion mechanisms make that happen. That's how you can assign a Range to a value:
Sheet1.Range("A1") = 42
That's implicitly assigning to Range.Value, via an implicit member call to Range.[_Default], a hidden property of the Range class.
If the right-hand side of the assignment was also an object, then let-coercion would be happening on both sides of the operator:
Sheet1.Range("A1") = Sheet1.Range("B1") '<~ implicit default member calls galore!
Sheet1.Range("A1").Value = Sheet1.Range("B1").Value
But we're not looking at a Range here, we're looking at a UserForm, and a UserForm does not have a default member, so let-coercion can't happen... but the compiler won't validate that, so the code gets to run anyway... and blows up at run-time instead.
So, we're looking at a Let assignment with both sides holding an object reference, for a class type that doesn't define a default member.
Something.SomeObject = someOtherObject
But VBA doesn't care that there's no default member - because there's no Set keyword, it tries as hard as it can to do what you told it to do, and coerce these objects into values... and fails, obviously.
If Something.SomeObject (left-hand side) is Nothing, then the let-coercion attempt will try to invoke the inexistent default member -- but since the object reference is Nothing, the call is invalid, and error 91 is raised.
If Something.SomeObject is already holding a valid object reference, then the let-coercion attempt will go one step further, and fail with error 438 because there's no default member to invoke.
If Something.SomeObject has a default member (and the reference isn't Nothing), then the value assignment succeeds, no error is raised... but no object reference was assigned, and this might be a subtle bug!
Adding a Set keyword makes the assignment a reference assignment, and now everything works fine.
My code pastes a shape onto Sheet1 and tries to resize the width, getting an error on this line below.
Worksheets("Global Quarterly").Shapes(Picture1).Width = 1607.76
GlobalFile.Activate
Sheets("Sheet1").Select
ActiveSheet.Paste Destination:=Range("B25")
Selection.Name = "Picture1"
Worksheets("Global Quarterly").Shapes(Picture1).Width = 1607.76
Range("A1").Select
Application.ScreenUpdating = False
Option Explicit is likely missing, making Picture1 an undeclared variable, so at run-time you're passing Variant/Empty to the Worksheet.Shapes collection's Item property getter - and that's neither an index nor the name of a shape, so you get a... well an arguably confusing run-time error: a more instinctive error to throw would have been error 5 here, for "invalid parameter or procedure call" - it's the Shapes.Item member (implicit) that's throwing; execution never even gets to the Shape.Width member call.
Specify Option Explicit at the top of every module; that will make your code uncompilable until all variables are declared, which helps prevent typos and forces a minimal rigor in variable usage.
If the name of the shape is "Picture1" (note the string delimiters / double-quotes), then you need to do as Lodi hinted:
Worksheets("Global Quarterly").Shapes("Picture1").Width = 1607.76
When I'm trying to get or set various properties for charts using the FullSeriesCollection method, I'm running into an odd little problem. I can access them via index or the series name, but when I try to use a name stored in a variable, I get a run-time error 13 (Type mismatch). For example:
Dim trendname As String 'I've also tried Variant, but it still gives me error 13
trendname = "Average" 'when the name is used directly as below
Debug.Print Charts(1).FullSeriesCollection(1).Formula 'This works
Debug.Print Charts(1).FullSeriesCollection("Average").Formula 'This works
Debug.Print Charts(1).FullSeriesCollection.Item("Average").Formula 'This works
Debug.Print Charts(1).FullSeriesCollection(trendname).Formula 'This gives runtime error 13
Debug.Print Charts(1).FullSeriesCollection.Item(trendname).Formula 'This gives runtime error 13
Debug.Print Charts(1).FullSeriesCollection("" & trendname).Formula '...but this works fine!
Debug.Print Charts(1).FullSeriesCollection.Item("" & trendname).Formula 'This works too
Is there a way I can get it to work referencing trendname alone, rather than needing to concatenate the variable with an empty string? Is there a different variable type I should be declaring trendname as, instead of Variant or String?
While the concatenation method does work, it looks rather silly, and I'm curious as to why it works when just using the variable by itself doesn't.
As you may already know, the Index argument must be a Variant. So, even if you declare your variable as a Variant, once a string has been assigned to it, it's recognized as a string. So you'll have to coerce the index to a Variant using the type conversion function CVar...
Debug.Print Charts(1).FullSeriesCollection(CVar(trendname)).Formula
or
Debug.Print Charts(1).FullSeriesCollection.Item(CVar(trendname)).Formula
The code below has worked until my most recent update to it in. It still does work, but for some reason, it errors when opening it on a new PC if you have to click Enabling Editing. If you Enable Editing, end the routine, and close the spreadsheet, it works from there. I am just trying to understand what might be causing the hiccup on the initial open after Enabling Editing.
The code (please note that "Mnger_Tags" is a named group defined in the spreadsheet):
Dim Mnger As Variant, MngerCheck As String
Application.DisplayAlerts = False
'Determine User/Manager
Mnger = Application.Transpose(Range("Mnger_Tags").Value)
MngerCheck = LCase(Environ("UserName"))
If IsInArray(MngerCheck, Mnger) Then
frmMngerCheck.Show
MngerCheck = frmMngerCheck.MngerCheck
Unload frmMngerCheck
End If
The Error:
Takes place on line "Mnger = Application.Transpose(Range("Mnger_Tags").Value)"
Run-time error '1004':
Method 'Range' of object '_Global' failed
The goal:
The first line of code is meant to take whatever names are listed in that named range (Mnger_Tags) and create the array Mnger.
The code will then check if any value in the array Mnger match the UserName (MngerCheck).
I hope this is clear enough. This is my first post. Thank you all in advance.
I wrote a VBA script that runs through a bank statement finding payments of a certain value. This code ran when I wrote it, but a couple of months later I get Run-time error '438' Object doesn't support this property or method; here is an extract of the code.
Set bankWB = ActiveWorkbook
Set bankWS = ActiveSheet
For rowcount = 0 To 250
skipline = False
If bankWS.Cells(rowcount, paidcol) = 5 Then
payee = Trim(bankWS.Cells(rowcount, payeecol))
paid = "5"
The error occurs on the 'if' line.
I've found various examples that reference cell values in the same way and this worked previously. If you Google this error there are lots of results and I see that using 'range' is more common than using 'cell' to reference a single cell, but it's not obvious to me how to easily translate my (x,y) cell variables/loop into a range "A1" type value so I've not tried rewriting the code to use range instead yet.
I assume that the object is bankWS.Cells and it's the property rather than the method that is the problem. I want to know what the value of the object is (=property), I'm not trying to do anything with the object (=method)
I've seen lots of different ways of writing the cell object, and tried various permutations, none of which make a difference. eg.
If worksheet.bankWS.Cells(rowcount, paidcol) = 5 Then
If bankWS.Cells.item(rowcount, paidcol) = 5 Then
If bankWS.Cells(rowcount, paidcol).value = 5 Then
I'm thinking that the code is ok, and that something else has changed.
Solved
Thanks to #99moorem my row count loop should have started at 1, not 0, there will be no cell(0,1).