mbt masai
 
Welcome !
         

                                
After experiencing a lot of down time, We decided to move this site to CrystalTech.com. CrystalTech.com is powered by only the finest Windows servers providing the best performance, reliability, and value anywhere.

 Variable Scope and How To Pass Data

Author Message
ebgreen

  • Total Posts : 8088
  • Scores: 95
  • Reward points : 0
  • Joined: 7/12/2005
  • Status: offline
Variable Scope and How To Pass Data Tuesday, March 09, 2010 6:53 AM (permalink)
0
Scope
  In programming Scope essentially means where a variable exists. In VBScript, there are essentially two scopes. Global and Local. This can be complicated through the use of classes, but I'm not going to talk about that here. Global scope means that a variable exists everywhere in the script. Local scope means that the variable exists only in the block of code where it was defined. In VBScript, only Subs and Functions can restrict scope. Again classes complicate this definition a bit, but that is for another post. Code is worth a thousand words, so here are some examples.

Option Explicit
Dim strTest

strTest = "FOO"
WScript.Echo strTest

OUTPUT:

FOO

This is pretty straightforward. We defined the variable outside of any restricting code block, so it has global scope. Since we tried to access the variable at the same level as it was defined, this was sort of trivial. Look at this instead:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest

Sub RunTest()
    WScript.Echo strTest
End Sub

OUTPUT:

FOO

This time we are trying to access the variable inside a Sub. Inside the Sub is considered a different level of scope, but since the variable has Global scope, there is no problem accessing it.

  Now let's look at an example of scoping a variable locally:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest
WScript.Echo strTest2

Sub RunTest()
    Dim strTest2

    strTest2 = "BAR"
    WScript.Echo strTest
End Sub

OUTPUT:

FOO
Microsoft VBScript runtime error: Variable is undefined: 'strTest2'

Since strTest is still defined Globally, there is no problem accessing it inside or outside the Sub. Since we defined strTest2 inside the Sub though, it is scoped Locally. This means that it can only be accessed inside the Sub. So when we try to access it outside the Sub, we get an error. This scoping is true for Functions also.

  A great many people avoid this issue by simply defining all their variables Globally. This does avoid any scoping issues, but personally I find it to be a short sighted solution. Defining variables Globally severely inhibits your ability to reuse your code. Let's say that you create the worlds best function ever. It solves every problem known to man. Since it is so useful, you obviously would want to use it over and over again. If you had created this function using Globally defined variables, that would mean that every time that you wanted to reuse the function, you would have to copy and paste it into your new script, then you would have to be sure to define every single one of the variables use in the function again Globally in the new script. You would have to go through this every time that you wanted to use your uber-spiffy function. Contrast that with properly defining the variables that the function uses Locally inside the function. If you did that, then every time that you wanted to reuse your function, you would copy and paste it into your new script then simply use it. That's all. Much simpler and much better in my opinion.

Data Trasnport - IN
  Using Local scope for Sub and Function variables does create one bit of extra effort on our part. When we use Global variables in a Sub/Function, we don't need to worry about getting data into the Sub/Function, since the variables we are using already have the data in them. When we use Local variables however, we need to pass all the data we need into the Sub/Function and for functions we need to pass data back out.

  Let's talk about passing the data in first since that is the same for both the Sub and the Function. Let's take our Global variable example and quickly tweak it to be local:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest strTest

Sub RunTest(strTest)
    WScript.Echo strTest
End Sub

OUTPUT:

FOO

  Now you might say, "But EB, you are still using the globally defined strTest". You would be right...sort of. Let's take a short deter here.

ByVal vs. ByRef
  There are actually two different ways to pass data into a Sub/Function. The default is ByRef. This stands for "By Reference" meaning that you are actually passing a reference pointer into the Sub/Function that points to the original variable outside the Sub/Function. When you do this, any changes that you make inside the Sub/Function will be seen outside the Sub/Function. Here is a demonstration:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest strTest
WScript.Echo "After running the Sub but in Global scope: " & strTest

Sub RunTest(strTest)
    WScript.Echo strTest
    strTest = "BAR"
    WScript.Echo "After change in SUB: " & strTest
End Sub

OUTPUT:

FOO
After change in SUB: BAR
After running the Sub but in Global scope: BAR

Notice that even outside the Sub the value of strTest has been changed. Let's do that again, but change the variable name inside the Sub, just to show that there isn't some weird Global scope hanky panky going on:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest strTest
WScript.Echo "After running the Sub but in Global scope: " & strTest

Sub RunTest(strIn)
    WScript.Echo strIn
    strIn = "BAR"
    WScript.Echo "After change in SUB: " & strIn
End Sub

OUTPUT:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest strTest
WScript.Echo "After running the Sub but in Global scope: " & strTest

Sub RunTest(strIn)
    WScript.Echo strIn
    strIn = "BAR"
    WScript.Echo "After change in SUB: " & strIn
End Sub

