Application.Run and range parameter? - excel

If I have an excel function such as:
=my_function(A1:C4)
and I want to call this from VBA like:
Dim t as variant
t = Application.Run("my_function",X)
What is the simplest way for X to represent A1:C4?

Your range has to come from a worksheet, so if you define that range first and then pass it to the function in your other workbook (I assume that's what you want to do since you wouldn't use Application.Run otherwise). So the following code will do the trick:
Sub RunFunctionInAnotherWorkbook()
Dim rThisRange as Range
Dim vResult as Variant
Set rThisRange = ActiveSheet.Range("A1:C4")
vResult = Application.Run("'MyOtherWorkbook.xls'!TheModuleName.TheSubName", rThisRange)
End Sub
And the function in the workbook "MyOtherWorkbook.xls":
Function TheSubName(inputRange as Range) as Variant
'Work your magic here
End Function

I haven't try it, but wouldn't
t=myfunction(range)

The simplest syntax is
Application.Run("my_function", [A1:c4])

Related

Syntax error CountIfs-function multiple criteria

I would like to use a CountIfs-function with two criterias. My programm should go through two different columns and compare the cells.
I used this code:
WorksheetFunction.CountIfs(Data!E:E;"=Open";Daten!Q:Q;"=company")
Could you please tell me if it is possible to use the CountIfs-function like that? Because my compiler is dropping a syntax-error.
Thanks a lot!
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Date")
Dim wksFn As WorksheetFunction
Set wksFn = Application.WorksheetFunction
Debug.Print wksFn.CountIfs(ws.Columns(5), "Open", ws.Columns(17), "company")
End Sub

Passing variable to macro [duplicate]

If I have an excel function such as:
=my_function(A1:C4)
and I want to call this from VBA like:
Dim t as variant
t = Application.Run("my_function",X)
What is the simplest way for X to represent A1:C4?
Your range has to come from a worksheet, so if you define that range first and then pass it to the function in your other workbook (I assume that's what you want to do since you wouldn't use Application.Run otherwise). So the following code will do the trick:
Sub RunFunctionInAnotherWorkbook()
Dim rThisRange as Range
Dim vResult as Variant
Set rThisRange = ActiveSheet.Range("A1:C4")
vResult = Application.Run("'MyOtherWorkbook.xls'!TheModuleName.TheSubName", rThisRange)
End Sub
And the function in the workbook "MyOtherWorkbook.xls":
Function TheSubName(inputRange as Range) as Variant
'Work your magic here
End Function
I haven't try it, but wouldn't
t=myfunction(range)
The simplest syntax is
Application.Run("my_function", [A1:c4])

Passing sheets as variables from one sub procedure to another in VBA

