Concat file format not supported - vb.net

Using VB I am trying to create a name for the file by concatenating together the words "NewEmployeesOut" with the short date and time of the day. I am getting the following error System.NotSupportedException: 'The given path's format is not supported.' Below is the Code I am currently using, it seems like VB does not like a character I am using in my concat function when trying to export the .txt file.
Private Sub btnWrite_Click(sender As Object, e As EventArgs) Handles btnWrite.Click
Dim writeRecord As New StreamWriter
(New FileStream("NewEmployeesOut" & Date.Today.ToShortDateString & Date.Now.ToShortTimeString & ".txt", FileMode.Append, FileAccess.Write))
Dim EmployeeInformation1 As New EmployeeInformation()
writeRecord.Write(EmployeeInformation1.LastName & "|")
writeRecord.Write(EmployeeInformation1.FirstName & "|")
writeRecord.Write(EmployeeInformation1.DepartmentNo & "|")
writeRecord.Write(EmployeeInformation1.CreateUserName(EmployeeInformation1.FirstName, EmployeeInformation1.LastName) & "|")
writeRecord.WriteLine(EmployeeInformation1.CreatePassword)
writeRecord.Close()
End Sub

From MS docs https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
The following characters are resevered.
< (less than)
> (greater than)
: (colon)
" (double quote)
/ (forward slash)
\ (backslash)
| (vertical bar or pipe)
? (question mark)
* (asterisk)
A file name formatted as follows will pass muster. The uppercase HH gives you 24 hour time.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim fileName As String = "NewEmployeesOut" & Now.ToString(" MMMM dd, yyyy HH,mm") & ".txt"
Debug.Print(fileName)
File.CreateText(fileName)
End Sub
In the immediate window...
NewEmployeesOut December 10, 2020 18,07.txt

Your short date probably looks like "31/12/2020" or "12/31/2020" which are no valid file names. Try something like
Dim now As DateTime = DateTime.Now
Dim fileName As String = $"NewEmployeesOut_{now:yyyy-MM-dd}_{now:HHmm}.txt"

Concerning the other question: It's the wrong place to post it, don't ask another question within a comment.
I think you have to learn a bit the basics first, read/watch some VB.Net tutorials and maybe some clean-code principles like the clean-code-techniques. Your questions suggest that you don't know yet how to write simple code.
Try to structure what you are doing, avoid (like in your example) to copy 4 times the same lines of code but to create functions instead to encapsulate business logic. e.g. writing a file has nothing to do with assembling a file name, therefore the two things should not be conducted in the same method etc.
But this all said, here an idea how you could structure your code (from the comment not the main question), although I'm not too positive about the usability of the two random digits...
Usage:
Dim fileName As String = GetFileName("Smith", "John")
Methods/Properties:
Private Shared Function GetFileName(lastName As String, firstName As String) As String
lastName = NormalizeAndCrop(lastName, 7)
firstName = NormalizeAndCrop(firstName, 10)
Dim randomNumber As Int32 = Randomizer.Next(0, 100)
Return $"{lastName}{firstName}{randomNumber:00}"
End Function
Private Shared Function NormalizeAndCrop(text As String, length As Int32)
'Check args
If (length < 0) Then Throw New ArgumentOutOfRangeException(NameOf(length), length, "A non-negative value expected!")
If (text Is Nothing) OrElse (length = 0) Then Return String.Empty
text = text.Normalize()
'Copy only valid characters
Dim result As New StringBuilder()
For i As Int32 = 0 To text.Length - 1
Dim c As Char = text(i)
If (IsValidFileNameChar(c)) Then
result.Append(c)
If (result.Length = length) Then
Return result.ToString()
End If
End If
Next
Return result.ToString()
End Function
Private Shared Function IsValidFileNameChar(c As Char) As Boolean
If (Char.IsControl(c)) Then Return False
If (InvalidFileNameChars.IndexOf(c) > -1) Then Return False
Return True
End Function
Private Shared ReadOnly Property Randomizer As Random = New Random(Environment.TickCount)
Private Shared ReadOnly Property InvalidFileNameChars As String = New String(Path.GetInvalidFileNameChars())

Related

Get a specific value from the line in brackets (Visual Studio 2019)

