How can I assign subroutine value to variable in access VBA - ms-access

I have below procedure in Module1:
public sub Evaluate(Salary as double)
Dim Overtimesalary as Double
Overtimesalary = salary * 1.5
End Sub
Now, I am calling this procedure for my form click button event to calculate overtime salary and taking input value from textbox value from form, Code for that,
When I am trying to execute below code, I am getting "Compile error: Expected function or variable":
Private sub cmd_Calculate()
Dim Test as Double
test = Evaluate(txt.salary.value)
MsgBox Test
End Sub

Convert your subroutine into a Function, and return your value as the function's value.
public Function Evaluate(Salary as double)
Evaluate = salary * 1.5
End Sub
This will run the procedure, perform the calculation, then return the value assigned within the function to the calling subroutine.
That said, I'm assuming that this is a simplified version of what you're actually doing - if all you're doing is literally multiplying a value by 1.5, you can just do that in the main subroutine!

Related

Byref vs Byval vba clarification

I was writing some VBA to futher my understanding of Byref and Byval. This is what I am using:
Private Function Checkcase()
Dim i As Integer
i = 1
Debug.Print i
num(i)
Debug.Print i
End Function
Public Function num(ByRef i As Integer)
i = 5
End Function
Output
1
1
However, when I use the call keyword in front of num(i) like:
call num(i)
The output changes to
1
5
I was expecting the output to be 1 and 5 in both cases as I am changing the reference of the variable i
num(i) is the error here. When you call a sub or a function without getting the return value, you must not put parentheses around the arguments.
When you pass arguments with parentheses to a function expecting ByRef arguments, those are automatically cast to ByVal.
Either use Call num(i) or remove the parentheses num i
References: Call :
If you omit the Call keyword, you also must omit the parentheses around argumentlist.
As always, Cpearson site is a must read

Using a custom function that returns items Selected from a list box

Windows 7, ACCESS 10
Based on a previous answer from HansUp, I created the following function that returns the values selected in a listbox:
Public Function listboxSel(ByVal listName As String) As Integer
MsgBox Nz(Me.Controls(listName).Value, "Null")
End Function
I call the function from the LostFocus event of the Listbox:
Dim cageHrsHold As Integer
cageHrsHold = listboxSel(cageHrs)
I left the MsgBox in the function just to see if it executed. That line, the MsgBox line in the function, bombs with "Anbiguous name detected:listboxSel".
jpl

Passing parameters in VBA events

I am relatively new to Access though I do have some experience in VB, my question is probably very simple though I don't seem to know the terminology to search in order to find an answer I can use.
I am in the process of creating an "OnChange" event for a tab control I am using, I would like to pass an undetermined amount of integers to the function. IE:
=myFunction(1,4,6) OR =myFunction(ArrayList[1,2,4])
I would either create an overloaded function to work with these numbers, or if possible I would like to pass them as an array of integers. Though for the life of me I cannot figure out exactly how to do this. The reason I have taken this path is to make my function as universal as possible, basically just having to change what numbers I send to the function to change its behaviour.
This is some rough coding of what I am try to do, though I have no idea how to pass anything besides something like =myFunction([Form])
Public Function Refresh(tabsToCheck As ArrayList)
For Each o In tabsToCheck
If Me.DevForm.Value = o Then
RefreshAllForms
End If
Next o
End Function
Public Function RefreshAllForms()
Dim f As Form
For Each f In Access.Forms
f.Refresh
Next
End Function
Update
I thought I would update with my finalized code in case anyone needs this in the future thanks for your help!
Public Function RefreshControlTab(ctrl As Access.Control, ParamArray TabsToRefresh())
Dim i As Long
Dim lngUBound As Long
If UBound(TabsToRefresh) >= 0 Then
lngUBound = UBound(TabsToRefresh)
For i = 0 To lngUBound
If ctrl.Value = (TabsToRefresh(i) - 1) Then
RefreshAllForms
End If
Next
End If
End Function
Public Function RefreshAllForms()
Dim f As Form
For Each f In Access.Forms
f.Refresh
Next
End Function
So one change you would say '=RefreshControlTab([DevForm],3,4)' and when the 3rd or 4th tab is selected a refresh will be performed.
"I would like to pass some an undetermined amount of integers to the function."
That sounds like a ParamArray to me. See the simple function below. It will return the sum of a set of numbers.
Public Function AddThem(ParamArray MyNumbers()) As Long
Dim i As Long
Dim lngReturn As Long
Dim lngUBound As Long
If UBound(MyNumbers) >= 0 Then
lngUBound = UBound(MyNumbers)
For i = 0 To lngUBound
lngReturn = lngReturn + MyNumbers(i)
Next
End If
AddThem = lngReturn
End Function
Note the ParamArray is an array of Variant values. So within the function you would need to verify the values are numbers to avoid trouble ... one example of trouble would be a "type mismatch" error when calling the function with string values: AddThem("a", "b")

Returning Multiple Values from a Custom Function

So, I've got a ValidateForm function that loops through a form to validate each control. I have a collection set up called ValData to capture different bits of info to be passed out of the function. This is working great.
However, I don't know how to access each item in ValData after the function returns. I can get one at a time like: ValidateForm().IsValid, but in order to get each item, I have to run the function again. I want to avoid this.
Is there a way to run the function once, but access the values of each item returned?
Depending upon your requirements (which are NOT clear in your question! ;-) ), you might consider using a Collection as the return from your function:
Private Function MyResultsFunction() As Collection
Dim output As Collection
Set output = New Collection
'Hydrate your collection with data by whatever means necessary:
With output
'Stupid example code:
.Add "Item1"
.Add "Item2"
.Add "Item3"
.Add "Item4"
End With
'Return a reference to the collection as the function output:
Set MyResultsFunction = output
End Function
As a simple, retarded test of the above:
Private Sub Form_Load()
'A variable to receive the results from your function:
Dim Results As Collection
'An iterator to loop through the results contained in the collection:
Dim CurrentItem As Variant
'For this example, a string to toss the results into to display in the
'MsgBox:
Dim output As String
'Use the local Collection defined above to access the reference returned by
'your function:
Set Results = MyResultsFunction
'Iterate through the collection and do something with the results
'per your project requirements:
For Each CurrentItem In Results
'This is stupid example code:
output = output & CurrentItem & vbCrLf
Next
'I am just displayng the results to show that it worked:
MsgBox output
'Clean up:
Set Results = Nothing
End Sub
Hope that heps!
Without seeing your code it's hard to say what exactly you are tyring to do, but here is one of several ways you can store results to query later.
Declare a public variable at the top of your module to represent the items from your ValData function. After you populate the array, you can access the items through a normal function.
You obviously could do more sophisticated things, especially if you use a collection object. You could even store a counter and create a GetNext() function. I hope this gives you a heads start.
Public Results(1 To 2) As String
Sub CreateTestArray()
Results(1) = "Foo"
Results(2) = "Bar"
End Sub
Function GetResult(ByVal i As Long) As String
If i <= UBound(Results) Then
GetResult = Results(i)
End If
End Function
Sub ProofOfConcept()
MsgBox GetResult(2) ' will show "Bar"
End Sub

Linq to SQL - Problem in Stored Procedure

I have storeProcesdure name called as prc_GetID, it's return value (ClientID)
Here thr proc Code:
Create PROCEDURE [dbo].[prc_GetID] (#ID VARCHAR(20))
AS
SET NOCOUNT ON;
SELECT ClientID FROM dbo.Clients WHERE [ID]=#ID
I use above STORED PROCEDURE with linq to sql, here's Code,
Public Class Form2
Dim dcClients As New dcDataContext(CNString)
Private Sub btnClick_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles btnClick.Click
Dim CID = dcClients.prc_P(txtID.Text)
txtClientID.Text = CID.ReturnValue
End Sub
End Class
Here's My dcDataContext Code
<FunctionAttribute(Name:="prc_GetID")> _
Public Function prc_GetID(<Parameter(Name:="ID", DbType:="VarChar(20)")> _
ByVal ID As String) As ISingleResult(Of prc_GetIDResult)
Dim result As IExecuteResult = Me.ExecuteMethodCall(Me, _
CType(MethodInfo.GetCurrentMethod,MethodInfo), ID)
Return CType(result.ReturnValue,ISingleResult(Of prc_GetIDResult))
End Function
but it's return value 0 Why?,
Are you confusing the return value with the result set?
You probably should be examining CID.ClientID, not CID.ReturnValue. ReturnValue is the response code of the stored procedure, not the returned data you're looking to find. If you don't have a ClientID property you may need to remap your stored procedure to get the proper return type visible to your app.
Correction applied to account for multiple results (wasn't thinking):
Your stored procedure will return multiple records. Do you want the first record returned? If so and you will always have at least one row returned, try this:
txtClientID.Text = CID.First().ClientID.ToString()
In reality you need to think about your multiple records or no records returned and deal with it appropriately. Also, please don't continue to do your data access from within a form; it's good practice to create a library/business layer project to keep business logic out of your UI.