How to pass a value to DGV Cell when its formatted to C2 format - vb.net

I'm struggling find a specific answer to this question, therefore asking it myself...
I have a DataGridView with columns which has the following formatting applied to it:
DGV.Columns(3).DefaultCellStyle.Format = "C2"
On the form there is a text box in which the user enters a number and that value is then entered in one of the cells in DGV:
For Each dr As DataGridViewRow In DGV.Rows
dr.Cells("ColumnHeader").Value = TextBox.Text
Next
Before the above code is executed, this event occurs on the TextBox to format its value:
Private Sub TextBox_Leave(sender As Object, e As EventArgs) Handles TextBox.Leave
TextBox.Text = FormatCurrency(TextBox.Text)
End Sub
The text within the TextBox is displaying correctly as a currency, but when the code to put that into a cell in the DGV executes it fails saying the value is in incorrect format.
Is DGV.Columns(3).DefaultCellStyle.Format = "C2" different format to FormatCurrency(TextBox.Text)?

That is all wrong. "C2" is a numeric format string, so it will only work on numbers. A String containing digit characters is not a number and a String containing currency text definitely isn't. You need to get the String from the TextBox, concert that to a number (probably Decimal for currency values) and then load that number into the grid. The grid converts that number, along with all the data, into text to display and will use your format string to do so:
dr.Cells("ColumnHeader").Value = CDec(TextBox.Text)
You would, presumably, already have validated the user input by this stage, so there's no possibility of CDec throwing an exception.
If the intent is to display the data formatted as currency in both the grid and the TextBox then you should get rid of your Leave event handler and handle the Validating and Validated events instead. The first will validate the input to ensure that it is numeric and the second will do the formatting:
Private Sub TextBox1_Validating(sender As Object, e As CancelEventArgs) Handles TextBox1.Validating
If Not Decimal.TryParse(TextBox1.Text, NumberStyles.Currency, Nothing, Nothing) Then
'Don't let the control lose focus when it contains invalid data.
e.Cancel = True
End If
End Sub
Private Sub TextBox1_Validated(sender As Object, e As EventArgs) Handles TextBox1.Validated
TextBox1.Text = Decimal.Parse(TextBox1.Text, NumberStyles.Currency).ToString("C2")
End Sub
That code will allow the user to enter the currency symbol or not, but it will ensure that the format is currency with two decimal places once it loses focus. You would then need to allow for the formatting when copying to the grid:
dr.Cells("ColumnHeader").Value = Decimal.Parse(TextBox1.Text, NumberStyles.Currency)

Related

How to fix System.FormatException: 'Input string was not in a correct format'

I am trying to change Font Family in VB.NET for a RichTextBox
I have tried searching through google and even specific sites for just code problems. Nothing works.
These are the codes for FontFamily changing (it is a tool strip combo button)
Private Sub TscFontFamily_TextChanged(sender As Object, e As EventArgs) Handles tscFontFamily.TextChanged
rtbContent.SelectionFont = New Font(Convert.ToString(tscFontFamily.Text), Convert.ToInt32(tscFontSize.Text))
End Sub
And the FontSize (also a tool strip combo button)
Private Sub tscFontSize_TextChanged(sender As Object, e As EventArgs) Handles tscFontSize.TextChanged
Dim newSize As Single = Convert.ToSingle(tscFontSize.Text)
rtbContent.SelectionFont = New Font(rtbContent.SelectionFont.FontFamily, newSize)
End Sub
I expect this to work since it makes sense, right? But it says "input string was not in correct format" and if i remove the Convert.ToString and other convert code, it says something like "Conversion from string "" to type 'Single' is not valid.".
Also to mentiion, is the fact that i have actually tried Convert.ToString and Convert.ToDouble and basically everything for BOTH.
There is no need to call ToString on tscFontFamily.Text because the Text property of a TextBox returns a String; you're essentially saying return a String value from this String value.
Convert.ToInt32 is a quick and dirty was of converting String values to Int32 (aka integer) values. If you're relying on input from a user then you should almost always use Int32.TryParse instead. This method returns a Boolean value based on if the conversion of the input is successful and then the second parameter passed is a reference variable so if the result of the method is True then the second parameter contains the converted value. However, it looks like you're wanting a Single value in which case you'd actually use Single.TryParse.
Here would be an example applying the changes to your code:
Private Sub tscFontSize_TextChanged(sender As Object, e As EventArgs) Handles tscFontSize.TextChanged
Dim newSize As Single
If Single.TryParse(tscFontSize.Text, newSize) Then
rtbContent.SelectionFont = New Font(rtbContent.SelectionFont.FontFamily, newSize)
End If
End Sub

