Save code-generated elements of form - vba

VBA, Excel 2010.
Given:
MultiPage Userform
Script, which makes copies of a page (based on this question)
Process:
Open form (1 page in multipage, screenshot 1);
Copy a page by running script (2 pages in multipage, screenshot 2);
Close form;
Re-open form (again only 1 page, same as on Step 1);
Script code:
Private Sub CommandButton1_Click()
Dim l As Double, r As Double
Dim ctl As Control
Dim totalPageNum As Integer
'Get number of existing pages
totalPageNum = MultiPage1.Pages.Count
'Add new one
MultiPage1.Pages.Add
'Copy elements
MultiPage1.Pages(0).Controls.Copy
MultiPage1.Pages(totalPageNum).Paste
MultiPage1.Pages(totalPageNum).Caption = "Page" & MultiPage1.Pages.Count
'Copying frame coordinates
For Each ctl In MultiPage1.Pages(0).Controls
If TypeOf ctl Is MSForms.Frame Then
l = ctl.Left
r = ctl.Top
Exit For
End If
Next
For Each ctl In MultiPage1.Pages(totalPageNum).Controls
If TypeOf ctl Is MSForms.Frame Then
ctl.Left = l
ctl.Top = r
Exit For
End If
Next
End Sub
Question: How to make pages to be saved on re-open of form/file (so I could get 2 pages on Step 4)
P.S. Unfortunately, I can't post pictures yet to explain the question in a better way.
Thanks for help!

The only way to do this is to simply hide the UserForm instead of unloading it if it is within the same session of Excel. If you have to close Excel and reopen it then there is not a way to save.
I would suggest saving the info you need to create your pages on a VeryHidden Worksheet and dynamically create the UserForm each time.

Related

Rename TextBoxes on Form after Copying it into a new multipage

I'm dealing with this issue. I have a userform that addapts after the user enters a value (for example, if he wants to add 3 members, the user form creates 3 different pages with the same boxes, after renaming them).
I have this right now:
After pressing "Lanzar", the userform will create more pages with "Datos Educando 2", "Datos Educando 3"... and so on, taking the value introduced on "Educandos a inscribir:"
The code is the following:
Private Sub lanzar_numero_educandos_Click()
Dim l As Double, r As Double
Dim ctl As Control
Me.MultiPage1.Pages(1).Visible = True
If Me.MultiPage1.Pages.Count > 2 Then
For a = Me.MultiPage1.Pages.Count - 1 To 2 Step -1
Me.MultiPage1.Pages.Remove a
Next a
End If
Me.MultiPage1.Pages(1).Visible = True
If educandos_a_inscribir.Value <> 1 Then
For a = 1 To educandos_a_inscribir.Value
MultiPage1.Pages.Add
MultiPage1.Pages(a).Controls.Copy
MultiPage1.Pages(a + 1).Paste
For Each ctl In MultiPage1.Pages(a).Controls
If TypeOf ctl Is MSForms.Frame Then
l = ctl.Left
r = ctl.Top
Exit For
End If
Next
For Each ctl In MultiPage1.Pages(a + 1).Controls
If TypeOf ctl Is MSForms.Frame Then
ctl.Left = l
ctl.Top = r
Exit For
End If
Next
Me.MultiPage1.Pages(a + 1).Caption = "Datos Educando " & a
Next a
Me.MultiPage1.Pages(1).Visible = False
End If
End Sub
Now, the problem I have is that the pages generated with this code have random names on each TextBox, so I'm not able to locate the information introduced from the user.
For example, this is the first page (the one that has the names I already know):
Here, the TextBox "Nombre Educando" is called "nombre_educando_1", so I can locate it easily on code:
The Textboxes created when copying the first page, have random names (like "TextBox 34", "TextBox 35"... and so on), so I'm not able to controll how are they called.
There is a way of generate the pages editing the TextBox names? Like, for example, for the second page generated, the TextBox in the example above should be "nombre_educando_2" and so on.
Thanks!
Each control on the first page has an attribute named Tag. You can value these with unique and meaningful values. When you paste the controls to the new page the Tag values will follow. Then as you loop through the controls on any page, use a Select Ctl.tag statement to identify what to do with the value of the control.

