I have a collection of Applicants. The collection has Names, University, Age, Date, etc.
I would like to create an array that just holds the unique Names from the Applicants collection.
I wanted to somehow create a new dictionary that uses the Names as keys since keys can't be duplicates:
Dim z As Variant
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
For Each z In Applicants
d(z("Names")) = 1
Next
However I do not know if this would work because I am running into errors. I want to create an array afterwards that will hold the unique keys or the Names in this case.
You need to test if the key exists before adding or you will throw an error. Additionally, you have the non-unique .Item in a Scripting.Dictionary that can store single or delimited fields from the same record.
For Each z In Applicants
if not d.exists(z("Names")) then
d.Add Key:=z("Names"), Item:=z("University") & "|" & z("Age") & "|" & z("Date")
end if
Next
I'm not sure about z("Names") but you have not provided enough information about Applicants to prove more than what your sample was using. The .Item. can be retrieved using the key and a Split function on the delimiter will create an array.
Related
I am trying to create an array of a user set length that users can add values to that will be saved and output on multiple sheets. I am very new to VBA so I do not know if what I am trying to do is possible but I have tried a few methods unsuccessfully.
This is the code I have so far
Sub addCost()
Dim costArray() As Variant
ReDim Preserve costArray(1 To Range("b2").Value)
For i = 1 To Range("b2").Value
costArray(i) = 0
Next i
Dim newCost As Variant
Dim costYear As Variant
newCost = InputBox("New cost amount:")
costYear = InputBox("Year new cost is active:")
costArray(costYear) = newCost
End Sub
Here is what the input tab looks like in excel
With the length of the array being the project lifespan and the add new cost activating the code, clear costs are still in progress. Is there a way for the array to store after multiple executions of the addCost sub?
Thanks!
This link Microsoft shows some methods of store values after the macro ending (in your case, sub addCost)
I think the first solution will be good for you.
Other solutions is use Access to store data (specially if you need these data over time) or a new and clean worksheet where you can store array entries in a cell (This is a very practical solution if the number of entries does not get too big)
I have a case where I have a pre-defined set of values/codes what in a combination make some message. I also have an incoming file that I have to analyze on the codes, compare the sets against predefined values. The problem is that the incoming file doesn't exactly match my library:
In my library I have set of 4 columns and each row has it's unique meaning. I want to get that meaning as a string to further proceed with calculations. The problem is that the incoming file is not consistent. It doesn't follow exact sequence as in pre-defined file.
I need to compare them regardless of sequence. After being matched I want to grab corresponding Meaning from Library and proceed working with Case in my file.
Any ideas how to implement it in VBA?
Offhand, you could create a VBA function that would return a string representing the unique values.
If there is some character that will never be in the values, you could delimit the values with that character (such as _):
Function GetUniqueValuesString(rng As Range) As String
Dim rngValues() As Variant
rngValues = rng.Value
' The following line requires a reference to Microsoft Scripting Runtime
' (via Tools -> References...)
Dim dict As New Scripting.Dictionary
'The function only parses the first row of the range
Dim i As Integer
For i = 1 To UBound(rngValues, 2)
dict(rngValues(1, i)) = 1 ' 1 here is a dummy value
Next
GetUniqueValuesString = Join(dict.Keys, "_")
End Function
(If every value is always the same number of characters, you could simply join them, without any delimiter.)
Using this function against a horizontal cell range:
=GetUniqeValuesString(A4:D4)
should return a string with only the unique values:
BGAA_TGHJ_WETY
If you apply this function to both the library rows and the file rows, you should be able to match on the function's returned value.
Note that the function has a few limitations that might need to be resolved:
It assumes the order of the values will be the same. In other words, BGAA, TGHJ, WETY will resolve to a different string than BGAA, WETY, TGHJ.
The function only joins the first row; other rows are ignored.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am having difficulties in trying to understand the following code. I found it here in the following link: vba: get unique values from array
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
'Set d = New Scripting.Dictionary
Dim i As Long
For i = LBound(myArray) To UBound(myArray)
d(myArray(i)) = 1
Next i
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
EDIT: I quite understand the whole code but I could not understand the last section being
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
and I cannot understand this line
d(myArray(i)) = 1
EDIT: I am looking for a code that executes the same objective but I would rather want to understand fully what I am applying than just copy and paste something that I do not understand.
More specifically, there are several elements in the macro that I am constructing and this one is among the ones I am looking for.
As first objective I need to find the duplicates in my dataset
After finding the duplicates I need to count how duplicates there are if there are 4 duplicates row my item is complete,
Then, if there are more than 4 duplicates, I need to transfer the duplicates to another sheet and store them there
On the other hand, if there are less than 4 duplicates, I would need to find such items and try to match these items with an inventory to try to find out the remaining elements in order to stack a full set of 4 elements.
This macro will serve me to fulfill point 4. Once I identify the items that have less than 4, I need to find such items and try to match them with the ones that I have in another sheet. I need to do so with the code above as I would rather use an array in a macro than functions in excel itself in order to avoid confusion to the user with phantom figures.
Section by Section:
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
'Set d = New Scripting.Dictionary
This creates the dictionary object
Dim i As Long
For i = LBound(myArray) To UBound(myArray)
d(myArray(i)) = 1
Next i
With dictionary objects, there are two ways to add a new item:
d.Add Key, Value
This method causes an error if the dictionary already has that key
d(Key) = Value
This method is technically a reassignment for the value of the specified key. If the key doesn't exist, it gets added implicitly. If the key already exists, the value just gets updated.
So what the code is doing, is it cycles through each value in the array and:
Reassigns the current index as the dictionary value with the current dictionary key (the array's value)
If the key doesn't already exist, create it.
This results in a dictionary with one key for every unique value. Any duplicate values would have just been reassigned the value for the existing key, instead of creating a new key.
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
Elaboration: d.Keys returns all of the keys in the dictionary in the form of an array. Since the keys are the unique values from myArray, d.Keys is an array on the unique values from myArray.
I have three columns (First Name , Last Name and phone Number) in my collection that I got from excel using "copy as collection" functionality of Excel VBO.
Please note that there is extra space at the end of First name and Phone number. I want to trim these spaces. Please suggest how to do that. Please also note that I have not defined the column names in my collection. I am directly copying it from excel so that if any changes done in excel then it reflect in the collection dynamically.
Thanks...
There are multiple action in collection manipulation object. You need to use read field action and rename field action with some logic.
You can for use action:
Object: Utility - Collection Manipulation
Action: Trim Collection
If you don't have it in your object, then you can add it to your object. Please see code below:
Dim i as integer
Dim j as integer
'For Each Column As DataColumn In Input_Collection.Columns
For j = 0 to Input_Collection.Columns.Count -1
For i = 0 to Input_Collection.Rows.Count -1
'dim x as string =CStr(Input_Collection.Rows(i)(j)).Trim()
Input_Collection.Rows(i)(j)= CStr(Input_Collection.Rows(i)(j)).Trim()
Next
Next
Output_Collection = Input_Collection
Or you may use
Object: Utility - Collection Manipulation
Action: Remove dot from headers
and in the code change "." to " "
Please find the exact code below and paste it in the code stage:
For Each Column As DataColumn In Input_Collection.Columns
Column.ColumnName=Microsoft.Visualbasic.Replace(Column.ColumnName," ","")
Next
Output_Collection = Input_Collection
I am struggling to make my Dictionary object work to return economic details of selected Reference number.
e.g. I have below reference nos and corresponding values, however, not sure if I can achieve this using Dictionary object , and alternative, suggestion would be highly appreciated.
Ref No Amount Price Year
IB1232 1000 1.23 2011
IB1231 1000 3.23 2011
IB1233 1000 3.43 2011
IB1234 1000 3.43 2011
I thought would be able to achieve by forming Key and Value for reference and their corresponding details, but not been able to achieve ..
#das_weezul
There is a Dictionary object in VBA in the scripting library (you need to add that reference to use it). The Dictionary has some extra functionality, such as the ability to check if a key exists before trying to access it.
#Sky Cobb
Yes, you could do all of the above tasks with the Dictionary. The syntax will the same, except you should provide a key for every item that you add to it.
I don't know what you're referring to as Dictionary in VBA, as the data structure with the said functionality is called Collection in VBA (but maybe you coded your own Ditionary, in that case we need the code in order to be able to help you).
If I get your example right, you want to access e.g {1000,1.23,2011} via the key "IB1232". You can do this easily by creating a Collection of Collections like this:
Dim coll as new Collection
Dim data as new Collection
data.Add 1000
data.Add 1.23
data.Add 2011
coll.Add data, "IB1232"
To access your data just get the desired record (Collection) via the key
Debug.Print coll.Item("IB1232")(1) 'Prints 1000
Debug.Print coll.Item("IB1232")(2) 'Prints 1.23
Debug.Print coll.Item("IB1232")(3) 'Prints 2010
You can also use an array of Variants for the data
As mentioned before, you need to enable a reference to get the Dictionary object, but it absolutely does exist. To add the reference: Tools > References > [x] Microsoft Scripting Runtime
Public Sub test_dict()
Dim td As Object
Set td = New Dictionary
td("IB1232") = "1000 1.23 2011"
td("IB1233") = "1000 3.43 2011"
'Another way to do it, may be around for legacy support
td.Item("IB1234") = "1000 3.43 2011"
'What you probably want... a key:value dictionary where the value is a collection
Set td("IB1231") = New Collection
td("IB1231").add 1000
td("IB1231").add 3.23
td("IB1231").add 2011
'Get value by key
Debug.Print td("IB1234")
'Get a collection's value.... it's 1-indexed
Debug.Print td("IB1231")(1)
'Test if a key exists
Debug.Print td.exists("IB12345")
'See how many items there are
Debug.Print td.Count()
End Sub