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)
Related
The current function I use to collect text InputBox can't accept more than 255 characters apparently, and I need to be able to collect more than that? Is there a parameter or different function I can use to increase this limit?
To be pedantic, the Inputbox will let you type up to 255 characters, but it will only return 254 characters.
Beyond that, yes, you'll need to create a simple form with a textbox. Then just make a little "helper function" something like:
Function getBigInput(prompt As String) As String
frmBigInputBox.Caption = prompt
frmBigInputBox.Show
getBigInput = frmBigInputBox.txtStuff.Text
End Function
or something like that...
Thanks BradC for the info that. My final code was roughly as follows, I have a button that calls the form that I created and positions it a bit as I was having some issues with the form being in the wrong spot the everytime after the first time I used.
Sub InsertNotesAttempt()
NoteEntryForm.Show
With NoteEntryForm
.Top = 125
.Left = 125
End With
End Sub
The userform was a TextBox and two CommandButtons(Cancel and Ok). The code for the buttons was as follows:
Private Sub CancelButton_Click()
Unload NoteEntryForm
End Sub
Private Sub OkButton_Click()
Dim UserNotes As String
UserNotes = NotesInput.Text
Application.ScreenUpdating = False
If UserNotes = "" Then
NoteEntryForm.Hide
Exit Sub
End If
Worksheets("Notes").ListObjects("Notes").ListRows.Add (1)
Worksheets("Notes").Range("Notes").Cells(1, 1) = Date
Worksheets("Notes").Range("Notes").Cells(1, 2) = UserNotes
Worksheets("Notes").Range("Notes").Cells(1, 2).WrapText = True
' Crap fix to get the wrap to work. I noticed that after I inserted another row the previous rows
' word wrap property would kick in. So I just add in and delete a row to force that behaviour.
Worksheets("Notes").ListObjects("Notes").ListRows.Add (1)
Worksheets("Notes").Range("Notes").Item(1).Delete
NotesInput.Text = vbNullString
NotesInput.SetFocus ' Retains focus on text entry box instead of command button.
NoteEntryForm.Hide
Application.ScreenUpdating = True
End Sub
I don't have enough rep to comment, but in the sub form_load for the helper you can add:
me.AutoCenter = True
Outside of that form, you can do it like this:
NoteEntryForm.Show
Forms("NoteEntryForm").AutoCenter = True
My Access forms get all confused when I go from my two extra monitors at work to my one extra monitor at home, and are sometimes lost in the corner. This AutoCenter has made it into the form properties of every one of my forms.
I'm having a class module with some data:
Private sharedFolders() As String
Public Property Let SetSharedFolders(val As String)
Dim i As Integer
sharedFolders = Array("folder one", "folder two")
i = UBound(sharedFolders)
i = UBound(sharedFolders)
ReDim Preserve sharedFolders(i)
sharedFolders(i) = CStr(val)
End Property
Property Get GetSharedFolders()
GetSharedFolders = sharedFolders()
End Property
And I want to add something to this property from other module like this:
Sub PrepareData()
Dim e
Dim s
Dim a(2) As String
Set e = New Entry
a(0) = "add one"
a(1) = "add two"
For Each s In a
e.SetSharedFolders (s) 'Here comes exception
Next
For Each s In e.GetSharedFolders
Debug.Print s
Next
End Sub
But I receive an "wrong number of arguments or invalid property assignment vba" exception... Can anyone assist?
Addendum
Thanks to #AJD and #Freeflow to pointing out a mistake and idea to make it easier. Decided to make as like below.
Class Module:
Private sharedFolders As New Collection
Public Property Let SetSharedFolders(val As String)
If sharedFolders.Count = 0 Then ' if empty fill with some preset data and add new item
sharedFolders.Add "folder 1"
sharedFolders.Add "folder 2"
sharedFolders.Add CStr(val)
Else
sharedFolders.Add CStr(val)
End If
End Property
Property Get GetSharedFolders() As Collection
Set GetSharedFolders = sharedFolders
End Property
and regular module:
Sub AddData()
Dim e As New Entry ' creating an instance of a class
Dim s As Variant ' variable to loop through collection
Dim a(1) As String 'some array with data to insert
a(0) = "add one"
a(1) = "add two"
For Each s In a
e.SetSharedFolders = s
Next
For Each s In e.GetSharedFolders
Debug.Print s
Next
End Sub
Initially I thought the problem lies in this code:
i = UBound(sharedFolders)
i = UBound(sharedFolders)
ReDim Preserve sharedFolders(i)
sharedFolders(i) = CStr(val)
i is set twice to the same value, and then the sharedFolders is reDimmed to the same value it was before! Also, there is some trickery happening with the use of ix within a 0-based array.
But the problem is most likely how you have declared your variables.
For Each s In a
e.SetSharedFolders (s) 'Here comes exception
Next
s is a Variant, and a is a Variant. At this point VBA is trying to guess how to handle a For Each loop with two Variants. And then the improper call is made. The correct syntax is:
e.SetSharedFolders s '<-- no parenthesis
There are plenty of posts on StackOverflow explaining how to call routines and what the impact of the evaluating parenthesis are!
However, at this point we are only assuming it is passing in a single element of the array - it could be passing the full array itself (albeit unlikely).
And the third factor -
Public Property Let SetSharedFolders(val As String)
The parameter val is being passed ByRef and should be passed ByVal. This also has unintended side effects as I found out (Type mismatch trying to set data in an object in a collection).
Public Property Let SetSharedFolders(ByVal val As String)
All in all you have the perfect storm of ambiguity driving to an unknown result.
The answer here is to strongly type your variables. This removes about two layers of ambiguity and areas where errors can happen. In addition, this will slightly improve code execution.
Another aspect is to understand when you should pass something ByVal and when to use the default (preferably explicitly) ByRef.
And a final gratuitous hint: Use a Collection instead of an Array. Your code you have implies a Collection will be more efficient and easier to manage.
Addendum
(thanks to #FreeFlow):
If the OP changes the definition of sharedfolders to Variant rather than String() then the array statement will work as expected.
The line e.SetSharedFolders (s) will work fine if it is changed to e.SetSharedFolders = s because the method SetSharedFolders is a Let Property not a Sub. There are other errors but these two changes will make the code run.
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
The last week I asked how to solve an error in an evaluate statement (Error in Evaluate statement macro).
Once fix it, I have other error with the same evaluate statement, it doesn't give me any value.
I will describe what I have and what I try.
#DbLookup in Calculate Text
I have this code into in an calculate Text and it works fine.
suc := #Trim(#Left(LlcPoliza;2));
_lkp := _lkp := #DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D"+suc; "FullName");
#If( #IsError( _lkp ) ; " " ; _lkp );
#Name([CN];_lkp)
LlcPoliza is a document field (doc.LlcPoliza) and in a document it has for example the value C2H2H2.
The formula give first the value C2 and then look up into People2 who is D+C2 and give me a person.
It works fine.
Evaluate Statement (#DbLookup) in a Class
I have a class DirectorSucursal.
Class DirectorSucursal
Private m_branch As String
'Constructor class
Public Sub New (branch)
Dim subString As String
subString = Left(branch, 2)
me.m_branch = subString
End Sub
'Deleter Class
Public Sub Delete
End Sub
'Sub show the code about Suc
Public Sub GetCodSuc
MsgBox m_branch
End Sub
'Function get the name director
Public Function getNameDirector As String
Dim varResult As Variant
varResult = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & m_branch & {"; "FullName)"})
getNameDirector = CStr( varResult(0) )
End Function
End Class
Then, in a button I instantiate the new object DirectorSucursal with the parameter of the field doc.LlcPoliza(0) like this.
Sub Click(Source As Button)
Dim director As New DirectorSucursal(doc.LlcPoliza(0))
director.GetCodSuc
director.getNameDirector
end Sub
The field doc.LlcPoliza(0) has the value C2H2H2. GetCodSuc show the value C2, but the function getNameDirector doesn't work.
It shows the error:
Operation failed
Evaluate Statement (#DbLookup) in click button
I have tried the same but into a click sub.
Sub Click(Source As Button)
Dim subString As String
subString = Left(doc.LlcPoliza(0), 2)
Dim eval As String
eval = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & subString & {"; "FullName)"})
Msgbox eval
End Sub
The field doc.LlcPoliza(0) has the value C2H2H2. But it doesn't work
It shows the error:
Operation failed
My question is: what am i doing wrong? Why the code works fine in a calculate text with #Formula but with Lotusscript not?
Thanks.
EDIT 1:
I have added and Error Goto, modified the class code, modified #dblookup in calculate text and I have this error:
Error in EVALUATE macro
Please read documentation and use help! evaluate always returns an ARRAY, as stated in the help:
Return value
variant
The result of the evaluation. A scalar result is returned.
To make your code return a STRING you need to change it like this:
Public Function getNameDirector As String
Dim varResult as Variant
varResult = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & m_branch & {"; "FullName")})
getNameDirector = Cstr( varResult(0) )
End Function
The CStr is just there for the case where the #DBLookup returns an error or a number (both possible)
Just a few things in general:
NEVER write even one line of LotusScript- code without error handler. It will cause you trouble FOR SURE. If you had error handling in place, then it would have told you in which line the error occured...
NEVER use the result of #DBLookup without checking for #IsError... It will cause lot of troubles when the lookup fails.
IF you use #Iserror, then don't do the Lookup twice, assign the lookup to a variable and check that one for #Iserror, like this. Otherwise performance will go down in big forms:
Example:
_lkp := #DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D"+suc; "FullName");
#If( #IsError( _lkp ) ; " " ; _lkp )
EDIT: As Knut correctly stated in his answer the real cause for the error was a typo in the formula ( Fullname)" instead of Fullname") that I fixed in my example as well.
1) My suggestion is to never (or at least very seldom) use Evaluate() in Lotusscript. You have proper Lotusscript functionality to do almost everything.
One of the major reasons is that the code is very hard to debug (which is what you are now experiencing).
2) Don't use extended notation when you work with fields. The best practice is to use the GetItemValue and ReplaceItemValue methods of the NotesDocument class for performance reasons as well as compatibility reasons.
3) In the examples with buttons you have a reference to doc, but it is never declared or initialized in the code. If you would use Option Declare at the top of your code you would catch these kinds of errors.
4) I also reccomend against using replica ID to reference databases, that makes it very hard to maintain in the future. Unless you have a very good and convincing reason, reference them by server and filename instead.
I would suggest you refactor your code to something like this:
'Function get the name director
Public Function getNameDirector() As String
Dim db as NotesDatabase
Dim view as NotesView
Dim doc as NotesDocument
Dim key as String
Dim fullname As String
Dim varResult As Variant
Set db = New NotesDatabase("Server/Domain","path/database.nsf")
If db Is Nothing Then
MsgBox "Unable to open 'path/database.nsf'"
Exit Function
End if
Set view = db.GetView("People2")
If view Is Nothing Then
MsgBox "Unable to access the view 'People2'"
Exit Function
End if
key = "D" & m_branch
Set doc = view.GetDocumentByKey(key)
If doc Is Nothing Then
MsgBox "Could not locate document '" & key & "'"
Exit Function
End if
fullname = doc.GetItemValue("FullName")(0)
End Function
Ando of course update the button actions in the same way.
Yes, it is a few lines longer, but it is much more readable and easier to maintain and debug. And you have error handling as well.
Change your last part in #DbLoookup code line to:
"FullName")})
I'm completely new to visual basic and somewhat new to programming in general. I'm trying to teach myself how to use visual basic because I was told it was easier to learn. My question is how do I connect an execute button to a text box to calculate a simple math problem? Do I double click the button I want to make the execution and then put in the code? Can someone give me a simple sample code that when you enter a number in a text box and press the execute button, the number entered would be multiplied by another number like 2 or whatever and then be displayed in another box? I just need a way to understand how the coding works and connects the gui buttons and text boxes so I can understand it better. I'm good and learning on my own when I see how things work and then I can put things together and figure them out. Thanks
That's pretty much it...
...of course the devil is in the details. The main problem you'll run into in this scenario is that your TextBox holds a String, but you want to manipulate it as a Number. First you need to convert the string to a number, then do the math. This also allows you to determine if the String in the TextBox is not a number, such as if the user entered "Unicorns are real!" in it:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As Integer
Dim strInput As String = TextBox1.Text
If Integer.TryParse(strInput, x) Then
Dim result As Integer = x * 2
Label1.Text = x.ToString & " * 2 = " & result.ToString
Else
Label1.Text = "Invalid Integer: " & strInput
End If
End Sub
End Class