Searching an Array in Word (Visual Basic for Applications) - arrays

I have set up three arrays in Word. The arrays are as follows:
tacData = Array("32064600", "33001000", "33001100", "33002400", "33003000", "33002400", "35011001", "35013200", "35124100", "35124100")
makeData = Array("Alcatel", "Alcatel", "Sagem", "Samsung", "AEG Mobile", "Samsung", "Nokia", "Maxon", "Siemes", "Nokia")
modelData = Array("One Touch EasyHD", "91009109MB2", "RC410G14", "SGH-200", "Sharp TQ6", "SGH-5300", "DCT-3", "MX6832", "MC399 Cellular Termnial", "DCT-4")
I have made a user form which get a TAC (Value) from the User. Can I get this value and search for it in the first array and get its ID so that I can get the make and model from the other two arrays? I have tried using some code samples that I found but they do not seem to work with Word throwing errors. They were things like Application.Match.
On a side note, would there be a better way to store this information rather than three arrays?

I think you need a collection object. Look at the code below
Dim tacData() As Variant, makeData() As Variant, modelData() As Variant
tacData = Array("32064600", "33001000", "33001100", "33002400", "33003000", "33002401", "35011001", "35013200", "35124100", "35124101")
makeData = Array("Alcatel", "Alcatel", "Sagem", "Samsung", "AEG Mobile", "Samsung", "Nokia", "Maxon", "Siemes", "Nokia")
modelData = Array("One Touch EasyHD", "91009109MB2", "RC410G14", "SGH-200", "Sharp TQ6", "SGH-5300", "DCT-3", "MX6832", "MC399 Cellular Termnial", "DCT-4")
Dim i As Integer, N As Integer
N = UBound(tacData, 1) 'Get the data size
Dim item As Phone 'Temp variable for creating elements into a collection
Dim list As New VBA.Collection 'Define a new collection
For i = 1 To N
Set item = New Phone 'Assign a new Phone object
With item
.TAC = tacData(i) 'Assign values to the phone
.Make = makeData(i)
.Model = modelData(i)
End With
list.Add item, item.TAC 'Add the phone to the list with a KEY
Set item = Nothing
Next i
Dim TAC As String
TAC = "33002400" 'get user input
Set item = list(TAC) '** lookup Phone using Key **
If Not item Is Nothing Then ' Show results
Debug.Print item.TAC, item.Make, item.Model
Else
Debug.Print "Not Found"
End If
It works with a new class called 'Phone' containing
Option Explicit
Public TAC As String
Public Make As String
Public Model As String
and inserted into VBA via this menu item, and renaming in the project tree as "Phone"
The requirement is that the 'TAC' code is unique. In your case it wasn't and I had to change some numbers to make them unique. How have to consider what to do if in real life there are multiple phones with the same TAC code.
PS. Welcome to the world of object oriented programming. This was your first step.

Related

Deserialize a JSON array (I know - not array) in VB.net using JSON.NET

