Get value from cell without transform in vba macros - vba

I have an issue with vba macros. Cell contains value 941144280284022000000. But when try to get this value in macros, variable is equal
9.41144280284022E+20. Is it possible to get "real" value?
Thanks.

Here is an example:
Sub dural()
MsgBox ActiveCell.Text
End Sub
This will insure that long strings of numerals are not converted to numbers.
EDIT#1:
This assumes that the cell actually displays the long string of numerals. If the cell displays ####, that is what the sub will pick-up. If the cell displays 9.41E+20, then that is what my sub will pick-up.
My sub will not necessarily pick-up the contents of the Formula Bar.

Try a simple :
Dim myVar as Variant
myVar = CDec(Range("A1").Value)

If you wish to store a value that looks like a number (or is a number) but has more than 15 digits of precision, then you must either format the cell as text before entering the value, or prepend the value with a single apostrophe to indicate to Excel that the value is to be treated as text and not a number.
If you don't do this, then as soon as the value is entered, there's a good chance it will be altered by Excel. The trailing zeros in the example value mean this does not happen in this specific case, but try changing that last 0 to 1 and you'll see what I mean.
You enter: 941144280284022000001
Excel converts this to: 941144280284022000000
More reading: https://en.wikipedia.org/wiki/Numeric_precision_in_Microsoft_Excel

Related

Formula in worksheet and VBA works differently

Cell A1 contains the number 25, which is right-aligned, implying it's a number, not text.
D1 contains the formula:
="" & A1
The 25 in D1 is left-aligned, implying it's text. That is confirmed by the following formula, which returns 1:
=IF(D1="25",1,0)
The following VBA code puts 25 in F1 but the 25 is right-aligned and the IF test returns 0:
Range("F1") = "" & Range("A1")
Any explanation for the discrepancy?
E1 contains the following formula which gives a left-aligned 25 and the IF test returns 1:
TEXT(A1,"0")
However, the following code gives a right-aligned 25 and the IF test returns 0:
Range("F1") = Application.WorksheetFunction.Text(Range("A1"), "0")
Not that I have to use the TEXT function. I just wonder why it works differently than when in a worksheet.
Any rule that tells when or what worksheet functions won't work in VBA code, or more precisely, will give different results than when in worksheet?
When a data is written by vba into a cell, an internal type conversion function is called if required, that is if the data type is different from the cell's numberformat property.
You dont want that conversion function to be called.
To avoid this conversion function to be called, choose the proper Numberformat property for the cell before writing the data.
Range("b4").NumberFormat = "#"
Range("b4") = Application.WorksheetFunction.Text(Range("A1"), "0")
You simply get the wrong idea of what is a number in Excel.
in general ALL input is a string. Also writing "25" in a cell.
However: If possible, Excel will convert all inputs to a numerical value if possible. Also for dates and times.
To prevent this, you simply insert a ' in front of your "text" in the cell.
The confusing part for you is the different behavior for formulas.
A formula will always output a "result" AND the "data type".
So =1+1 will be numeric as the last action was math.
=Left(1+1,1) will be text as the last action was text-based.
For =A1 it will simply copy the type. If there is a formula, then this will be the same. But if there is a "direct input" it will always try to convert to numerical and only be text if it can't be converted or if it starts with a leading ' (A1 itself does this already).
As a result: If there is a plain 25 in the cell, it will always be "numerical" no matter "how" you input the 25.
For newer Excel there is only one exception: if the cell formatting is text prior to entering a number, it will be treated as text (no converting). This does not apply if you change the formatting later.
Simple test:
enter 25 in A1 (formatting general)
enter =ISNUMBER(A1) in A2 (will be TRUE)
set formatting for A1 to "text" (A2 will still be TRUE)
enter 25 in A1 (now A2 will become FALSE)
This may fail (Excel confuses itself sometimes here). Try it with a new sheet. ;)
Hopefully you understood the fault in your logic ;)
The cell alignment says nothing about the cell's contents. Forget about anything being "implied" by it. When you start on a virgin worksheet the format for all cells is "General" which means that Excel will decide the format of what you enter. If you enter a number the format will be "Number". If you enter what looks like a date to Excel the format will be "Date", and for most other things the format will be "Text".
So, if you enter " 25" in a cell formatted as "General" Excel will recognise this to be a number despite the leading spaces, read it is numeric, and format the cell to the right. This will happen regardless of whether you made the entry by hand or used VBA. You can then proceed to format the alignment as you wish.
However, if you enter the number 25 in a cell formatted as Text Excel will recognise the number as text and display it formatted to the left (unless you expressly formatted the horizontal alignment to the right).
The best way to deal with any problems you might encounter in this regard, set the NumberFormat and HorizontalAlignment properties for the cells that you want to write to. You can do that both manually or using VBA.
Worksheet function when used in the worksheet behaves / works the same way as when used in VBA. Consider below code:
Note: Range("B1") contains a numeric value 25
Dim r As Range, v As Variant
Dim wf As WorksheetFunction: Set wf = Application.WorksheetFunction
With Sheet1
Set r = .Range("B1")
v = r.Value2
v = wf.Text(r.Value2, "0")
End With
Now using the local window, let us check the data type of variant v.
SC1: All variables un-initialized
You can see, at the start that all variables have no value and the variant type v is empty.
SC2: Variables initialized and v assigned a value
After executing lines up to v = r.value2, all variable types were confirmed (e.g. Range/Range etc.) and variant v is now Variant/Double.
SC3: Re-assign a value on v but using worksheet function Text
Executing the last line which uses the worksheet function Text, variant v type becomes Variant/String. I think this confirms that the function Text works as expected converting the numeric 25 into a string type.
As for the behavior of passing VBA generated value to worksheet, it is covered by Docmarti's post above.

