Count lines before specified string of Text File? In VB - vb.net

is there a way to count the amount of lines before a specific line / string in a text file.
For Example:
1
2
3
4
5
6
7
8
9
Say i want to count the amount of line before '8'...
How would i do that?
thanks!

Hope that this actually you are looking for,
it will read all lines from a file specified. then find the IndexOf particular line(searchText) then add 1 to it will gives you the required count since index is0based.
Dim lines = File.ReadAllLines("f:\sample.txt")
Dim searchText As String = "8"
msgbox(Array.IndexOf(lines, searchText) + 1)

Here's another example using List.FindIndex(), which allows you to pass in a Predicate(T) to define how to make a match:
Dim fileName As String = "C:\Users\mikes\Documents\SomeFile.txt"
Dim lines As New List(Of String)(File.ReadAllLines(fileName))
Dim index As Integer = lines.FindIndex(Function(x) x.Equals("8"))
MessageBox.Show(index)
In the example above, we're looking for an exact match with "8", but you can make the predicate match whatever you like for more complex scenarios. Just make the function (the predicate) return True for what you want to be a match.
For example, a line containing "magic":
Function(x) x.ToLower().Contains("magic")
or a line that begins with a "FirstStep":
Function(x) x.StartsWith("FirstStep")
The predicate doesn't have to be a simple string function, it can be as complex as you like. Here's one that will find a string that ends with "UnicornFarts", but only on Wednesday and if Notepad is currently open:
Function(x) DateTime.Today.DayOfWeek = DayOfWeek.Wednesday AndAlso Process.GetProcessesByName("notepad").Length > 0 AndAlso x.EndsWith("UnicornFarts")
You get the idea...
Using a List, instead of an Array, is good for situations when you need to delete and/or insert lines into the contents before writing them back out to the file.

Related

Refined list sorting by substring integer after alphabetical sorting

I have some information in a list (called listLines). Each line below is in a List(Of String).
1|This is just a header
3|This is just a footer
2|3456789|0000000|12312312313|BLUE|1|35.00
2|7891230|0000000|45645645655|BLUE|1|22.00
2|7891230|0000000|45645645658|RED|2|13.00
2|3456789|0000000|12312312316|RED|2|45.00
2|3456789|0000000|12312312317|YELLOW|5|-9.00
2|3456789|0000000|12312312315|ORANGE|3|15.00
2|7891230|0000000|45645645659|YELLOW|5|32.00
2|3456789|0000000|12312312314|GREEN|4|-20.00
2|7891230|0000000|45645645656|GREEN|4|39.00
2|7891230|0000000|45645645657|ORANGE|3|-18.50
I'm doing a listLines.sort() on the list to sort it alphabetically. Below is what I get after the .sort().
1|This is just a header
2|3456789|0000000|12312312313|BLUE|1|35.00
2|3456789|0000000|12312312314|GREEN|4|-20.00
2|3456789|0000000|12312312315|ORANGE|3|15.00
2|3456789|0000000|12312312316|RED|2|45.00
2|3456789|0000000|12312312317|YELLOW|5|-9.00
2|7891230|0000000|45645645655|BLUE|1|22.00
2|7891230|0000000|45645645656|GREEN|4|39.00
2|7891230|0000000|45645645657|ORANGE|3|-18.50
2|7891230|0000000|45645645658|RED|2|13.00
2|7891230|0000000|45645645659|YELLOW|5|32.00
3|This is just a footer
With that said, I need to output this information to a file. I'm able to do this ok. I still have a problem though. There is a sequence number in the above data at position 5 just after the listed colors (RED, BLUE, ETC..) that you can see. It's just before the last value which is a decimal type.
I need to further sort this list, keeping it in alphabetical order since position 2 is an account number and I want to keep the account numbers grouped together. I just want them to be resorted in sequential order based on the sequence number.
I was looking at another thread trying to figure out how I can do this. I found a piece of code like listLines.OrderBy(Function(q) q.Substring(35)).ToArray. I think this would probably help me if this was a fixed length file, it isn't however. I was thinking I can do some kind of .split() to get the 5th piece of information and sort it but then it's going to unalphabetize and mix the lines back up because I don't know how to specify to still keep it alphabetical.
Right now I'm outputting my alphabetical list like below so I can format it with commas and double quotes.
For Each listLine As String In listLines
strPosition = Split(listLine, "|")
Dim i As Integer = 1
Dim iBound As Integer = UBound(strPosition)
Do While (i <= iBound)
strOutputText = strOutputText & Chr(34) & strPosition(i) & Chr(34) & ","
i += 1
Loop
My main question is how do I re-sort after .sort() to then get each account (position1) in sequential order (position 5)? OR EVEN BETTER, how can I do both at the same time?
The List(Of T) class has an overload of the Sort method that takes a Comparison(Of T) delegate. I would suggest that you use that. It allows you to write a method or lambda expression that will take two items and compare them any way you want. In this case, you could do that like this:
Dim items = New List(Of String) From {"1|This Is just a header",
"3|This Is just a footer",
"2|3456789|0000000|12312312313|BLUE|1|35.00",
"2|7891230|0000000|45645645655|BLUE|1|22.00",
"2|7891230|0000000|45645645658|RED|2|13.00",
"2|3456789|0000000|12312312316|RED|2|45.00",
"2|3456789|0000000|12312312317|YELLOW|5|-9.00",
"2|3456789|0000000|12312312315|ORANGE|3|15.00",
"2|7891230|0000000|45645645659|YELLOW|5|32.00",
"2|3456789|0000000|12312312314|GREEN|4|-20.00",
"2|7891230|0000000|45645645656|GREEN|4|39.00",
"2|7891230|0000000|45645645657|ORANGE|3|-18.50"}
items.Sort(Function(x, y)
Dim xParts = x.Split("|"c)
Dim yParts = y.Split("|"c)
'Compare by the first column first.
Dim result = xParts(0).CompareTo(yParts(0))
If result = 0 Then
'Compare by the second column next.
result = xParts(1).CompareTo(yParts(1))
End If
If result = 0 Then
'Compare by the sixth column last.
result = xParts(5).CompareTo(yParts(5))
End If
Return result
End Function)
For Each item In items
Console.WriteLine(item)
Next
If you prefer a named method then do this:
Private Function CompareItems(x As String, y As String) As Integer
Dim xParts = x.Split("|"c)
Dim yParts = y.Split("|"c)
'Compare by the first column first.
Dim result = xParts(0).CompareTo(yParts(0))
If result = 0 Then
'Compare by the second column next.
result = xParts(1).CompareTo(yParts(1))
End If
If result = 0 Then
'Compare by the sixth column last.
result = xParts(5).CompareTo(yParts(5))
End If
Return result
End Function
and this:
items.Sort(AddressOf CompareItems)
Just note that this is rather inefficient because it splits both items on each comparison. That's not a big deal for a small list but, if there were a lot of items, it would be better to split each item once and then sort based on those results.