I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.
As an example I have a text file called system.txt which contains single line text. The text is something like this:
[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]
What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box
Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.
Here is what i could write so far but i dont have any idea if there is any logic in my code:
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
For i = 1 To 3
If line.Contains("Last Name=" & i) Then
field.Add(line.Substring(line.IndexOf("=") + 2))
End If
Next
Next
End Sub
Im
You can get this down to a function with a single line of code:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function
But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")
Return File.ReadLines(fileName).
Select(Function(line) exp.Match(line)).
Where(Function(m) m.Success).
Select(Function(m) m.Groups("LastName").Value)
End Function
See a simple example of the expression here:
https://dotnetfiddle.net/gJf3su
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
.Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
.ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()
Using your sample data...
I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.
Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)
Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).
If no match is found, an empty string is returned.
Private Function readcrnFile() As String
Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
For Each s In splits
If s.StartsWith("Last Name=") Then
Return s.Substring(10)
End If
Next
Return ""
End Function
Usage...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = readcrnFile()
End Sub
You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.
Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)
At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array
For Each p As String In parts
If p.StartsWith("Last Name") Then
Dim data = p.Split("="c)
field.Add(data(1))
Exit For
End If
Next
Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry
Dim data = parts(1).Split("="c)
A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.
So, for example, the loop above could be replaced with
field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))
As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string
You should first know the difference between ReadAllLines() and ReadLines().
Then, here's an example using only two simple string manipulation functions, String.IndexOf() and String.Substring():
Sub Main(args As String())
Dim entryMarker As String = "[Last Name="
Dim closingMarker As String = "]"
Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
If Not IsNothing(value) Then
Console.WriteLine("value = " & value)
Else
Console.WriteLine("Entry not found")
End If
Console.Write("Press Enter to Quit...")
Console.ReadKey()
End Sub
Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
Dim entryIndex As Integer
Dim closingIndex As Integer
For Each line In File.ReadLines(fileName)
entryIndex = line.IndexOf(entry) ' see if the marker is in our line
If entryIndex <> -1 Then
closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
If closingIndex <> -1 Then
' calculate the starting position and length of the value after the entry marker
Dim startAt As Integer = entryIndex + entry.Length
Dim length As Integer = closingIndex - startAt
Return line.Substring(startAt, length)
End If
End If
Next
Return Nothing
End Function

Split a string array problems vb.net

