VBA-variable in cell reference - vba

Just wondering if anyone can help me with the syntax of this.
The value of F14 is 12.
I want to select column C and the row number will be the number that is in cell F14.
Range("f14").Value = x
Dim x As Integer
range("cx").select

Range("cx").select
You need to understand the fundamentals here - in VBA anything you put in double quotes is a string literal, so "cx" is just that: a string literal.
Yes, the Range function (which is implicitly referring to the active sheet, so it's like calling ActiveSheet.Range, which isn't ideal) wants a String parameter to specify an address - but x is an Integer local variable, not a string literal.
First things first, stick Option Explicit at the top of your module.
Then, declare your variables before you use them.
Now, you need to "grab" the value of F14 and store it in x - to do that you need to assign x. Your assignment operation is reversed - you're assigning F14's value to X, when you intend to do it the other way around; flip that around:
Dim x As Integer
x = ActiveSheet.Range("F14").Value
Now if all goes well you have the value of F14 stored in X. If the cell doesn't contain a numeric value you'll run into problems for which you'll find plenty of solutions on this site if you bother searching a bit.
So x has the numeric value 12, and you need a String that says C12 - you need to concatenate the string literal "C" with the value of x. VBA gives you the string concatenation operator for that: &.
Dim theAddress As String
theAddress = "C" & CStr(x)
The CStr function isn't really needed, but it makes it explicit that you're converting x (a number) to a String. If you don't do the conversion explicitly, VBA will try to do it implicitly for you (and that's not always a good thing).
So theAddress is now a string variable that contains the value "C12" (assuming x was 12).
Give it to that Range function:
Range(theAddress).Select
Hope it helps.

Related

"VBA.len" is 4 times slower than "len" (?!) [duplicate]

When I run the following macro:
Sub try()
Dim num As Integer
num = 123
MsgBox Len(num)
MsgBox VBA.Len(num)
End Sub
The first Msgbox displays 2 and the second Msgbox displays 3.
If I remove the first line which says Dim num As Integer, both MsgBoxes display 3.
Can anyone explain why?
Len and LenB are not just ordinary functions, they are keywords, and as such are found on the list of VBA keywords (although LenB is only mentioned after you click through to Len).
Mid would be another example of such keyword disguised as function, whereas e.g. Left isn't on the list at all, because that is just an ordinary function.
It has to be a keyword because one of its jobs is to perform the compile-time task of determining the storage size of a variable. E.g. with private user-defined types, an ordinary function could not do that at all:
Private Type foo
a As Long
b As String
End Type
Sub TestLens()
Dim f As foo
MsgBox Len(f) ' OK
MsgBox VBA.Len(f) ' Compile time error
End Sub
The fact that the object browser brings you to VBA.Len when you press Shift+F2 on that Len(f) is both correct and misleading.
The Len(f) here does not actually call the VBA.Len function that determines the string size, it simply cannot do that because it would require coercing a private struct into a Variant. Instead it calculates the size of foo at compile time and substitutes the result as a literal constant into the executable.
In your example the Len(num) calculates the compile-time size of variable num (which is 2) and substitutes the constant 2 into the resulting object code, whereas VBA.Len(num) packs the value of num into a Variant and passes that variant to VBA.Len where it's further converted to string "123" and the length of that is returned.
It has to do with the way that VB stores integers and how the Len() function handles arguments that are not strings.
When a datatype that is not a string is passed to the Len() function, it returns the nominal number of bytes used to store the data (VB uses 2 bytes to store an integer). See the documentation for the Len function.
The Len() function will automatically cast the variant variable (which is created by assigning a value to a variable without declaring it first) as a string. The return isn't changing because the storage allocation changes (although it does; variants require 16 bytes of storage space, minimum). Since the implicitly declared variable is actually a variant type, VB will automatically change its type based on the situation. In this case, Len() expects a string so VB makes the variable a string.
You could use Msgbox Len(Cstr(num)) to cast the integer variable as a string before passing it to the Len function if your intent is to return the number of characters in your integer value.

