1

I have not used VB much but as far as I can tell scope works the same as in C#. The problem is, I'm using VB in MS Access so I am unsure if the rules are a bit different (though I assume they are not). The following code shows values being assigned to variables which have only been declared within the function parameters. Specifically looking at PurchaseOrderID, I am unsure as to how it is retaining its assigned value for use in the function proceeding it.

Function Create(SupplierID As Long, EmployeeID As Long, OrderID As Long, PurchaseOrderID As Long) As Boolean
    Dim rsw As New RecordsetWrapper
    If rsw.OpenRecordset("Purchase Orders") Then
        With rsw.Recordset
            .AddNew
            ![Supplier ID] = SupplierID
            If EmployeeID > 0 Then
                ![Created By] = EmployeeID
                ![Creation Date] = Now()
                ![Submitted By] = EmployeeID
                ![Submitted Date] = Now()
                ![Status ID] = Submitted_PurchaseOrder
            End If

            If OrderID > 0 Then
                ![Notes] = InsertString(PurchaseGeneratedBasedOnOrder, CStr(OrderID))
            End If
            If rsw.Update Then
                .Bookmark = .LastModified
                PurchaseOrderID = ![Purchase Order ID]
                Create = True
            End If
        End With
    End If
End Function


Function CreateLineItem(PurchaseOrderID As Long, ProductID As Long, UnitCost As Long, Quantity As Long) As Boolean
    Dim rsw As New RecordsetWrapper
    If rsw.OpenRecordset("Purchase Order Details") Then
        With rsw.Recordset
            .AddNew
            ![Purchase Order ID] = PurchaseOrderID
            ![Product ID] = ProductID
            ![Quantity] = Quantity
            ![Unit Cost] = UnitCost
            CreateLineItem = rsw.Update
        End With
    End If
End Function

Can someone give me some insight on this?

3 Answers 3

2

In VBA, how you call a procedure can be important.

"Even if a called procedure has declared its parameters as ByRef, you can force those to be ByVal by enclosing each argument within parentheses."

-- http://www.cpearson.com/excel/byrefbyval.aspx

This is true of VBA in all Office applications. For example, let us say you have two procedures:

Sub SubByVal(ByVal Total As Integer)
    Total = 50
End Sub

Sub SubByRef(ByRef Total As Integer)
    Total = 50
End Sub

And you run a few tests:

Dim Total As Integer
Total = 100

These three versions work as expected and Total is equal to 100

Call SubByVal(Total)
SubByVal (Total)
SubByVal Total

These two work as expected and Total is equal to 50

Call SubByRef(Total)
SubByRef Total

However, in this version, in spite of calling ByRef, Total is equal to 100, because it is forced to ByVal by the parentheses.

SubByRef (Total)
Sign up to request clarification or add additional context in comments.

Comments

2

Perhaps this is best handled by types. Something like this:

Type PurchaseSet
   PurchaseOrderID As Long
   OrderCreated as boolean
End Type


Function Create(SupplierID As Long, EmployeeID As Long, OrderID As Long ) As PurchaseSet
    Dim rsw As New RecordsetWrapper
    Dim ps as PurchaseSet 
   ps.OrderCreated = false

    If rsw.OpenRecordset("Purchase Orders") Then
        With rsw.Recordset
            .AddNew
            ![Supplier ID] = SupplierID
            If EmployeeID > 0 Then
                ![Created By] = EmployeeID
                ![Creation Date] = Now()
                ![Submitted By] = EmployeeID
                ![Submitted Date] = Now()
                ![Status ID] = Submitted_PurchaseOrder
            End If

            If OrderID > 0 Then
                ![Notes] = InsertString(PurchaseGeneratedBasedOnOrder, CStr(OrderID))
            End If
            If rsw.Update Then
                .Bookmark = .LastModified
                ps.PurchaseOrderID = ![Purchase Order ID]
                ps.OrderCreated = True

            End If
        End With
    End If

    Create = ps
End Function

Comments

1

You can pass arguments to a VBA procedure by value or by reference. If you don't specify either ByVal or ByRef in the procedure's declaration, it defaults to ByRef. So the following two declarations are equivalent ...

Function DoSomething(PurchaseOrderID As Long) AS Boolean
Function DoSomething(ByRef PurchaseOrderID As Long) AS Boolean

The key here is that ByRef allows changes to the argument within the procedure to be transmitted back to the caller.

7 Comments

I thought Long was immutable i.e only passed by value?
In VBA/VB6, procedure arguments of any type are passed by reference unless qualified as ByVal.
@Nate Check out the Access help topic for the ByRef keyword and Function Statement.
@David It would explain how this code seems to run without error. Do you know if this is this also true for newer versions of VB?
@HansUp Thanks, you're answer basically answers my query fully.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.