How do I get the textbox to enable after a certain amount of text is inputted?

So my next question(i know i know ive had a lot of questions already but im learning and my teachers suck)
but I am trying to get the textbox to go to readonly after a certain amount of text has been entered. I know how to make it a read only textbox but only after Ive had one set of data entered. i need it to be readonly after 7 days of data has been entered
I've tried inputtextbox.enabled = false
'Validating if user input is a number or not
Dim output As Integer
If Not Integer.TryParse(InputTextbox.Text, output) Then
MessageBox.Show("ERROR! Data must be a number")
InputTextbox.Text = String.Empty
Else
UnitsTextbox.AppendText(Environment.NewLine & InputTextbox.Text)
InputTextbox.Text = String.Empty
End If
InputTextbox.Enabled = False
I'm expecting it to disable after the user has entered 7 days worth of data but it only disables after one day of data is entered
Since the entries to UnitsTextbox are all done in code, this TextBox can be set to read only at design time.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim output As Integer
If Not Integer.TryParse(InputTextbox.Text, output) Then
MessageBox.Show("ERROR! Data must be a number")
Else
UnitsTextbox.AppendText(Environment.NewLine & InputTextbox.Text)
End If
'Moved this line outside of the If because it happens either way
InputTextbox.Text = String.Empty
If UnitsTextbox.Lines.Length >= 7 Then
Button2.Enabled = False
End If
End Sub
Here's some simple psuedocode
Private Sub InvalidateTextbox(sender As TextBox, e As KeyEventArgs) Handles TextBox1.KeyUp, TextBox2.KeyUp
'FOR ANY TEXTBOX YOU WANT TO CONTROL WITH THIS SUB, ADD AN ADDITIONAL HANDLE.
If Strings.Len(sender.Text) > 7 Then
'^SIMPLE CONDITIONAL, CHECKING IF THE LENGTH IS MORE THAN SEVEN CHARACTERS, MODIFY THIS TO SUIT YOUR NEEDS.
sender.Enabled = False
'^IF THE CONDITIONAL IS TRUE, DEACTIVATE THE CONTROL, IF THAT IS WHAT YOU ARE LOOKING FOR.
sender.ReadOnly = true
'^IF YOU WANT READONLY,NOT ENABLED/DISABLED.
End If
End Sub
This code will execute every time a key is pressed while the text boxes are active. What is after "Handles" defines what events will trigger the sub.
sender becomes the textbox object that triggered the sub. e holds all the event arguments for the keyboard, so you can evaluate things like which key was pressed and other neat things.
There was some confusion on if you wanted enabled/disabled or readonly, both options included.

How do I validate user input?

So I'm having a problem with my code. I need to validate if the user input is a number or not in a textbox. Now I can get it to see whether or not it is a number and it displays the error message just fine but the problem is that the word still gets inputted in to the textbox when I want there to be only numbers
If tried using if not IsNumeric(Number) then
msgbox.show("ERROR! Data must be a number!")
'Getting user input
Dim Number As String = Me.InputTextbox.Text
UnitsTextbox.AppendText(Environment.NewLine & Number)
'Make the textbox delete the text once the button is clicked
InputTextbox.Text = String.Empty
If Not IsNumeric(Number) Then
MsgBox("ERROR! Data must be a number")
End If
I'm expecting it to accept numbers only
i have a text box for input and a textbox for the results and when the number comes up false I want it to not show in the results textbox
As per #Jens comments, only I changed it to .TryParse. IsNumeric is an old VB6 method that has been optimized in .Net to TryParse.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim output As Integer
If Not Integer.TryParse(InputTextbox.Text, output) Then
MessageBox.Show("ERROR! Data must be a number")
Else
UnitsTextbox.AppendText(Environment.NewLine & InputTextbox.Text)
InputTextbox.Text = String.Empty
End If
End Sub

