ekenman
asked on
Thousand separator and decimals in textbox
I'd like to input numbers in a textbox and format it with a thousand separator and two decimals.
I've tried the Masked Edit with a lot of different masks, but I just can't get it to work.
I've also tried to put some code at the TextChanged event using TextBox1.Text = val(TextBox1.Text).Tostrin g("#,#.##" ). This will only work for some globalisations though. Most users of this app have Swedish settings where decimal points are decimal commas.
Any suggestions are much appreciated.
I've tried the Masked Edit with a lot of different masks, but I just can't get it to work.
I've also tried to put some code at the TextChanged event using TextBox1.Text = val(TextBox1.Text).Tostrin
Any suggestions are much appreciated.
ASKER
Thank's abel!
Yes... I've started on my own numericTextBox but it just seems like a lot of work for something that must be an issue for many programmers. Isn't there an easier way to do it?
I'll leave the question open today but will assign you the points if nothing easier comes up.
Thanks again
Tomas
Yes... I've started on my own numericTextBox but it just seems like a lot of work for something that must be an issue for many programmers. Isn't there an easier way to do it?
I'll leave the question open today but will assign you the points if nothing easier comes up.
Thanks again
Tomas
TextBox1.Text = FormatNumber(val(TextBox1. Text).tost ring,2)
The "easier way" is using the best of both worlds by adding a key handler like in that example, which does the formatting when a user types a comma or a dot. At least, that's the "easiest" I could find at the time...
@JackOfPH: but then you do not have the benefits of the masked edit control anymore....
ASKER
JackOfPH, That will ignore the local globalisation settings. If I enter:"123,23" which is the Swedish way of entering "123.23" it wont work.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes... Now I'm getting close. I'll put the code of my NumericTextBox here when done and assign points to you abel.
If you do this on the onchange or on the keypress event, you probably want to store the selectionstart value of the textbox, to prevent that the user's cursor is being moved away whenever he adds something in the middle or at the beginning of the textbox.
ASKER
yes... I'm working on it now :). It's a hassle though since the parsed text is changed. but I'm getting there. I've gotten this far...
Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
MyBase.OnKeyPress(e)
Dim localNumberFormat As NumberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat
Dim decimalSeparator As String = localNumberFormat.NumberDecimalSeparator
Dim groupSeparator As String = localNumberFormat.NumberGroupSeparator
Dim negativeSign As String = localNumberFormat.NegativeSign
If Asc(groupSeparator) = 160 Then groupSeparator = " " 'Change the groupseparator to ASCII 32 (space) from 160 (inserted space)
Dim keyInput As String = e.KeyChar.ToString()
If [Char].IsDigit(e.KeyChar) Then
ElseIf keyInput.Equals(decimalSeparator) OrElse keyInput.Equals(groupSeparator) OrElse keyInput.Equals(negativeSign) Then
' Nothing needs to be done
ElseIf e.KeyChar = vbBack Then
' Nothing needs to be done
Else
'Ignore the key entered
e.Handled = True
Beep()
End If
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
Dim localNumberFormat As NumberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat
Dim decimalSeparator As String = localNumberFormat.NumberDecimalSeparator
Dim groupSeparator As String = localNumberFormat.NumberGroupSeparator
Dim negativeSign As String = localNumberFormat.NegativeSign
If Asc(groupSeparator) = 160 Then groupSeparator = " " 'Change the groupseparator to ASCII 32 (space) from 160 (inserted space)
Dim oldselectionstart As Integer = SelectionStart
Dim oldtextlength As Integer = Len(Text)
If Microsoft.VisualBasic.Right(Text, 1) = decimalSeparator Or (Mid(Text, 1) = negativeSign And Len(Text) = 1) Then 'Dont remove minussign or decimal sign
Else
Dim dbl As Double = 0.0
Double.TryParse(Text, dbl)
Text = dbl.ToString("#,#.##")
SelectionStart = oldselectionstart + 1
End If
End Sub
ASKER
Ok, I've got a working class I believe that I put here for others to use. Thanks for your help abel
Imports System.Globalization
Public Class NumericTextBox
Inherits TextBox
Private Changingtext As Boolean = False
Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
MyBase.OnKeyPress(e)
Dim localNumberFormat As NumberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat
Dim decimalSeparator As String = localNumberFormat.NumberDecimalSeparator
Dim groupSeparator As String = localNumberFormat.NumberGroupSeparator
Dim alternativeSeparator As String = ""
Dim negativeSign As String = localNumberFormat.NegativeSign
'If Asc(groupSeparator) = 160 Then alternativeSeparator = " " 'Add alterantivegroupseparator to ASCII 32 (space) from 160 (inserted space)
Dim keyInput As String = e.KeyChar.ToString()
If [Char].IsDigit(e.KeyChar) Then
'Do nothing
ElseIf keyInput.Equals(decimalSeparator) OrElse keyInput.Equals(groupSeparator) OrElse keyInput.Equals(negativeSign) Then
' Nothing needs to be done
ElseIf e.KeyChar = vbBack Then
'If we're at a groupseparator, there won't be a differense to the ontextchange so we need to remove an extra.
If Mid(Text, SelectionStart, 1) = groupSeparator Then
Changingtext = True
Dim oldselectionstart As Integer = SelectionStart
Text = Mid(Text, 1, SelectionStart - 2) & Mid(Text, SelectionStart)
SelectionStart = oldselectionstart
Changingtext = False
Text = Text.Replace(groupSeparator, "")
SelectionStart = oldselectionstart - 1
e.Handled = True
End If
Else
'Ignore the key entered
e.Handled = True
Beep()
End If
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
If Not Changingtext Then
Changingtext = True
Dim localNumberFormat As NumberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat
Dim decimalSeparator As String = localNumberFormat.NumberDecimalSeparator
Dim groupSeparator As String = localNumberFormat.NumberGroupSeparator
Dim negativeSign As String = localNumberFormat.NegativeSign
If Asc(groupSeparator) = 160 Then groupSeparator = " " 'Change the groupseparator to ASCII 32 (space) from 160 (inserted space)
Dim oldselectionstart As Integer = SelectionStart
Dim oldtext As String = Text
If Microsoft.VisualBasic.Right(Text, 1) = decimalSeparator Or (Mid(Text, 1) = negativeSign And Len(Text) = 1) Then 'Dont remove minussign or decimal sign
Else
Dim dbl As Double = 0.0
Double.TryParse(Text, dbl)
Text = dbl.ToString("#,#.##")
End If
If Len(oldtext) <> Len(Text) Then
SelectionStart = oldselectionstart + 1
Else
SelectionStart = oldselectionstart
End If
Changingtext = False
End If
End Sub
End Class
That looks quite daunting. Since you are doing all by yourself... Instead of getting all this information from the culture, you can also use the .ToString("N2") which I showed you, which does all this replacement automatically, but then you need to maintain the position of the cursor.
Note that all conversion functions of the .Format, FormatXXX and .ToString(...) use the current culture by default.
Note that all conversion functions of the .Format, FormatXXX and .ToString(...) use the current culture by default.
ASKER
The .tostring("N2") does not give me separators for thousands. But I do use the .tostring("#,#.##") and that's the same then isn't it?
Then I wanted to limit keycahrs allowed to numbers.
Then if I start with the "-" sign, the .tostring removes that since "-" = 0..., also if I put a decimal sign in the tostring is going to treat it as .0 and remove it. Then if the cursor was to the right of a groupseparator and the vbBack-key was pressed, it would only remove the separator . So I can't figure out any other way to make this work.
I'm sure it's not the neatest way of doing it but at least it seems to be working. I'm always open to suggestions of making it better though!
Thanks for your time and effort!
Then I wanted to limit keycahrs allowed to numbers.
Then if I start with the "-" sign, the .tostring removes that since "-" = 0..., also if I put a decimal sign in the tostring is going to treat it as .0 and remove it. Then if the cursor was to the right of a groupseparator and the vbBack-key was pressed, it would only remove the separator . So I can't figure out any other way to make this work.
I'm sure it's not the neatest way of doing it but at least it seems to be working. I'm always open to suggestions of making it better though!
Thanks for your time and effort!
> The .tostring("N2") does not give me separators for thousands.
interesting, because it should, unless in the Language Settings in your windows version, the thousand separator is blank.
Anyway, you've got a working version now. It has taken myself a long time at the time to understand all that's going on with this formatting....
interesting, because it should, unless in the Language Settings in your windows version, the thousand separator is blank.
Anyway, you've got a working version now. It has taken myself a long time at the time to understand all that's going on with this formatting....
I recently created a nice workaround for someone else on EE. Have a look, it shows you how you can do just this. It probably needs a bit of tweaking, just tell me where you need some additional help: https://www.experts-exchange.com/questions/24340590/MaskedEditTextbox-mask-numeric.html?#24209640