This is my first post on stackoverflow. I have two sub procedures in Excel VBA. The first one, called Sub IAR_part_2(), is intended to assign two sheets (by index location) to two variables named sheetname1 and sheetname2. after assigning the variables I am trying to pass them to my second sub procedure, called IAR_macro, to be processed. The two sheets are dependant on one another, so sheets 4 and 8 are ran through the IAR macro, sheets 5 and 9, sheets 6 and 10, etc. My problem is that I cannot figure out how to pass the sheetname variables from IAR_part_2 to IAR_macro. What am I doing wrong?
Sub IAR_part_2()
sheetname1 = Worksheets(4)
sheetname2 = Worksheets(8)
Call IAR_macro
End Sub
Sub IAR_macro(sheetname1 As Worksheet, sheetname2 As Worksheet)
Dim h As Long
Dim i As Long
Dim l As Long
Dim j As Long
Dim k As Long
Dim lr As Long
Worksheets(sheetname1).Activate
' Find the number of the last cell with data in column A and subtract 1 to populate variable i
On Error GoTo Canceled
i = (Range("B1").End(xlDown).Row) - 1
'Switch over to the Code sheet
Worksheets(sheetname2).Activate
'While the number of loops is less than variable i minus 1, copy the contents of cells A2 through A29 over and over down the worksheet
Do While l < (i - 1)
Range("A2:A29").Select
Selection.Copy
lr = Cells(Rows.Count, "A").End(xlUp).Row
Range("A" & lr + 1).Select
ActiveSheet.Paste
l = l + 1
'rest of macro follows from here...
Simple example of how to pass worksheet objects to a different sub:
Sub Macro1()
'Declare variables
Dim ws1 As Worksheet
Dim ws2 As Worksheet
'Assign variables to worksheet objects
Set ws1 = Worksheets(4)
Set ws2 = Worksheets(8)
'Call the second sub and pass the worksheet variables to it
Call Macro2(ws1, ws2)
End Sub
Sub Macro2(ByVal arg_ws1 As Worksheet, ByVal arg_ws2 As Worksheet)
'Reference the accepted arguments (in this case worksheet variables) directly:
MsgBox arg_ws1.Name
MsgBox arg_ws2.Name
'This will result in an error because you're using the passed argument incorrectly:
MsgBox ActiveWorkbook.Sheets(arg_ws1).Name '<-- Results in error
End Sub
You must reference the passed arguments directly. If you want to use the structure shown in your code, then the arguments passed need to be a string (but this method is NOT recommended):
Sub Macro1()
'Declare variables
Dim sSheet1 As String
Dim sSheet2 As String
'Assign variables to worksheet objects
sSheet1 = Worksheets(4).Name
sSheet2 = Worksheets(8).Name
'Call the second sub and pass the worksheet variables to it
Call Macro2(sSheet1, sSheet2)
End Sub
Sub Macro2(ByVal arg_sSheetName1 As String, ByVal arg_sSheetName2 As String)
'Because the arguments are strings, you can reference the worksheets this way
'This method is NOT recommended
MsgBox Worksheets(arg_sSheetName1).Name
MsgBox Worksheets(arg_sSheetName2).Name
End Sub
I noticed in your examples, you have your variables declared inside the function. Normally any variables you wish to use are better implemented by using option explicit. Also when identifying sheets, you will have less problems when addressing a sheet by its sheet number as opposed to the sheet name. That way if you need to use a variable, you can use just a integer instead as well.
Option Explicit
Dim h as Long, i as Long, l as Long, j as Long, k as Long, lr as Long
Dim x as Integer
Sub IAR_macro()
On Error GoTo Canceled
i = (Range("B1").End(xlDown).Row) - 1
Sheets(x).Activate
Do While l < (i - l)
Sheet ids can be located in the development tool. Here is an example:
This is minimal way of passing the worksheets. As far as they are objects, they are passed by reference by default:
Sub TestMe()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = Worksheets(1)
Set ws2 = Worksheets(2)
Passing ws1, ws2
End Sub
Sub Passing(arg_ws1 As Worksheet, arg_ws2 As Worksheet)
Debug.Print arg_ws1.Name
Debug.Print arg_ws2.Name
End Sub
VBA is not as easy and as simple as many people (mainly those who consider it to be a funny-scripting-language, written by wanna-be-developers) think. Sometimes it allows to write ByVal, but it follows its own rules and takes the argument ByRef, just to comfort you and make sure you are not going to make an error.
Saw the answer from #tigeravatar here and I have decided not to write a comment under it, but to explain in a different post why it is wrong and dangerous, as far as explaining it as a comment would have been tough.
If you try to write a Stop line here from the answer:
Sub Macro1()
'Declare variables
Dim ws1 As Worksheet
Dim ws2 As Worksheet
'Assign variables to worksheet objects
Set ws1 = Worksheets(4)
Set ws2 = Worksheets(8)
'Call the second sub and pass the worksheet variables to it
Call Macro2(ws1, ws2)
End Sub
Sub Macro2(ByVal arg_ws1 As Worksheet, ByVal arg_ws2 As Worksheet)
'Reference the accepted arguments (in this case worksheet variables) directly:
MsgBox arg_ws1.Name
Stop
MsgBox arg_ws2.Name
'This will result in an error because you're using the passed argument incorrectly:
MsgBox ActiveWorkbook.Sheets(arg_ws1).Name '<-- Results in error
End Sub
Run the answer and wait for the Stop line:
If the arg_ws1 were taken byVal, then if someone changes the name of the 8th worksheet, while the Stop is lighting, then it should still take the old name. It is ByVal, remember? Well, go ahead and change the name. Then continue with F5. Which name are you getting? Why?
The answer is because of the way the Sub is called with parenthesis in the arguments. These force ByVal and ignore anything explicitly written.
CPearson ByRef vs ByVal
Disclaimer - My Article for how to refer a function ByVal when it is ByRef
You need to pass the two variables you created to your second sub when you call the procedure:
Sub IAR_part_2()
Set sheetname1 = Worksheets(4)
Set sheetname2 = Worksheets(8)
Call IAR_macro (sheetname1,sheetname2)
End Sub