Get the nth character, string, or number after delimiter in Visual Basic

In VB.net (Visual Studio 2015) how can I get the nth string (or number) in a comma-separated list?Say I have a comma-separated list of numbers like so:13,1,6,7,2,12,9,3,5,11,4,8,10How can I get, say, the 5th value in this string, in this case 12?I've looked at the Split function, but it converts a string into an array. I guess I could do that and then get the 5th element of that array, but that seems like a lot to go through just to get the 5th element. Is there a more direct way to do this, or am I pretty much limited to the Split function?
In case you are looking for an alternative method, which is more basic, you can try this:
Module Module1
Sub Main()
Dim a As String = "13,1,6,7,2,12,9,3,5,11,4,8,10"
Dim counter As Integer = 5 'the number you want (in this case, 5th one)
Dim movingcounter As Integer = 0 'how many times we have moved
Dim startofnumber, endofnumber, i As Integer
Dim numberthatIwant As String
Do Until movingcounter = counter
startofnumber = InStr(i + 1, a, ",")
i = startofnumber
movingcounter = movingcounter + 1
Loop
endofnumber = InStr(startofnumber + 1, a, ",")
numberthatIwant = (Mid(a, startofnumber + 1, endofnumber - startofnumber - 1))
Console.WriteLine("The number that I want: " + numberthatIwant)
Console.ReadLine()
End Sub
End Module
Edit: You can make this into a procedure or function if you wish to use it in a larger program, but this code run in console mode will give the output of 12.
The solution provided by Plutonix as a comment to my question is straightforward and exactly what I was looking for, to wit:result = csv.Split(","c)(5)In my case I was incrementing a variable each time my program ran and needed to get the nth character or string after the incremented value. That is, if my program had incremented the variable 5 times, then I needed the string after the 4th comma, which of course, is the 5th string. So my solution was something like this:result = WholeString.Split(","c)(IncrementedVariable)Note that this is a zero-based variable.Thanks, Plutonix.

