I hate designing userforms. I mean the part where I’m lining up controls, renaming controls, and all the other super-fiddly parts of making a form look and act right – like setting the tab order. I always wait until the very end so I don’t have to do it twice. And that Tab Order dialog? Forget about it.
When I’m finally ready to set the tab order, I find the first control and click Move Up until it’s at the top. Next, I find the second control and click Move Up until it’s just below the first control. Then I go to Whammyburger and force them to serve me breakfast. Then I go back and do the rest of the controls. It’s maddening. I decided finally to do something about it.
First I set a reference to the VBA Extensibility Library.
Then I put this code in a standard module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Public Sub FixTabOrder() Dim ctl As Control Dim i As Long, j As Long Dim lCnt As Long Dim vbc As VBIDE.VBComponent 'Change this to the name of your userform Set vbc = ThisWorkbook.VBProject.VBComponents("UInvoice") For i = 1 To vbc.Properties("Width") For j = 1 To vbc.Properties("Height") For Each ctl In vbc.Designer.Controls If ctl.Top = i And ctl.Left = j Then ctl.TabIndex = lCnt lCnt = lCnt + 1 End If Next ctl Next j Next i For Each ctl In vbc.Designer.Controls Debug.Print ctl.Name, ctl.TabIndex Next ctl End Sub |
This is pretty brute force, but it only take a few seconds to run, so who cares. The i and j variables move through the userform point-by-point, left to right, top to bottom (that’s the typographical point, not the agenda items point). For every point on the userform, it loops through every control to see if that control starts at that point. If it finds one, it sets the controls TabIndex to the next number. At the end it just prints out the control names and tabs.
Even if that’s not exactly how I want my tab order, it gets it close and I can make other modifications manually.
If you have a super-wide or super-long form, it will take longer. The right way to do this is to put all the controls in an array and sort them by their Top and Left properties. If this method is too slow, you should write that up. Then send me a copy.
There is an easy way to set TabIndex properties.
1 – Left click in the first control;
2 – Hold Ctrl key and click in each control in the order you want;
3 – Open the Properties window
4 – Set the TabIndex property to 0 and press Enter
You’ll see that the the order will be rearranged according to the order you made your clicks.
@Felipe, that’s crazy! (in a good way). I never knew that.
On a somewhat related note, I’ve got some code that lists all the accelerator keys on a form. I think it could benefit from Dick’s VBIDE code above. It’s at http://yoursumbuddy.com/listing-userform-accelerator-keys/
Genius, Felipe. Thanks.
I have that too Doug (http://dailydoseofexcel.com/archives/2008/07/22/list-userform-hotkeys/) but only to see what’s available.
@Felipe – Brilliant!!!!
Felipe –
This is awesome. Thanks.
There is a handy UserForm method called SetDefaultTabOrder.
If you UserForm has a lot of controls, you can first run:
Then, you run:
*Change UserForm1 to the name of your target UserForm
*You must enable trust to your VBE project to run the second procedure.
Without bothering the worksheet: