Visual Basic Member Already Exists in an object module - vba

I am brand new to visual basic today and I was writing my program but I get a compile error
Member already exists in an object module from which this object module derives
My function prototype is
Function calculate(count As Integer) As String
I was wondering why this is giving me this error

It would appear that you are designing a form, and have an object on that form (such as a text box or command button) which is also named calculate, disregarding case, since VBA is generally not case sensitive.

It is because your function has same name as the system's reserve function name, such as AfterInsert()

Related

VBA: Only user-defined types defined in public object modules can be coerced to or from a variant or passed to a late-bound functions

Compile Error:
Compile Error: Only user-defined types defined in public object
modules can be coerced to or from a variant or passed to a late-bound
functions.
I'm new to VBA and I was tasked with debugging some code for a custom screen in Dynamics SL. The first thing I did was to see if it compiled and I got the above message.
When I read the built-in help reference I found the following for the above error:
You attempted to use a public user defined type as a parameter or
return type for a public procedure of a class module, or as a field of
a public user defined type. Only public user defined types that are
defined in a public object module can be used in this manner.
I also went through these similar questions:
How to put user defined datatype into a Dictionary
Only user-defined type defined in public object modules can be coerced when trying to call an external VBA function
They have the same error but I don't see a collection object that the above two questions focused on.
If you may have any idea what may be causing this error please don't hesitate to suggest it.
Code:
Private Sub cpjt_entity_Chk(ChkStrg As String, retval As Integer)
Dim ldDate As Sdate
Dim xStrDailyPost As Sdate
ldDate.val = GetObjectValue("cpe_date")
'xStrDailyPost = DateToStr(ldDate)
'Call MsgBox("Daily Post Date: " & xStrDailyPost, vbOKOnly, "TEST")
serr1 = SetObjectValue("cld_id08", xStrDailyPost) <- Error highlights "xStrDailyPost"
End Sub
Definition for SetObjectValue:
Declare Function SetObjectValue Lib "swimapi.dll" Alias "VBA_SetObjectValue" (ByVal ctlname$, newval As Variant) As Integer
Thank you in advance!
You are probably working with code that was originally written with the Dynamics SL (actually it was Solomon IV at the time) Basic Script Language (BSL) macro language instead of VBA.
Regardless... the fix is, pass results of the "val" method of your xStrDailyPost instance of SDate. SO the code should look like:
serr1 = SetObjectValue("cld_id08", xStrDailyPost.val)
I've not actually tested this but I'm pretty sure this will address your issue.
If you want a little more background, "Sdate" is really just a very thin wrapper of an integer (actually I think it's a short, but I've never found I really needed to know for sure). the "Val" method returns the underlying integer in the SDate variable.

How to use Lambda functions with embedded code in SSRS 2008 R2 reports?

Using SSRS 2008 R2 with embedded code, the VB.Net code compiler seems to err whenever I need to do anything beyond the simplest of statements.
For instance, I want to use the LINQ Select function to perform some operations on the elements of a collection, but BIDS keeps throwing compiler errors on lines of perfectly valid VB.Net code.
Public Function SplitToIDs(ByVal multiValue As String) As Integer()
Dim regex As New System.Text.RegularExpressions.Regex("((?>.*?);#\d*;#)", System.Text.RegularExpressions.RegexOptions.Compiled Or System.Text.RegularExpressions.RegexOptions.ExplicitCapture Or System.Text.RegularExpressions.RegexOptions.CultureInvariant Or System.Text.RegularExpressions.RegexOptions.IgnoreCase)
Dim results As New System.Collections.Generic.List(Of String)()
Dim matches As System.Text.RegularExpressions.MatchCollection = regex.Matches(multiValue)
For Each mvMatch As System.Text.RegularExpressions.Match In matches
results.Add(mvMatch.Value)
Next
'Dim pairs As String() = SplitToPairs(multiValue)
'Dim names As System.Collections.Generic.IEnumerable(Of Integer) = System.Linq.Enumerable.Select(pairs, Function(p) Integer.Parse(Microsoft.VisualBasic.Split(p, ";#")(1)))
Dim names As System.Collections.Generic.IEnumerable(Of Integer) = System.Linq.Enumerable.Select(results, Function(p) Integer.Parse(Microsoft.VisualBasic.Split(p, ";#")(1)))
Return System.Linq.Enumerable.ToArray(names)
End Function
On the line 42, which is the comment immediately above where I call System.Linq.Enumerable.Select, Visual Studio 2008 (the VS Shell installed by SQL Server 2008 R2), gives this error when I attempt to preview my report:
An error occurred during local report processing.
The definition of the report '/XXXX' is invalid.
There is an error on line 42 of custom code: [BC30201] Expression expected.
I have already learned that [BC30201] is a generic error with little relation to a missing expression. As seen in my code, I have fully namespace qualified every function or variable beyond the most basic System namespace classes. In the Report Properties dialog, References tab, I've already referenced both mscorlib and System.Core to make sure all the functions I'm using in my code can be resolved to a System assembly.
So a few questions...
Can Anonymous Functions be called and used in SSRS 2008 R2 Reports' embedded code?
In getting to this point, I was getting the same [BC30201] error when I attempted to call one method in the embedded code from another. Yet, I was sure I had some simpler methods in an earlier iteration of this report (or another report) were this actually worked... Should we be able to call one custom method from another within the embedded code?
Notes:
I'm highly tempted to create a separate code module, but I really don't want to fight the political battle necessary to convince lots of people that we should install custom assemblies on our Reporting servers. But unless, I can call those assemblies directly from various report expressions, I may still need to use the embedded code to make the assemblies' methods available to the report.
The source data comes from a SharePoint 2010 list. Many of the columns are Lookup columns that allow multiple values. The method above strips out the delimiters and values to return a collection of IDs.

