How and where to use Private or Public sub, function, variables

113303
7
01-27-2011 06:06 AM
VirginiaReid
New Contributor
In one of the courses I'm taking, it talks about Private and Public subs, functions and variables. I understand the definition of Private of Public, but it does not clearly specify to me when and where to use them. 

Can Private and Public (variable, sub, and/or function) be used in the same Module? 

Does it matter what kind of Module it is? (Form, Standard, ThisDocument, Class Module)

Or where the variable is declared.  Can you have a Variable declared as Public in General Declaration, but then use it in a Private Sub or Function - and viceversa?

Also, examples have procedures that start with Sub or Functions, but no Private or Public.  Are they automatically Private?

I'm also confused as to when you use a Sub instead of a Function.  The examples do not make it clear to me at all.
0 Kudos
7 Replies
RuchiraWelikala
New Contributor III
Hey Virginia,
Try out this link...
http://www.your-save-time-and-improve-quality-technologies-online-resource.com/vba-private-sub.html

I'm assuming you use VBA (since you mentioned ThisDocument).
I use VB.NET but the concepts are pretty similar with regards to ArcObjects.
In any given program you might have a number of Procedures (Sub) or Functions.  If you have your code in a modular fashion (broken up into components), then you have to decide whether to make it Public or Private.  If you plan to use a repetitive bit of code to return a value (say A + B = C, where you send the function values of A and B and it returns C) throughout many modules in the same program, you would make this a PUBLIC Function.  If you only plan to use it in the same module, then you are better of making it Private.
This applies for variables as well.  If you declare a GLOBAL variable as Public or Private, then you're just assigning the extent of that variable within your program.
Any procedure WITHOUT Public or Private is the same as PUBLIC.

And here's a link to illustrate the answer to your final question:
http://www.getdotnetcode.com/gdncstore/free/Articles/Sub%20Statement%20vs%20Function%20Statement.htm
Hope that helps,
Cheers
0 Kudos
VirginiaReid
New Contributor
I think my major problem is that I'm having to change from MS Access VBA to ArcMap VBA.  All the code I did in Access was linked to an Event.  A lot of If..then..Else, msgbox, controlling where the user could go, making them fill in info before continuing, opening/printing reports,  etc.  You had the option of using 'Macros' but they were too simple and never did what I wanted, so I went to code.  I was also able to reference a value on FormB (Form Name . Variable Name) and if it said "no", the Report Button on FormA would be inactivated.


Now I'm lost.  Everything that I did in Access, was that a 'Sub'? 


This is next thing is really stupid, but ... is a 'Sub' essentially 'Red Rove, Red Rover, I Call .... Over" and a 'Function' essentially my programmable calculator I used for Physics because I was tired of typing in the same sets of steps to calculate a value.
0 Kudos
RuchiraWelikala
New Contributor III
Well, VBA is the same across pretty much all platforms.  The interfaces used in each program differ but the language and the structure is the same. For instance, ThisDocument in Access references the current document being worked on and ThisDocument in ArcMap references to the current Map document being worked on.
Think of Subs (also called Procedures) and Functions as blocks of code that do specific tasks.  You only need to launch these things when they are necessary.  You do this by calling them sub.
Say you have a listbox in Access that needs to be populated with a bunch of records from a certain column in a table. However, you only do this when the user presses a button on the form.  So you would put that code in a Sub

Private Sub PopulateListbox
  Put the code to populate the list box here. 
End Sub
you would call the above listbox from the ClickEvent of the button on the form that the user pressed.

A function is pretty much like a programmable calculator (though, it can be used for other things as well besides calculations).
But it has to return something.

Private Function Pythagorean(ByVal intA As Integer, ByVal intB As Integer) As Double

  Dim answer As Double
  answer = (intA ^ 2) + (intB ^ 2)
  Pythagorean = answer
End Function


So if you want to populate a variable from within a Sub by using a function, you can.

Private Sub PythTheory
  Dim A as Integer
  Dim B as Integer
  Dim C as Integer
 
  Set A = 2
  Set B = 3
  ' This is where you call the function to calculate C (from above)
  Set C = Pythagorean(A, B)
  ' so you pass the function 2 and 3 and it will return the sum of the squares.

End Sub