Can't assign cell value to double variable

Good afternoon,
I have a sheet of data that has text and number values. I'm trying to assign the values to an array and check if it's within a certain range. Whenever I get a negative number I get a type mismatch error. I'm not sure how else to convert the data to a double data type. Here's a snippet of the code
Sub()
Dim amount1() as double
Dim h as integer
Dim amtc as range, amtr as range
ReDim amount1(AmtR.Cells.Count)
For Each amtc In AmtR.Cells
h = h + 1
amount1(h) = amtc.Value
end sub
Any ideas to assist a brother?
Thanks
If amtc.Value contains an Error value, VBA cannot implicitly convert it to a Double (or any other type for that matter).
The value of a cell that contains a #VALUE! error will be seen by VBA as being of a special Error type. You can generate these error values yourself for testing, with the CVErr function:
Debug.Print TypeName(CVErr(xlErrValue)) ' prints "Error"
Debug.Print VarType(CVErr(xlErrValue)) = vbError ' prints "True"
You can use the IsError VBA function to determine if a Variant contains an Error value:
If Not IsError(amtc.Value) Then amount1(h) = amtc.Value
But that can still give you a type mismatch if the Variant contains a non-numeric String, so you can use the IsNumeric VBA function to ensure the type conversion will succeed:
If IsNumeric(amtc.Value) Then amount1(h) = amtc.Value
That's still an implicit type conversion though. You can use the CDbl VBA function to explicitly perform the type conversion:
If IsNumeric(amtc.Value) Then amount1(h) = CDbl(amtc.Value)
And now you have code that does what it says, and says what it does.
Good day Matt & Scott,
I've tried both solutions, one thing that's clear is that it's not Numeric. What is baffling me now is that it's only on negative numbers where I can't format the data type, but it's allowing me to convert the negative number to a string and I'm unable to convert the string to a double.
Hope you guys can shed some light...

Data type confusion... for word with both alphabet and numbers eg. tlc5?

In my code i want to provide inputs which are both alphabet and numbers. Eg- tlc5. What data type should i use for such an input since only integer or only string isn't working?
Without having seen your current code: use string. VBA can convert any number to a string.
e.g.
Dim i as Integer
Dim s as String
i = 2
s = "test" & i
will result in a string "test2". To convert any other data type to a string there is the CStr() function.
If you need to work with a number contained in said string later on, I would suggest you store the number and string in a seperate variables as show above.

Why do Len and VBA.Len return different results?

When I run the following macro:
Sub try()
Dim num As Integer
num = 123
MsgBox Len(num)
MsgBox VBA.Len(num)
End Sub
The first Msgbox displays 2 and the second Msgbox displays 3.
If I remove the first line which says Dim num As Integer, both MsgBoxes display 3.
Can anyone explain why?
Len and LenB are not just ordinary functions, they are keywords, and as such are found on the list of VBA keywords (although LenB is only mentioned after you click through to Len).
Mid would be another example of such keyword disguised as function, whereas e.g. Left isn't on the list at all, because that is just an ordinary function.
It has to be a keyword because one of its jobs is to perform the compile-time task of determining the storage size of a variable. E.g. with private user-defined types, an ordinary function could not do that at all:
Private Type foo
a As Long
b As String
End Type
Sub TestLens()
Dim f As foo
MsgBox Len(f) ' OK
MsgBox VBA.Len(f) ' Compile time error
End Sub
The fact that the object browser brings you to VBA.Len when you press Shift+F2 on that Len(f) is both correct and misleading.
The Len(f) here does not actually call the VBA.Len function that determines the string size, it simply cannot do that because it would require coercing a private struct into a Variant. Instead it calculates the size of foo at compile time and substitutes the result as a literal constant into the executable.
In your example the Len(num) calculates the compile-time size of variable num (which is 2) and substitutes the constant 2 into the resulting object code, whereas VBA.Len(num) packs the value of num into a Variant and passes that variant to VBA.Len where it's further converted to string "123" and the length of that is returned.
It has to do with the way that VB stores integers and how the Len() function handles arguments that are not strings.
When a datatype that is not a string is passed to the Len() function, it returns the nominal number of bytes used to store the data (VB uses 2 bytes to store an integer). See the documentation for the Len function.
The Len() function will automatically cast the variant variable (which is created by assigning a value to a variable without declaring it first) as a string. The return isn't changing because the storage allocation changes (although it does; variants require 16 bytes of storage space, minimum). Since the implicitly declared variable is actually a variant type, VB will automatically change its type based on the situation. In this case, Len() expects a string so VB makes the variable a string.
You could use Msgbox Len(Cstr(num)) to cast the integer variable as a string before passing it to the Len function if your intent is to return the number of characters in your integer value.

