Userform MultiPage Navigation - vba

I have a Userform I built in Excel that has roughly ten tabs utilizing the MultiPage setup. Problem is I am running out of space for additional tabs and would really like to replace the tabs with a friendlier Navigation Menu or Toolbar. I've looked into the Microsoft ToolBar Control, which is close to what I'm looking for but I can't change the height and the dropdown has to have the arrow clicked and nto the text, which is not that intuitive in my opinion.
So my question is, are any of you familiar with a better multipage navigation setup, perhaps using a form of ActiveX?

I would reccommend seperating your User Form into seperate forms or Child forms based on category.
You can have one form launch another one if they are both Modeless, and both can be on screen at the same time. This way, you can work with both consecutively.
To launch a form as modeless, when you do Form1.Show change it to Form1.Show vbModeless

What I ended up doing was making a Listbox with all my different pages that is apart of my Multipage then placed this listbox on the left hand side of my Userform then used this code
Populate the listbox
i = 0
With Main_Window.form_navigation_list
.AddItem "Domestic"
.List(i, 0) = "Page 1"
.List(i, 1) = 0
i = i + 1
.AddItem
.List(i, 0) = "Page 2"
.List(i, 1) = 1
i = i + 1
End With
Then I have this for the on click
Private Sub form_navigation_list_Click()
Dim i As Integer
Dim SelectedRow As Integer
For SelectedRow = 0 To Main_Window.form_navigation_list.ListCount - 1
If Main_Window.form_navigation_list.Selected(SelectedRow) Then
nav_page = Main_Window.form_navigation_list.List(SelectedRow, 1)
With Main_Window
.MultiPage1.Value = nav_page
.Show
End With
End If
Next
End Sub
I started off using a flexgrid but kept getting a memory leak issue and program would crash, so I swapped to the listbox and it's working fine now. Now I can customize this listbox to look a bit more like the navigation I want.

Related

Sub to add controls works when called from one sub but the other

I am getting an error that I just can't figure out. I wrote a sub that opens a form in Design view, deletes all of the dynamic controls, then adds the requested number.
The sub gets called in two different ways. The user opening the form (via a Main Menu form) to fill out a new form (so the dynamic controls are deleted then recreated) OR after the form is created, the user can click a button on the form to add more rows of controls. Both the Main Menu and button form call the same sub, BUT when the button is clicked the code gets stuck and error 29054 'Microsoft Access can't add, rename, or delete the control(s) you requested.' is thrown. The button to debug is deactivated so I can't see what line is actually getting stuck, but when I step through the code this is the last line before the error pops up (the last indent block in the context below):
With Application.CreateControl("BOM5", acComboBox, acDetail, frm.Controls("Tabs").Pages(PageNum).Name, , ChangeTypeLeft, LastControlTop, ChangeTypeWidth, ControlHeight)
The rest of the code is as follows.
DoCmd.OpenForm "BOM5", acDesign
Set frm = Application.Forms("BOM5")
' Cycle through controls and set LastControlTop based on the last dynamic control, if any
For i = 0 To frm.Controls.Count - 1
Set ctl = frm.Controls(i)
Debug.Print ctl.Name
If ctl.Tag Like DYNAMIC_TAG & "*" Then
If ctl.ControlType = acComboBox Or ctl.ControlType = acTextBox Then
LastControlTop = ctl.Top + ControlHeight + ControlPadding
FormRowCount = FormRowCount + 1
End If
Else
FormRowCount = (FormRowCount / 6) + 1 ' Convert number of fields to number of rows then add one to start new batch of controls
Exit For
End If
Next
PageNum = frm.Controls("Tabs").Pages.Count - 1 ' .Pages has an index of 0. Getting PageNum to follow suit with the -1
' Add controls for inputting parts
For FormRowCount = FormRowCount To NewControlCount
With Application.CreateControl("BOM5", acComboBox, acDetail, frm.Controls("Tabs").Pages(PageNum).Name, , ChangeTypeLeft, LastControlTop, ChangeTypeWidth, ControlHeight)
.Name = "ChangeType" & FormRowCount
.Tag = DYNAMIC_TAG
.RowSourceType = "Table/Query"
.RowSource = "ChangeType"
End With
The last for loop has 5 other With Application.CreatControl statements, but I just showed the first one. The other 5 are similar except text boxes instead of combo.
I've had this error before, but I think I resolved it by moving the DoCmd.OpenForm statement to a different part of the code (like out of an if statement or for loop or somewhere that wasn't letting it get called) but I don't think that will resolve it. Besides, the first for loop iterates correctly since I see it grabbing the control height of the last dynamic control.
You can't do this. A form or report can only hold a certain amount of controls, deleted or not, so - eventually - it will not accept more controls. At that point, you must recreate the form from scratch.
So, don't delete the controls. Create those you may need and, at any time, hide those not needed and rename the rest if necessary.

Removing the tab page in code will remove the tab page permanently?