VB.NET 2010 Post-KeyPress Event

..This is a reworking of a previously deleted question, I'm rewording to try to be more clear..
VB.NET 2010 Winform with a Datagridview.
User is able to type into an editable cell.
As they type, the "current" value of the cell should be used to search through an array of radiobuttons and select the button that matches the typed value.
Issue is that the user could type a value, but then type a DEL or BACKSPACE to alter the value. And the DEL/BACKSPACE of course doesn't have to be done at end of value, could be anywhere. Also a cells value isn't "finalized" until after this event is complete.
My original code looked like this...
Private Sub txtdgvDiaryEdit_Keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
'Test for numeric value or backspace
If IsNumeric(e.KeyChar.ToString()) _
Or e.KeyChar = ChrW(Keys.Back) Then
e.Handled = False 'if numeric
'******************************************************
If IsNumeric(e.KeyChar.ToString()) Then
If DirectCast(sender, TextBox).Text.Length = 0 Then
Call SelectRadioButtonForValue(e.KeyChar.ToString)
Else
Dim strvar As String
strvar = DirectCast(sender, TextBox).Text.ToString + e.KeyChar.ToString
Call SelectRadioButtonForValue(strvar.ToString)
End If
Else ...
But this doesn't pick up the value of the cell AFTER the DEL/BACKSPACE.
AND I can't use any kind of CELL VALUE CHANGES Because those don't fire till i'm actually LEAVING the cell.
I need to be able to pick up the actual cell value AFTER the Keypress had been processed but remain in EDIT MODE.
Thoughts?

Sender and MessageBox oddities

New poster here and a VB hack of sorts.
I have a windows form that contains a picture box and three textboxes.
The three textboxes (Red, Green, Blue) are used to enter a numeric value from 000 to 255 representing a color code.
The PictureBox will display the resulting color from the three TextBox values.
My validation routine ValidDecCode makes sure the values entered are within the allowable limits (000-255).
If a user enters a ‘2’ in the first position all is well. If a user then enters a ‘6’ in the second position it will not pass my validation test.
After entering the KeyDown event I save the sender.selectionstart and the sender.text values. After entering the ‘6’ the selectionstart will be a 1 and text contains data that has been validated, ‘2’.
Once the ‘6’ fails my validation test I display a MessageBox, reload my saved sender data, text and selectionstart. This returns the form back to its state prior to entering the ‘6’. The TextBox will show a ‘2’ and the cursor is placed after the ‘2’.
What I find strange is that if I comment out the MessageBox.Show() line the TextBox will show ‘26’ after failing validation. If I comment out the reload of my sender data and not the MessageBox.Show() line, the TextBox will show ‘26’.
I would like to know why commenting out the MessageBox.Show() line does not return the form to its state prior to entering invalid data and what can I do about it. What is it about calling the MessageBox that makes it work?
Private Sub RedBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles RedBox.KeyDown, GreenBox.KeyDown, BlueBox.KeyDown
Dim InChr As String
Dim InPos As Integer = sender.selectionstart
Dim InText As String = sender.text
If IsNumeric(Chr(e.KeyCode)) Then
InChr = Chr(e.KeyValue)
If Not ValidDecCode(InText + InChr, InPos) Then
MessageBox.Show("Invalid value")
sender.text = InText
sender.selectionstart = InPos
End If
Else
MessageBox.Show("Invalid value")
sender.Text = InText
sender.selectionstart = InPos
Exit Sub
End If
End Sub