I am relatively new to programming, and am starting off with VB.net using Microsoft VB Studio 2019. I usually use Python, and therefore take heavy advantage of the
> If String in("y","yes","YES"):
statement so I don't have to compare the string to every item individually.
I've been trying to do this on Virtual Basic for some time now, but have not even managed to get 1 value to compare to the string to work. I've tried 2 different methods, the first just being a basic String.Contains() command, which I've set out as such:
Dim UserSelection As String
Console.Write("Play again? ")
UserSelection = Console.Read()
If UserSelection.Contains("n") = True Then
UserPlaying = False
End If
My thought process here was that the computer would look at UserSelection, and if it contained the letter 'n' at any point then it would result as being True (eg: if UserSelection = 'no', 'nope', 'n' ext ext) However, every time I've ran this code, the result always comes back as false, no matter what UserSelection is.
I've also tried using the IndexOf command (which makes the search case insensitive) to see if it would work then, but again something seems to be up with it:
Dim UserSelection As String
Console.Write("Play again? ")
UserSelection = Console.Read()
Dim subtxt As String = "n"
Dim comp As StringComparison = StringComparison.OrdinalIgnoreCase
Dim result As Boolean = If(UserSelection.IndexOf(subtxt, comp) > 0, True, False)
If result = True Then
UserPlaying = False
End If
My indentation appears correct in both blocks of code, and I cannot for the life of me figure out what it wrong here.
If someone could help me with this (especially if you could adjust the code so that it could work with multiple comparisons) then that would be more than appreciated.
Thanks so much,
Alfie :)
Console.Read returns an Integer (documentation), so naturally it would return false. The method you're looking for is Console.ReadLine (documentation), which returns a string.
Take a look at this example:
Console.Write("Play again? ")
Dim input = Console.ReadLine()
Dim stopPlaying = input.IndexOf("n", StringComparison.OrdinalIgnoreCase) > -1
If (stopPlaying) Then
' the user replied with "n", "no", "nope", etc.
Else
' the user replied with something that did not contain the letter "n"
End If
Fiddle: https://dotnetfiddle.net/Fihq02
I just added .ToLower to the UserSelection string before the Contains so N or n would be recognized.
Private UserPlaying As Boolean
Sub Main()
Console.Write("Play again? ")
Dim UserSelection = Console.ReadLine()
If UserSelection.ToLower.Contains("n") = True Then
Debug.Print("It contains n")
UserPlaying = False
Else
Debug.Print("No n")
UserPlaying = True
End If
Console.ReadKey()
End Sub
Related
I want to do a date comparison to check whether is the Before Period is bigger than After Periode
So far it has been working properly until the date range is a bit tricky
For example
The value is from a dropdownlist item
Before period is 21-10-2022
After period is 04-11-2022
It will trigger the error message I set if the before period is bigger than the period after
I have a code like this
If CDate(ddlPeriodeBefore.SelectedValue) <= CDate(ddlPeriodeBefore.SelectedValue) Then
'Does the job if the the before period is smaller than after period
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
Can anyone help me? it keeps saying "conversion from string to date is not valid"
I've tried datetime.parse, parse exact, cdate, convert.todatetime but nothing works so far, or maybe I used it the wrong way
Please help, thanks in advance
Tim Schmelter's suggestion is not wrong, but I did want to provide an alternative. Create a collection of Tuple, add the dates (both formatted string and native value) to the collection, then bind the control to the list.
Here is the alternative:
Dim dates As New List(Of Tuple(Of String, DateTime))()
Dim today = DateTime.Today
For daysSubtract = 90 To 0 Step -1
Dim dateToAdd = today.AddDays(-daysSubtract)
dates.Add(New Tuple(Of String, DateTime)(dateToAdd.ToString("dd-MM-yyyy"), dateToAdd))
Next
ddlPeriodeBefore.ValueMember = "Item1"
ddlPeriodeBefore.DisplayMember = "Item2"
ddlPeriodeBefore.DataSource = dates
ddlPeriodeAfter.ValueMember = "Item1"
ddlPeriodeAfter.DisplayMember = "Item2"
ddlPeriodeAfter.DataSource = dates
Now when you go to get the selected value, you can use a simpler conversion since the stored object is already a DateTime:
Dim beforePeriod = DirectCast(ddlPeriodeBefore.SelectedValue, DateTime)
Dim afterPeriod = DirectCast(ddlPeriodeAfter.SelectedValue, DateTime)
If (beforePeriod <= afterPeriod) Then
' ...
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
The advantage to this approach is that you do not have to refactor your code if the date formatting changes.
If DateTime.Parse works depends on your curren culture because you don't pass any. For me this works fine (but for you not):
Dim selectedValue1 = "21-10-2022"
Dim selectedValue2 = "04-11-2022"
Dim beforePeriod = Date.Parse(selectedValue1)
Dim afterPeriod = Date.Parse(selectedValue2)
So either you know the correct culture that you have used when you have created this string, then you can pass this as second parameter to Date.Parse, or you use ParseExact:
Dim beforePeriod = Date.ParseExact(selectedValue1, "dd-MM-yyyy", CultureInfo.InvariantCulture)
Dim afterPeriod = Date.ParseExact(selectedValue2, "dd-MM-yyyy", CultureInfo.InvariantCulture)
The culture is relevant because they can have different date separators and the order of the day-, month- and year-tokens are different.
I'm having trouble converting a String to Integer in VB.net
I tried the following, but it wont quite work:
Code:
1:
Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged
My.Settings.ydelay = Convert.ToInt32(TextBox3.Text)
End Sub
2:
My.Settings.ydelay = Textbox3.Text
My.Settings.ydelay = Convert.ToInt32(Textbox3.Text)
3:
My.Settings.ydelay = Convert.ToInt32(Textbox.3Text)
My.Settings.ydelay = Textbox3.Text
4:
My.Settings.ydelay = Textbox3.Text
Convert.ToInt32(Textbox3.Text, My.Settings.ydelay)
I am pretty much going crazy over this maybe im just missing a little detail but I cant figure it out. Help would really be appreciated if you need more details let me know.
First, make sure that your ydelay setting in project properties is set to Scope User because Application scope is Read Only. Then double check the datatype is Integer.
You will not see the changes in Project Properties. They are stored in User.config. Location: C:\Users\[User Name]\AppData\Local\TestCode2\TestCode2.exe_Url_aq2yohztn2r23tmvf0pbczm25mx0yx11\1.0.0.0 for my project which is named TestCode2.
Lo and behold...
<setting name="ydelay" serializeAs="String">
<value>1</value>
</setting>
If you were to go to another computer the setting for ydelay would be the initial value as shown in the Project Properties. This makes sense because it is a "User" setting and each user will have there own setting.
As to the code. I don't like the TextChanged event. It fires every time a key is pressed; that includes backspace. Maybe Leave will work for you.
.TryParse is a good way to check input. It does double duty by setting a variable and returning a boolean so it fits right into an If statement.
Private Sub TextBox16_Leave(sender As Object, e As EventArgs) Handles TextBox16.Leave
Dim i As Integer
If Integer.TryParse(TextBox16.Text, i) Then
My.Settings.ydelay = i
Else
MessageBox.Show("Please enter a number in TextBox 16")
TextBox16.Select() 'If you want to insist
End If
End Sub
You want to convert string to integer. Check if you input is just a number.
is use this code on textbox keypress
If (e.KeyChar <= ChrW(47)) Or (e.KeyChar >= ChrW(58)) Then
If e.KeyChar = vbBack Then
Else
e.KeyChar = ChrW(0)
End If
Else
End If
If sender.text = "" Then
sender.text = 0
End If
after that i just use Cint(textboxt.text)
This is for VB.NET 2017. I am creating a program and keeping score with the best time. The timer in the program runs like a stopwatch. I would like at the end to compare the best record from a past game with the current time of a new game. If the new game has a faster time then I would like to replace it on the data file. I can do that just fine but sometimes it will put a slower time ahead of the fastest time. I have tried multiple scenarios and cannot get it consistent. If anyone could help that would be appreciated very much. I have some message boxes so I can see some outcomes. They will be commented out later when it is working properly.
If TotalBalls = 2 And SelectPoison = 2 Then
tmrTime.Enabled = False
CurrentScore = lblTime.Text
MsgBox("You win.")
'''''''''''''''''''''''''''''''''''''''''''''''''''
' CurrentScore = lblTime.Text
MsgBox("Current Time is " & CurrentScore)
NewScoreCheck = String.Compare(CurrentScore, RecordHighScore)
MsgBox(NEwScoreCheck)
'NewScoreCheck will be less than 0 if CurrentScore is less (alphabetically) than RecordhighScore
'NewScoreCheck will be greater than 0 if RecordHighSchore is greater than CurrentScore
If NewScoreCheck < 0 Then
MsgBox(CurrentScore)
Try
MsgBox("In the try statement. Writing new time")
Dim FileWrite As System.IO.StreamWriter
FileWrite = New System.IO.StreamWriter("PoisonHighScore.TXT", False)
FileWrite.WriteLine(CurrentScore)
FileWrite.Close()
Catch
MsgBox("Saving error")
End Try
Else
MsgBox("Not the fastest time.")
End If
Else
MsgBox("You lose.")
End If
strExit = MsgBox("Do you want to play again?", vbYesNo)
If strExit = vbYes Then
Application.Restart()
End If
End Sub
Edit 1: I am using some variables as TimeSpan which is why I have the values CurrentScore and RecordHighScore as Strings. When I am using TimeSpan it will not store as an Integer and will return an error. I am looking for a way to compare two times but need to store them in such a way that they can be compared which is why I used the compare string method mentioned above. I understand after looking at the solution below as to why I cannot. My question now becomes how do I store them since it cannot be stored as double, single, or integer?
To make it a little more clear think of two racers who finish with two different times and those times being unpredictable. The fastest time would win and we would write to the text file (which I know how to do) the time of the winner.
P.S. I have also tried the CInt(CurrentScore) < CInt(RecordHighScore) but that just returns an error too. Any help again would be greatly appreciated and thank you for taking the time to help me with this.
Right off the bat it looks like you're doing some implicit type conversions such as:
CurrentScore = lblTime.Text
Presumably CurrentScore is a numeric data type (like an Integer or Double), but you're setting the value equal to a String. To correct those errors, turn Option Strict on. Looking even deeper, this appears to be your problem because you use the String.Compare method to compare the scores alphabetically. To give you an example, String.Compare returns -1 when you pass 1112 and 121 as your current score and high score respectively, but obviously 121 is quicker than 1112.
What you need to do is convert all numeric values as numeric data types and then compare them using the appropriate comparison operator.
If you want the Timer to behave like a stopwatch then why not use a StopWatch? If you use a StopWatch, you can get the ElapsedMilliseconds which returns a long. The Stop method only pauses the timer; you need to call the Reset method to reset the StopWatch to zero. Call this after you collect the ElapseMilliseconds into a variable.
NewScoreCheck = String.Compare(CurrentScore, RecordHighScore) Strings are not compared in the same way numbers are.
Dim a As String = "72"
Dim b As String = "100"
If String.Compare(a, b) < 0 Then
MessageBox.Show("a comes first")
Else
MessageBox.Show("b comes First")
End If
Result b comes first!
Using a MsgBox to check values is not a great idea. Visual Studio has all sorts of great debugging tools. Inevidibly you will forget to remove a MsgBox; I have :-). Use Debug.Print which will not be in the release version.
Dim sw As New Stopwatch()
Private Sub BeginGame()
sw.Start()
End Sub
Private Sub OPCode2()
Dim TimeInMilliseconds As Long = sw.ElapsedMilliseconds
Dim TotalBalls As Integer = 2
Dim SelectPoison As Integer = 2
Dim RecordHighScore As Long
Dim CurrentScore As Long
If TotalBalls = 2 And SelectPoison = 2 Then
sw.Stop()
CurrentScore = sw.ElapsedMilliseconds
sw.Reset() 'So you can play again and get a new time
MsgBox("You win.")
'''''''''''''''''''''''''''''''''''''''''''''''''''
Debug.Print($"Current Time is {CurrentScore}")
If CurrentScore > RecordHighScore Then
Try
Debug.Print("In the try statement. Writing new time")
Dim FileWrite As System.IO.StreamWriter
FileWrite = New System.IO.StreamWriter("PoisonHighScore.TXT", False)
FileWrite.WriteLine(CurrentScore.ToString)
FileWrite.Close()
Catch
MsgBox("Saving error")
End Try
Else
MsgBox("Not the fastest time.")
End If
Else
MsgBox("You lose.")
End If
Dim strExit As MsgBoxResult
strExit = MsgBox("Do you want to play again?", vbYesNo)
If strExit = vbYes Then
'Not a good way to do this, clear your variables and UI
Application.Restart()
End If
End Sub
I have a code which asks for an input between 1-3 using an InputBox which then runs a code depending on what input it is given. The problem i have is that i don't need that InputBox anymore, as the work i intend to do only uses one input which is 3.I tried removing the input box and just inserting 3 there but then the code doesnt do anything. I then tried to insert a default value in the box, but it still appears and needs me to click enter which is what i am trying to avoid. Pls how should i go about this problem.
My Code
Function GetTypeFile() As Integer
Dim strInput As String, strMsg As String
Dim Default
choice = 0
While (choice < 1 Or choice > 3)
Default = "3"
strMsg = "Type in the kind of entities to create (1 for points, 2 for points and splines, 3 for points, splines and loft):"
strInput = InputBox(Prompt:=strMsg, _
Title:="User Info", Default:=3, XPos:=2000, YPos:=2000)
'Validation of the choice
choice = CInt(strInput)
If (choice < 1 Or choice > 3) Then
MsgBox "Invalid value: must be 1, 2 or 3"
End If
Wend
GetTypeFile = choice
End Function
Your function returns the value to wherever it's called, so you could just use:
Function GetTypeFile() As Integer
GetTypeFile = 3
End Function
or just replace any calls to the function with the number 3.
So rather than something like:
Sub Test()
ThisWorkbook.SaveAs "MyFileName", GetTypeFile
End Sub
You'd have:
Sub Test()
ThisWorkbook.SaveAs "MyFileName", 3
End
Thank you all for your reply. I just understood what to do, by setting the variable which is dependent on the value in the inputbox to 3 instead of it being TypeDocument=GetTypeFile it is now TypeDocument=3 directly..I think that is what you all had been trying to say all the while. Thank you again.
Code works fine when on the active sheet, but when it attempts to use the same code from another sheet, loops infinitely.
I forced a break, and checked the values in the immediate window.
? colRAE.count
187433
? cmbNumberOfRuns
3
? colRAE.count < cmbNumberOfRuns
True
My while loop is based on that last part, and seems to be the reason why the loop continues.
Can anyone explain this?
My only guess is that you're doing a string comparison. If cmbNumberOfRuns is a ComboBox, you're getting the default property by calling it like that - .Text. If colRAE.Count is being interpreted as a String, you'll get the result shown in your question:
Sub TextCompare()
Dim cmbNumberOfRuns As String
Dim colRAE As String
cmbNumberOfRuns = "3"
colRAE = "187433"
Debug.Print colRAE < cmbNumberOfRuns
End Sub
I'd recommend explicitly calling the property of cmbNumberOfRuns (both for readability and to avoid repeats of this issue), and explicitly casting to a Long for numerical comparisons:
Debug.Print colRAE.Count < CLng(cmbNumberOfRuns.Text)