Create Userform on the Fly?

PA HS Teacher

Well-known Member
Joined
Jul 17, 2004
Messages
2,838
Is it possible to create a userform on the fly?

I know how to create controls on the fly.
e.g.
Set ctl = MyForm.Controls.Add("forms.CommandButton.1")

But what if I wanted to create MyForm on the fly?
 

Excel Facts

Can Excel fill bagel flavors?
You can teach Excel a new custom list. Type the list in cells, File, Options, Advanced, Edit Custom Lists, Import, OK
Hi Dan and Norie...

Dan. You do not need Access to utilize an Access database. You would need to design it though. I understand Norie's point and thought of it as well. Even so, wrapping your data in classes is preferred to directly accessing a database as far as your project is concerned because of the compartmentalization aspect. I glanced at your project again and am not really concentrating on your code but on your logical design that the code should clearly portray. One very important consideration and a common mistake is to create objects explicitly that should only be create implicitly.

For example. You have a "Car" class. You do not want to explicitly create a "SteeringWheel" class in your code. This class should be returned as a property of the "Car" class and implicitly created from within the "Car" class. The Range object is a good example of this. You cannot directly create a range object. It can only be returned as a property of another class such as the application or worksheet classes. That is why this code will never compile...

Dim r As New Range

It is almost always a bad idea to use a collection outside of a class to maintain a collection of objects. It's easier in the short term but will bloat your project down the road and lead to more complicated and error prone calling code. The collection should be maintained within the parent class. Again, the Range object is a good example of this...

Sub Example()
Dim r As Range
'without your consideration, the Range
'being referenced by 'r' also contains
'an implicit collection of ten ranges
Set r = Range("A1:A10")

Debug.Print r(1).Address
Debug.Print r(10).Address
End Sub

The collection is created and maintained for you without your intervention and is available via the default 'Index' property...

Debug.Print r.Index(1).Address
Debug.Print r.Index(10).Address

My favorite part of a project is the logical design and a good logical design will lead to good code. A bad logical design leads to code that you will not be able to understand down the road even if you are the author.

Am going fishing with my son so I do not really have time to post a decent example right now. Your logical design should match the phyical design of your objects as closely as possible.

Briefly, create an outline on paper and decide how your objects should be aligned. Your procedure creates several different objects that might be better contained within a parent...

Example:
Sections
....Section
........Piece

The toplevel object being the 'Sections' class. This class would contain a method called 'Add' which accepts generic arguments. The 'Sections' object might return one or more child 'Section' objects. The 'Sections' object would be responsible for the actual creation and maintenance of the individual 'Section' objects. The 'Section' objects, in turn, would create 'Piece' objects. I may be making this sound more complex than it really is, but am really just trying to help you out. It is well worth your time to look deeper into the object based design. Especially if you later move into more recent versions of VB which are actually object oriented. I'll provide an example tommorrow that will make good sense too you...

Error:
Debug.Print r.Index(1).Address
Debug.Print r.Index(10).Address

The default property of the range is 'Item':
Debug.Print r.Item.Address
Debug.Print r.Item).Address
 
Upvote 0
Tom,
You explanation is clearing up many concepts in my mind. I really appreciate your perspective and I think I see what you mean. Please permit me to explain back to you what I think I am learning.

If I understand you,

Rather than creating the controls from my Regular module as in my posted file above, I would be much better off creating them in my 'Piece' class module. Similarly I would be much better off collecting my 'Piece' objects into a property of type collection in a 'Section' module, or better maybe as properties of a 'uf' object which would be a property of Section object. Maybe I should rethink of my sections as Uf objects. I will think this through on paper as you've suggested and post back an object model outline.

In this way I would be creating objects 'implicitly', they are created simply by instantiation of the parent object (code in the class module of the parent object is used to create these objects as a propert(y/ies) of the parent object), rather than having to 'explicitly' create these objects in a general code module everytime I create the parent object. If I sit down and really think through and map out an object model that closely resembles my physical situation, I save myself a lot of time and headaches, by setting up my objects the simple act of instantiation does most of the 'heavy lifting', leaving me less opportunities to make mistakes in my general modules, and greatly simplifying my code.