Get text between \ and \PARTS from file name string vb.net

I need to obtain a value of everything between \ & \PARTS
Example:
`XamoutOFdirectorys\THIS IS WHAT I WANT\PARTS`
resulting in the text, THIS IS WHAT I WANT
in dir1\dir2\THIS IS WHAT I WANT\PARTS
I want the text THIS IS WHAT I WANT and not dir2\THIS IS WHAT I WANT
How can I achive that?
The reason is that I need to know what the files name is that is found before the PARTS directory, regardless of howmany directorys are found before and after...
the closest i can achive is ...
Dim text As String = "fat\dir1\dir2\PARTS\bat"
Dim str As String = text.Split("\"c, "\PARTS"c)(1)
MsgBox(str)
Dim str As String = "fat\dir1\dir2\PARTS\bat"
Dim dir As Match = Regex.Match(str, "\\([A-Za-z0-9\-]+)\\PARTS")
MsgBox(dir.Groups(1).ToString)
Try this
It should return an array with each text between "\". Then you can search for the text "PARTS" and take the previous index.
Split -> [dir1, dir2, your text, PARTS]
index of PARTS = 3
index of your text = 2
I don't really know vb.net but that's how I would do it with any other language.
If your path variable type is String. You can find "\PARTS" in path, get the start index A in path. Then find another index B of last "\" before A. Using substring function to get what you want between range [B, A] in path variable:
Dim str As String = "fat\dir1\XamoutOFdirectorys\_THIS IS WHAT I WANT\PARTS\bat"
Dim beginIdx, endIdx As Integer
endIdx = str.LastIndexOf("\PARTS") - 1
beginIdx = str.LastIndexOf("\", endIdx - 1) + 1
Dim result = str.Substring(beginIdx, endIdx - beginIdx + 1)
By the way, there are more elegant methods such as regular expression. But I really advice you should read MSDN about String, dirt your hand, get the solution by yourself. There are also many solution about "split path" in Stack Overflow that you can change them after you understand the solution. Best regards.
regular expression like this:
Dim str As String = "fat\dir1\XamoutOFdirectorys\_THIS IS REALLY WHAT YOU WANT.&%+\PARTS"
Dim dir As Match = Regex.Match(str, "\\([^\\]+)\\PARTS")
MsgBox(dir.Groups(1).ToString)
Which can work in real world and support all possible path versions(tested in windows system).
And the state machine illustration of my regular expression
\\([^\\]+)\\PARTS
[Debuggex Demo](https://www.debuggex.com/r/rYms5zrhWCby_FdP

Get the line number of a mutiline textbox that contains a string

For example, if a mutiline textbox has the string "apple" in one of the lines how do I get the line number?
You can use Array.IndexOf:
Dim indexOfText = Array.IndexOf(textBox1.Lines, "apple")
If you want to find a string which can be a part of the line, also searching case-insensitive:
indexOfText = Array.FindIndex(textBox1.Lines, Function(str) str.IndexOf("apple", StringComparison.InvariantCultureIgnoreCase) >= 0)
Since indices are zero based you need to add 1 if you want the line number(in case the index isn't -1).
Another option is to use a RichTextBox which has a GetLineFromCharIndex method which you can use the .Text.IndexOf method to get the index.

Replacing nth occurrence of string

This should be fairly simple but I'm having one of those days. Can anyone advise me as to how to replace the first and third occurrence of a character within a string? I have looked at replace but that cannot work as the string could be of different lengths. All I want to do is replace the first and third occurrence.
There is an overload of the IndexOf method which takes a start position as a parameter. Using a loop you'll be able to find the position of the first and third occurences. Then you could use a combination of the Remove and Insert methods to do the replacements.
You could also use a StringBuilder to do the replacements. The StringBuilder has a Replace method for which you can specify a start index and a number of characters affected.
aspiringCoder,
Perhaps something like this might be useful to you (in line with what Meta-Knight was talking about <+1>)
Dim str As String = "this is a test this is a test this is a test"
Dim first As Integer
Dim third As Integer
Dim base As Integer = 0
Dim i As Integer
While str.length > 0
If i = 0 Then
first = str.IndexOf("test")
else if i = 2 Then
third = base + str.IndexOf("test")
end if
base = base + str.IndexOf("test")
str = str.Remove(0, str.IndexOf("test") + "test".length -1 )
i++
End While
It might have a one-off error somewhere...but this should at least get you started.