If I put a DateTime value into an Excel cell using Range.set_value through .Net COM Interop, and then retrieve the value of that same cell using Range.get_value, the Millisecond part of the value is not returned, though everything else is correct.
Is this a bug?
What is the workaround? I'm guessing that using the Value2 property instead might help. Has anybody else tried this?
If you set a date/time with a millisecond value in Excel manually, does it maintain it? I don't know about the Excel internal object model, but it's conceivable that it just doesn't support milliseconds.
EDIT: Okay, now we know that the set fails (the get may also fail, of course)... you could try setting it as a double after converting it via DateTime.ToOADate(). I'm not saying I'm holding out much hope, but it's worth a try...
As Jon suggested, converting the DateTime to a double using DateTime.ToOADate (then back again using DateTime.FromOADate) works if you set the value using the Range.Value2 property.
The only trouble with this property is that, if you don't already know, it doesn't tell you that the cell is supposed to be treated as a DateTime. I guess to solve this, you'd need to use a two-pass approach: get cell values using Range.get_Value to determine their type, then, for any DateTime cells, get their values again using Range.Value2, then convert using DateTime.FromOADate.
It's probably because of the issue described in this KB article.
In which case, setting the Value2 property should work.
Related
I'm facing a problem when reading the excel-sheet data using ExcelDataReader in c#.
I am reading data from excel-sheet(.xlsm)
One of the cell has a list of values to choose.
Eg.
5.1
5.2
5.1a
When I choose the value either 5.2 or 5.1a and read, I get the same exact value in the dataset
But when I choose 5.1 and read, I get 5.0999999999999996 in the dataset
Here is the code which I used to read the data in c#,
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fileStream);
DataSet findingsData = excelReader.AsDataSet();
Note :
For a workaround, I put a space after the value 5.1 in the cell. Then it read the value exactly same as expected(5.1 instead of 5.0999999999999996).
But I'm wondering, when it read the value 5.2 exactly same without applying any space, why doesn't work for 5.1?
Any suggestions are welcome to resolve this issue...
Thanks,
Karthik
Take a look at this question: Why can't decimal numbers be represented exactly in binary?
My maths isn't quite up to figuring it out precisely (comments welcome) but I suspect that 5.1 doesn't convert to the C# double precisely, but 5.2 does.
The reason it works when you add the space is that Excel will assume that the field is text, the same way 5.1a is, but when it receives something that looks like a number it assumes it is a number. (You can see this behaviour in a default blank spreadsheet as it will be right aligned if it is a number and left aligned when you add a space or any other text).
I expect that if you explicitly format all the cells as text in your source spreadsheet then the value will be read as you expect
I'm using an Infragistics UltraGrid and I have a table where the first column is a Double field, I use a dll NCalc.Expression so the user can input a formula and get a double value, of course only if it is a valid formula. The problem is on method beforeCellUpdate, I can't change the value to the value generated by the evaluate method from NCalc.Expression. I tried to store the new value as a class variable and then update the value at afterCellUpdate method but then I get a Data Error - data error due to formula being not a double but a string, input not valid
What does this mean? And how can it be fixed?
After all night I use the method berofeExitEditMode, that way I evaluate the input formula, if its not valid cancel the event, if the formula its correct, then change the value for the generated value.
It worked so far.
IF anyone knows a better way it would be much appreciated
You may check this article where is shown how you can validate the user's input "Validate User Input"
I have a little funny problem that I would like to share with you and am thankfully expecting from you some replies because I don't have an answer myself.
I have a DataGridView (dgv) in which one column is saved for datetime display.
I initialize it like a date string often used in MySQL, i.e 2011/1/3 in the dgv construction, and sure enough it displays correctly as a human readable string, that is 1/3/2011. I then save all the displayed content into another excel file.
After that I try to reopen it, here is the code after pressing the Open button
private void OpenClicked(object sender, ....)
{
dataGV.Rows.Clear();
OpenAndBindXls(filename,dataGV);
}
Sadly, the datetime display is not as expected, it is all 5762,3552,3354 etc.
I have two real questions,
[1] How can I explain the above problem ?
[2] In the above code, it only deletes rows, what methods should I use if I would like to delete even the columns but still keep the instance alive?
[Edit] Sorry the second question was made when my mind wasn't fresh at all, I noticed my stupidity. I correct it by just add dataGV.Columns.Clear(); :-D. How stupid! Well I am tired, I will take some sleep to refresh my mind now. Thanks anyway for reading.
I think that you are getting the date time format in ticks and not as you expect.
You can try either converting the data before binding or use the CellFormatting event to convert the value to a visual datetime:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellformatting.aspx
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...
Suppose i have some value in excel cell,its type may be anything date,numeric or string
and i want that cell to be validated against its type...
Is there any way of doing this ?
thanks in advance..
I assume you mean that you have contents in a cell, which could be either a date, a double, or a plain string, and that you want to assert what corresponding .NET type it is. I believe there is no direct way of doing this. One approach would be to retrieve the Value2 in the cell, and try to cast it to each of these types, starting from the most restrictive one, until the cast works - i.e. DateTime (DateTime.FromOADate), then double (Convert.ToDouble), then string - and then apply the validation rule that applies to the particular type you found.
I am not quite sure what you mean by validation, though, and what that would buy you. Once you know the type of the content, what would you do with it?
I use Excel's data validation technique in a VSTO application myself. It obviously isn't VSTO but it works well enough. There are some drawbacks like you can't have multiple validations on the same cell (i.e. you have to know what your validating for)
You can directly use the excel's functionality !!!
no need of any coding for that !!
instead of hard work go for the smart work ...
In excel,
Go to the cell where you want the validation to come
Menu ->> Data --> validation
Here you can directly use the various excel validation terms.
Which you can refer here or..
http://support.microsoft.com/kb/211485
Thanx
Regards.