I would learn greatly from any example you might post. Do not feel rushed, My wife is off today and I will not be putting a lot of time into this project today anyway. I will post back an object model for my project, and perhaps you could look it over. I am particularly interested in the possibility of indexing a property 'Instance' of 'Piece' of 'Section' by the syntax Section.Piece(sPieceID).Instance(dDay,iPeriod), similar to the MyCar.Doors(x,y). , example I saw in Tushar-Meta's insightful post http://www.mrexcel.com/board2/viewt...c&highlight=implicit+class+property&&start=10

As always, thank you for your guidance. Good Luck getting your bait wet.
 
Upvote 0
I think you are grasping it. In essense, you are hiding complexity by encapsulating most of the functionality within your objects. This includes 'mass' error handling. You don't want to have to write code to teach a car how to drive from outside the car object. The car object should know how to drive already and should have a method called DriveMe. I'll get to that example but am hoping that Tusharm will add to this discussion or at least tear it apart! :)
 
Upvote 0
My Object Model 7-24-06 1:30 pm EST

Tom, Norie et al.,
Here is my draft of an object model for my model. See my next post for my attempt at implementing this model.
Edit [Here's my Current Attempt] http://www.box.net/public/yajt3katad
Object Model Planning System 7-20-06.xls
ABCDEFGHIJKL
1Courses(cls_5_Course)Object Model for My Course Planning System
2Course
3Units(cls_4_Unit)
4Unit
5Titleas RangeSections(cls_3_Section)
6Descriptionas RangeSection
7Titleas RangePieces(cls_2_Piece)
8Descriptionas RangePiece
9Commentsas RangeFrmas SectionTemplateFrmUses(cls_1_Use)
10TargetNumDaysas RangeIDas WorksheetUse
11UnitFileAddressas RangePiecesRngas RangeIDas Range
12Unitas workbookTitleas RangeTxtas RangeDayas Range
13Lineas RangeRetiredas RangeSectionas Range
14DisplayHeaderas RangeLastTermas RangeTermas Range
15CollectionCenterHeaderas RangeLastUseas RangeOrderas Range
16Excludeas RangeCreatedas RangeUseTBas Range
17ObjectLastModifiedas RangeUseLBas Range
18TxtTBas Control
19PropertyTxtLBas Control
20updated: 7/24/06 1:30 PMIDLBas Control
Object Model
 
Upvote 0
The Class Modules for the Object Model outline above would be contained in a Workbook Called, Dans Courses.xls. This workbook will contain a Preferences Worksheet, and a Worksheet containing the data for each 'Course'.
Dans Courses.xls
ABCDE
1TitlePhysics
2DescriptionCollege Prep
3
4Units
5TitleDescriptionCommentsTargetNumDaysUnitFileAddress
6Unit 1: Kinematics1-D MotionGreat Unit15C://Course 1/Unit1.xls
7Unit 2: Newton's LawsForcesAlso a Great Unit12C://Course 1/Unit2.xls
8Unit 3: MomentumCollisionsLike this too10C://Course 1/Unit3.xls
9
Course 1


Each 'Unit' is stored as an .xls file in a course folder as outlined above. Each 'Section' is stored as a worksheet in the 'Unit' file as shown below. Each 'Piece' is represented by a Column. Each 'Use' is represented by a Row.
Unit 3.xls
ABCDEFG
1TitleSection 1ID12
2Line1TxtTxt P-1Txt P-2
3DisplayHeaderTRUERetiredFALSEFALSE
4CenterHeaderTRUELastTerm2004-20052004-2005
5ExcludeFALSELastUse5/21/20055/21/2005
6Created5/1/20025/1/2002
7LastModified5/1/20025/1/2002
8
9DaySectionTermOrder
107/15/2006Per 12006-20071Specific Use Info Goes in these Cells
117/16/2006Per 12006-20071
127/17/2006Per 32006-20071
S1
 
Upvote 0
I've had some succes "wrapping" my lower objects into my higher objects, but I don't know how to use a class module to collect smaller objects into a collection.

For example, How can I use my cls_2_Piece to collect 'Use' objects into a Uses collection?

Here is the class module for my "smallest" object
cls_1_Use

<font face=Courier New><SPAN style="color:#00007F">Private</SPAN> p_rngDay <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_rngSection <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_rngTerm <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_rngOrder <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_ctlUseTB <SPAN style="color:#00007F">As</SPAN> Control
<SPAN style="color:#00007F">Private</SPAN> p_ctlUseLB <SPAN style="color:#00007F">As</SPAN> Control
                    
                    <SPAN style="color:#007F00">' Day</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Day(rngDay <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_rngDay <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_rngDay = rngDay
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Day() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Day = p_rngDay
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Section</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Section(rngSection <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_rngSection <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_rngSection = rngSection
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Section() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Section = p_rngSection
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Term</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Term(rngTerm <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_rngTerm <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_rngTerm = rngTerm
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Term() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Term = p_rngTerm
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Order</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Order(rngOrder <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_rngOrder <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_rngOrder = rngOrder
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Order() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Day = p_rngOrder
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' UseTB</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> UseTB(ctlUseTB <SPAN style="color:#00007F">As</SPAN> Control)
  <SPAN style="color:#00007F">If</SPAN> p_ctlUseTB <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_ctlUseTB = ctlUseTB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> UseTB() <SPAN style="color:#00007F">As</SPAN> Control
  <SPAN style="color:#00007F">Set</SPAN> UseTB = p_ctlUseTB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' UseLB</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> UseLB(ctlUseLB <SPAN style="color:#00007F">As</SPAN> Control)
  <SPAN style="color:#00007F">If</SPAN> p_ctlUseLB <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_ctlUseLB = ctlUseLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> UseLB() <SPAN style="color:#00007F">As</SPAN> Control
  <SPAN style="color:#00007F">Set</SPAN> UseLB = p_ctlUseLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
</FONT>

Here is the class Module for the next object up
cls_2_Piece

<font face=Courier New><SPAN style="color:#00007F">Private</SPAN> p_RngID <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngTxt <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngRetired <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngLastTerm <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngLastUse <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngCreated <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_RngLastModified <SPAN style="color:#00007F">As</SPAN> Range
<SPAN style="color:#00007F">Private</SPAN> p_ctlTxtTB <SPAN style="color:#00007F">As</SPAN> Control
<SPAN style="color:#00007F">Private</SPAN> p_ctlTxtLB <SPAN style="color:#00007F">As</SPAN> Control
<SPAN style="color:#00007F">Private</SPAN> p_ctlIDLB <SPAN style="color:#00007F">As</SPAN> Control
<SPAN style="color:#00007F">Private</SPAN> p_colUses <SPAN style="color:#00007F">As</SPAN> Collection
                  
<SPAN style="color:#007F00">' ??????????????????????????????????????????????????????????????</SPAN>
                   <SPAN style="color:#007F00">' Uses</SPAN>
<SPAN style="color:#007F00">' I'm not sure how to add cls_1_Use objects to p_colUses collection</SPAN>
<SPAN style="color:#007F00">' Related, how do I Add a ctlTxtTB, ctlTxtLB, and ctlIDLB to</SPAN>
<SPAN style="color:#007F00">' Frm of the parent cls_3_Section object ?</SPAN>

                    <SPAN style="color:#007F00">' ID</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> ID(rngID <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngID <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngID = rngID
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> ID() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> ID = p_RngID
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Txt</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Txt(rngTxt <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngTxt <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngTxt = rngTxt
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Txt() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Txt = p_RngTxt
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Retired</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Retired(rngRetired <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngRetired <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngRetired = rngRetired
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Retired() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Retired = p_RngRetired
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' LastTerm</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> LastTerm(rngLastTerm <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngLastTerm <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngLastTerm = rngLastTerm
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> LastTerm() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> LastTerm = p_RngLastTerm
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' LastUse</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> LastUse(rngLastUse <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngLastUse <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngLastUse = rngLastUse
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> LastUse() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> LastUse = p_RngLastUse
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' Created</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> Created(rngCreated <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngLastUse <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngCreated = rngCreated
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> Created() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> Created = p_RngCreated
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' LastModified</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> LastModified(rngLastModified <SPAN style="color:#00007F">As</SPAN> Range)
  <SPAN style="color:#00007F">If</SPAN> p_RngLastModified = <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_RngLastModified = rngLastModified
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> LastModified() <SPAN style="color:#00007F">As</SPAN> Range
  <SPAN style="color:#00007F">Set</SPAN> LastModified = p_RngLastModified
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' TxtTB</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> TxtTB(ctlTxtTB <SPAN style="color:#00007F">As</SPAN> Control)
  <SPAN style="color:#00007F">If</SPAN> p_ctlTxtTB <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_ctlTxtTB = ctlTxtTB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> TxtTB() <SPAN style="color:#00007F">As</SPAN> Control
  <SPAN style="color:#00007F">Set</SPAN> TxtTB = p_ctlTxtTB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' TxtLB</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> TxtLB(ctlTxtLB <SPAN style="color:#00007F">As</SPAN> Control)
  <SPAN style="color:#00007F">If</SPAN> p_ctlTxtLB <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_ctlTxtLB = ctlTxtLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> TxtLB() <SPAN style="color:#00007F">As</SPAN> Control
  <SPAN style="color:#00007F">Set</SPAN> TxtLB = p_ctlTxtLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>

                    <SPAN style="color:#007F00">' IDLB</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Set</SPAN> IDLB(ctlIDLB <SPAN style="color:#00007F">As</SPAN> Control)
  <SPAN style="color:#00007F">If</SPAN> p_ctlIDLB <SPAN style="color:#00007F">Is</SPAN> <SPAN style="color:#00007F">Nothing</SPAN> Then _
  <SPAN style="color:#00007F">Set</SPAN> p_ctlIDLB = ctlIDLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN>
<SPAN style="color:#00007F">Public</SPAN> <SPAN style="color:#00007F">Property</SPAN> <SPAN style="color:#00007F">Get</SPAN> IDLB() <SPAN style="color:#00007F">As</SPAN> Control
  <SPAN style="color:#00007F">Set</SPAN> IDLB = p_ctlIDLB
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Property</SPAN></FONT>
 
Upvote 0
Here is a beginning example. We'll work our way down your model and then create more concise code so we don't end up having code that looks like this:

Object(Index).Item(Index).Item(Index).Item(Index).SomeProperty

Use generic arguments whenever possible. Do not pass a range unless you have to. I replaced your range arguments with string. If you later decide to store your data in some other medium, your class code will break.

Download the example and step through the code in Module1.

Object Model Planning System 7-24-06 (Version 2).zip

Module1
Code:
Option Explicit

Dim cps As CoursePlanningSystem

Sub Example()
    Set cps = New CoursePlanningSystem
    
    If Not cps.CourseExists("Course One") Then
        cps.AddCourse "Course One", "Course One Description"
    End If
    
    If Not cps.CourseExists("Course Two") Then
        cps.AddCourse "Course Two", "Course Two Description"
    End If
    
    'same as cps.Courses(1).Title
    Debug.Print cps(1).Title
    'same as cps.Courses("Course One").Description
    Debug.Print cps("Course One").Description
    Debug.Print cps.CoursesCount
    cps.RemoveCourse "Course Two"
    Debug.Print cps.CourseExists("Course Two")
    Debug.Print cps.CoursesCount
End Sub

Class
CoursePlanningSystem

Code:
Option Explicit

Private pCourseCollection As Collection
Private WithEvents pCourse As Course
'it may seem redundant to wrap a collection object, but it is a good practice
'by giving you more control over your objects and providing code
'that is easier to understand and maintain

'this is a readonly property.  No Property Set.
'we do not want to allow direct access to create 'stand-alone' course objects.
'Access to the Course object and all child objects will be managed
'by this parent class.  You should change this limitation only if you think it is necc.
'
'the index is a variant to allow an integer or string
'this will allow you to refer to a course object by position or Course Title
'same as Sheets("Sheet1") or Sheets(1)
'VBA does not provide overloading so this is the only way we can provide
'this flexibility while using only one argument
'
'this is the default property
'see
'http://www.cpearson.com/excel/DefaultProperty.htm
Public Property Get Courses(Index As Variant) As Course
    'you will need to validate the index before using it
    
    Set Courses = pCourseCollection(Index)
    Set pCourse = Courses
End Property

'read only count of course objects
Public Property Get CoursesCount() As Integer

    CoursesCount = pCourseCollection.Count
    
End Property

'require the minimum amount of information to actually
'create a valid 'Course' object
Public Function AddCourse(Title As String, Description As String) As Boolean

    If Not CourseExists(Title) Then
        Dim c As New Course
        c.Title = Title
        c.Description = Description
        pCourseCollection.Add c, Title
    Else
        Err.Raise 457, , "This key is already associated with an element of this collection" & vbCr & "The course, """ & Title & """, already exists..."
    End If
    
End Function

Public Function RemoveCourse(Title As String) As Boolean

    If CourseExists(Title) Then
        pCourseCollection.Remove Title
    End If
    
End Function

Public Function CourseExists(Title As String) As Boolean

    On Error Resume Next
    
    Dim c As New Course
    Set c = pCourseCollection(Title)
    If Err.Number <> 0 Then Exit Function
    CourseExists = True
    
End Function

Private Sub Class_Initialize()

    'this is where you would load the data for all of your objects
    'set up defaults, ect...
    Set pCourseCollection = New Collection
    
End Sub

Private Sub pCourse_UpDate(Instance As Course, OldTitle As String, NewTitle As String)

    Dim SaveIndex As Integer
    
    For SaveIndex = 1 To pCourseCollection.Count
        If pCourseCollection(SaveIndex).Title = OldTitle Then Exit For
    Next
    
    pCourseCollection.Add Instance, NewTitle, SaveIndex
    pCourseCollection.Remove SaveIndex
    
    Set pCourse = Nothing
    
End Sub

Class
Course

Code:
Option Explicit

Private p_colUnits As Collection
Private p_Title As String
Private pDescription As String

Event UpDate(Instance As Course, OldTitle As String, NewTitle As String)

' Again, How do I collect up cls_4_Unit objects into p_colUnits ?

                    ' Title
Public Property Let Title(NewTitle As String)
    RaiseEvent UpDate(Me, p_Title, NewTitle)
    p_Title = NewTitle
End Property

Public Property Get Title() As String
    Title = p_Title
End Property
                    
                    ' Description
Friend Property Let Description(Description As String)
    pDescription = Description
End Property

Public Property Get Description() As String
    Description = pDescription
End Property
 
Upvote 0
Hi Dan.

Am awaiting some input from you. I know that I have strayed far from your original question. We'll get to that as we move down the chain and get to your Section object or, if you have determined to go at it the way you have currently designed your object templates, we can just answer your original post. I think I have a pretty good handle on your project and your approach, but want to mention one more thing before continuing on. Your method of binding your ranges to object properties may not be a good idea and you may regret it down the road. My opinion and my approach would be to use native types whenever possible such as string or integer. The objects should not be directly bound to the type of container that is holding your data such as a range. What if you decide to store your data in a database? Or even a simple textfile? All of your objects would need to be changed. This, in turn, would alter the interface causing your calling code to break. A better approach is to make your objects as generic as possible. Make them independant of the data source. If you are set on storing your data in worksheets and ranges then create a "Binding" object to bind your object's properties to specific ranges. This way, if you later decide to change the way your data is stored, you will only need to change the way your data is bound. A much easier alternative.

Whatever you decide is just fine. Let me know your direction and I'll actually answer your original question. I hope I did not kill this post with bloat...
 
Upvote 0
Tom,
I appologize for not getting back to you sooner. I should have posted an update yesterday. I worked on a project for my wife yesterday (It was actually Excel VBA!), but I did not pick up this one.

I am about to sit down and work with your 7/24/06 post. You have in no way killed this post. I am eternally greatful to work with someone such command of Object oriented programming.

As I was reading, http://www.microsoft.com/technet/prodtechnol/office/office2000/solution/part2/ch09.mspx?mfr=true before my previous post, I thought it might be better to use "Scalar" properties. I was hoping you might see a better way than setting the properties of my objects = Ranges. I just didn't/ don't know how to do that. I am interested in how to use a "binding" object. You're absolutely right about using basic data types. It sounds like minimal work now that could save untold hours of work later if I were to change the storage medium. (Say to Access or a txt file (interesting)).

I am very much interested in doing this the right way, and I understand the original question about userforms may be a few steps away. I will post back after working with your example. (Though I realize I may need a binding object example first?) I will post back soon.

~ Dan
 
Upvote 0

Forum statistics

Threads
1,215,064
Messages
6,122,939
Members
449,094
Latest member
teemeren

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top