Setup: I have many projects with many UserForms, and when opening these on a dual monitor system, the default StartUpPosition is 1 = CenterOwner and it comes up off to the right of the primary display (the center of the windows desktop). I am trying to write a small piece of code that changes one property for every User Form in the project. In this case, specifically, .StartUpPosition = 2 (CenterScreen)
Using Microsoft Office Professional Plus 2010
I already know how to change the StartUpPosition using the Properties editor in VBA, under Positions.StartUpPosition. The issue is that there are so many UserForms over so many projects, I want to change them all on each project at once. Ultimately, I want to use the same code to alter any property by using overload arguments of the method (FormName, Property, Value) . For now, I'm OK with having just one to handle StartUpPosition.
When I run this code, upon opening the UserForm, it works as expected, overriding the default of StartUpPosition = 1 (CenterOwner) and it displays the form in the center of the screen.
Sub UserForm_Initialize()
With UserFormName
.StartUpPosition = 2 'CenterScreen'
End With
End Sub
However, when I run it embedded in this loop that cycles through the controls of the project from a module, in an attempt to change the defaults of all the forms at once, I get the following error.
Error: Run-time error '438': Object doesn't support this property or method.
Sub UserFormStartUp_Center()
Dim VBComp As Object
'For each control in project'
For Each VBComp In Application.VBE.ActiveVBProject.VBComponents
'Check to see if control is a UserForm'
If VBComp.Type = 3 Then '3 = vbext_ct_MSForm'
'Change Property - StartUpPosition - SAME AS ABOVE'
With VBComp
.StartUpPosition = 2 'CenterScreen'
End With
End If
'Loop through controls'
Next
End Sub
Question: How can I set the property for the form to be stored as the default, not just in an instance at Run-time, besides going into each UserForm and change it manually by scrolling down to the property and clicking on it, and then closing the form and moving on to the next to repeat. (Yes, I'd be done by now, but I have a lot of projects that will require changes to the UserForms as I learn new techniques, I need to patch other projects for clients)
I have the feeling it's something about run-time that I don't understand. I have to believe that you can set this property programmatically since it stores it with other properties.
Research:
MSDN: StartUp Object Property
According to MSDN, only objects at runtime can be StartUp objects.
MSDN: StartUpPosition Property
Thank you in advance for any help on this. This will save me many hours of clicking.
EDIT: Adding the following, after reading answers:
UPDATE: When I run the code with each of the suggestions you mentioned in the answer, I'm still getting an error. Run-Time error: '-2147467259 (80004005)' Method 'Properties' of object '_VBComponent' failed.
So I decided to try a few things out, like printing a MsgBox of the Property Item.. value, name, etc.
For Each VBComp In ActiveWorkbook.VBProject.VBComponents
'~~> Check to see if control is a UserForm'
If VBComp.Type = 3 Then
With VBComp
MsgBox (VBComp.Properties.Item(50).Value)
End With
End If
Next
When I do this, it's interesting. The Message Box appears, with the correct information that matches the Locals window for that item.. THEN, AFTER the msgbox, it give an object error. If it's an error, then why does the message box print out correctly? It's as if the UserForm is an Object, but the Property.Item is Not. Yet, it has parameters that can be defined such as Name, Value, etc.
Screenshot included of the Locals info on that property Item where Object Type = Nothing
Every UserForm/Control has a property which can be accessed by it's .Properties.Item
For example
Sub GetPropertiesDetails()
Dim VBComp As Object
Dim i As Long, j As Long
i = 1
For Each VBComp In ActiveWorkbook.VBProject.VBComponents
'~~> Check to see if control is a UserForm'
If VBComp.Type = 3 Then
With VBComp
For j = 1 To .Properties.Count
Debug.Print i & ". "; .Properties.Item(j).Name
i = i + 1
Next j
End With
Exit For '<~~ Just want to check for one userform
End If
Next
End Sub
When you run the above code you will get this in the Immediate Window
1. ActiveControl
2. BackColor
3. BorderColor
4. BorderStyle
5. CanPaste
6. CanRedo
7. CanUndo
8. Controls
9. Cycle
10. _Font_Reserved
11. Font
12. ForeColor
13. InsideHeight
14. InsideWidth
15. KeepScrollBarsVisible
16. MouseIcon
17. MousePointer
18. PictureAlignment
19. Picture
20. PictureSizeMode
21. PictureTiling
22. ScrollBars
23. ScrollHeight
24. ScrollLeft
25. ScrollTop
26. ScrollWidth
27. Selected
28. SpecialEffect
29. VerticalScrollBarSide
30. Zoom
31. DesignMode
32. ShowToolbox
33. ShowGridDots
34. SnapToGrid
35. GridX
36. GridY
37. DrawBuffer
38. Name
39. Caption
40. Left
41. Top
42. Width
43. Height
44. Enabled
45. Tag
46. HelpContextID
47. WhatsThisButton
48. WhatsThisHelp
49. RightToLeft
50. StartUpPosition
51. ShowModal
So from this we see that the property that we are after is at 50
. Now all we need to do is use that instead of .StartUpPosition = 2
like you did.
Sub SetUserformStartUp()
Dim VBComp As Object
For Each VBComp In ActiveWorkbook.VBProject.VBComponents
'~~> Check to see if control is a UserForm'
If VBComp.Type = 3 Then VBComp.Properties.Item(50).Value = 2
Next
End Sub
Courtesy of Chris Neilsen (From comments)
You can also use:
VBComp.Properties.Item("StartUpPosition") = 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With