How to format currency from database - c#

The goal
I want to format correctly the currency from database.
The problem
I'm formatting the currency from database with this:
#String.Format("{0:C}", #Model["MinProductPrice"])
The problem is: 150 have to be 1,50, and not 150,00 — and this formatting is doing this.
What is the right formatting type to my case?

You probably want to divide the number by 100 first (remember to change the type), so 150 becomes 1.50, which gets converted to "1,50" depending on locale:
#String.Format("{0:C}", #Model["MinProductPrice"] / 100.0m)

I'll extend my comments into an answer, I think that's more appropriate. I think you should change the column type to a money or decimal type to prevent bugs by making the use of the column more obvious. Your output on your page will be correct and won't require any "magic numbers" to get it to print out properly.
Just a note but you can also print a currency string doing this:
#Model["MinProductPrice"].ToString("C")

I attributed the casting responsibility to database. I'm using MySQL and the query is like this:
ROUND(CAST(MIN(`map`.`Product_Price`) AS DECIMAL)/100,2) as `minProductPrice`
Anyway, I would to thanks jlafay and csharpler about their answers — they were very helpful and worked well for me.

Related

C#/ClosedXML: problem with reading long numbers as text

I have a table with account numbers in one column and I need to read it. Some of them are read just fine, but some are treated as numbers and either converted into a scientific notation or wrong if I change the format to "0"
For example this dummy account :
is read as
after changing the format to "#".
If I don't change it, it's wrong:
which, obviously is a completely random account number then.
I've searched for and tried out different options, but none is working.
Any idea? Thank you
Account numbers aren't real numbers. You're never going to perform mathematical operations on them. You're better off treating them as text. Use cell.SetValue(value.ToString()).

How can I create a RangeValidator for Int64? BigInt? Long?

So I'm trying to use the RangeValidator to ensure the minimum and maximum value of Int64 is validated. But, the only or closest option that I seem to have is Double.
Dim Range As New RangeValidator
Range.ControlToValidate = "..."
Range.Type = ValidationDataType.Double
Range.MinValue = Int64.MinValue.ToString
Range.MaxValue = Int64.MaxValue.ToString
I don't want to use a custom validator. I suppose I could use some crazy regular expression.. but just trying to understand why I can't do this.
For example, the max value of Int64 is:
9223372036854775807
But this validates:
9223372036854775808
9223372036854775810
9223372036854775899
It will not validate if I jump up a larger number:
9223372036854799999
I'm assuming it's due to some conversion taking place for a Double.
I do see there's a LongValidator in System.Configuration, but I'm trying to avoid creating a CustomValidator type if at all possible and it's a different validate type, as in not intended for use like RangeValidator.
All of this is more so for learning purposes than anything else. I'm aware I can jump through other hoops but hoping to get better clarity.
Tagged C# as well. Ignore my vb.net example.. not really important based on the question. Will convert any code either way.
I found a plausible answer on a forum by PLBlum
I want to clarify something. RangeValidator does not use a
regularexpression to validate a double. It uses a regular expression
to extract the digits and decimal character out of the string. It then
converts the result into an actual number using the javascript
parseFloat() function. If that function cannot convert, the
RangeValidator knows the value was not acceptable to javascript.
I suspect that the problem is that the value you are assigning to
MaximumValue is too large for javascript's floating point. I think
both .net's Double and javascript are 80bit floating point but its
possible they are slightly different at the min and max range. In any
case, I recommend changing your code like this:
Use a CompareValidator, Operator=DataTypeCheck, Type=Double. It will report an illegal value due to the format or its too big for an 80 bit
number.
Use another CompareValidator, Operator=GreaterThanEqual, Type=Double, ValueToCompare= your minimum double. This will report an
error if anything is below the minimum. The max was handled in the
other validator.
Maybe that explains why it is validating incorrectly.
Unless someone else wants to chime in, realistically there's one way I found to do this, and that's with a custom validator. There's a function in System.configuration that allows the ability to check if a value is a valid "Long". The problem is, if you want client-side validation it seems the only valid option is to use a regex. Otherwise, the number is just too big and JavaScript parses it as a float, as Sam mentioned.
So, I ended up using a regex as to gain client-side and server-side validation.

Why are these two UPC-E values converting to the same UPC-A values?

I am trying to convert UPC-E to UPC-A, and I am seeing strange results. I believe they might be correct, because two reference sites I have found show the same conversion, but I thought UPC-E should convert distinctly to UPC-A.
Both of 678905 and 678954 are converting to 067890000053.
When I check these on the number converter at http://www.morovia.com/education/utility/upc-ean.asp, I see the same, but when I convert from 067890000053, it becomes 678954.
I see the same thing here: http://www.taltech.com/barcodesoftware/symbologies/upc
Any thoughts?
Thanks!
http://en.wikipedia.org/wiki/UPC-E#UPC-E
Yup, it looks like your example just happens to be a case where, two different UPC-E codes expand to the same UPC-A.
In fact, this will happen for any pairs of the forms
XXXX54 - XXXX05,
XXX063 - XXX006,
XX0072 - XX2007,
XX0081 - XX1008,
and possibly others.
Sorry.