I've been killing myself for days on this and I can't figure it out. I'm by no means a programmer and this is my first attempt at working with JSON.
I have a GUI that I'm writing in VB.NET which gathers information for a script. I am using JSON.NET. I have it capturing the data entered into the GUI and exporting it as a JSON file, but I now need the functionality of reading the JSON file and putting the data back into the GUI.
I'm reading the contents of the datafile like this:
Dim Json As String = File.ReadAllText(fileDlg.FileName)
Dim data As JObject = JObject.Parse(Json)
Then going through each element of the file pulling the data in like this:
AD_DomainNameTB.Text = data.SelectToken("ActiveDirectory.DomainName")
AD_FQDNTB.Text = data.SelectToken("ActiveDirectory.FQDN")
AD_DomainControllerTB.Text = data.SelectToken("ActiveDirectory.DomainController")
AD_SVCUsernameTB.Text = data.SelectToken("ActiveDirectory.SVCUsername")
AD_SVCPasswordTB.Text = data.SelectToken("ActiveDirectory.SVCPassword")
AD_BaseDNTB.Text = data.SelectToken("ActiveDirectory.BaseDN")
Now, I need to cycle through an array of Sites and Site details and enter those into a datagridview on the GUI. I know I can do a for next loop for each of the items, but I don't know how to identify the number of items in the array.
The JSON data looks like this:
{
"ActiveDirectory": {
"DomainName": "CORP",
"FQDN": "corp.company.local",
"DomainController": "DC01",
"SVCUsername": "SVC_AD",
"SVCPassword": "SuperPass1",
"BaseDN": "OU=Active,DC=CORP,DC=Ccompany,DC=Local",
"CreateOUs": true,
"CreateGPOs": true,
"Sites": [
{
"Site": "Prod",
"HSA": "True",
"HSD": "True",
"HVD": null
},
{
"Site": "Test",
"HSA": "True",
"HSD": null,
"HVD": "True"
}
]
}
}
I've looked at the documentation on the site pretty extensively, but I can't find what I'm looking for. I've tried reading it into a dataset, like https://www.newtonsoft.com/json/help/html/DeserializeDataSet.htm, and I've tried creating a Class like Deserialize json array in vb.net but this doesn't make sense to me. It's way over my head.
Any help would be greatly appreciated. Please understand, that like I said, this is extremely new to me, so I need full details (don't assume that I know anything....because I don't!!)
(Using Newtonsoft.Json.Linq)
The ActiveDirectory.Sites node is of type JArray, which has a Count property.
You could iterate over the sites like this:
Dim Sites As JArray = data.SelectToken("ActiveDirectory.Sites")
For I = 0 To Sites.Count - 1
Dim Site = Sites(I)
' use `Site` and `I` in this loop body
Next
But if you don't care about the indexes, you should use a For Each loop:
Dim Sites As JArray = data.SelectToken("ActiveDirectory.Sites")
For Each Site In Sites
' use `Site` in this loop body
Next
JObject also lets you access properties using the following property lookup syntax:
Dim ActiveDirectory = data("ActiveDirectory")
Dim Sites = ActiveDirectory("Sites")
Dim SiteCount = Sites.Count
So another way you could write it is:
For Each Site In data("ActiveDirectory")("Sites")
' use `Site` in this loop body
Next
Based on the recommendations, I've gotten the code to work as I needed.Posting the full block below:
Dim Json As String = File.ReadAllText(fileDlg.FileName)
Dim data As JObject = JObject.Parse(Json)
Dim site
Dim SiteName
Dim HSA
Dim HSD
Dim HVD
AD_DomainNameTB.Text = data.SelectToken("ActiveDirectory.DomainName")
AD_FQDNTB.Text = data.SelectToken("ActiveDirectory.FQDN")
AD_DomainControllerTB.Text = data.SelectToken("ActiveDirectory.DomainController")
AD_SVCUsernameTB.Text = data.SelectToken("ActiveDirectory.SVCUsername")
AD_SVCPasswordTB.Text = data.SelectToken("ActiveDirectory.SVBPassword")
AD_BaseDNTB.Text = data.SelectToken("ActiveDirectory.BaseDN")
AD_CreateOUsCB.Checked = data.SelectToken("ActiveDirectory.CreateOUs")
AD_CreateGPOCB.Checked = data.SelectToken("ActiveDirectory.CreateGPOs")
Dim Sites As JArray = data.SelectToken("ActiveDirectory.Sites")
For Each site In Sites
SiteName = site.item("Site").ToString()
HSA = site.item("HSA").ToString()
HSD = site.item("HSD").ToString()
HVD = site.item("HVD").ToString()
If HSA = "" Then
HSA = False
End If
If HSD = "" Then
HSD = False
End If
If HVD = "" Then
HVD = False
End If
AD_SitesDatagrid.Rows.Add({SiteName, HSA, HSD, HVD})
Next
Now, there might be a better, more efficient way of going through the data in the array, but this worked.