How to loop through VBA ActiveX (OLE) image controls on worksheet and load picture through the index

I have a bundch of ActiveX controls on a worksheet. I'm wondering if it's possible to Loop through all of them and load pictures depending on certain criteria.
Indeed, I can loop through them and print their name using:
For each obj in SheetName.OLEObjects
Debug.Print obj.Name
Next obj
I can also load pictures using simply
SheetName.Image1.picture = LoadPicture(Path)
What I can't do is to load pictures through a loop like :
For each obj in SheetName.OLEObjects
SheetName.OLEObjects("Image" & counter).Picture = LoadPicture(Path)
Next obj
It would be tedious to load them using the controls names: SheetName.Image1.Picture=...., SheetName.Image2.Picture...
Hope to find help from you!
Try the next way, please:
Sub testAddPictureByIteration()
Dim obj As OLEObject, Path As String
Path = ThisWorkbook.Path & "\yourPicture.bmp"
For Each obj In ActiveSheet.OLEObjects
If TypeOf obj.Object Is MSForms.Image Then 'to avoid buttons, text boxes etc.
obj.Object.Picture = LoadPicture(Path)
End If
End Sub

vba - Best Practice - Access Form Tab Control List Box Selected Items

What works ...
I have an Access I have a form, with a folder that has two pages or tabs. Each of these has it's own combobox related to the tabs topic. I wanted a fairly simply way to do this, by looking into the form, folder, tab I wanted, then pulling all selected values. I didn't know I was going to have to double for loop just to get this information.
Regardless, this is my good enough solution..
Private Sub getComboBoxInsideTabControl()
Dim selectedPage As Page
Dim pageIter As Page
Dim ctrl As Control
Dim varItm As Variant
Dim str As String
Set selectedPage = Me.folder1.Pages(1)
' GETS THE CONTROLS ON A PAGE
For Each ctrl In selectedPage.Controls
If ctrl.Name = "fields_lb" Then
MsgBox ("ok...")
' SEARCHES THROUGH A COMBOBOX CONTROLS SELECTED ITEMS
For Each varItm In ctrl.ItemsSelected
str = str & ctrl.ItemData(varItm) & ","
Next varItm
End If
Next ctrl
MsgBox (str)
End Sub
What I had hoped for ...
I really just want to know if there is a more simplistic way of doing it. For example, I kind of wanted something like this:
Dim results As String
Set results = Me.folder1.Pages(1).Controls("fields_lb").ItemsSelected
Is there a better way of doing this I am missing?

Dynamically Duplicating a page in a Multipage

