At the moment all my arrays are implemented in the vba code. This works fine
Dim COST As String
Dim GAT As String
Dim OND As String
COST = "C:\Users\update\COST.xlsb"
GAT = "C:\Users\BACKUP\GAT.xlsb"
OND = "C:\Users\BACKUP\OND.xlsb"
MyArray = Array(COST, GAT, OND)
However I would like to select the above arrays from a textbox via a form
Below code works but I have to implement the file path
MyArray = Array(Forms![LAYOUT_F]![Update_F])
with file path
MyArray = Array("C:\Users\BACKUP\" & Forms![LAYOUT_F]![Update_F])
Using the above will require me to be file name specific and doesn't take into account arrays plus the file paths are different
Is there a way of selecting declared arrays from a textbox
I would use a multi-line textbox, where the user e.g. enters
C:\Users\update\COST.xlsb
C:\Users\BACKUP\GAT.xlsb
and then use the Split() function on the line breaks:
MyArray = Split(Me!myTextbox, vbCrLf)
But I my have misunderstood your question - not sure what you mean by "selecting declared arrays from a textbox".
Related
Okay my website is connected to mysql database and it reads off strings of data from the database into plain text. I want to get each line from my website and add it to a list box.
This is what I have so far.
Dim GetInfo As String = WBInfo.DownloadString("https://MyWebsite.com/test.php?id=data")
GetInfo Outputs Like:
user1:user2:user3
user2:user3:user4
user3:user4:user5
etc..
For Each line In GetInfo
Dim parts As String() = line.ToString.Split(New Char() {":"c})
ListBox1.Items.Add(parts(1))
ListBox1.Items.Add(parts(2))
ListBox1.Items.Add(parts(3))
Next
In first, use
Dim parts As String() = line.ToString.Split(":"c)
Note, the indexes of an array starts from 0. Also you can use For Each loop statement instead of indexes, for example:
For Each part As String In parts
ListBox1.Items.Add(part)
Next
To maintain performance while items are added to the ListBox use BeginUpdate() and EndUpdate() methods.
I am attempting to create a VBA script for Microsoft Access that pulls titles (such as Mr., Mrs.,Dr.,etc.) from a name field and then return a cleaned specific version of that title. I tried to make a multidimensional array with the title in one column and the cleaned title in another column but when I attempt to compile the script, I get a syntax error. I know the syntax error is because of the multidimensional array as I based this off a previous script that used to just find the old titles and it worked fine. What am I missing that's causing this to be a syntax error? Did I not call the multidimensional array correctly? Admittedly I am new to VBA scripts and rusty in programming in general so forgive me if I'm missing something simple.
Public Function findTitles(inName) As String
' Returns cleaned up titles
Dim strName As String
Dim strTitle As String
Dim Titles As Variant
Titles = Array(Array("Ms", "Ms."), Array("Miss ", "Miss"), Array("Mrs", "Mrs."), Array("Mr", "Mr."), Array("Master", "Master"), Array("Rev", "Rev."), Array("Reverend", "Reverend"), Array("Fr", "Fr."),Array("Father", "Father"), Array("Dr", "Dr."), Array("Doctor", "Doctor"), Array("Atty", "Atty."), Array("Attorney", "Attorney"),Array("Prof", "Prof."), Array("Professor", "Professor"), Array("Hon", "Hon."), Array("Honorable", "Honorable"), Array("Pres", "Pres."), Array("President", "President"), Array("Gov", "Gov."), Array("Governor", "Governor"))
Dim I
I = 0
strTitle = ""
'Compare input to list of Titles
Do
If inName Like Titles(I, 0) & " *" Then
strTitle = Titles(I, 1)
Else
I = I + 1
End If
Loop While (strTitle = "" And I < UBound(Titles))
cleanTitles = strTitle
End Function
The problem is that your array is not multi-dimensional, but nested. The error you are likely getting is not a syntax error, but instead a "Subscript out of range." error. You need to change your array statments like so:
Titles(I, 0)
Should be
Titles(I)(0)
Additionally on your last line you have:
cleanTitles = strTitle
I think you meant:
findTitles = strTitle
I need to pass 8 database column dates to my CalculateMostRecentDate function since vb6 doesnt have a max function. Am i simply able to pass the database values like this? or how would I do it?
Public Function CalculateMostRecentDate(ParamArray dates() As Variant) As Variant
Dim i As Integer
Dim MostRecentDate As Variant
MostRecentDate = dates(LBound(dates))
For i = LBound(dates) + 1 To UBound(dates)
If MostRecentDate < dates(i) Then MostRecentDate = dates(i)
Next i
CalculateMostRecentDate = MostRecentDate
End Function
Call function within another function:
RECENT_APPRV_DT = CalculateMostRecentDate(EMPLOYER.UW_APPRV_DT, EMPLOYER.BE_APPRV_DT, . . .)
Looks about right.
Google turned up this which looks quite polished, also this from the old VB6 newsgroup.
The function looks OK but you cannot call it the way you have indicated. You will need to load the dates into an array and then pass the array in.
Is there a way to call a function, where the call is stored in a table
**Record 1 task Function call**
124567 Email customer Call function emailcus(a,b,c,d)
434535 AddCost Call function addcost(a,b,c,d)
Cheers
Graham
Yes, you can use the Eval() function for that.
Syntax:
Dim ReturnValue As String
ReturnValue = Eval("MyFunction(1, 2)")
Note that you have to provide the exact function call including parameters.
I'm pointing this out because I'm not sure if the parameters a, b, c, d in your example are only dummy values for your example, or if you expect VBA to fill in the values of some variables named a, b, c, d automatically.
The Eval function does not do this, so if you need variable values as parameters, you would have to do something like this:
Dim ReturnValue As String
Dim EvalString As String
EvalString = "MyFunction(" & Variable1 & ", " & Variable2 & ")"
ReturnValue = Eval(EvalString )
This is a variation on the answer already given by haarrrgh, so if you find it useful be sure to upvote that one as well.
There's another way to deal with placeholders in your DB-stored function calls. First, change your data thusly:
**Record 1 task Function call**
124567 Email customer Call function emailcus([TokenA],[TokenB])
434535 AddCost Call function addcost([TokenA],[TokenB])
Note that the [SquareBrackets] are not actually required syntax in this example, just something that I tend to use in this situation. The important part is to make the parameter tokens something that doesn't appear elsewhere in the string value (including other tokens). You can use as many parameters as you need, just make sure that the calling code knows about how many are expected by each function-call string (I cut it down to shorten my following code).
Then when it's time to call your function, do this:
Dim ReturnValue As String 'or as appropriate for individual the function's return
Dim EvalString As String
EvalString = 'code to fetch from table
EvalString = Replace(EvalString, "[TokenA]", strValueA) 'strValueA passed in?
EvalString = Replace(EvalString, "[TokenB]", strValueB) 'strValueB passed in?
ReturnValue = Eval(EvalString)
In VB6, at least (so I assume it's true in VBA), Replace is faster than concatenation. I also find this more readable, but that may be because I'm used to it from using a similar technique to build SQL commands in code (using Const declarations rather than DB storage, but that would work too).
EDIT
As I reread my "finished" post just after submitting it, I realized that there's a gotcha lurking in there. Because you're doing substitution before submitting the string to Eval, these are actual values that are being put into the string, not variables. The code I presented above works fine if your parameters are numeric, but if they're String type you have to include the quotes, either in your data or in your Replace call. I prefer the former, so change your data to this:
**Record 1 task Function call**
124567 Email customer Call function emailcus('[TokenA]','[TokenB]')
434535 AddCost Call function addcost('[TokenA]','[TokenB]')
This works as tested with a Const. Stored in a DB record, you might need this instead:
**Record 1 task Function call**
124567 Email customer Call function emailcus(""[TokenA]"",""[TokenB]"")
434535 AddCost Call function addcost(""[TokenA]"",""[TokenB]"")
(which also works with a Const...).
The alternative is to leave the data as it is in my first part, & change the Replace calls:
EvalString = Replace(EvalString, "[TokenA]", """" & strValueA & """") 'strValueA passed in?
'or maybe
EvalString = Replace(EvalString, "[TokenB]", "'" & strValueB & "'") 'strValueA passed in?
A couple of other potential gotchas: These must be Functions, not Subs, and they must be declared Public in a module, not in a Form's code.
I'm using VBA in an Access application and I would like to have a n-tuple object that contains values of different data types. Then I would like a collection of those objects.
If I was doing this in javascript it would look like:
var myStructure = {
name: "blah"
age: 33
moreStuff : "test"
};
And then I would need a collection of myStructure. How can I best accomplish this in VBA?
You can define your own variable type with code such as:
Public Type T_Person
name as string
dateOfBirth as date
....
email() as string (*)
....
End type
You can then declare a T_person type in your code with:
Dim currentPerson as T_Person
currentPerson.name = myName
currentPerson.dateOfBirth = myDate
currentPerson.email(1) = myFirstEmail
....
(*) I do not remember the details for declaring arrays in such circumstances. You might have to determine array's length when defining the variable. Please check help.
The same result can also be reached by declaring a class module named, for example, "Person". In this class module, you'll be not only able to follow the objet properties (such as name, dateOfBirth, etc), but also object events (initialisation and deletion). You'll be also able to create methods on this object. You code would then look like:
Dim myPerson as Person
set myPerson = New Person
myPerson.name = myName
myPerson.dateOfBirth = myDate
if myPerson.age > 18 then (*)
'the guy is an adult'
myPerson.createAccount
Else
'the guy is not ...'
Endif
(*) Here, age is a calculated proerty of your object, available when dateOfBirth is not null. Please google "VBA class module" to find different examples for the implementation of a class module in VBA.
Now, if you want to manage a collection of similar "objects" (here, Persons), you will have to go through the creation of a class module for your objects collection (a "Persons" class module for example) and make use of the "Collection" objet available in VBA. You will then end with 2 different class modules: Person (will hold each person's detail), and Persons (will hold the collection of Persons). You'll then be able to have code like this:
Public myPersons as Persons 'at the app level, 1 main collection'
myPersons.add .... 'adding a new person to your collection'
myPersons.count ... 'counting number of persons in myPersons'
Please google on "VBA collection object" for examples on Collection management in VBA. Check my code proposal, as this was written on the fly, and without VBA help file.
The "Class" solution is clearly more powerfull, but more complex than the "Type". Go for it if you need it. It is definitely worth the pain!
PS: I am not very happy with my namings here, as this can lead to very confusing code when dealing with the myPersons collection and myPerson instance of o Person object. I'd advise you to find a more obvious one, like "PersonCollection" and "Person", or even "Individual"
You can use Variant multidimensional arrays to store your collections. Variants can store any data type making it very versatile.
Const Name as Integer = 0
Const Age as Integer = 1
Const moreStuff as Integer = 2
Dim myStructure as Variant
Redim myStructure(0 to 2, 0 to n)
myStructure(Name, 0) = "Blah"
myStructure(Age, 0) = 33
myStructure(moreStuff, 0) = "test"
Note: You can only expand the last dimension of a multidimensional array in VBA and preserve the values, so make sure that it is for the dimension you want to scale.
That is the basic data structure and you can develop a class or functions to wrap everything up to suit your needs.
You may also want to look into the Scripting.Dictionary object, though I have read that it is considered unsafe. It is more dynamic than using Type definitions, and unlike Collection, it gives you access to the keys.
Here's a sample:
Public Function TestDictionary()
Dim d As New Scripting.Dictionary 'need reference to Microsoft Scripting Runtime
'Dim d As Object
'Set d = CreateObject("Scripting.Dictionary")
Dim k As Variant
d.Add "Banana", "Yellow"
d.Add "Apple", "Red"
d.Add "Grape", "Green"
For Each k In d.Keys
Debug.Print k; ": "; d.Item(k)
Next k
End Function
The Collection class is an option.
Dim col As New Collection
col.Add("blah", "name")
col.Add(33, "age")
col.Add("test", "moreStuff")
This gives you the most flexibility. However it isn't very efficient and the Collection class has no way to get a list of keys.