How do I sort an array of different times?

So I have an array of various timeslots, but I want to sort out the times from the earliest ones to the latest ones, however, I also want to delete any elements within the array that has the time value of 12:00am.
Appointment(0) = #10:45:00 AM#
Appointment(1) = #12:00:00 AM# 'My actual has up 80 elements of different timeslots but I'm using 3 elements as an example
Appointment(2) = #12:00:00 AM#
Is there anyone who can help me with this problem?
Using a string array is not a good idea if that's what you used just use a list of DateTime and the Sort method.
Dim list As List(of DateTime) = new List(of DateTime)
For Each val As String In Appointment
list.Add(val.replace(" ",""))
Next
list.Sort(New Comparison(Of Date)(Function(x As Date, y As Date) y.CompareTo(x)))
Nothing in .Net for removing specific items from array, but it can be "simplified" a bit with LINQ:
Dim Appointment = {#10:45#, #12AM#, #12AM#}
Appointment = (From a In Appointment Where a <> #12AM# Order By a).ToArray
or
Appointment = Appointment.Except({#12AM#}).ToArray
Array.Sort(Appointment)
A bit more efficient alternative can be to use generic collection like List or SortedSet instead:
Dim list = New List(Of Date) From {#10:45#, #12AM#} ' or Dim list = Appointment.ToList
list.Add(#12AM#)
list.RemoveAll(Function(a) a = #12AM#)
list.Sort()

Correspond first line of arrays with second line VB

I have a file that shows A song name on the first line, then the genre on the second, and the time on the third.
Example
All You Need is Love-Beatles
Rock
4.25
This goes on. I need some way of corresponding the songs with the genres and then display them in a list box called lstPlayList using Arrays
I have
strSongs(intCount) = objReader.ReadLine()
strGenre(intCount) = objReader.ReadLine()
dblLength(intCount) = Convert.ToDouble(objReader.ReadLine())
For storing every variable but I can't append songs to genres
Instead of having three separate arrays for one item, you could indeed as other commenters have said, create a database, but if you don't want to go that far try this.
Create a structure at the top of your Form's class definition list this :-
Structure Song
Dim Name As String
Dim Genre As String
Dim Duration As Single
End Structure
This effectively creates a new Datatype.
Next create a list of this datatype like this :-
Dim Songs As New List(Of Song)
When you read your data from the file, instead of what you've included in your question, you can add the data to the list like this :-
Dim newSong As Song
newSong.Name = objReader.ReadLine()
newSong.Genre = objReader.ReadLine()
newSong.Duration = Convert.ToDouble(objReader.ReadLine())
Now that you have one list of all the data, you can search the list and return results as a new list of all the results. This is the function that does the searching and returning of a list :-
Private Function SearchSongsByGenre(searchGenre As String) As List(Of Song)
Dim returnList As New List(Of Song)
For Each searchSong As Song In Songs
If searchSong.Genre = searchGenre Then
returnList.Add(searchSong)
End If
Next
Return returnList
End Function
To use it in another sub, just create a list in the sub called.. say.. SearchResults :-
Dim SearchResults As New List(of Song)
Searchresults = SearchSongsByGenre("Rock")
Now you have a list of all the Songs that have the genre Rock
A lot safer than searching an array and getting data from 3 arrays that could become desynchronised.

reference dictionary within array output to listbox

Title kind of states my problem.
I'm using an Api (For Vertical Response, an email list manager) which works fine. But for a particular method returns an Array where the information I need to reference is within a Dictionary inside that Array.
Array[list_id, list_name, list_type, member_data] <- member_data being the dictionary housing all my goodies.
Best I've managed to get is the listbox outputting "com.verticalresponse.api.NVPair[]" for each member.
Code
Protected Sub GetBounces()
Dim listID As Integer = 284662333
Dim isMember As Boolean = False
Dim newSession As New loginArgs()
newSession.username = username
' Your VerticalResponse username
newSession.password = password
newSession.session_duration_minutes = "120"
Dim VRUser As New VRAPI()
Try
sessionID = VRUser.login(newSession)
Dim GetMembers As New getListMembersArgs()
Try
GetMembers.session_id = sessionID
GetMembers.list_id = listID
GetMembers.max_records = 8
Try
Dim listmembers As Array = VRUser.getListMembers(GetMembers)
lstBounces.DataSource = listmembers
lstBounces.DataValueField = ("member_data").ToString()
lstBounces.DataBind()
Catch ex As Exception
lstBounces.Text = "One: " + ex.ToString()
End Try
Catch listex As Exception
lstBounces.Text = "Two: " + listex.ToString()
End Try
Catch ex As System.Exception
lstBounces.Text = "Three: " + ex.ToString()
End Try
End Sub
Edit
I have taken the suggestion of Keith Mifsud and added a breakpoint just before the Databind. It shows me that "listmembers" has eight indices (currently only testing by searching for 8 (total list will be close to 8000, of which about 1900 are needed.))
Each of those 8 indices contains the 4 columns I am looking at, so when I use listmembers(3) as the datasource I'm really only searching the fourth result, not the member_data column...
Is there a correct way to reference the column of results?
Something like:
lstbounces.DataSource = listmembers( ,3)
But instead of that, a correct one?
I think you should set the datasource as the dictionary not the array holding it
Try
Dim listmembers As Array = VRUser.getListMembers(GetMembers)
lstBounces.DataSource = listmembers(3)
'As the datasource is a dictionary, I don't think you have to set up the display and value fields
'lstBounces.DataValueField = ("member_data").ToString()
lstBounces.DataBind()
Catch ex As Exception
lstBounces.Text = "One: " + ex.ToString()
End Try
UPDATE
Based on what the collection type (dictionary within every element of an array) I would recommend you use the .net DataView with allows for expandable rows. There are some very good tutorials which can guide you to create your view

Using Variables as module/array names

My ultimate goal is to load a comboBox with elements from different arrays (vba coded). I have 8 different arrays and 6 option buttons. The first 2 optionButtons are grouped to eliminate 4 arrays which leaves the last 4 grouped optionButtons to determine the actual input for the combo box.
It works like this:
'first grouped option buttons
maleOptionButton
femaleOptionButton
'second grouped option buttons
basketballOptionButton
footballOptionButton
soccerOptionButton
hockeyOptionButton
The array's as you can guess are filled with student names that play the sports. So when the user clicks the first grouped buttons of Male/Female the click even does nothing.. however when they click the second group of option buttons of sports, it calls the same sub procedure within a module that has IF's and Else Ifs to determine the combination of buttons that were selected.
sub maleInitArray()
'declaration section:
Public maleSoccerArray(1 to 6) as string
'sub section
dim mike as student 'calls the class student
set mike = new student
with mike
.name = "Michael"
.age = 14
.so on and so on = something
end with
maleSoccerArray(1) = mike.name
End Sub
What I'm trying to do is this:
dim i as integer
dim l as integer
dim gender as string
dim sport as string
if inputForm.soccerOptionButton.value = true then
if inputForm.maleOptionButton.value = true then
gender = "male"
sport = "maleSoccerArray"
call male.maleInitArray ' inits the array thats hard coded.
else
gender = "female"
sport = "femaleSoccerArray"
call female.femaleInitArray
Else If...
' the list goes on to assign variables depending on the combo boxes.
' doesn't work, but it beats using this every time
l = UBound(sport) ' Doesn't recognize "sport" as an Array
for i = 1 to l
' .AddItem(gender.sport(i)) will not work as well.
inputForm.studentComboBox.AddItem(gender.sport(i))
next i
Seems as though UBound(variable) and AddItem(Variable.Variable)
will not work...
I found a few things so far, but none of them have worked.. such as the application.run method and assigning the actual "male.maleSoccerArray" method.
Any help would be greatly appreciated.. thanks

Resources