A better way of writing this : growing array - vb.net

Was looking at some code earlier, and am thinking that there has to be a more elegant way of writing this....
(returnVar.Warnings is a string array, it could be returned as any size depending on the number of warnings that are logged)
For Each item In items
If o.ImageContent.ImageId = 0 Then
ReDim Preserve returnVar.Warnings(returnVar.Warnings.GetUpperBound(0) + 1)
returnVar.Warnings(returnVar.Warnings.GetUpperBound(0)) = "Section: " & section.<header>.<title>.ToString & " , Item: " & item.<title>.ToString
End If
Next

use the generic List(of string) then get an array containing the list data if you need it
dim list = new List(of string)
list.Add("foo")
list.Add("bar")
list.ToArray()

Can't you use ArrayList which does this for you?
http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx

Start by moving the If statement out of the loop.
If you are using framework 3.5, you can use LINQ to loop the items.
If o.ImageContent.ImageId = 0 Then
returnVar.Warnings = items.Select(Function(item) "Section: " & section.<header>.<title>.ToString & " , Item: " & item.<title>.ToString).ToArray()
Else
returnVar.Warnings = New String() {}
End If

Related

VB - Sorting Alphabetically From a CSV File

I don't know a lot about the subject of sorting but here goes: I am trying to sort a music library (comma seperated in a csv file. Some examples):
1,Sweet Home Alabame,Lynyrd Skynyrd,4:40,Classic Rock
2,Misirlou,Dick Dale,2:16,Surf Rock
I need to sort them alphabetically (by title of track) but I don't know two things: 1. Why my current technique isn't working:
Dim array() As String = {}
sr = New StreamReader("library.csv")
counter = 1
Do Until sr.EndOfStream
array(counter) = sr.ReadLine()
counter += 1
Loop
System.Array.Sort(Of String)(array)
Dim value As String
For Each value In array
Console.WriteLine(value)
Next
Console.ReadLine()
I don't know if this is the best way of sorting. I then need to display them as well. I can do this without sorting, but can't figure out how to do it with sorting.
Help please (from people who, unlike me, know what they're doing).
Right now you're putting all fields in one long string of text (each row).
In order to sort by a particular field, you'll need to build a matrix of rows and columns. For example, a DataTable.
Here's a class that should do the trick for you:
https://www.codeproject.com/Articles/11698/A-Portable-and-Efficient-Generic-Parser-for-Flat-F
Here's the sample usage code from the article, translated to VB:
Public Class CsvImporter
Public Sub Import()
Dim dsResult As DataSet
' Using an XML Config file.
Using parser As New GenericParserAdapter("MyData.txt")
parser.Load("MyData.xml")
dsResult = parser.GetDataSet()
End Using
' Or... programmatically setting up the parser for TSV.
Dim strID As String, strName As String, strStatus As String
Using parser As New GenericParser()
parser.SetDataSource("MyData.txt")
parser.ColumnDelimiter = vbTab.ToCharArray()
parser.FirstRowHasHeader = True
parser.SkipStartingDataRows = 10
parser.MaxBufferSize = 4096
parser.MaxRows = 500
parser.TextQualifier = """"c
While parser.Read()
strID = parser("ID")
strName = parser("Name")
' Your code here ...
strStatus = parser("Status")
End While
End Using
' Or... programmatically setting up the parser for Fixed-width.
Using parser As New GenericParser()
parser.SetDataSource("MyData.txt")
parser.ColumnWidths = New Integer(3) {10, 10, 10, 10}
parser.SkipStartingDataRows = 10
parser.MaxRows = 500
While parser.Read()
strID = parser("ID")
strName = parser("Name")
' Your code here ...
strStatus = parser("Status")
End While
End Using
End Sub
End Class
There's also this from here, demonstrating DataTable usage:
Dim csv = "Name, Age" & vbCr & vbLf & "Ronnie, 30" & vbCr & vbLf & "Mark, 40" & vbCr & vbLf & "Ace, 50"
Dim reader As TextReader = New StringReader(csv)
Dim table = New DataTable()
Using it = reader.ReadCsvWithHeader().GetEnumerator()
If Not it.MoveNext() Then
Return
End If
For Each k As var In it.Current.Keys
table.Columns.Add(k)
Next
Do
Dim row = table.NewRow()
For Each k As var In it.Current.Keys
row(k) = it.Current(k)
Next
table.Rows.Add(row)
Loop While it.MoveNext()
End Using
And this Q&A illustrates how to sort the DataTable by a given column.

Access VBA How can I filter a recordset based on the selections in a multi select list box?

I am trying to use the OpenForm function to filter based on the selections in a multi select list box. what is the correct syntax for this, or is there a better way to go about it? For the sake of example let's say:
List Box has options Ken, Mike, and Sandy.
Car has options Car1, Car2, and Car 3. All cars are owned by 1 or more people from that list box.
If someone from the list box is selected, I would like to open a form containing the cars owned by those people selected.
Thank you!
Ok So I figured out a way to do it:
Create a string to hold a query
Use a For loop to populate the string based on each item selected
Put that string as a filter in the OpenForm command.
Here is the specific code I used to to it. My example in the original post used Cars and People, but my actual context is different: Estimators and Division of Work are the filters. Let me know if you have any questions about it if you're someone who has the same question! Since it might be confusing without knowing more about what exactly I'm trying to accomplish.
Dim strQuery As String
Dim varItem As Variant
'query filtering for estimators and division list box selections
strQuery = ""
If Me.EstimatorList.ItemsSelected.Count + Me.DivisionList.ItemsSelected.Count > 0 Then
For Each varItem In Me.EstimatorList.ItemsSelected
strQuery = strQuery + "[EstimatorID]=" & varItem + 1 & " OR "
Next varItem
If Me.EstimatorList.ItemsSelected.Count > 0 And Me.DivisionList.ItemsSelected.Count > 0 Then
strQuery = Left(strQuery, Len(strQuery) - 4)
strQuery = strQuery + " AND "
End If
For Each varItem In Me.DivisionList.ItemsSelected
strQuery = strQuery + "[DivisionID]=" & varItem + 1 & " OR "
Next varItem
strQuery = Left(strQuery, Len(strQuery) - 4)
End If
Using the JOIN function for cleaner and safer code
When you find yourself repeatedly building incremental SQL strings with delimiters like "," "AND" "OR" it is convenient to centralize the production of array data and then use the VBA Join(array, delimiter) function.
If the interesting keys are in an array, a user selection from a multiselect listbox to build a SQL WHERE fragment for the form filter property could look like this:
Private Sub lbYear_AfterUpdate()
Dim strFilter As String
Dim selction As Variant
selction = ListboxSelectionArray(lbYear, lbYear.BoundColumn)
If Not IsEmpty(selction) Then
strFilter = "[Year] IN (" & Join(selction, ",") & ")"
End If
Me.Filter = strFilter
If Not Me.FilterOn Then Me.FilterOn = True
End Sub
A generic function to pick any column data from selected lisbok rows may look like this:
'Returns array of single column data of selected listbox rows
'Column index 1..n
'If no items selected array will be vbEmpty
Function ListboxSelectionArray(lisbox As ListBox, Optional columnindex As Integer = 1) As Variant
With lisbox
If .ItemsSelected.Count > 0 Then
Dim str() As String: ReDim str(.ItemsSelected.Count - 1)
Dim j As Integer
For j = 0 To .ItemsSelected.Count - 1
str(j) = CStr(.Column(columnindex - 1, .ItemsSelected(j)))
Next
ListboxSelectionArray = str
Else
ListboxSelectionArray = vbEmpty
End If
End With
End Function
A few array builders in the application library and coding can be made look more VB.NET

Listbox Remove Spaces

I am trying to use this code to remove spaces from a listbox but it is not working
Dim word As String() = {" "}
For i As Integer = 0 To ListBox5.Items.Count - 1
For Each Word As String In word
If ListBox5.Items(i).ToString.Contains(Word) Then
ListBox5.Items(i) = ListBox5.Items(i).ToString.Replace(Word, String.Empty)
End If
Next
Next
any help would be appreciated a lot.
You define a string array with one value and its static, why?
It seems you could do this simply by coding it like this
scan every item and replace " " with string.empty,
don't bother checking if it exists, just run the replace statement on every item
For i As Integer = 0 To ListBox5.Items.Count - 1
ListBox5.Items(i) = ListBox5.Items(i).ToString.Replace(" ", String.Empty)
Next
try this code
For i As Integer = 0 To ListBox5.Items.Count - 1
ListBox5.Items(i) = ListBox5.Items(i).ToString.Replace(" ", Nothing)
Next
fist we have to loop through the listbox items. we declared the items from index 0 to the final item index,ie listbox.items.count-1 . this is stored in a variable i. next all the items ,say from 0 to count-1 is replaced.
istBox5.Items(i).ToString.Replace(" ", Nothing) " " indicates a space and'nothing' indicates null.you can also use regex.replace here by importing system.regularexpressions.

If a listbox contains an item LIKE

Is there anywhere to check whether a listbox contains an item which is similar to a string?
I have tried to use a Like statement but this doesn't work.
I have tried:
For i As Integer = 0 To TopicListBox.Items.Count - 1
If (TopicListBox.Items(i).ToString.Contains(Record.Item("Keyphrase2"))) Then
Dim Item As String = TopicListBox.Items(i).ToString
If Item Like "Questions related to:" & Record.Item("Keyphrase2") & ": |*| Qs" Then
Dim ItemSplit() As String = Item.Split(New Char() {"|"c})
Dim AmountOfQuestionsAfter As Integer = AmountOfQuestions + CInt(ItemSplit(1))
Item = ItemSplit(0) & AmountOfQuestionsAfter & ItemSplit(1)
Else
TopicListBox.Items.Add("Questions related to:" & Record.Item("Keyphrase2") & ": |" & AmountOfQuestions & "| Qs")
Exit For
End If
End If
Next
I don't really understand what you are trying to accomplish, but here is a LINQ function to return all the items that contain a certain string.
Dim lb As New ListBox
lb.Items.Add("asdf")
lb.Items.Add("asdfasdf")
lb.Items.Add("aifisasdf")
lb.Items.Add("adf")
'' find all items in the ListBox that contain the string "asdf"
Dim found = lb.Items.Cast(Of String).Where(Function(f) f.Contains("asdf"))
For Each s In found
'' do something with those items
Next
Can't you just do
If Item.Contains("Questions related to:" & Record.Item("Keyphrase2")) Then
...
End If
or
If Item.StartsWith("Questions related to:" & Record.Item("Keyphrase2")) Then
...
End If
?
Dim Found = (From Result In lb.Items Where Result.ToString = "Value" Select Result)
If (Found.Count > 0) Then
' your code
End If

vb.net: index number in "for each"

Sometime in VB.net i have something like:
For Each El in Collection
Write(El)
Next
But if i need the index number, i have to change it to
For I = 0 To Collection.Count() - 1
Write(I & " = " & Collection(I))
Next
Or even (worse)
I = 0
For Each El In Collection
Write(I & " = " & El)
I += 1
Next
Is there another way of getting the index?
If you are using a generic collection (Collection(of T)) then you can use the IndexOf method.
For Each El in Collection
Write(Collection.IndexOf(El) & " = " & El)
Next
I believe your original way of doing it with a counter variable is the most efficient way of doing it. Using Linq or IndexOf would kill the performance.
Dim i as Integer = 0
For Each obj In myList
'Do stuff
i+=1
Next
If you need the index then a for loop is the most straightforward option and has great performance. Apart from the alternatives you mentioned, you could use the overloaded Select method to keep track of the indices and continue using the foreach loop.
Dim list = Enumerable.Range(1, 10).Reverse() ''# sample list
Dim query = list.Select(Function(item, index) _
New With { .Index = index, .Item = item })
For Each obj In query
Console.WriteLine("Index: {0} -- Item: {1}", obj.Index, obj.Item)
Next
However, I would stick to the for loop if the only reason is to iterate over it and know the index. The above doesn't make it clear why you chose to skip the for loop.
If you need the index, change the way you iterate through the collection:
You have already come up with the simplest answer:
For i = 0 To Collection.Count() - 1
DoStuffWith(Collection(i))
Next