adding variables numical values (newb question)

Yesterday i had a look at how to set values of variables from nummbers stored in external txt files
the variables then needed to be added up so i used trial and error first
((XVAL) + (NEWVAL))
assuming that XVAL was set to 10 and NEWVAL was set to 20 i expected to get the answer of thirty but waqs presented with the new value of 10 20
VB.net pysicaly added the two values together but i wanted the mathematical product of the two which is ((10) + (20)) = 30
yep its a newb question could anyone explain how to achieve what im affter
XVAL and NEWVAL are strings, so they are simply being concatenated together. You need to convert them to integers, so that VB.NET will treat them as such. To do this, use the Int32.Parse() method.
Dim intXVAL As Integer = Int32.Parse(XVAL)
Dim intNEWVAL as Integer = Int32.Parse(NEWVAL)
Dim result = intXVAL + intNEWVAL
You want to cast them to a number first.
Try CDbl.
See http://msdn.microsoft.com/en-us/library/Aa263426 for more.
edit: Oops, thought you were talking about VBA.
Try using Double.Parse(YOURVALUE) if you're talking about VB.NET.
Have you tried the Val() function?
Val(XVAL) + Val(NEWVAL)
The + operator in VB.NET (for backwards-compatibility reasons) means both add and concatenate depending on the types of the variables it is being used with. With two numeric types (Integer, Single, Double, etc.), it adds the values together as you would expect. However, with String types, it concatenates the two strings.
Presumably, then, your XVAL and NEWVAL variables are String types because they're being read out of a text file, which is causing VB.NET to concatenate them into a new string instead of add them together. To get the behavior you're expecting, you need to convert them to numeric types.
Some of the other answers suggest casting simply casting the string values to numeric types (CInt, CSng, CDbl, etc.), but this may not work as expected if the value contained by your string cannot be converted to number. The Int32.Parse method will throw an exception if the value held by your string cannot be represented as a number. This is especially important to keep in mind if you're reading values from a text file that are not guaranteed to adhere to any particular constraints.
Instead, you probably want to use something like Int32.TryParse, which returns a Boolean value indicating whether or not the conversion succeeded and will not throw an exception.
As you are reading from a text file I assume that you are reading your values out as strings, so when you do this:
((XVAL) + (NEWVAL))
It is effectively concatenating the two strings together. In order to get the mathematical product of the two values these need to be int/integers which is the number type.
There are a number of ways you can do this, but in essence you have to 'cast' the strings to ints and then do your calculation.
So in vb.net it would be something like this (pseudo code):
Dim xval As String = "10"
Dim newval As String = "20"
Dim x As Integer = Int32.Parse(xval)
Dim n As Integer = Int32.Parse(newval)
Dim prod As Integer = x + n
Console.WriteLine(prod)
There are a number of other methods of doing this, for example using:
int.Parse(...)
or
Integer.TryParse(...)
More information on these sorts of type conversions can be found here:
http://dotnetperls.com/integer-parse-vbnet
One thing to bear in mind with these sorts of conversions is that you have to be certain that your input data is convertable. Otherwise your code will throw exceptions. This is where TryParse is useful as you can use this to check the inputs and handle invalid inputs without the need for exceptions.