This is a follow-up question for my previous question: How Can I Prevent The Suggestion of Custom VBA Functions When Writing Formulas in Excel?
I have implemented the suggestions made in the answer given in order to make my macros and UDFs private, in a way which allows them to be called within other modules in the same workbook but prevents them from being suggested when writing formulas.
I'm trying to produce an Add-In which contains reusable macros and UDFs, and in other VBA projects I am adding this Add-In as a reference (tools > references) so that I can call the functions directly rather than using Application.Run()
By doing this, projects using these reusable functions will be easier to write as the required / optional parameters can be seen at the point of writing the line, and will generally keep the code looking tidier.
By implementing the solution to my first question to make these functions private, the functions are accessible from within the same workbook, however are not accessible to other workbooks.
Does anyone know a solution to achieve this?
If it needs to be accessible beyond the project it's defined in, then it must be Public.
Make macros and UDFs public in a standard code module.
Implement the "utility" code in class modules, and make these classes PublicNotCreatable. Now export these classes and open the .cls file in Notepad.
Locate the VB_PredeclaredId attribute and switch it to True, save and reimport it back in - given class Utilities, a VBA project that references that addin can call the code without creating an instance of the class (it can't New it up anyway), but you can access its public members as you would a default instance of any UserForm class, by qualifying the method with the class name:
foo = Utilities.DoSomething(42)
This is because the PredeclaredId makes a global-scope instance of the class named after the class itself: now you can use that class as if it were a standard module (or a Shared class in VB.NET), and its members won't be available as macros or UDF's.
Related
Compile error:
Cannot define a Public user-defined type within an object module
What does the above compile error mean in Visual Basic for Applications (VBA)?
I would like to point out that the exact same code had no error in a separate empty Powerpoint file.
Thank you.
You need to understand the different types of code modules in VBA. Basically, you can have
A regular module - here you put in code like subs, functions, types
A userform - I guess you know what a userform is. It contains the layout of the form and the so called code behind - that is all the code that is glued to the form, like event triggers.
A class module. A class is an own, user defined type. Additionally to a simple UDT (user defined type), a class has it's own functions and subroutines (yes, I know, this is extremely simplified)
Depending on the environment, you can have build-in modules. In Excel, these are Workbook and Worksheet modules, in Word the Document module (as far as I know in Powerpoint, there are no build in modules).
Now, all of the above, except for a regular module, define classes (user forms, worksheets, workbooks, documents are special kind of classes). And a class cannot contain a public type (it is already a public type), as simple as that. It's similar to the fact that you cannot define a Type within a Type.
I assume that you have your type defined in a user form code. If you need the type only within that form, declare it as private. It is allowed to define types within a class, but they need to be private, with other words, the type in unknown in other modules of your project, and, as a consequence, you cannot have public variables of that type or public functions that return that type.
If you need the type in more than one module, you need to move the type definition into a regular module (this is what GSerg wrote in the comments)
I am writing a range of VBA functions / subs that can be reused in a number of projects. The issue I have is that these functions are listed in the suggested formula functions when using sheets.
Making the functions private will prevent this, but what it will also do is remove the handy hints showing the parameters for the functions when called from a module other than where the function is stored.
Does anyone know of a way to prevent the suggestion of custom functions without making them private?
Parameterless Public members of a standard module are one of two things:
Sub procedures and they're exposed as macros.
Function procedures and they're exposed as UDF's.
Note that members are implicitly Public if no access modifier is specified.
A Sub that has parameters can't be executed as a macro, so it won't show up as an available macro.
A Function that has side-effects (e.g. mutates some module/global state, or changes other cells' value) is bad code, and a UDF can't change another cell's value anyway.
Making the functions private will prevent this, but what it will also do is remove the handy hints showing the parameters for the functions when called from a module other than where the function is stored.
Making it Private not only "removes the handy hints", it makes the function inaccessible to other modules, and your code won't compile.
If your code has UDF's, put them all in the same standard module, e.g. UserFunctions, and make them explicitly Public for readability's sake.
If your code has macros, put them all in the same standard module, e.g. Macros, and make them explicitly Public for readability's sake.
If your code has functions and procedures that need to be Public (e.g. they're accessed from UDF's and/or macros), make them explicitly Public for readability's sake, and put them in standard modules named appropriately (i.e. avoid Helper and Manager modules, they inevitably become a dumping bag of whatever doesn't quite fit anywhere, and grow to a mess).
Then put this at the top:
Option Explicit
Option Private Module
That option (Private Module) prevents all public/exposed members from being picked up as macros and UDF's. Option Explicit should just be there anyway.
Another way is to implement logic in class modules; members of a class module can't be accessed without an instance of that class (i.e. an object), and therefore won't be exposed as macros/UDF's.
First of all, sorry about my English. I'm still learning....
I wanna know how can I make some function or modulus inaccessible for another workbook. In contrast I need these function public for all modulus inside workbook. I make myself clear?
For example:
I need to open two workbook that contains function with the same name but these functions perform things a little bit different.
See here for an answer http://www.cpearson.com/excel/scope.aspx
Here's a copied summary:
If you want a variable to be accessible from anywhere within the project, but not accessible from another project, you need to use Option Private Module as the first line in the module (above and outside of any variable declaration or procedure). This option makes everything in the module accessible only from within the project. This means also that if you do want some project variables to be accessible from other projects and other project variables to be inaccessible from other projects, you need to declare them in separate modules.
I have a VB.net program that I received from someone else. I am trying to make modifications to it. The program consists of one main form and 6 classes (all .vb files).
In the main form, I want to call a sub-routine in one of the other modules. What is strange is that if I enter the name of the module followed by a ".", i.e.
QuoteMgr.
I don't see the names of the sub-routines in the module. I only see the Public Const's that are defined.
The sub-routine that I want to call is in a section labelled:
#Region "Methods"
What do I need to do to be able to call one of these methods?
The confusion was because of the wording you used in your original question before you edited it to say "class" instead of "module".
The two terms in VB.net mean entirely different things. A class typically must be insantiated as an object to invoke its methods.
So what you need to do is:
dim qt as new QuoteMgr
qt.Method("foo");
In this case you're creating an instance of QuoteMgr called qt and then invoking its methods. Alternatively you could modify the QuoteMgr class and set the method you're trying to call to "Shared" and then call it by simply going "QuoteMgr.Method" as you were trying before.
A module is more like a free-standing library of methods that can be called by anything in the same project (by default).
I have a VBA .xla file containing
one main module with the main interface, e.g. readDiagram()
approx 10 modules which provide the functionality implementation to readDiagram(). As I do not like modules having thousands of lines, I decided to separate the interface from the implementation.
In order to make the interface function see the implementation, the implementation functions have to be declared as public. However, that implies that upon referencing the .xla in another project, all the implementation functions can be seen from that project, which is undesirable. Is there a way to separate a .xla into more modules and at the same time make only one function of the whole .xla visible to the outside world?
In all the implementation Subs, put this as the fisrt line
Option Private Module