It's very important you grasp these basic rules of programming before you attempt ArcObjects as it is far more complex. 
This is an excellent book I used to help me when I was learning ArcObjects.  There might be a PDF of the book on the web.. or you can use Google Books.
http://www.amazon.ca/Programming-ArcObjects-VBA-Task-Oriented-Approach/dp/0849392837
Cheers,
0 Kudos
VirginiaReid
New Contributor
Ok, It think I got it.

Unless I need to use my 'programmable calculator' then use a Sub.

But if I need to use a Sub with a lot of code when ever something happens (On Click change all these properties) then I can call on the Sub to do it instead of typing all that code again.

Back on Public and Private: Found the example given to me that really got me confused. This is ArcMap.

[INDENT]
----------------------------------------------------------------------------
' General Declaration Section
Private m_strUser As String
----------------------------------------------------------------------------
Public Sub Login()
[INDENT]m_strUser = InputBox("What's your name?")[/INDENT]
End Sub
----------------------------------------------------------------------------
Public Sub GoodByeUser()
[INDENT]MsgBox "GoodBye " & m_strUser & ", see you next time."[/INDENT]
End Sub[/INDENT]
0 Kudos
RuchiraWelikala
New Contributor III
That code you've posted is universal to VB... It doesn't have to be ArcGIS.  But basically, the Variable declared at the top (Private) is only exposed to that module.  Other modules cannot see nor use that Variable.  However, it is a global variable within the module. 
The Public Subs in that code is exposed to the entire program and all of it's modules.  Those subs can be used in any form/module/class.
"Private strName As String" is the same as writing "Dim strName as String"

You cannot however write the former inside a code block (a Sub or a Function)... you have to use Dim.

Cheers,
0 Kudos
VirginiaReid
New Contributor
Ok, I think I get the Private and Public thing.

Still some questions on Sub and Functions.  Understand the functions.  There is some confusion on the Sub because I've searched and read forums on the subject.  Summary of what I found:  There are people using subs when it should be a function.  Some say it's ok to do that, but others don't.  If a sub doesn't return a value like a function, then how can they be using a sub instead to do what a function does?

God, I must sound like an idiot.  They said that the VBA for Access and ArcMap is the same.  It's not and I have to reprogram my brain to do things differently.

Below is a list with my guesses. Can you tell me if I'm correct?

Before I start the list - is this correct:  If it is a Sub or Function that will be called on many times either in a single module or multiple modules, it should be stored in a public module.  (or stored in ThisDocument at Project level?)  How do you know when to use a module or ThisDocument (which is a module)?

1) Conditional text that will be called on to change a property(s) or variable number:  Sub?

2) Complex math calculation the using VBA Functions and will be called on by an Event: Function?

3) Code used to sort data for a report in an unusual way (selected from option button): Sub?

4) If..Then Else and Case.  Sub?