I am new to VB.NET and would like to split a string into an array.
I have a string like:
613,710,200,127,127,'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
I want to split this into a array at ",".
I tried:
Dim variable() As String
Dim stext As String
stext = "mystringhere"
variable = Split(stext, ",")
My problem is the part of
'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}',
is split too. I want this to get all together in variable(5). Is this posible?
thank you for help
What you need is a CSV parser in which you can set the field quote character. Unfortunately the TexFieldParser which comes with VB.NET doesn't have that facility. Fortunately, other ones do - here I have used the LumenWorksCsvReader, which is available as a NuGet package *.
Option Strict On
Option Infer On
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Module Module1
Sub Main()
Dim s = "613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL"
Using sr As New StringReader(s)
Using csvReader = New CsvReader(sr, delimiter:=","c, quote:="'"c, escape:="\"c, hasHeaders:=False)
Dim nFields = csvReader.FieldCount
While csvReader.ReadNextRecord()
For i = 0 To nFields - 1
Console.WriteLine(csvReader(i))
Next
End While
End Using
End Using
Console.ReadLine()
End Sub
End Module
which outputs
613
710
200
127
127
{"js":{"":"16","43451":"16","65815":"16","43452":"16","41147":"16","43449":"16","43467":"16","1249":"16","43462":"16","43468":"48","43438":"64","43439":"80"}}
rca
95
2048000
3
1
AABBCCDDEEFFGGHHIIJJKKLL=
xx.xx.xx.xx
NULL
Note that the double-quotes are doubled up in the literal string as that is the way to enter a single double-quote in VB.
If you really want the backslashes to remain, remove the escape:="\"c parameter.
If you are reading from a file then use the appropriate StreamReader instead of the StringReader.
Using the above, perhaps you have a Windows Forms program where you wanted to populate a RichTextBox with the data from, say, a text file named "C:\temp\CsvFile.txt" with the content
613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
614,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','din',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','yy.yy.yy.yy',NULL
615,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','jst',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','zz.zz.zz.zz',NULL
you could use the above to come up with
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Public Class Form1
Public Class Datum
Property A As Integer
Property B As Integer
Property C As Integer
Property D As Integer
Property E As Integer
Property JsonData As String
Property SocketType As String
Property F As Integer
Property G As Integer
Property H As Integer
Property I As Integer
Property Base64Data As String
Property IpAddy As String
Property J As String
Public Overrides Function ToString() As String
Return $"{A}, {SocketType}, {IpAddy}, {B} ,{C}, {D}, {E}, {F}, {G}, {H}, {I}, {JsonData}, {Base64Data}, {J}"
End Function
End Class
Public Function GetData(filename As String) As List(Of Datum)
Dim data As New List(Of Datum)
Using sr As New StreamReader(filename)
Using csvReader = New CsvReader(sr, hasHeaders:=False, delimiter:=","c, quote:="'"c, escape:="\"c, comment:=Nothing, trimmingOptions:=ValueTrimmingOptions.UnquotedOnly)
Dim nFields = csvReader.FieldCount
If nFields <> 14 Then
Throw New MalformedCsvException("Did not find 14 fields in the file " & filename)
End If
While csvReader.ReadNextRecord()
Dim d As New Datum()
d.A = Integer.Parse(csvReader(0))
d.B = Integer.Parse(csvReader(1))
d.C = Integer.Parse(csvReader(2))
d.D = Integer.Parse(csvReader(3))
d.E = Integer.Parse(csvReader(4))
d.JsonData = csvReader(5)
d.SocketType = csvReader(6)
d.F = Integer.Parse(csvReader(7))
d.G = Integer.Parse(csvReader(8))
d.H = Integer.Parse(csvReader(9))
d.I = Integer.Parse(csvReader(10))
d.Base64Data = csvReader(11)
d.IpAddy = csvReader(12)
d.J = csvReader(13)
data.Add(d)
End While
End Using
End Using
Return data
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim srcFile = "C:\temp\CsvData.txt"
Dim dat = GetData(srcFile)
For Each d In dat
RichTextBox1.AppendText(d.ToString() & vbCrLf)
Next
End Sub
End Class
It might be necessary to perform more checks on the data when trying to parse it. Note that I made a function for the .ToString() method of the Datum class and put the properties in a different order just to demonstrate its use.
* Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution... Choose the "Browse" tab -> type in LumenWorksCsvReader -> select the one by Sébastien Lorion et al., -> tick your project name in the pane to the right -> click Install.
I am new to VB.NET and would like to split a string into an array.
...
variable = Split(stext,",")
Instead of
variable = Split(stext,",")
use
variable = stext.split(",")
If you want to get a bit more complicated on your split you would create an array of char data as such
dim data(3) as char
data(0) = ","c
data(1) = vbcrlf
data(2) = chr(34)
data(3) = vbtab
... and so on
variable = stext.split(data)

Replacing character in a text file with comma delimited

I have a comma delimited file with sample values :
1,1076103,22-NOV-16,21051169,50,1083,AAA,TEXT
Question : how to replace the comma in the last column which is "AAA,TEXT"
The result should be this way:
1,1076103,22-NOV-16,21051169,50,1083,AAATEXT
There is an overload of String.Split which takes an argument telling it the maximum number of parts to return. You could use it like this:
Option Infer On
Option Strict On
Module Module1
'TODO: think up a good name for this function
Function X(s As String) As String
Dim nReturnParts = 7
Dim parts = s.Split({","c}, nReturnParts)
If parts.Count < nReturnParts Then
Throw New ArgumentException($"Not enough parts - needs {nReturnParts}.")
End If
parts(nReturnParts - 1) = parts(nReturnParts - 1).Replace(",", "")
Return String.Join(",", parts)
End Function
Sub Main()
Dim s() = {"1,1076103,22-NOV-16,21051169,50,1083,AAA,TEXT",
"1,1076103,22-NOV-16,21051169,50,1083,BBBTEXT",
"1,1076103,22-NOV-16,21051169,50,1083,C,C,C,TEXT"}
For Each a In s
Console.WriteLine(X(a))
Next
Console.ReadLine()
End Sub
End Module
Outputs:
1,1076103,22-NOV-16,21051169,50,1083,AAATEXT
1,1076103,22-NOV-16,21051169,50,1083,BBBTEXT
1,1076103,22-NOV-16,21051169,50,1083,CCCTEXT
Is simple, but learn a bit how to use string ;)
Public Function MDP(strWork As String)
Dim splitted() As String = strWork.Split(","c)
Dim firsts As New List(Of String)
For i As Integer = 0 To splitted.Count - 3
firsts.Add(splitted(i))
Next
Dim result As String = System.String.Join(",", firsts)
Return result & "," & splitted(splitted.Count - 2) & splitted(splitted.Count - 1)
End Function
Then call with:
Dim finished As String = MDP("1,1076103,22-NOV-16,21051169,50,1083,AAA,TEXT")

VB.NET AlphaNumeric into integer

If Textbox1.text contains a string value of ZU4, how can I convert that string to it's numeric ASCII codes, and output it to a second text box?
I'd like to do this using a FOR LOOP conditional statement which will read every character in INPUT?
Sample:
INPUT Textbox1.Text = ZU4
OUTPUT Textbox2.Text = 908552
You could also use LINQ:
TextBox2.Text = String.Join(String.Empty, From c In Textbox1.Text.ToCharArray Select (Asc(c).ToString))
Could be useful on some job interviews... :)
All of the other answers will work with your given example, however, some of the suggestions are using unicode encoding rather than ASCII. If strictly adhering to ASCII encoding is important, then you should explicitly specify the encoding that you want to use.
Convert.ToInt32 uses UTF-16 encoding. I'm not sure what CInt will do, but I suspect it works the same way. Using Asc is better, but it is still dependent on the code page setting for the thread, so it's still not entirely safe. Besides that, Asc is an old VB6 function which is provided in VB.NET, primarily for backwards compatibility.
Therefore, I would recommend using the ASCIIEncoding class instead. You can get an instance of that class using the shared ASCII property of the Encoding class in the System.Text namespace, for instance:
Public Function ConvertTextToAsciiDigits(text As String) As String
Dim builder As New StringBuilder()
For Each b As Byte In Encoding.ASCII.GetBytes(text)
builder.Append(b.ToString())
Next
Return builder.ToString()
End Function
Then, you can call the function like this:
Textbox2.Text = ConvertTextToAsciiDigits(Textbox1.Text)
However, I can't imagine that the resulting string will be usable unless every character results in a two digit number. Therefore, I would force it to be two digits by doing something like this:
Public Function ConvertTextToAsciiDigits(text As String) As String
Dim builder As New StringBuilder()
For Each b As Byte In Encoding.ASCII.GetBytes(text)
If b > 99 then
Throw New FormatException() ' Throws an exception if the value is three digits
End If
builder.Append(b.ToString("00")) ' Adds a leading zero to one-digit values
Next
Return builder.ToString()
End Function
To add a hyphen after every fourth digit, as you mentioned in a comment below, you could just keep track of the total digits added since the last hyphen, like this:
Public Function ConvertTextToAsciiDigits(text As String) As String
Dim builder As New StringBuilder()
Dim digitsSinceHyphen As Integer = 0
For Each b As Byte In Encoding.ASCII.GetBytes(text)
If b > 99 then
Throw New FormatException()
End If
builder.Append(b.ToString("00"))
digitsSinceHyphen += 2
If digitsSinceHyphen >= 4 Then
builder.Append("-")
digitsSinceHyphen = 0
End If
Next
Return builder.ToString()
End Function
Here is one approach, in C#:
Textbox2.Text = string.Empty;
foreach(var c in Textbox1.Text)
{
Textbox2.Text += ((int)c).ToString();
}
VB.NET:
Textbox2.Text = String.Empty
For Each c As Char In Textbox1.Text
Textbox2.Text = Textbox2.Text + Convert.ToInt32(c).ToString()
Next
It:
Clears out Textbox2.Text
Loops over each character in the input
Concatenates the integer value output as a string to the output text
TextBox2.Text = ""
For i As Integer = 0 To TextBox1.TextLength - 1
TextBox2.Text += Asc(TextBox1.Text(i)).ToString()
Next
i modified the code from this Link
Function AsciiEncode(ByVal value As String) As String
Dim encValue As New System.Text.StringBuilder(value.Length * 6)
Dim c As Char
For Each c In value
encValue.Append(Convert.ToInt32(c))
Next
Return encValue.ToString()
End Function
usage:
Private Sub TextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBox1.TextChanged
TextBox2.Text = AsciiEncode(TextBox1.Text)
End Sub

