0

I have this simplified class module clXXX....

':: backing field
Private fTemplateBk As Excel.Workbook

':::::::::::::::::::::::::::
'::
':: constructor
Private Sub Class_Initialize()

End Sub

':::::::::::::::::::::::::::
'::
':: properties
Property Get TemplateBk() 'As Excel.Workbook '<< different error messages depending on if "As Excel.Workbook" is included or not
    TemplateBk = fTemplateBk
End Property

':::::::::::::::::::::::::::
'::
':: methods
Public Sub openTemplate()
    Set fTemplateBk = Excel.Workbooks.Open("\\xxx\yyy\zzz.xlsx")
End Sub

Public Sub someMethod()
    Me.TemplateBk.Sheets(1).Activate
End Sub

Normal module:

Sub control()

Dim x As clXXX
Set x = New clXXX
x.openTemplate
x.someMethod  '<<<<<<errors here

End Sub

I want to only access the private field fTemplateBk via the read-only property TemplateBk using code such as me.TemplateBk. .... How do I amend the above so this is possible?

whytheq
  • 34,466
  • 65
  • 172
  • 267
  • Missing `Set` in your property Get.... – Tim Williams Oct 31 '14 at 15:05
  • Also, why use the property within the class? You already have access to the member field. – citizenkong Oct 31 '14 at 15:05
  • 1
    @citizenkong - it's a good practice to use the property vs the backing field. Eg see http://stackoverflow.com/questions/271318/should-you-access-a-variable-within-the-same-class-via-a-property – Tim Williams Oct 31 '14 at 16:01
  • @citizenkong I believe within a class's constructor it is fair play to access a private backing field directly but anywhere else good practice is to use setters and getters. – whytheq Oct 31 '14 at 16:30

2 Answers2

1

Your someMethod should use the private field fTemplateBk as it is private from outside, not from inside.

Public Sub someMethod()
    Me.fTemplateBk.Sheets(1).Activate
End Sub

If you need to use the property from outside, in your normal module you should use:

Sub control()
    Dim x As clXXX
    Set x = New clXXX
    x.openTemplate
    x.TemplateBk.Sheets(1).Activate
End Sub

UPDATE 1

If you want to keep your code as it is, just add the SET in your TemplateBk getter and the code will work. As you can see in the picture, I used your same code with this change and it works.

Property Get TemplateBk() 'As Excel.Workbook
    Set TemplateBk = fTemplateBk  'add the SET at the beggining
End Property

enter image description here

Miguel Febres
  • 2,153
  • 2
  • 21
  • 31
  • As stated in the question - I want to access `fTemplateBk` via the property `TemplateBk` _even when inside_ - this is good practice. I believe the general `OO` rule of thumb is to only access private backing fields when constructing. – whytheq Oct 31 '14 at 16:33
  • As the others said, you are missing the Set TemplateBk = fTemplateBk, after that It will work. I have tested and there is no error. – Miguel Febres Oct 31 '14 at 17:02
  • Thanks Miguel. Your code will not error but you should use `Me.TemplateBk.Sheets(1).Activate` within `someMethod` in order that the class follows best practices. – whytheq Oct 31 '14 at 17:07
1

You need to make that property public and must use Set keyword.

Check the below code and confirm if it works:

Private fTemplateBk As Excel.Workbook

Public Property Get TemplateBk() As Excel.Workbook 
    Set TemplateBk = fTemplateBk
End Property
Paresh J
  • 2,401
  • 3
  • 24
  • 31
  • how do I add a Let/Set procedure to run with this Getter? – whytheq Oct 31 '14 at 16:41
  • 1
    Check this URL: http://stackoverflow.com/questions/5092662/set-property-of-vba-class-with-object-reference – Paresh J Nov 01 '14 at 06:02
  • Thanks for link. I did some research via this book last night and now feel a bit more confident: http://www.amazon.com/Rob-Bovey-Professional-Excel-Development/dp/B00JHX5GVE – whytheq Nov 01 '14 at 08:10