(Something I did in Access) For a report, If I need to get a variable value (1stValue) of a field on frmOne and use it to, conditionally, calculate a variable value (2ndValue) on frmTwo - and update update every time 1stValue changes.  1) 1stValue would be declared public in General Declarations  2) 1stValue would be referenced frmOne.1stvalue.  3) The whole this, 2 procedures?  Both sub or function or mix of sub and function.  (Or is my brain to stuck on how Access works and not GIS?  (In Access this was used on a Form and subform situation where data stored in table and attached to a Print Report CmdButton)

What if you have a set of procedures that all run on an Event?  Would you put it in a Public Module and call on the Module instead of the (subs & functions)  Ex. a specialized Buffering method that a company want's all employees to use and you would put it on the Toolbar (IUEditBoxControl).  Would be saved in ThisDocument under Normal (Global)

I've just been asked today if I could do this:
On an ArcMap template, use an inputbox to get the Title (a Project name) and then put it in the Title text box followed by also putting the Title into the disclaimer text box, i.e., strDisclaimer = "1st part of disclaimer text " & strTitle & "rest of disclaimer text." (One procedure? Sub or Function? And then make the Title Editable (and update in the disclaimer).  The edit wouldn't be a new procedure - just run the 1st one again. I'm assuming that this would be on the click event of the Title text box (that's how it was done in Access). Then attach a msgBox to the disclaimer box that says, "The disclaimer text can only be changed by the Administrator" and have the OK button.  Is there a module for the templates display?  Haven't even finished the course an I'm already being asked to program.

Thanks for your patience.
0 Kudos
RuchiraWelikala
New Contributor III
Wow, that's a long list of questions. Alright... let me try to address some of them.
>> If a sub doesn't return a value like a function, then how can they be using a sub instead to do what a function does?

-- Well, they're are both used to structure code and if necessary repeat blocks of code.  A sub doesn't have to RETURN a value explicitly to the original SUB it was called from to change or assign a value.  (Google search ByVal vs ByRef).
Ex. Say you have a form with a textbox that is used to display some result from a calculation (a number).
So you have a click event (a command button in the form).  A click event is a sub (which stands for subroutine) itself. 
Private Sub cmdBtnCalc_Click()
    Call CalculateValue
End Sub

Private Sub CalculateValue
    Dim Num1 as Integer
    Set Num1 = 2
    Dim Num2 as Integer
    Set Num2 = 6

    Set frmTest.TBCalcValue.Text = Num1 * Num2

End Sub


So in the above code, the textbox would be changed to display 12.  I just performed a calculation using a SUB.  The same code could be modified to change the textbox using a function:

Private Sub cmdBtnCalc_Click()
    Dim Num1 as Integer
    Set Num1 = 2
    Dim Num2 as Integer
    Set Num2 = 6

    frmTest.TBCalcValue.Text = CalculateValue (Num1, Num2)
End Sub

Private Function CalculateValue (ByVal Num1 as Integer, ByVal Num2 as Integer) as Integer

    CalculateValue = Num1 * Num2

End Function


The two examples of code I've used essentially do the same thing but in different ways using different methods.  It's up to you as a programmer to determine what the best and most efficient course of action is for your programming needs.

>>  If it is a Sub or Function that will be called on many times either in a single module or multiple modules, it should be stored in a public module. (or stored in ThisDocument at Project level?) How do you know when to use a module or ThisDocument (which is a module)?

-- Generally, if you think you might have to use procedures (subs) and functions anywhere in the program either in modules, forms, or ThisDocument, or all of em multiple times, it's a good idea to go Public.  Just to be safe.  But if it is staying within a module, then make it Private.  As in, if you have a block of code which is only used in a certain form, then have that code in the FORM code and make it private.  However, if you need that same code for MULTIPLE FORMS, then put that code in a MODULE, and make it PUBLIC so it can be accessed by ALL THE FORMS in your program.  If you put something in the PROJECT Level and save that document, the code is only applied to that specific document.  If you have it under NORMAL then it is universal to any document you open within that program.  So if you want ArcMap TO Open to your company's specific map template each time you open a new instance of a ArcMap, then you would put this code in NORMAL.  If you have a certain project you're working on that requires VBA coding to change/update the date textbox in your map to the current date and time then you would put such code in the PROJECT level and save it. 
Anyway the other questions:
1.  Sub or function will do for this.  Again, depends on your needs.
2.  Function generally (nothing is really set in stone..but it'd be good practise).
3.  Sub
4.  Conditional statements are separate from Subs and Functions.  They are another form of code blocks that go WITHIN Subs or Functions.  They simply allow you manipulate or do whatever you want to the data based on a condition.  It isn't exclusive to neither Sub or Function.... Say you're passing 2 numbers to be calculated in a function.  When in that Function, you can check to see if a number is less than 10.  If it is, it will calculate using a different formula and return a value back to the procedure it was called from. (Functions can also be called from other Functions).

In GIS, I've never used reports so perhaps someone else can comment on that.  But the structure and passing variables from one form (which is a module) to another is basically the same.  If you have a click event, then you for sure have at least 1 SUB in your program. 

>>What if you have a set of procedures that all run on an Event? Would you put it in a Public Module and call on the Module instead of the (subs & functions) Ex. a specialized Buffering method that a company want's all employees to use and you would put it on the Toolbar (IUEditBoxControl). Would be saved in ThisDocument under Normal (Global)

-- A Module is just a holder or container for all of your code. So if you want to run a bunch of procedures sequentially, then you would call them from a click event one by one.
EX:
Private Sub cmdBtn_Click()
     Call Sub1
     Call Sub2
     Call Sub3
End Sub



For the template question refer to this link.  It has the ArcMap VBA code to add a textbox to the Layout view.  You have to specify the X Y location on the map document though.
http://edndoc.esri.com/arcobjects/9.0/Samples/ArcMap/AddTextElement.htm

Cheers,
0 Kudos