Find Consecutive numbers in an Array

I need to find consecutive numbers in an array and return a string which tells the range and numbers that don't form a range.
I found some of the already asked questions but none of them is in VB.Net:
Add to array consecutive numbers
If the array of numbers looks like {11,12,67,68,69,70,92,97} then returned string should be of the form 11,12, 67 through 70, 92 and 97.
This is not homework; I need this function for a word document containing statistical data.
Entered directly into the reply window, so there's almost certainly a bug or three:
Public Class Range
Public Shared Function PrintRanges(ByVal numbers() As Integer) As String
Dim buffer As New List(Of Range)()
Dim CurrentRange As Range = Nothing
For Each i As Integer in numbers ' you may want to add a .OrderBy() here
If CurrentRange IsNot Nothing AndAlso i - 1 = CurrentRange.EndValue Then
CurrentRange.Increase()
Else
CurrentRange = New Range(i)
buffer.Add(CurrentRange)
End If
Next i
'Got a little lazy for this line - it still does a ", " rather than " and " for the final delimiter. Simple code to fix it, just tedious.
Return String.Join(", ", buffer.Select(Function(r) r.ToString()).ToArray())
End Function
Private Sub New(ByVal InitialValue As Integer)
EndValue = IntialValue
Length = 1
End Sub
'For completeness, these two properties should be made read only outside the class, but the private constructor makes that largely moot
Public Property EndValue As Integer
Public Property Length As Integer
Public Sub Increase()
Length += 1
EndValue += 1
End Sub
Public Overrides Function ToString() As String
If Length == 1 Then Return EndValue.ToString()
If Length == 2 Then Return (EndValue -1).ToString() & "," & LastValue.ToString()
Return (EndValue - Length).ToString() & " through " & EndValue.ToString()
End Function
End Class