Custom .Net library or existing library to handle sequence formatting?

I am thinking a library already exists for this, but I need allow my users to create a numbering format for their documents.
For example, let's say we have an RFI from and the user has a specific format the numbering sequence needs to be in. A typical RFI number looks like this for their system: R0000100. The next RFI in line would be R0000101.
Before I set out to creating a formatting engine for numbers such as these, does something already exist that can accommodate this?
Update:
I failed to save the edit to this question. Anyway, I also want to give the users the ability to create their own formats. So, I may have a form where they can input the format: R####### And also allow them to specify the starting integer: in the case 100. Also, I may want to allow them to specify how they want to increment. maybe only by 100s. So the next number may be R0000200. I know this may sound ridiculous, but you never know. That is why I asked if something like this already exists.
If you keep value and format separated, you won't need a library or such a thing.
The numbers would be simple, say, integers i, i.e. 100, 101, 102, that you manage/store however you see fit. The formatting part would simply be a matter of R + i.ToString("0000000"), or if you want to have the format as a string literal string.Format("R{0:0000000}", i).
I know, this might only be an example, but as your question stands, the formatting options, that .NET provides out of the box seem to suffice.
The incrementing of identity field values is most often handled in an RDBMS-style database. This comes with a few benefits, such as built-in concurrency handling. If you want to generate the values yourself, a simple class to get the last-issued value and increment by one would be very easy to create. Make it thread-safe so you don't get any duplicates or gaps and you'll be good to go.

sql type float, real, decimal?

well in my database i had a colum for price of one product
i had it as float, my problem is if i saved it since my c# application
as 10.50 .. in a query it returns 10,50 and if i update i get a error
10,50 cant convert to float ... or something so..
and if i saved it as decimal, in queries inside sql management .. are ok..
but in my c# application... i get the same error..
10.50 retuns as 10,50 i dont know why, and how to solved it.. my unique solution is saved it
as varchar...
That's a localisation problem of some sort. 10,50 is the "European" way of writing ten and a half. If you're getting that from your select statements then your database is probably configured incorrectly.
Generally speaking you should use the same type throughout your layers. So if the underlying types in the database are x, you should pass around those data with identical types in c#, too.
What type you choose depends on what you are storing--you shouldn't be switching around types just to get something to "work". To that end, storing numeric data in a non-numeric type (e.g. varchar) will come back to bite you very soon. It's good you've opened this question to fix that!
As others have miraculously inferred, you are likely running into a localization issue. This is a great example of why storing numbers as strings is a problem. If you properly accept user input in whatever culture/localization they want (or you want), and get it into a numeric-type variable, then the rest (talking to the DB) should be easy. More so, you should not do number formatting in the database if you can help it--that stuff is much better placed at the front end, closer to the users.
I think your setting in windows regional and language for decimal symbol is wrong.please set it to dot and again test it.
This may help out for temporary use but I wouldn't recommend it for permanent use:
Try making it so that just before you save the file, convert the number to a string, replace the commas with periods (From , to .) and then save it into the database as the string, hopefully it should see that it is in the correct format and turn it into what the database sees as "Decimal" or "Floating".
Hope this helps.
Yep, localization.
That said, I think your pice is being stored on a "money" field in SQLServer (I'm assuming it's SQLServer you're using). If that was a float in the DB, it would return it with a normal decimal point, and not the European money separator ",".
To fix:
Fist DO NO USE FLOAT in your c# code, unless you absolutely require a floating point number. Use the decimal type instead. That's not just in this case, but in all cases. Floating point numbers are binary (base-2), not decimal (base-10), so what you see in the interface is only a decimal approximation of the actual number. The result is that frequently (1 == 1) evaluates as false!
I've run into that problem myself, and it's maddening if you don't know that can happen. Always use decimal instead of float in c#.
Ok, after you've fixed that, then do this to get the right localization:
using System.Globalization;
...
NumberFormatInfo ni = new NumberFormatInfo();
ni.CurrencyDecimalSeparator = ",";
decimal price = decimal.Parse(dbPriceDataField, ni);
Note that "dbPriceDataField" must be a string, so you may have to do a ".ToString()" on that db resultset's field.
If you end up having to handle other "money" aspects of that money field, like currency symbols, check out: http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.aspx
If you need more robust error handling, either put that decimal.Parse in a try/catch, or use decimal.TryParse.
EDIT --
If you know what culture (really, country), the db is set to, you can do this instead:
using System.Globalization;
...
CultureInfo ci = new CultureInfo("fr-FR"); // fr-FR being "french France"
decimal price = decimal.Parse(dbprice, ci.NumberFormat);
Such problems were faced by me in my Web Apps... but i found the solution like I was fetching my price value in textbox. So I was have database attached with that. So when you attached your database with textbox... When you right click textbox and click Edit DataBinding.... in that you have to provide.... type like in Bind Property..... {0:N2}
This will work only for web apps or websites... not for desktop applications...

Categories