Good afternoon, So I have been assigned a task where I'm supposed to take a Calendar Userform I made and implement the ability to duplicate as many calendars as needed as tabs on a multipage Userform.
My question is : Is it possible to do so dynamically? I copied over all the controls over to another tab to test it, but all the control buttons get renamed and I'm not able to name them the the same name as the buttons on the 'master page' because of the ambiguity error when naming 2 buttons the same on one userform.
I could write new code using the new button names, but this would not be able to be done dynamically since for ever new tab added, I'd have to have code ready for it prior to creation.
Any help would greatly be appreciated.
Demo Workbook
The key to handling this type of problem is to create a class to hold references to the newly created controls. Using WithEvents will allow you to handle the events of the referenced controls.
Read about WithEvents here: Events And Event Procedures In VBA
In order to make this work you'll have to Set references between the newly created Page controls and their doppelgangers in your class. You'll also need to keep the class references alive by adding them to a global collection, dictionary or array.
In my example I created a subroutine that will iterate over the template page controls, creating and copy the code necessary to declare the variable and set the references into the Windows ClipBoard.
The final step is to copy the event code from the Userform into the class module.
Download Demo Workbook for the code example.
Alternatively, you could replace the Multipage control with a TabStrip control. The difference is that you can have the controls on a TabStrip span across all the Tabs. You could than use the TabStrip1_Change() to update the controls based on the selected tab (TabStrip1.SelectedItem).
First of all I would recommend looking at Thomas Inzina's answer.
However, in one of my worksheets I did the same without relying on WithEvents, so I wanted to show the alternative method.
This method sets names of the controls along a predetermined format (e.g. "Input1_" (counter + 1)) so the controls are easily referenced from other operations.
The controls themselves are within Frames with set Captions, so I can still reference them after they've been copied.
I've edited the code somewhat since I stripped it from a longer procedure, but hopefully it's still intact.
Dim Ctrl As msforms.Control
Dim Mpage As msforms.Control
Dim Ctrl2 As msforms.Control
Dim pge As msforms.Page
Dim L As Double, R As Double
Dim PageName As String, PageTitle As String
Dim counter As Long
counter = 0
Set Mpage = Me.Controls("Multipage_1") 'set Multipage
'count current number of tabs within MPage
For Each pge In Mpage.Pages
counter = counter + 1
Next pge
'set name/title for new page
PageName = "Tab_" & (counter + 1)
PageTitle = "Tab " & (counter + 1)
With Mpage 'add tab
.Pages.Add PageName, PageTitle
.Pages(0).Controls.Copy
.Pages(counter).Paste
End With
'get position of original frame (controls are within this frame)
For Each Ctrl In Mpage.Pages(0).Controls
If TypeOf Ctrl Is msforms.Frame Then
L = Ctrl.Left
R = Ctrl.Top
Exit For
End If
Next
'apply position to new frame
For Each Ctrl In Mpage.Pages(counter).Controls
If TypeOf Ctrl Is msforms.Frame Then
Ctrl.Left = L
Ctrl.Top = R
Exit For
End If
Next
'renames input-controls and removes copied values by looping through frames
'that contain the controls, since frame-captions can be duplicates
For Each Ctrl In Mpage.Pages(counter).Controls
If TypeOf Ctrl Is msforms.Frame Then
Select Case Ctrl.Caption
Case "Input1"
For Each Ctrl2 In Ctrl.Controls
Ctrl2.Name = "Input1_" (counter + 1)
Ctrl2.Text = ""
Next Ctrl2
Case "Input2"
For Each Ctrl2 In Ctrl.Controls
Ctrl2.Name = "Input2_" (counter + 1)
Ctrl2.Text = ""
Next Ctrl2
Case "Input3"
For Each Ctrl2 In Ctrl.Controls
Ctrl2.Name = "Input3_" (counter + 1)
Ctrl2.Text = ""
Next Ctrl2
End Select
End If
Next Ctrl
use a prefix for the control names. eg. tab1_button1, tab2_button1, tab33_button1. then have only one one event handler that services all the events (button presses, checkbox clicks)
here is some info using one sub for multiple buttons in excel vba

Clear Text boxes within a Multipage Control on Userform

I am working on a school project while learning vba for the first time. The project is built around a wedding planning worksheet. I plan to lockdown the worksheet so that formulas and formatting don't get broken by the user (my fiance would find a way). In order to do this, I am building a userform that collects the data via text boxes on different pages of a multipage control.
This example only has one page, but it will show others like "Apparel" later:
I currently have the following code on _Click for the "Clear" button.
Dim C As Control
For Each C In frmExpenses.Controls
If TypeName(C) = "TextBox" Then
C.Value = ""
End If
Next C
This effectively clears the data from the text boxes. However, I want to be able to clear the data on ONLY the active page on the multipage. For example if there is later a tab called "Flowers" and it's the active tab, I want to leave the data on "Apparel" and clear the data from "Flowers."
I tried being as thorough as possible above. Let me know, if you need clarification on something.
Try this
For a particular Page (Say 1)
Dim ctl As Control
For Each ctl In Me.MultiPage1.Pages(1).Controls
If TypeName(ctl) = "TextBox" Then ctl.Value = ""
Next
From ActivePage
Dim ctl As Control
For Each ctl In Me.MultiPage1.Pages(Me.MultiPage1.Value).Controls
If TypeName(ctl) = "TextBox" Then ctl.Value = ""
Next