What is a public object module in VBA?

I'm trying to get as close to function pointers / abstract classes as I can in VBA.
I have a class called VerificationManager and verifies a bunch of cells in a couple of spreadsheets match up. This will be done in different ways depending on the information and spreadsheets being used with it.
I'd like to be able to make the code reusable by specifying a method to be called in a string using the Application.Run function. So I can rewrite the function that changes.
Now if I was using Java or C# I would be able to extend an abstract class and rewrite the internals to the function. If I was using JavaScript I could store a function in a variable and pass the variable to the class and call it from there.
Inside my class I have a public property called "verificationModule" which I set to the name of the function I want it to call.
Sub VerifyWorkLocations(empLoc As EmployerLocation)
...
For i = 0 To empLoc.numOfEmp
Application.Run verificationModule, empLoc.taxdescmatch, empLoc.employees(i)
Next i
...
End Sub
However, when I try to call Application.Run I receive the following error:
Compile Error:
"Only user-defined types defined in public object modules can be
coerced to or from a variant or passed to late-bound functions"
I already tried placing my User Defined Types in a Class Module but it basically said that a class module was the wrong place for a type.
The error comes from full-fledged VB, where you can create an ActiveX dll project, create a public class there and put a UDT into that class.
In VBA, you use classes instead of UDTs when you need to coerce to or from a variant.
So just declare a class with all the fields you have in your UDT, and delete the UDT.
Alternatively, create a DLL in VB6 that would only contain the declaration of the type, and reference that dll from VBA. Or, if you're comfortable with IDL, just create a TLB file directly.
To add a module to a VBA application, try the following steps (assuming you've already entered the VBA IDE):
From the Project Explorer, right-click on your project.
Click on "Insert..."
Select "Module."
If no modules exist, a new folder within the VBA/Excel project will be created, named "Modules," and a module with a default name of "Module1" will be created.
Double-click the module to open it in the source editor.
This is where you have to place UDT's. I believe this is because of the difference in the way such types are stored internally by VBA relative to the COM-style structure of elements/objects declared/manipulated as Classes...

How to specify a code module as the "Object Ref" parameter in VB.Net CallByName?

I am trying to call a public subroutine from a Windows form based on a string variable containing the name of the subroutine. The subroutine is a procedure in a code module and works fine when called by using the procedure name directly.
The VB.net function CallByName should work, but I don't know how to specify the module name as the "Object Ref" parameter.
In the code shown, "ReportLibrary" is a module containing the public sub with the name contained in the string strReportProcedure. This results in the following error helper:
The Help says this about the ObjectRef parameter:
ObjectRef
Type: System.Object
Required. Object. A pointer to the object exposing the property or method.
What am I missing or is it just not possible to call a routine from a module using CallByName?
CallByName will not work for code in VB.Net modules since the first parameter requires an object. You need to move the methods into a class, then create an instance of the class in order to make CallByName work.
Hmmm, I think the problem is somewhere else.
I think you haven't declared a variable like this:
Dim RL as NEW Reportlibrary
And after declaring it, use this:
CallByName(RL, strReportProcedure , CallType.Method , blnPreview)
Probably the problem was in declaration, because (in your case) your class doesn't let you access to your library's subroutines. That's why you need to declare "as New ReportLibrary".
Good Luck !
Dim object As NEW Reportlibrary and then just use that Object.

Why is it not necessary to indicate ByVal/ByRef anymore?

I just installed Visual Studio 2010 Service pack (proposed on Windows Update), and I can see a new feature on the "intellisense" that means when I write a Function or Sub in VB.NET it doesn't auto-complete parameters with ByRef or ByVal...
1) Is there anyway that I can configure this option back to how it was before?
2) If I don't specify ByX, which one is used by default? (it seems like it is always ByRef)
It seems that this post covers your question:
http://msmvps.com/blogs/carlosq/archive/2011/03/15/vs-2010-sp1-changing-quot-byval-quot-vb-net-code-editor-experience.aspx
So no, there is no way to get the old behaviour. From now on ByVal is the default (what it was before) and it won't get added automatically to the method parameters.
In my opinion this is a good decision since it's making VB.NET a bit more consistent with C# and avoids unnecessary "noises"(it's already verbose enough).
Old behaviour:
Private Sub test(ByVal test As String)
End Sub
New behaviour
Private Sub test(test As String)
End Sub
Tim covered what you asked directly, but something else to keep in mind is that any reference type variable, like a user defined class even if passed by value will allow you to make changes to that instances properties etc that stay. It won't however allow you to change the entire object. Which may be why it seemed to you to be defaulting to by reference
Public Sub (Something As WhateverClass)
Something = New WhateverClass 'will result in no changes when outside this method
Something.Property1 = "Test" 'will result in an updated property when outside this method
End Sub
From MSDN:
The value of a reference type is a pointer to the data elsewhere in memory.
This means that when you pass a reference type by value,
the procedure code has a pointer to the underlying element's data,
even though it cannot access the underlying element itself. For
example, if the element is an array variable, the procedure code does
not have access to the variable itself, but it can access the array
members.
Beware when transferring routines to VBA, where the default is ByRef (see, e.g., "The Default Method Of Passing Parameters" at the bottom of this page, by the great Chip Pearson).
That can be messy.