I have written a small piece of code which doesn´t work like I want.
My goals:
I have a textbox with 3 lines. Each line = one product.
I have a second textbox with 2 lines. Each line = 1 variant of a product.
My result should be something like this:
Artificial grass | Red
Artificial grass.1 | Blue
Dark hole plate | Red
Dark hole plate.1 | Blue
Test hole plate | Red
Test hole plate.1 | Blue
I have this code (deleted all the unneccessary parameters for you):
For value1 As Integer = 0 To NumberOfArticles - 1
Dim Name As String = ProductTB.Lines(value1)
Dim Variants As String = VariantsTB.Lines(value1)
For value2 As Integer = 1 To VariantsCountTB.Text - 1 'TextBox with number of variants
DataGridView1.Rows.Add(New String() { VariantsTB.Lines(value2 - 1)})
DataGridView1.Rows.Add(New String() {VariantsTB.Lines(value2)})
Next
If value1 = NumberOfArticles Then
Exit For
End If
Next
Name is each line of the product textbox.
Variants is each line of the variants TextBox.
The problem: It works, but ONLY if there are as many variants as products. But I need for example only 2 variants, but 3 products. So, where to edit this loop?
Thank you very much! :)
Best regards
As jmcilhinney mentioned use lines() to save textbox text in a array and then do the looping on the same
''Get all Products in array
Dim products As String() = ProductTB.Lines()
''Get all attributes in array
Dim attrributes As String() = VariantsTB.Lines()
''Create as list for result
Dim resultlist As New List(Of String)
''Loop over product
For Each prod As String In products
''Loop over Attributes
For Each atr As String In attrributes
Dim resultprd = prod & "|" & atr
resultlist.Add(resultprd)
Next
'' if you want proiducts without attributes also add here
''resultlist.Add("Prod")
Next
Related
I have this textfile:
Paul George|2.87|29
Stephen Curry|2.85|28
Jamal Murray|2.72|21
PJ Tucker|2.72|11
Kyle Lowry|2.61|15
Game
Paul George|g2d|g2p
Stephen Curry|g2d|g2p
Jamal Murray|g2d|g2p
PJ Tucker|g2d|g2p
Kyle Lowry|g2d|g2p
Game
Paul George|g3d|g3p
Stephen Curry|g3d|g3p
Jamal Murray|g3d|g3p
PJ Tucker|g3d|g3p
Kyle Lowry|g3d|g3p
Game
Paul George|g4d|g4p
Stephen Curry|g4d|g4p
Jamal Murray|g4d|g4p
PJ Tucker|g4d|g4p
Kyle Lowry|g4d|g4p
I want to add the items to the arrays
Names(name, gamenumber)
Distance(distance, gamenumber)
Points(Points, gamenumber)
with the first index being the data for the player, and the second being the game that data is from
For example,
distance(1, 0) = 2.87
distance(5, 0) = 2.61
distance(1, 1) = g2d
So that the indexes match up with the player for the given game number.
So far I have:
Private Sub openFile_Click(sender As Object, e As EventArgs) Handles openFile.Click
OpenFileDialog.ShowDialog()
Dim strFileName = OpenFileDialog.FileName
Dim objReader As New System.IO.StreamReader(strFileName)
Dim textline As String
Dim Names(100, 3) As String
Dim Distance(100, 3) As String
Dim Points(100, 3) As String
Dim Count As Integer = 0
Dim GameNumber As Integer = 0
Do While objReader.Peek() <> -1
textline = objReader.ReadLine() & vbNewLine
If textline = "Game" Then
GameNumber = GameNumber + 1
Else
Dim parts() As String = textline.Split("|")
Names(Count, GameNumber) = parts(0)
Distance(Count, GameNumber) = parts(1)
Points(Count, GameNumber) = parts(2)
Count = Count + 1
End If
Loop
End Sub
The parts of each line are split up by |, putting them into "parts", it then assigns the three parts it gets from the line (the player name, distance, and points) into there separate arrays as
Names(<Name>, 0)
Distance(<Distance>, 0)
Points(<Points>, 0)
It continues down the textfile but IF the line = "Game" it should, increment GameNumber, and then move to the next line, continuing to add the data, instead as
Names(<Name>, 1)
Distance(<Distance>, 1)
Points(<Points>, 1)
and so on, but it my code isn't working. After getting this working, I wont it to print the desired Game statistics for the players on the page in a listbox with something like:
For n = 0 To Count - 1
lstNames.Items.Add(Names(n, GameWanted))
lstNames.Items.Add(" ")
lstDistance.Items.Add(Distance(n, GameWanted) + " Miles")
lstDistance.Items.Add(" ")
lstPoints.Items.Add(Points(n, GameWanted))
lstPoints.Items.Add(" ")
Next
This would become a lot easier if you create a class representing your player and index them with a dictionary
Class Player
Public Property Distances as List(Of Decimal)
Public Property Points as List(Of Integer)
Public Property Name as String
Public Sub New(n as String)
Name = n
Distances = New List(of Decimal)
Points = New List(of Integer)
End sub
End class
And then in your method that reads your file:
Dim d as new Dictionary(of String, Person)
ForEach line as String in File.ReadAllLines(...)
Dim bits = line.Split("|"c)
If bits.Length < 3 Then Continue For
If Not d.ContainsKey Then d.Add(bits(0), New Person(bits(0))
Dim p = d(bits(0)) 'retrieve the old or just added person
p.Distances.Add(decimal.parse(bits(1)))
p.Points.Add(integer.parse(bits(2)))
Next line
Note; I'm a c# programmer and seldom do vb any more. I code with array indexes starting at 0, if you're on 1 base indexing, add one to the indexes above. This code should probably be treated as pseudocode; it was written on a cellphone from a 5 year old memory of what vb looks like and might have a raft of vb syntax errors(sorry) or take the long way round to do things that we have shorter sybtaxes for these days (list initializers etc)
At the end of this loop through all the file you will have a dictionary of your people, one per name encountered. Each person will have a list of scores and distances. If you want to add them up or average them add a Function to person class that iterates the list and returns the result, and to print them all out do a
foreach s as string in d.Keys
Console.Write(d(s).Name & " got avg distance " & d(s).GetAverageDist())
Or similar
To print out all their distances:
foreach s as string in d.Keys
foreach dis as decimal in d(s).Distances
Console.Write(d(s).Name & " got distance " & dis)
This is object oriented programming; we model the world using classes to represent things and do useful stuff. We don't try to collect data together in 20 different arrays and tie it all together with indexes etc - that's a very procedural code mindset and the opposite of what vb.net was invented for
It's likely actually that this falls short of a proper solution and is also somewhat hypocritical because I use two lists to track distance and points and assert that the list indexes are equal - the distance at index 3 and the points at index 3 are from game 4 (zero based indexing note)
What we really should do is also define a GameResult class and it have properties of distance, points and gamenumber, then each person class has a single List(of GameResult) - person could have a function that returns a nicely formatted score card for that person - that's proper OO :)
VB2010. May be a bit hard to understand but I have a list of classes and one field is a string message. I'm outputting these messages to an RTF document but want to maximize use of horizontal space so am trying to dynamically create a table and fit as many messages in one row as possible and then another row. This while I maintain a max width possible for a row.
Public Class TripInfo
Public SysId As String = ""
Public CreateDate As DateTime
Public OutMessage As String = ""
Public OutMessageWidth As Integer = 0 'the width of the message in char count up to first LF
End Class
Dim myTrips1 as New List(Of TripInfo)
Dim myTrips2 as New List(Of TripInfo)
So as I iterate through the lists I want to create rows that are themselves no longer than 45 characters. Something like:
---------------------------------------------
|"Message1 |"Message2 |"Much longer message |
| Trip1 "| Trip2" | with two lines" |
---------------------------------------------
|"message is even longer than the others" |
---------------------------------------------
|"trip is ok |"trip was cancelled due to CW |
| enroute" | must log to system" |
---------------------------------------------
|"Message3 |"Message4 |"Message5 |"Message6"|
| Trip3 "| Error" | Stop" | |
---------------------------------------------
*Note that the message itself can span more than 1 line with LFs to display a multi-line message
I have scratch code to write the RTF code for the tables and have substituted fake messages with multiple embedded LFs and the output looks good.
Dim sbTable As New StringBuilder
sbTable.Append("\pard \trowd\trql\trgaph108\trleft36\cellx1636\cellx3236\cellx4836\intbl R1C1\cell R1C2\cell R1C3\cell\row \pard")
sbTable.Append("\pard \trowd\trql\trgaph108\trleft36\cellx4642\intbl R1C1\cell\row \pard")
sbTable.Append("\pard \trowd\trql\trgaph0\trleft36\cellx4642\cellx5500\intbl R1C1\cell R1C2\cell\row \pard")
However I just cant seem to get my head around how to even start this to do it dynamically. It seems like I may need to do two iterations. One to break up the messages into rows and then another to actually write the RTF code.
I have so far pseudo code but need some help with my logic.
dim v as integer = 0 'total width of current row
For each t as TripInfo in myTrips1 and myTrips2
if (t.OutMessageWidth added to v) > 45 then
start new row and append
else
append to current row
endif
Next t
Without knowing the properties of your TripInfo class, I'm going to have to make some assumptions. If any property I assume doesn't exist, you can either create it or modify the code to get the same effect.
Dim t As TripInfo, AllTrips As New List(Of TripInfo)
For Each t In myTrips1
AllTrips.Add(t)
Next
For Each t In myTrips2
AllTrips.Add(t)
Next
If AllTrips.Count > 0 Then
For Each t In AllTrips
Dim NewRow() As String = t.Lines
Dim w As Integer = t.OutMessageWidth
Dim h As Integer = t.Lines.Count
For ItemHeight As Integer = h To 1 Step -1
For Each CompareTrip As TripInfo In AllTrips
If AllTrips.IndexOf(t) <> AllTrips.IndexOf(CompareTrip) _
And CompareTrip.Lines.Count = ItemHeight _
And w + CompareTrip.OutMessageWidth <= 45 Then
w += CompareTrip.OutMessageWidth
For l As Integer = 0 To h -1
NewRow(l) = NewRow(l).PadRight(w) & CompareTrip.Lines(l)
Next
AllTrips.Remove(CompareTrip)
End If
Next
Next
AllTrips.Remove(t)
'Write lines of NewRow to your RTF
Next
End If
I have this text file that I need to parse and put the parsed data in the database
Name Qty1 Qty2 Name Qty1 Qty2
ABC 1 2
BCD 2 3
EFG 7 9 PQR 56 97
DEF 3 18 RET 988 11
I have a table where I need to put the above data
The table structure is like this
Name, Qty1, Qty2,Col
so If I parse from left side then I can put the ABC,1,2, L in the table and if Parse from right side then I can put PQR, 56, 97, R in the same table.
My problem is how can I differentiate between left column and right columns. As soon as I start reading, I can read ABC,1,2 and then I don't know if there is a value in Right column and if I keep reading through my VB.net code then, I will start reading BCD,2,3 and at that point I don't know if BCD belongs to Right Column or left column so I am not sure whether I put L or R in the database. I am trying to parse this file in .net using substring and Indexof. This file is generated from the pdf document. below is the code to read the pdf document:
Public ReadOnly Property getParsedFile() As String
Get
Dim document As New PDFDocument(filePath)
Dim parsedFile As StringBuilder = New StringBuilder()
For i As Integer = 0 To document.Pages.Count - 1
parsedFile.Append(document.Pages(i).GetText())
Next
Return parsedFile.ToString()
End Get
End Property
any help will be greatly appreciated.
below is the answer
Public Function ExtractTextFromPdf(path As String) As String
Dim its As iTextSharp.text.pdf.parser.ITextExtractionStrategy = New iTextSharp.text.pdf.parser.LocationTextExtractionStrategy()
Using reader As New PdfReader(path)
Dim str As New StringBuilder()
For i As Integer = 1 To reader.NumberOfPages
Dim thePage As String = PdfTextExtractor.GetTextFromPage(reader, i, its)
Dim theLines As String() = thePage.Split(ControlChars.Lf)
For Each theLine As String In theLines
str.AppendLine(theLine)
Next
Next
saveTextFileOnComputer(str.ToString())
Return str.ToString()
End Using
End Function
I have an application in VB.Net that displays the results of a math operation to a listbox. For example I have the 1 + 1 = 2.
What I'm trying to do is to have the first 2 numbers (1 and 1) copied to 2 different textboxes when listbox item is selected.
Any help would be greatly appreciated.
Thank you.
My VB.Net is a bit rusty, but something like this should do it:
In the SelectedIndexChanged event put this:
'Make sure that we have a selected item before continuing
If listBox1.SelectedIndex = -1 Then
Return
End If
'Get the text of the selected item
Dim selectedtext As String = listBox1.Items(listBox1.SelectedIndex).ToString()
'Split the item by the + and the = into an array of strings
Dim parts As String() = selectedtext.Split("+"C, "="C)
'If we have more than 2 parts
If parts.Length > 2 Then
'Define a variable for each part
Dim part1 As String = parts(0).Trim()
Dim part2 As String = parts(1).Trim()
'Make text boxes set to part1 and part2. part1 = 1, part2 = 1
End If
I would like to generate a combination of words. For example if I had the following list:
{cat, dog, horse, ape, hen, mouse}
then the result would be n(n-1)/2
cat dog horse ape hen mouse
(cat dog) (dog horse) (horse ape) (ape hen) (hen mouse)
(cat dog horse) (dog horse ape) (horse ape hen) etc
Hope this makes sense...everything I found involves permutations
The list I have would be a 500 long
Try this! :
Public Sub test()
Dim myAnimals As String = "cat dog horse ape hen mouse"
Dim myAnimalCombinations As String() = BuildCombinations(myAnimals)
For Each combination As String In myAnimalCombinations
'Look on the Output Tab for the results!
Console.WriteLine("(" & combination & ")")
Next combination
End Sub
Public Function BuildCombinations(ByVal inputString As String) As String()
'Separate the sentence into useable words.
Dim wordsArray As String() = inputString.Split(" ".ToCharArray)
'A plase to store the results as we build them
Dim returnArray() As String = New String() {""}
'The 'combination level' that we're up to
Dim wordDistance As Integer = 1
'Go through all the combination levels...
For wordDistance = 1 To wordsArray.GetUpperBound(0)
'Go through all the words at this combination level...
For wordIndex As Integer = 0 To wordsArray.GetUpperBound(0) - wordDistance
'Get the first word of this combination level
Dim combination As New System.Text.StringBuilder(wordsArray(wordIndex))
'And all all the remaining words a this combination level
For combinationIndex As Integer = 1 To wordDistance
combination.Append(" " & wordsArray(wordIndex + combinationIndex))
Next combinationIndex
'Add this combination to the results
returnArray(returnArray.GetUpperBound(0)) = combination.ToString
'Add a new row to the results, ready for the next combination
ReDim Preserve returnArray(returnArray.GetUpperBound(0) + 1)
Next wordIndex
Next wordDistance
'Get rid of the last, blank row.
ReDim Preserve returnArray(returnArray.GetUpperBound(0) - 1)
'Return combinations to the calling method.
Return returnArray
End Function
The first function is just something that shows you how to call the second function. It really depends on how you get your 500 list - you can copy and paste it over the animal names, or you can load a file with the words in it. If it doesn't fit on one line you can try:
Dim myAnimals As New StringBulder
myAnimals.Append("dog cat ... animal49 animal50")
myAnimals.Append(" ")
myAnimals.Append("animal51 ... animal99")
myAnimals.Append(" ")
myAnimals.Append("animal100 ... animal150")
etc.
then
Dim myAnimalCombinations As String() = BuildCombinations(myAnimals.ToString)
Say your list is arr = {cat, dog, horse, ape, hen, mouse}
Then you can do:
for i = 0; i < arr.size; i++)
for j = i; j < arr.size; j++)
print i,j;
The idea is basically - for each item, pair it with every other item on the list. However, to avoid the duplication (e.g. 1,2 and 2,1) you don't start the internal loop from the beginning every time but from your current index of the outer loop.