Specify column index of selected data in ItemBox to retrieve when iterating through selected items - vba

Basically have an ItemBox with three columns in an Access form. I want to get specific columns when I iterate though the selected items, but I am having difficulty doing so.
Function GetSelectedValues(famList As Variant) As Collection
Dim famListColl As New Collection
' Loop through all of the selected surveys
For Each fam In famList.ItemsSelected
Debug.Print (fam) ' prints the index number of the selected item
Debug.Print (famList.ItemData(fam)) ' this prints out the last columns value for the selected item
famListColl.Add famList.ItemData(fam)
Next
Set GetSelectedValues = famListColl
End Function
If I try to do the following I get an Run-time error '424': Object required error:
Debug.Print(fam.Column(1))
Debug.Print(famList.ItemData(fam).Column(1))
This somewhat works, but only displays the values of the first selected item indefinitely (it doesn't iterate):
Debug.Print(famList.Column(1))
So I need to combine the two somehow, but struggling to figure that much.
Thanks for the help!

Stumbled across this post that helped me sort it out. I doubt I would have figured it out otherwise. Looks like this:
Debug.Print (famList.Column(2, fam))
So the entire solution for me is the following:
Function GetSelectedValues(famList As Variant) As Collection
Dim famListColl As New Collection
' Loop through all of the selected surveys
For Each fam In famList.ItemsSelected
famListColl.Add famList.Column(1, fam)
famListColl.Add famList.Column(2, fam)
Next
Set GetSelectedValues = famListColl
End Function

Related

Dictionary.Item returns collection but Dictionary.Item.Add adds new collection item to every key instead of specified key

I am trying to create a data structure in which a dictionary stores collections assigned to a key as a double. Each collection contains further array variants also. I am looping through rows in worksheet and adding certain values in each row to its associated collection for further manipulation later.
When I am adding data from a row to a collection, whether it belongs in a new collection--ergo a new key value pair in the dictionary--or simply just added to an existing collection, the data in the format of an array variant is being added to every key in the dictionary. Is somebody able to identify my problem?
For Each row In Selection.Rows 'Loop through each row in chunks of 5000
Dim NewInv(0 To 1) As Variant
If MasterDict.Exists(row.Cells(3).Value) Then
NewInv(0) = row.Cells(15).Value
NewInv(1) = row.Cells(15).EntireRow.Address
MasterDict.Item(row.Cells(3).Value).Add (NewInv)
'for some reason the line above is adding the array variant to every collection assigned to every key, not just the specified key.
Else
Dim NewAcct As New Collection
NewInv(0) = row.Cells(15).Value
NewInv(1) = row.Cells(15).EntireRow.Address
NewAcct.Add (NewInv)
MasterDict.Add Key:=row.Cells(3).Value, Item:=NewAcct
End If
Next
In the code above MasterDict is the dictionary in question.
Thank you for your response.
You are making a fundamental error. You only have one NewInv array. Even though you change the values of the individual items this does not make it a new array thus during the loop the reference is to NewInv only and consequently only the last values assigned to NewInv will be visible in each item. To do what I think you intended you need to revise your code as follows
For Each Row In Selection.Rows 'Loop through each row in chunks of 5000
If Not MasterDict.Exists(Row.Cells(3).Value) Then
MasterDict.Add Key:=Row.Cells(3).Value, Item:=New Collection
End If
MasterDict.Item(Row.Cells(3).Value).Add Array(Row.Cells(15).Value, Row.Cells(15).EntireRow.Address)
Next

Find Item.index after using Items.find

How do you look up the index of a contact item that was set using the items.find method? After finding the item, I want to be able to move to the next item, but my code sends me to the first item in the collection. A condensed version of my plan is below...
dim ColItms as items
dim CI as contactItem
Dim CIindex as integer
set CI= ColItms.find("[CompanyName] = ""IBM""")
CIindex = CI.???? ''''' This shows what I'm wanting to do, but don't know how
' now advance to next item in collection
set ci = ColItms.item(CIindex +1) ' i think this would work if I could find CIindex
set ci = ColItms.GetNext ' this fails as it returns the 1st item in the collection
Right now all that seems to work is to loop through each item in the collection to see if it matches the found contact,
Items have no intrinsic index, only an entry id.
To find the next match, use Items.FindNext.

vb.net getting a collection of rows from a bound datagridview based on selection

I've read around and googled but didn't find the little thing which would help me. I think I've got some simple logical error.
Ok, so here is what I have:
A DataGridView bound to a Datatable populated with filenames (and other info, mainly audio format).
Well, now I've written a sub (VS2013 and using .Net 4.0) for printing which works fine, I tried to add an option to print only selected rows from the DataGridView and thought ok, then I give the printing routine the whole rows of the DataGridView or only the selected rows based on that option.
This is what I tried:
On the form Level I defined the rowCollection as:
Dim rowCollection As DataGridViewRowCollection
The BeginPrint Sub then has the following lines to get the rows:
'*** Get Rows to print
rowCollection = New DataGridViewRowCollection(FileDataGridView)
If My.Settings.PrintSelected And (FileDataGridView.SelectedRows.Count > 0) Then
Dim row As New DataGridViewRow
For r = FileDataGridView.SelectedRows.Count - 1 To 0 Step -1
row = FileDataGridView.SelectedRows(r)
rowCollection.Add(FileDataGridView.Rows(row.Index))
Next
Else
rowCollection = FileDataGridView.Rows
End If
I thought a rowCollection would be something like an array of the single rows,
but apparently this doesn't do the job.
If I want to print all rows, this works fine, but for the selected rows, I get an error the no elements could be added to the row collection because the DataGridView is databound. I thought the rowCollection could be population by single rows, an not only link to the whole DataGridView. Where am I wrong?
I also tried to get only the .SelectedRows as a collection but then I get type errors as DataGridView.Rows and DataGridView.SelectedRows do not have the same format?
I would like to get a list/collection/array of the rows or selected rows, which I then can use for printing.
Any help would be appreciated
regards,
Christian
Surely not a perfect solution but does the job:
Dim rows As List(Of DataGridViewRow)
Dim rowarray(DataGridView1.Rows.Count) As DataGridViewRow
If DataGridView1.SelectedRows.Count > 0 Then
DataGridView1.SelectedRows.CopyTo(rowarray, 0)
Else
DataGridView1.Rows.CopyTo(rowarray, 0)
End If
rows = rowarray.ToList
rows.RemoveAll(Function(a As DataGridViewRow) a Is Nothing)
There is a difference between a SelectedRowCollection and a RowCollection, for what ever reason they didn't used inheritence for those 2, so you need to cheat a little to process both the same way

VBA collection with 2 or more fields

I'm using a Collection to store data from a recordset in VBA. The recordset has two fields.
I'm using a collection because I want to utilise its ability to prevent duplicates by using the key parameter. I'm running an SQL query to generate the recordset many times and a lot of the results will be identical to the previous, but some will be different. I want to capture a collection of the unique results from each recordset.
I can do this currently using the following:
rs.Open sql_vehicles, cn
If rs.RecordCount > 0 Then
Do While Not rs.EOF
On Error Resume Next
value = rs.Fields("EVN").value
catalogue_Tags.Add Item:=value, Key:=value
rs.MoveNext
On Error GoTo 0
Loop
End If
which all resides in a for loop generating a new recordset each time which may or may not be different.
This will give me a collection with unique values from the "EVN" field in the recordset, but I need to be able to store the second field in the recordset as well, but I want to still avoid duplicates of the EVN field!
Any ideas on how to do this?
Seems to me you can just use 2 collections to get 2 unique lists...
value = rs.Fields("EVN").value
catalogue_Tags_EVN.Add Item:=value, Key:=value
value = rs.Fields("ABC").value
catalogue_Tags_ABC.Add Item:=value, Key:=value
I just notice your requirement is slightly different then I read the first time...
Add "Microsoft Scripting Runtime" reference to your project and use a dictionary of dictionaries.
Dim evnValues as new Scripting.Dictionary ' this will actually be a dictionary of dictionaries.
inside the loop do this...
ABCvalue = rs.Fields("ABC").value
if not evnValues.Exists(value) then
' sub dictionary does not exist yet. initialize the list for this evn value
evnValues(value)=New Scripting.Dictionary
end if
evnValues(value).item(ABCValue)=ABCValue ' accumulate a list of the ABCValues relative to the unique evnValue.
At the end you will have a dictionary with the Names of the top level being your unique EVN values and the sub value will be a collection of 1 or more ABC values.

Error when trying to delete data from table with LINQ to SQL

In LINQ I am trying to write a query that will, once a button is clicked, delete a record from a database table, namely "Amendments_Awaiting_Approval". This row will be found and deleted based on the value entered in a text box. So far I have this: ' Your input string
Dim parseRef As String = txtReferenceCode.Text
'Convert string to integer value '
Dim deleteRecord As Integer = Integer.Parse(parseRef)
' Query the database for the rows to be deleted. '
Dim deleteModuleChanges = _
From amendments In db.Amendments_Awaiting_Approvals _
Where amendments.Amendments_ID = deleteRecord _
Select amendments
For Each amendment As Amendments_Awaiting_Approval In deleteModuleChanges()
db.OrderDetails.DeleteOnSubmit(detail)
Next
This segment is not working. The page won't even load and when I mouse over the deleteModuleChanges() section I get the error "Overload resolution failed because no accessible ElementAtOrDefault accepts this number of arguments"
Any ideas?
deleteModuleChanges is IEnumerable, so when you add () to it VB.NET compiler tries to fire ElementAtOrDefault extension method on that collection, what can't be done without a parameter. Try that one:
For Each amendment As Amendments_Awaiting_Approval In deleteModuleChanges
db.OrderDetails.DeleteOnSubmit(detail)
Next
However, I don't know why you're iterating over amendment, but delete detail. Are you sure that's what you want to do?
And of course, you have to submit changes:
db.SubmitChanges()