I'm trying to write a test using the Marathon testing tool with Jython. I'm using the Apache POI in order to read/write with Excel files. I'm very new to Jython and the Apache POI so this question may seem very simple to some, but I can't get past it. I'm using the getCell() function in the Cell interface and it grabs the cell just fine, but the contents that it prints for me are not what I want. I want the integer value, but it returns a floating point.
for r in range(1, rowsBusiness):
row = sheetBusiness.getRow(r)
idNum = row.getCell(0) # it is returning double values here
print idNum
print idNum.getStringCellValue()
I'm okay with it returning double values so long as I can convert them to a string or integer because the application that I'm testing converts from string to integer or spits out an error, but I can't figure out how to convert from double and get rid of the decimal point. The getStringCellValue() function doesn't work on idNum. It just leaves it blank and the test gets stuck. I also formatted the Excel file so that it only takes integer values in the cells that I'm referring to. So, for example, in the excel file I have the value 1(formatted to not contain any decimal points), but the print idNum returns 1.0
Any helpful hints on how to get this to a string or integer? Or any other ideas that might contribute to a successful workaround?
The Excel file format only has a few basic types, like Numeric and String. Most numbers get stored as a floating point value + formatting rules. That's why you're getting back a double not an int - that's simply what lives in the file!
Apache POI provides the DataFormatter class, which takes a floating point value and the format string, and does its best to return a string of the number as shown in Excel. For your case, calling that is likely to yield what you're after.
Related
In the below code I am having problems making sure the file writer does not round my number off to a certain number of decimal places. I need to use a variant because sometimes the value is string and at other times it is a number.
How can I force it to write exactly what the variable is? For example the below code might show 0.00038 and I want to show the exact value.
Dim MyFile1 As Variant
Dim MyNumber as Variant
MyFile0 = "C:/myfile.csv"
fnum0 = FreeFile()
Open MyFile0 For Output As fnum0
MyNumber = 0.0003759656
Print #fnum0, MyNumber
Your code is fine. The issue is with excel. When opening a CSV in excel, including thru VBA, excel detirmines what a cell is. Typically, if it lloks like a number with more then 5 characters it will express it in Scientific notation or rounded to 5 places.
Note sure what you are doing with the CSV file before or where you are getting it from, but here are some options to prevent excel from changing your data:
In VBA use the Workbook.OpenText command to open the CSV with either:
-the all excel cells as text*
-the column stored number with so many decimal places
(note a max of 30 decimal places apply)
-a particular column store as text.
--A full list of option syntax here http://msdn.microsoft.com/en-us/library/office/bb22351(v=office.12).aspx
You may also import your CSV into an excel spreadsheet, it will give you the option to choose data type for each column. Then run the VBA against the excel file.
If you are not doing formulations in excel, I would recomend storing the number as a text string. VBA automatically converts strings of numbers into numeric values when needed.
It's likely that you're experiencing floating point errors. They are are very small errors that occur when numbers are converted from/to base 10 (human) to/from base 2 (computer). For your purposes, you need to determine what it means that two values are not equal. It's not just val1 <> val2 because that won't account for the tiny errors. If you're dealing with money, for instance, you probably don't care about anything less than a penny. So you might determine inequality as ABS(val1 - val2) > .001. You just need to determine what your tolerance for equality is and compare to that standard.
It may be that your number is not being stored as a number in vba, and when you write it Excel converts it. Say you're number is 1.789 and you write it to a cell that is formatted as 'GENERAL'. Excel will write 1.79 (and think that's the number, not even a formatting issue).
What I've discovered, is if you convert the number to a decimal first CDEC(YOURNUMBER), it will write it correctly. For good measure, I also verify that the cell is '.NUMBERFORMAT = "GENERAL'
I'm trying to write an Excel macro using VBA that will return only the first 5 numbers in a cell when the length of that cell exceeds 20. The field normally returns 15-digit alphanumeric results (which I need to leave alone) but in certain exceptions will return a 5-digit number with a multitude of zeroes following it (1234500000000000000000000...) which Excel converts into scientific notation (1.2345E+160). I am able to convert the cells to numbers instead of scientific notation and view the whole number.
I've tried to use code such as =IF(LEN(A1)>20,LEFT(A1,5),A1) and it just returns 1.2345E+160. Even though the whole number is displaying, Excel still thinks the cell length is 11 and won't display the first 5 digits.
I've also tried lines such as =IF(A1="E",LEFT(A1,6),A1) thinking it would detect the E, return 1.2345, and I could just remove the decimal points, but that didn't work either (it just returns the original 1.2345E+160).
I got the same results whether the cell was formatted as number or text. Is there a way around this?
Thank you for your time!
You are trying to use string manipulation on a number. Instead use math:
=A1/1E+160
If you do actually want to treat this thing as text, understand that the underlying value being stored is your 12345000000000000... and there is no decimal point in that thing. So you'll have to convert to text and add the decimal:
=LEFT(TEXT(A1,"0"), 1) & "." & MID(TEXT(A1,"0"), 2, 4)
But that's pretty ugly. I would just stick with math.
Background: I'm receiving data for my Excel application from an API in JSON format. For this matter I'm receiving numerical values as a string, as everything sent in JSON naturally is a text format - and so does VBA also interpret it. As I'm located in Denmark, using a different decimal separator than the native on in Excel (my Danish version utilizes , as separator rather than .).
Case:
This is causing quite a bit of trouble as Excel interprets this as a thousand-separator when converting the string to a number.
Searching for answers I've found that the best solution, normally, is to convert the string to double when using VBA, utilizing CDbl(string to convert to number).
This usually is the case, but in my case I'm receiving a number with a lot of decimals such as: "9.300000190734863".
When doing a CDbl("9.300000190734863") this results in a very large integer: 9,30000019073486E+15
Also, I don't think utilizing a replace() approach is feasible in my case as I might also have data that uses both decimal- and thousand separators at the same time, making my results prone to replacement errors.
However, inserting the string value directly into a cell within Excel converts the number correctly to 9,30000019073486 in my case.
Question: Can it be right that there's no way to mimic, or tap into, this functionality that Excel obviously is using when inserting the string into a cell?
I've searched for quite some time now, and I haven't found any solution other than the obvious: inserting the value into a cell. The problem here is that it's giving me some performance overhead which I would rather avoid.
You can swap the positions of the periods and commas in your input prior to casting as a double, in three steps:
Replace commas with 'X' (or some other value that won't appear in your data)
Replace periods with commas
Replace 'X' with periods
In the below code I am having problems making sure the file writer does not round my number off to a certain number of decimal places. I need to use a variant because sometimes the value is string and at other times it is a number.
How can I force it to write exactly what the variable is? For example the below code might show 0.00038 and I want to show the exact value.
Dim MyFile1 As Variant
Dim MyNumber as Variant
MyFile0 = "C:/myfile.csv"
fnum0 = FreeFile()
Open MyFile0 For Output As fnum0
MyNumber = 0.0003759656
Print #fnum0, MyNumber
Your code is fine. The issue is with excel. When opening a CSV in excel, including thru VBA, excel detirmines what a cell is. Typically, if it lloks like a number with more then 5 characters it will express it in Scientific notation or rounded to 5 places.
Note sure what you are doing with the CSV file before or where you are getting it from, but here are some options to prevent excel from changing your data:
In VBA use the Workbook.OpenText command to open the CSV with either:
-the all excel cells as text*
-the column stored number with so many decimal places
(note a max of 30 decimal places apply)
-a particular column store as text.
--A full list of option syntax here http://msdn.microsoft.com/en-us/library/office/bb22351(v=office.12).aspx
You may also import your CSV into an excel spreadsheet, it will give you the option to choose data type for each column. Then run the VBA against the excel file.
If you are not doing formulations in excel, I would recomend storing the number as a text string. VBA automatically converts strings of numbers into numeric values when needed.
It's likely that you're experiencing floating point errors. They are are very small errors that occur when numbers are converted from/to base 10 (human) to/from base 2 (computer). For your purposes, you need to determine what it means that two values are not equal. It's not just val1 <> val2 because that won't account for the tiny errors. If you're dealing with money, for instance, you probably don't care about anything less than a penny. So you might determine inequality as ABS(val1 - val2) > .001. You just need to determine what your tolerance for equality is and compare to that standard.
It may be that your number is not being stored as a number in vba, and when you write it Excel converts it. Say you're number is 1.789 and you write it to a cell that is formatted as 'GENERAL'. Excel will write 1.79 (and think that's the number, not even a formatting issue).
What I've discovered, is if you convert the number to a decimal first CDEC(YOURNUMBER), it will write it correctly. For good measure, I also verify that the cell is '.NUMBERFORMAT = "GENERAL'
So I've spent the better part of the day debugging my VBA Class module and came upon a worrying phenomenon.
On the main spread sheet I have a cell formatted as "currency", with 9 decimal place precision. In my VBA class, I have an attribute (a double) which takes on that cell value upon instantiation. i.e.,
myClass.loanDefault_7 = Range("loanDefaults")(1,7)
However, when I check the value stored in myClass.loanDefault_7 after the assignment, it has only 4 decimal place precision.
My question is why is VBA automatically (without my permission) truncating down this value? I want to understand why this happens, and how I can prevent it in the future.
Any help is much appreciated!
Try using the Value2 property instead:
myClass.loadDefault_7 = Range("loadDefaults")(1,7).Value2
From MSDN:
The only difference between this property and the Value property is that the Value2 property doesn’t use the Currency and Date data types. You can return values formatted with these data types as floating-point numbers by using the Double data type.
It seems that the Value property will automatically coerce the value into a Currency data type (which, AFAIK, is only capable of representing 4 numbers to the right of the decimal point).