VBA use string for range - vba

I need help for my VBA tool.
In my program I define a string keyword:
Public Sub SetKeyword()
Call Define_Variables.variables
Call Database.Allocation
strKeyword="KINDACC"
Now I would like to set the name of the range keyword with my string keyword, so it looks like this:
Public Sub SetKeyword()
Call Define_Variables.variables
Call Database.Allocation
strKeyword="KINDACC"
rngKeyword= r_KINDACC
End Sub
In my module "Database" I have those r_strKeywords already defined:
Sub Allocation()
'General accident information
...
Set r_KINDACC = Worksheets("Database").Range("N4:N14")
End sub
So later with my GUI I would like to define a string-keyword and my program automatically defines my range-keyword with my string keyword:
Public Sub SetKeyword()
Call Define_Variables.variables
Call Database.Allocation
strKeyword=blabla
rngKeyword= r_strKeyword
End Sub
Is that possible?
I hope it's not too confusing
thanks!!
Viktoria

Related

better way to call global config variables from another modules

I have three modules in my VBA project:
module 1: config_variable
module 2: main_script1
module 3: main_script2
In "config_variable", the codes like this:
Public dir_source1 As String
Public dir_source2 As String
Public dir_source3 As String
Sub global_config()
dir_source1 = range("A2").value
dir_source2 = range("A3").value
dir_source3 = range("A4").value
End Sub
I manage all configurations in this script. And I call this "global_config" Sub for each Sub in module 2 and module 3 to get global variables. Like this:
module 2 - main_script1:
Sub my_sub1()
' call global variables
Call config_variable.global_config
' main codes for my_sub1
.....
End Sub
Sub my_sub2()
' call global variables
Call config_variable.global_config
' main codes for my_sub2
.....
End Sub
module 3 - main_script2:
Sub my_sub3()
' call global variables
Call config_variable.global_config
' main codes for my_sub3
.....
End Sub
The problem is that I need to call the line "Call config_variable.global_config" in the beginning of each Sub.
Is it possible I can just run this line once and every Sub in the same modules can catch the global variables? Like this:
' call global variables on top of each modules
Call config_variable.global_config
Sub my_sub1()
' main codes for my_sub1
.....
End Sub
Sub my_sub2()
' main codes for my_sub2
.....
End Sub
Call the setting of the global variables when you launch your workbook or project file:
Call config_variable.global_config
Of course, if the range values may change during a session, you will have to reset the global variabels after such a change.
If settings values are stored in sheet cells, there is no need to move them to global variables at all. You can take those values directly from the cells. For convenience, you can name these cells and refer to them, for short, with [] (syntactic sugar = Evaluate()). If the settings are not called very often, this method may be suitable, requiring no variables to be updated. For example:
Sub run_once() ' or make names manually
For Each x In Array("dir_source1:A2", "dir_source2:A3", "dir_source3:A4")
y = Split(x, ":")
ThisWorkbook.Names.Add y(0), ThisWorkbook.Worksheets("Settings").Range(y(1))
Next
End Sub
Sub UsageExample()
Debug.Print "dir_source1 = " & [dir_source1] ' equivalent for ThisWorkbook.Worksheets("Settings").Range("A2")
End Sub
If "config_variable" is a standard module (as it looks to be), you can simple call the sub as global_config. It is not Private and it will be called. But, I should suggest you to call it only if one of the Public variable is "" (nullString):
If dir_source1 = "" Then global_config
In this way, even if an error occurred and the Public variable lost their value, they will be used only after global_config runs and give values to them.

How Do I fill in this Structure String Array in vbNET?

Visual studio tells me the variable must be declared even though it already is.
I filled in a structured array in a similar way using a loop though the type was an Int.
I do not want to use a loop this time just hard code it.
Structure Sentence
Dim strWord As String
End Structure
Dim strArticles(1) As Sentence
strArticles(0).strWord = "The"
Thanks
Are you defining the Structure in your method body? It must be defined outside of a method, either in a module ore a class. See this example.
This works just fine:
Module Module1
Sub Main()
Dim s = New Sample()
s.DoIt()
End Sub
End Module
Class Sample
Structure Sentence
Dim strWord As String
End Structure
Public Sub DoIt()
Dim strArticles(1) As Sentence
strArticles(0).strWord = "The"
Console.WriteLine(strArticles(0).strWord)
End Sub
End Class

Why does my function's name appear twice in the "locals" window?