I Have the tabcontrol with number of tabpages.and also a treeview control where we have nodes defining the reports list which will be shown in different tabs Apart from the controls i used in tabs.
Now i want initially all the tabpages to be hidden and the moment i select the node from treeview control which is a name of that tab. it should open that tabpage.
From https://msdn.microsoft.com/en-us/library/system.windows.forms.tabpage.aspx I read that we can not hide the tabage using the tabcontol.tabpages.hide() . So i used Remove() and Add() methods to show and hide the tabpages.
My question is using the remove() method will it remove the tabpage permanently?
am using the code
Dim Tabindex As Integer
Dim tabheaderText As String
Tabindex = TabControlReports.TabPages.IndexOf(Me.TabControlReports.SelectedTab)
tabheaderText = Mid(TabControlReports.SelectedTab.Text, 1, 4)
If tabheaderText <> "Auto" Then
TreeView_ReportList.SelectedNode = TreeView_ReportList.Nodes(0).Nodes(Tabindex)
TreeView_ReportList.Focus()
ElseIf TabControlReports.SelectedTab.Text = "Auto Eras Downloading" Then
TreeView_ReportList.SelectedNode = TreeView_ReportList.Nodes(1).Nodes(0)
TreeView_ReportList.Focus()
ElseIf TabControlReports.SelectedTab.Text = "Auto Claim Submission" Then
TreeView_ReportList.SelectedNode = TreeView_ReportList.Nodes(1).Nodes(1)
TreeView_ReportList.Focus()
End If

VBA - another userfom open itself while I don't code this order

First of all, I'm sorry for my english speaking.
I test a code in order to implement a list of item for a business. My userform is use to search an item regarding other item which is linked. The valid bouton is used to search that and write the links on other listbox. When I click on the valid bouton, another userform open it. I don't understand why.
This is my code regarding this userform, can you explain me why vba do this ?
Private Sub valider_Click()
Dim i As Integer
subcat2.Enabled = True
cat2.Enabled = True
fami2.Enabled = True
depar2.Enabled = True
i = 1
While nom2 <> Feuil1.Cells(i, 1)
i = i + 1
Wend
subcat2 = Feuil1.Cells(i, 2)
cat2 = Feuil1.Cells(i, 3)
fami2 = Feuil1.Cells(i, 4)
depar2 = Feuil1.Cells(i, 5)
End Sub
Tkank you,
Best regards
Try putting a breakpoint in the valider_Click() method and running in debug mode and clicking the button.
If your program hits the breakpoint, then the button is wired to the event handler method correctly.
Otherwise, look at the button properties to see whether it's wired to the right event. Maybe it's accidentally wired to something that opens the other form?

Behind-the-scenes VBA activity interfering with listboxes

Background:
I have a VBA project in an Excel spreadsheet. In it, I have a form that contains a frame that contains multiple labels/listboxes.
When the application is loaded, these listboxes are populated with data. (Nearly) everything works as expected, and this is what the form looks like:
My Problem:
My problem is that when a user clicks on an item in a listbox, that listbox is automatically "jumped into view" or something. For example; if I click on list item 5 like so, the frame scrolls down so that the listbox is at the top:
Before Click:
After Click:
You can see that the list item under my click has been selected, but the list was scrolled up beforehand so it's not actually the intended selection. This is not being done by any of my code.
If I put a "Stop" as the "Enter" and "Click" event handlers, the correct list item is selected and the list has not jumped at "Enter", but has by "Click".
More information:
If I continue to click on other elements from the same listbox, the listbox does not "jump". I can scroll up and down, and the listbox will not jump. As soon as I click in a DIFFERENT listbox (so "listbox1_Exit" and "listbox2_Enter" have been raised), the new listbox is "jumped" into view.
My Question:
My Question is: what "behind-the-scenes" code is VBA executing between these two events, and how can I prevent this from occuring? Or is there a way to "monitor" events?
(VBA appears to just resume execution if you "step" past the end of an event handler, rather than move to the next executing line of code - which would REALLY be helpful here...)
Edit:
Minimal example - plonk a frame on an empty form, add 2 listboxes to the frame and execute this code in the form:
Private Sub UserForm_Initialize()
Dim lb1 As Control
Dim lb2 As Control
Dim Frame1 As Control
Set Frame1 = Me.Controls("Frame1")
Set lb1 = Me.Controls("ListBox1")
Set lb2 = Me.Controls("ListBox2")
lb1.Height = 500
lb2.Height = 500
For i = 1 To 25
lb1.AddItem ("Potato " & i)
lb2.AddItem ("Frog " & i)
Next i
lb1.Top = 0
lb2.Top = lb1.Height + 10
Frame1.ScrollHeight = lb1.Height + lb2.Height + 10
End Sub
then scroll to the point where you can see the end of Listbox1 and the start of Listbox2, and try clicking elements in Listbox2.

How do I load something when the page is selected?

I'm trying to make a form with a lot of pages. So far it works ok and I added the controls from the code. There are hundreds of them and it makes the app "heavy".
Now I'm adding all the stuff in the comboboxes in at Initialization but what I want to do is to load the Controls when I change the page.
So when I start the form the controls should be loaded for page 1. What I want to do is when I click on Page 2 of the Multipage to load it's components (instead of adding all of them at the initialization of the UserForm).
Thanks!
If you want to initialize each page only when it becomes clicked, you can track which has been clicked using something like;
Private mbInitialised() As Boolean
Private Sub UserForm_Initialize()
ReDim mbInitialised(MultiPage1.Pages.Count - 1)
SetupPage 0
End Sub
Private Sub MultiPage1_Change()
SetupPage MultiPage1.Value
End Sub
Private Sub SetupPage(index As Integer)
If (mbInitialised(index)) Then Exit Sub
mbInitialised(index) = True
MsgBox "init page " & index + 1
'//setup here
End Sub
I think this is an easier way to do it
Load UserForm: UserForm.MultiPage1.Value = 0: UserForm.Show
where the multipage value starts to "page1" as arrays starts from zero
if you want a different page change .Value = 0 into the page value - 1
ex:
Load UserForm: UserForm.MultiPage1.Value = 4 : UserForm.Show
this will take you to "page3" of multipage upon initializing userform
*edit:
misunderstood the question a bit, my code will take you to the page but not execute something when changing pages, use Alex's code instead