PDA

View Full Version : Collection of userform textboxes not accessible nor is created correctly



Operon
07-21-2016, 11:03 AM
I have a userform in PowerPoint 2016 that contains several textboxes and I'd like to identify those whose contents have been edited since the last save. To this end I created a test scenario whereby a userform has two text boxes and a commandbutton that prints the contents of a collection which is created when these textboxes have undergone change events. More specifically, my thinking is to parse through all the objects on the userform identifying the textboxes and assigning to the textbox's change event a class module that compiles the textbox's name and an associated boolean as an object into a collection. This collection then can be used to identity those objects (textboxes) and resets them.


This code creates the class module, mkTextBox that will be initiated within the class module clsTextBox which is used to enumerate these textboxes:

Public TName As String
Public TFlag As Boolean

Public Function State_TB(ByVal T_Name As String, ByVal T_Flag As Boolean)
TName = T_Name
TFlag = T_Flag
End Function


This class module clsTextBox, which is invoked upon the textbox's change event, assigns the object MT_TB with the attributes of mkTextBox and then adds the object as MT_TB to the collection TBList:


Public TBList As New Collection
Private WithEvents MyTextBox As MSForms.TextBox

Public Property Set Control(tb As MSForms.TextBox)
Set MyTextBox = tb
End Property

Public Sub MyTextBox_Change()
Set MT_TB = New mkTextBox
MT_TB.State_TB MyTextBox.Name, True
TBList.Add MT_TB

Debug.Print MT_TB.TName, MT_TB.TFlag, TBList.Count
End Sub


This code, upon he userform load event, parses through the userform and creates a collection as tbCollection of all the textboxes on the userform. It aslo assigns the class module clsTextBox to these textboxes:

Public ctrl As MSForms.Control
Dim tbCollection As Collection
Public MT_TB As mkTextBox

Private Sub UserForm_Initialize()
Dim ctrl As MSForms.Control
Dim obj As clsTextBox

Set TBList = New Collection
Set tbCollection = New Collection

For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.TextBox Then
Set obj = New clsTextBox
Set obj.Control = ctrl
tbCollection.Add obj
End If
Next ctrl

Set obj = Nothing
End Sub


This code assigns to a commandbutton instructions that lists the contents of the collection TBList:


Private Sub CommandButton1_Click()
For Each MT_TB In TBList
Debug.Print MT_TB.TName
Next
End Sub

This code doesn't through off any errors but the:
1. command button doesn't work.
2. Also the TBList collection's count resets itself each time a change event upon moving to another textbox of the userform. I know why; the clsTextBox class module reforms the collection each time the statement:

Public TBList As New Collection is processed. However moving the statement:

Public TBList As New Collection
anywhere else in the code causes an error when MT_TM is attempted to be added to TBList.

I'm not sure why I can't get this to work as intended. any assistance is gratefully appreciated.

Paul_Hossler
07-24-2016, 07:47 AM
Can you post a small sample presentation with the details of how to reproduce the issue?

SamT
07-24-2016, 04:54 PM
Personally, I would just use a common Collection Object, either in the UserForm code or in a Standard Module

In Standard Module "modControlStates":

Option Explicit

Public TextBoxStates As Collection

Public Function ResetAllStates()
Dim i As Long

For i = 1 to TextBoxStates.Count
TextBoxStates(i) = False
next i
End Function

Public Function ChangeState(Ctrl As MSForms.TextBox)
If Ctrl.Text = "" Then
TextBoxStates(Ctrl.Name) = False
Else
TextBoxStates(Ctrl.Name) = True
End If
End Function

Public Function HasChanged(Ctrl As MSForms.TextBox) As Boolean
HasChanged = TextBoxStates(Ctrl.Name)
End Function

Public Function AnyChangedContols() As Boolean
Dim i As Long

For i = 1 to TextBoxStates.Count
AnyChangedControls = AnyChangedControls + TextBoxStates(i)
next i
End Function

Public Function AllControlsChanged() As Boolean
Dim i As Long

AllControlsChange = True

For i = 1 to TextBoxStates.Count
AnyChangedControls = AnyChangedControls * TextBoxStates(i)
next i
End Function


Class Module clsTextBox code
Option Explicit

Private WithEvents MyTextBox As MSForms.TextBox

Public Sub MyTextBox_Change()
ChangeState MyTextBox
End Sub

Where you choose to load the collection is up to you, but I would put that code in the Standard Module "modControlStates" and Call it from the UserForm_Initialize sub. Just set the Collection Key to the Control Name and the Item to False.

The above should let you. . . for examples

Private Sub CommandButton1_Click()
ResetAllStates
'
'
End Sub

'
'
If HasChanged(TextBox1) then
'
'

Private Sub CommandButton1_Click()
If not AllControlsChanged then Exit Sub
'
'
End Sub

Operon
07-24-2016, 07:05 PM
Can you post a small sample presentation with the details of how to reproduce the issue?
Here is the "proof of concept" file to be viewed in VBA explorer

Operon
07-28-2016, 01:08 AM
I humbly thank you for all yoyr excellent replies. Sadly, I have to have some surgery tomorrow and will be unable to deal with this for about a month. I promise to re3turn to it as soon as I am able.

Cheers,

John

SamT
07-28-2016, 04:05 AM
Good luck. I have had a few major surgeries and am still kicking, so don't worry too much.