I have created a Class Module in which I have defined a function. Whenever that function is called, it is listed twice in the locals window. Only the second one's value changes, the first one stays either empty or "zero", depending on its type, until the end of the code's execution. I don't have this problem with functions defined in standard modules. Did I do something wrong, is this a bug, or is there a logical reason behind this?
Contents of the TestClass class module:
Public Value As Double
Function AddFive() As Double
AddFive = Me.Value + 5
End Function
Contents of the standard module:
Sub TestSub()
Dim TestObject As New TestClass
TestObject.Value = 2
MsgBox TestObject.AddFive
End Sub
Here is a screenshot showing that, when the code is executed line-by-line, the function's value is listed twice in the locals window, and only the second value has changed after the function's code was executed.
(link to screenshot)
I'm using VBA for Excel 2010.
Thanks in advance.
The issue is more in how you are doing it. If you have a function that just adds 5 to an internal variable of a class object, then it's technically a void (Sub in VBA) since you don't need a return value.
Your code should be:
CLASS
Public Value As Double
Sub AddFive()
Me.Value = Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.AddFive
MsgBox testObject.Value
End Sub
I can imagine there could be a number of reasons why there are 2 variables created, but I find it a bit pointless to go into why there is unexpected behavior since you are doing improper code.
If you want, you can even write class function that will show it's value + 5 in a msgbox and this would not create an extra variable either. But that is strange and I think you want the code above. But here it is regardless:
CLASS
Public Value As Double
Sub ShowPlusFive()
MsgBox Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.ShowPlusFive
End Sub

VBA [classes] - how to access a previously instanciated instance of a class in another sub

I've created the instance "Lassie" of the class "Dog" within a particular sub in my program. I have also given it some useful properties, such as Lassie.Age = 7 and Lassie.HeelCapability = False.
Now I would like to access another sub and change the Lassie.HeelCapability to True.
How do I go about defining the instance "Lassie" within this new sub so it can be worked with?
All the code I have come accross goes like this:
Dim Lassie As classDog
Set Lassie = New classDog
Essentially what I am looking for is a way to import the existing instance "Lassie" into another sub, without using the keyword "New" and thereby creating a new "Lassie" (without all the properties previously given).
The errormessages I have been receiving tell me either "object required" or "object variable or with block variable not set".
Surely there is a way to do this.
Thanks in advance.
You will need to pass 'Lassie' as a parameter to your other sub.
public sub DeclareSub()
Dim Lassie as classDog
Lassie = new classDog
OtherSub Lassie
end sub
public sub OtherSub(ByRef dog as classDog)
end sub
The variable 'dog' in the subroutine 'OtherSub' refers to the same object instance as the variable 'Lassie' from 'DeclareSub'.
Pass the object in ByRef to your new Subroutine.
Sub ChangeHeel(ByRef olassie As classDog)
'change the object here, and it will be changed in the calling sub
olassie.HeelCapability = True
End Sub

Calling a Sub or Function contained in a module using "CallByName" in VB/VBA

It is easy to call a function inside a classModule using CallByName
How about functions inside standard module?
''#inside class module
''#classModule name: clsExample
Function classFunc1()
MsgBox "I'm class module 1"
End Function
''#
''#inside standard module
''#Module name: module1
Function Func1()
MsgBox "I'm standard module 1"
End Function
''#
''# The main sub
Sub Main()
''# to call function inside class module
dim clsObj as New clsExample
Call CallByName(clsObj,"ClassFunc1")
''# here's the question... how to call a function inside a standard module
''# how to declare the object "stdObj" in reference to module1?
Call CallByName(stdObj,"Func1") ''# is this correct?
End Sub
I think jtolle's response addressed the question best - the small reference to Application.Run may be the answer. The questioner doesn't want to use simply func1 or Module1.func1 - the reason one would want to use CallByName in the first place is that the desired function.sub name is not known at compile time. In this case, Application.Run does work, e.g.:
Dim ModuleName As String
Dim FuncName As String
Module1Name = "Module1"
FuncName = "func1"
Application.Run ModuleName & "." & FuncName
You can also prepend the Project Name before the ModuleName and add another period ".".
Unfortunately, Application.Run does not return any values, so while you can call a function, you won't get its return value.
Although it is an old question and OP asked for CallByName in a standard module, the correct pieces of advice are scattered through answers and comments, and some may not be that accurate, at least in 2020.
As SlowLearner stated, Application.run DOES return a Variant, and in that way both branchs below are equivalent, except by handling errors, as commented around Horowitz's answer:
Dim LoadEnumAndDataFrom as Variant
'FunctionName returns a Variant Array
if fCallByName then
LoadEnumAndDataFrom = CallByName(ClassObj, "FunctionNameAtClass", VbMethod)
else
'After moving back function for a standard module
LoadEnumAndDataFrom = Application.Run("StandardModuleName" & "." & "FunctionNameAtStandard")
endif
I actually just did this above and had no errors at all, tested in Word, Excel and Access, and all return the same Array.
Unfortunately, there is an exception: Outlook's object Model is too protected and it does not have the Run method.
CallByName works only with class objects.
If your subroutine is in a standard module, you can do this:
Sub Main()
Module1.Func1
End Sub
If it's a function, then you'll probably want to capture the return value; something like this:
Sub Main()
Dim var
var = Module1.Func1
End Sub
Modules in VB6 and VBA are something like static classes, but unfortunately VB doesn't accept Module1 as an object. You can write Module1.Func1 like C.Func1 (C being an instance of some Class1), but this is obviously done by the Compiler, not at runtime.
Idea: Convert the Module1 to a class, Create a "Public Module1 as Module1" in your Startup-module and "Set Module1 = New Module1" in your "Sub Main".
Unfortunately it is not possible to prepend the ProjectName before the ModuleName and add another period "." In MS Word this throws a runtime error 438. The call is restricted to the use of simply ModuleName.ProcName.