VBA Inputbox strips decimal comma, converts double to string

I'm trying to create an Inputbox which has a number, with decimals, as the default value. I'm setting the Inputbox to the formula type, because the user might input a formula or reference a cell.
The problem is that the Inputbox seems to strip the comma and coerse the number to a string. I could fix this casting the number as a string with Format, and then going back to a number afterwards, but losing precision. And I'd like to understand what's going on.
The code is:
Sub test()
Dim Defolt As Double
Defolt = 1.1866701960364
Dim InputValue
InputValue = Application.InputBox("Value?", , Defolt, , , , , 0)
'for this example, the user just clicks OK to the default value
Debug.Print InputValue
End Sub
The results are these:
Thanks!
ps: the locale is Spanish. Excel version is Excel 2010 32bits.
Have a look here. The important part is right under the table:
You can use the sum of the allowable values for Type. For example, for an input box that can accept both text and numbers, set Type to 1 + 2.
and a little further down in the remarks:
If Type is 0, InputBox returns the formula in the form of text — for example, "=2*PI()/360". If there are any references in the formula, they are returned as A1-style references. (Use ConvertFormula to convert between reference styles.)
Try setting the type as 1 and see if you can still use a formula and number. The documentation leads me to think that you can (basically you get formula for free). Since you're setting the type to 0, you're getting back the default Text type.

How to properly read a single Excel cell

I've been looking up in Google in these past days but I still can't find a good answer to this one.
Currently, this is how I do it:
For Each cell In ws.Range(fromCol, toCol)
If IsNothing(cell.Value) Then Exit For
valueList.Push(cell.Value.ToString())
Next
But when it reads a cell whose assumed data type is Time, it returns a Double value. I try to parse that value but it's not the same as expected.
How can I properly read a single Excel cell with an assumed type of Time?
As per the comment suggesting the article,
.Text is a bad idea in the sense that it will give you just the displayed string in that cell. If you use TypeName on the cell's content, for example, it will always return string regardless of any datatypes the content might be. However, if you use .Value, it will return the actual datatype name of the content of that cell.
This can prove useful to you if you're using TypeName in a comparison for instance. It saves you using conversion functions.
Take this example:
Sub Test()
Range("A1") = "True"
Debug.print(TypeName(Range("A1").Value))
Debug.print(TypeName(Range("A1").Text))
End Sub
This Output is:
Boolean
String

Copy Value Of Cell, Not Formula

I am trying to grab only the current number of minutes in an hour.
I use the NOW() function and I have the format of the cell it's in set to only mm. So in the cell display, if it's 9:08, I get 08.
Whenever I try a excel formula like =VALUE(D5) or =D5, I get (I'm assuming this is what it is) an unformatted date string.
I am now looking to macros using VBA to solve my problem.
I've tried:
Worksheets("Sheet1").Cells(23, 1) = Worksheets("Sheet1").Range("E20").Value
However I get the same thing as with my excel formulas. Is there any VBA way of getting only the value that's displayed in the cell and copied to a new area. It doesn't really need to be copied over, I just need to use the value further in my macro.
I'm open to other ways of getting the current number of minutes in the current hour as well.
Do try not to confuse formatting and data.
why not use =MINUTE(D5) in a cell which will set that cell to the minute value irrespective of formatting? Use that cell as your source in your VBA.
=HOUR(D5) would operate similarly but return the hour part.
If the displays 9:08
then select that cell and:
Sub dural()
Dim s As String
s = Split(ActiveCell.Text, ":")(1)
MsgBox s
End Sub
Note this is a String
Might be calculated like so:
=60*(NOW()*24-INT(NOW()*24))

Validate entered cell value according to a given data type

I use an Excel macro to create new workbooks filled with data of given csv files. One column is open to user input of certain attribute values. These values must fit a datatype and a certain formatting to be accepted by another processing system, here are some examples:
Value A: String value formatted like "#"
Value B: Integer Value formatted "#"
Value C: Float value formatted "#.##0,0###"
Value D: Decimal value formatted "#.##0,0#"
Now i want to add a validation to check if a typed input value is ok for processing or has to be changed, examples:
a String value may not be entered in a Decimal field
negative values are not accepted for all number formatted fields
How do I set up this validation? I am quite new to VBA not shure about the best way to go. The possibilities I found so far:
Add a validation via Worksheet.Range.Validation, but I don't have any clue how to set up the Formula1 to check for correct values.
Go by Worksheet_Change, the problem here is that i create new Workbooks which apparently not contain the Worksheet_Change I wrote in my program code because it is a new workbook.
So what's the best way to go?
You can do quite a bit with data validation on the workbook side, without VBA. For example, for Value C, you could put in the formatting (Float value formatted "#.##0,0###") in the custom number format for that cell, then apply data validation to make sure only numbers are entered in a range you'd like.
Using Worksheet.Range.Validation is not very save because it is not triggered if user pastes data from clipboard.
Go for Workbook_SheetChange. Implement the validation there and save the workbook as your template.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Debug.Assert (Format(Target.Value, "#.##0,0#") = Target.Value)
End Sub
Make sure all cells are formatted as text if you use this approch. Otherwise Target.Value will give you an interpolated value.
Then later open the template and import the cvs into it:
wb = Application.Workbooks.Add("path-to-template.xslm")
Application.EnableEvents = false ' You don't want to trigger change events during import
myimport(wb)
Application.EnableEvents = true