So as we can see, when you pass a variable into a Sub/Function, by default whatever you do to it will remain outside the Sub/Function. This is the "What happens in Vegas does not stay in Vegas" scenario.

The other way that data can be passed into a Sub/Function is ByVal. Here is the same code that we just ran, but we will specify that the dat be passed ByVal ("By Value") instead of ByRef:

Option Explicit

Dim strTest

strTest = "FOO"
RunTest strTest
WScript.Echo "After running the Sub but in Global scope: " & strTest

Sub RunTest(ByVal strIn)
    WScript.Echo strIn
    strIn = "BAR"
    WScript.Echo "After change in SUB: " & strIn
End Sub

OUTPUT:

FOO
After change in SUB: BAR
After running the Sub but in Global scope: FOO

As you can see, this time our changes inside the Sub had no effect on the global variable outside the Sub. I have to be honest with you that this is how I personally wish the default was set up instead of the default method being ByRef. The more loosely coupled your code is, the more easily it is reused.

More Data Transport - IN
  Now that we understand the differences between ByVal and ByRef, let's talk about some things that you can pass into Subs/Functions. We have already seen that you can pass in simple strings. As a matter of fact, anything that you can assign to a variable you can pass into a Sub/Function.

Data Transport - Out
 
So we have seen that getting data into a Sub/Function is relatively easy. Just pass the data in when you call the Sub/Function. Getting data out of a function can be a little tougher. When you return data from a function, you are limited to returning one thing. This sounds like a tough limitation. Let's look at the simple case first. We really do want to return just one thing:

Option Explicit

WScript.Echo qq("Quote me baby!")

Function qq(strIn)
    qq = Chr(34) & strIn & Chr(34)
End Function

OUTPUT:

"Quote me baby!"

Anyone that read the Quote Like Pro tutorial will be familiar with that function. It does demonstrate though that the way you return data from a function is to set the function name equal to the data that you want to return. It can get a little tricky when the data that you are returning is an object instead of a simple data type. Let's say that you were a good coder and any time that you used the same code multiple places, you refactored the code into a function. And let's further say that for some odd reason you were writing a script that needed to instantiate several different dictionaries. You decided to make a function that would return an empty dictionary just to make your life easier:

Option Explicit

Dim dicOne
Dim dicTwo
Dim dicThree

Set dicOne = GetADictionary()
Set dicTwo = GetADictionary()
Set dicThree = GetADictionary()

Function GetADictionary()
    Dim dicTemp

    Set dicTemp = CreateObject("Scripting.Dictionary")
    Set GetADictionary = dicTemp
End Function

This code doesn't actually output anything. There is one thing to remember when the item that you are returning is an object. It is the most common error that people commit when they start returning objects from functions. Any time that you assign an object, you must use the Set keyword. Notice that inside the function, I use the Set keyword when I assign the temporary dictionary to the function name. Since the function is returning an object and whatever it returns is being assigned to a variable, I also must use the Set keyword when I call the function.

Let's get back to the limitation that a function can only return one thing. The last code sample shows us how we get around this limitation. We just make sure that the one thing we return is a container that holds all the things that we really wanted to return. Here are containers that I will frequently return from functions:

Arrays
ArrayLists
Dictionaries
Folder Collections
File Collections
ADO Recordsets

Basically you can return any data structure that is contained completely in a single object.

As always, let me know if I have missed something or further clarification is required.

"... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
http://www.visualbasicscript.com/m_47117/tm.htm
#1
    Fredledingue

    • Total Posts : 572
    • Scores: 0
    • Reward points : 0
    • Joined: 5/9/2005
    • Location: Europe
    • Status: offline
    Re:Variable Scope and How To Pass Data Sunday, May 09, 2010 2:40 AM (permalink)
    0
    I don't see the difference between this
    Function GetADictionary() 
             Dim dicTemp          Set dicTemp = CreateObject("Scripting.Dictionary") 
             Set GetADictionary = dicTemp 
         End Function 

    and this:
    Function GetADictionary() 
             Set GetADictionary = CreateObject("Scripting.Dictionary")
         End Function 

    Fred
    #2
      ebgreen

      • Total Posts : 8088
      • Scores: 95
      • Reward points : 0
      • Joined: 7/12/2005
      • Status: offline
      Re:Variable Scope and How To Pass Data Monday, May 10, 2010 2:07 AM (permalink)
      0
      There isn't any.
      "... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
      Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
      http://www.visualbasicscript.com/m_47117/tm.htm
      #3
        ginolard

        • Total Posts : 1347
        • Scores: 23
        • Reward points : 0
        • Joined: 8/11/2005
        • Status: offline
        Re:Variable Scope and How To Pass Data Monday, August 16, 2010 7:36 PM (permalink)
        0
        Of course, you could always define everything you ever needed in a single script and then use ExecuteGlobal to run that in every script you write.

        *runs*


        Author of ManagePC - http://managepc.net

        #4
          ebgreen

          • Total Posts : 8088
          • Scores: 95
          • Reward points : 0
          • Joined: 7/12/2005
          • Status: offline
          Re:Variable Scope and How To Pass Data Tuesday, August 17, 2010 2:35 AM (permalink)
          0
          Sure you could, but then your brain might fall out.
          "... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
          Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
          http://www.visualbasicscript.com/m_47117/tm.htm
          #5
            ginolard

            • Total Posts : 1347
            • Scores: 23
            • Reward points : 0
            • Joined: 8/11/2005
            • Status: offline
            Re:Variable Scope and How To Pass Data Tuesday, August 17, 2010 2:40 AM (permalink)
            0
            Presumably because you will have been repeatedly hitting me over the head with an iron bar screaming "HERETIC!"
            Author of ManagePC - http://managepc.net

            #6
              ebgreen

              • Total Posts : 8088
              • Scores: 95
              • Reward points : 0
              • Joined: 7/12/2005
              • Status: offline
              Re:Variable Scope and How To Pass Data Tuesday, August 17, 2010 2:45 AM (permalink)
              0
              While you are at it, make sure that you have several versions of the file that you read in and that each of them is 90% the same as the others with very subtle differences.
              "... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
              Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
              http://www.visualbasicscript.com/m_47117/tm.htm
              #7
                ginolard

                • Total Posts : 1347
                • Scores: 23
                • Reward points : 0
                • Joined: 8/11/2005
                • Status: offline
                Re:Variable Scope and How To Pass Data Wednesday, August 25, 2010 12:11 AM (permalink)
                0
                One should not totally discount Global scope.

                For example, consider a login script that uses an IE window to display the on-going state of the script.  You'll probably have a single sub that writes messages to the IE window but you don't want to create the IE object each time otherwise you'll have multiple IE windows opening.  In that case, you NEED to have declared the IE object with Global Scope and then reference in your logging sub.
                Author of ManagePC - http://managepc.net

                #8
                  ebgreen

                  • Total Posts : 8088
                  • Scores: 95
                  • Reward points : 0
                  • Joined: 7/12/2005
                  • Status: offline
                  Re:Variable Scope and How To Pass Data Wednesday, August 25, 2010 2:39 AM (permalink)
                  0
                  Nope. I do exactly that (having one IE window to display messages for logging) and I do it without global scope. I just pass the one IE object to each function that needs it.
                  "... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
                  Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
                  http://www.visualbasicscript.com/m_47117/tm.htm
                  #9
                    ginolard

                    • Total Posts : 1347
                    • Scores: 23
                    • Reward points : 0
                    • Joined: 8/11/2005
                    • Status: offline
                    Re:Variable Scope and How To Pass Data Wednesday, August 25, 2010 3:37 AM (permalink)
                    0
                    Care to elaborate a little?  Whilst I am fully familiar with the OO concept of passing objects around like candy at a birthday party I am struggling to see how you can create an IE object in local scope and then pass it to whatever needs it.

                    I have a single function that updates the IE window, as so

                     
                     
                     Sub DoSomething 
                         Writelog "Hello World" 
                     End Sub 
                     
                     Sub WriteLog(strMessage)     
                     '************************************************* 
                     ' Writes the contents of strMessage to the logfile 
                     '************************************************* 
                         StrStatus = strmessage + VBCRLF + StrStatus  
                         ie.document.all.wstatus.InnerText = strstatus 
                     
                     End Sub 
                     


                    Now, obviously the IE object is in Global scope.  What you are proposing is that the DoSomething sub should pass the IE object to the Writelog function.  Whilst I fully appreciate the OO methodology behind that concept,, where do you propose defining the IE object in the first place?
                    Author of ManagePC - http://managepc.net

                    #10
                      ebgreen

                      • Total Posts : 8088
                      • Scores: 95
                      • Reward points : 0
                      • Joined: 7/12/2005
                      • Status: offline
                      Re:Variable Scope and How To Pass Data Wednesday, September 01, 2010 4:08 AM (permalink)
                      0
                      Well, it's a little confusing because in a way you do create it globally.

                      You just don't reference it globally. You always pass it.
                      "... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick
                      Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm
                      http://www.visualbasicscript.com/m_47117/tm.htm
                      #11

                        Online Bookmarks Sharing: Share/Bookmark

                        Jump to:

                        Current active users

                        There are 0 members and 1 guests.

                        Icon Legend and Permission

                        • New Messages
                        • No New Messages
                        • Hot Topic w/ New Messages
                        • Hot Topic w/o New Messages
                        • Locked w/ New Messages
                        • Locked w/o New Messages
                        • Read Message
                        • Post New Thread
                        • Reply to message
                        • Post New Poll
                        • Submit Vote
                        • Post reward post
                        • Delete my own posts
                        • Delete my own threads
                        • Rate post

                        2000-2012 ASPPlayground.NET Forum Version 3.8
                        mbt shoes www.wileywilson.com