VBA pass the name of activesheet to a function

I have created a function to receive three parameters.:
An array of strings
A worksheet name
An index for the array of strings
When I compile I am getting a compile error stating:
Compile Error:
Expected:=
My call is:
Sub C_Button_ImportBOM_Click()
Dim strFilePathName As String
Dim strFileLine As String
Dim v As Variant
Dim RowIndex As Long
Dim mySheet As Worksheet
ActiveSheet.Name = "Import"
mySheet = Worksheets("Import")
strFilePathName = ImportFilePicker
v = QuickRead(strFilePathName)
For RowIndex = 0 To UBound(v)
PopulateNewLine (v(RowIndex), mySheet, RowIndex)
Next
End Sub
The function declaration is:
Function PopulateNewLine(SourceString As String, ImportSheet As Worksheet, CurrentRow As Long)
I have tried many things to no avail. Initially with just the first argument declared and used this worked okay.
Any ideas greatly appreciated.
Excel 2010 VBA
You are calling your function like a subroutine, i.e., you're not returning a value from it and assigning it to a variable, as you'd normally do with a function. That means you need to call it without the parentheses surrounding the arguments:
PopulateNewLine v(RowIndex), mySheet, RowIndex
If you really aren't returning anything from it, you should probably turn it into a Sub for clarity's sake:
Sub PopulateNewLine(SourceString As String, ImportSheet As Worksheet, CurrentRow As Long)
... your code here
End Sub
On another note, you should qualify your mySheet reference, and as I mentioned in the comments, use Set. It should look something like:
Set mySheet = ActiveWorkbook.Worksheets("Import")
Substitute whatever workbook Import is in for ActiveWorkbook above.

Setting a Sheet and cell as variable

I am new in VBA coding. Lets say I am retrieving value from Sheet3.Cell(23, 4) for a value, is there any way in the VBA code which let me set this as a variable?
For example, I have changed the interface and let the value stay at Sheet4.Cell(20,1), everywhere in my code which refer to Sheet3.Cell(23, 4) need to be changed to Sheet4.Cell(20, 1). I am thinking is there any best practice for coding VBA for situation like this?
Yes. For that ensure that you declare the worksheet
For example
Previous Code
Sub Sample()
Dim ws As Worksheet
Set ws = Sheets("Sheet3")
Debug.Print ws.Cells(23, 4).Value
End Sub
New Code
Sub Sample()
Dim ws As Worksheet
Set ws = Sheets("Sheet4")
Debug.Print ws.Cells(23, 4).Value
End Sub
Yes, set the cell as a RANGE object one time and then use that RANGE object in your code:
Sub RangeExample()
Dim MyRNG As Range
Set MyRNG = Sheets("Sheet1").Cells(23, 4)
Debug.Print MyRNG.Value
End Sub
Alternately you can simply store the value of that cell in memory and reference the actual value, if that's all you really need. That variable can be Long or Double or Single if numeric, or String:
Sub ValueExample()
Dim MyVal As String
MyVal = Sheets("Sheet1").Cells(23, 4).Value
Debug.Print MyVal
End Sub

Resources