vba assigning sub routine to variable - vba

I have the following sub routine (in module10).
Sub varWorksheet(wksht As String)
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(wksht)
Set ws = Nothing
End Sub
I want to be able to pass this sub routine as a reference to a variable with something like this rather than have to declare it explicitly in each routine:
Set ws = module10.varWorksheet("Sheet1")
I'm getting a compilation error -> expected Function or Variable.

You shoud use a function like this.
Function varWorksheet(wksht As String) As Worksheet
On Error Resume Next
Set varWorksheet = ThisWorkbook.Sheets(wksht)
End Function
It will return nothing if the worksheet doesn't exist. This works fine.
Sub Test()
Dim ws As Worksheet
Set ws = Modul10.varWorksheet("Tabelle4")
If ws Is Nothing Then
Debug.Print "No worksheet"
Else
' what ever you want
End If
End Sub

Related

How to loop through only the worksheets included in a list?

I am trying to use VBA to loop through worksheets in my file but only those that are included in a list on a control worksheet, e.g.
Worksheet List
When I try to look up the worksheet name in this list, it does not recognise the worksheet name as a string.
Current code below:
I create a function to vlookup on the list:
Public Function IsInRunList(WsName As Variant, RunList As Range) As Boolean
If Application.VLookup(WsName, RunList, 1, False) = WsName Then
IsInRunList = True
End If
End Function
Then I call this function in my subroutine:
Dim Ws As Worksheet
For Each Ws In ThisWorkbook.Worksheets
If IsInRunList(Ws.Name, Range("Run_List").Columns(j)) Then
I get a mismatch error for Ws.Name here.
Any ideas?
Thanks.
Try the next approach, please:
Sub iterateBetweenSheetInList()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
Select Case sh.Name
Case "Sheet1", "Sheet2", "Sheet4", "Sheet7"
Debug.Print sh.UsedRange.Rows.Count
'your code can do here whatever you need...
End Select
Next
End Sub
Or a version to take the sheets name from a range (in column X:X in the code example). You did not show us in which column the sheets list exists:
Sub iterateBetweenSheetInListBis()
Dim sh As Worksheet, ws As Worksheet, arrSh As Variant, El As Variant
Set sh = ActiveSheet
'adapt the next range with the lettr of your column where the sheets name exists:
arrSh = sh.Range("X2:X" & sh.Range("X" & Rows.Count).End(xlUp).row).Value
For Each El In arrSh
Set ws = Worksheets(El)
Debug.Print ws.UsedRange.Rows.Count
'do here whatever you need...
Next
End Sub
Application.VLookup returns a Range when successful and an error if not (same behavior as in Excel). An error is not a string, it's a special type that you can check with IsError.
Change your checking routine to something like:
Public Function IsInRunList(WsName As Variant, RunList As Range) As Boolean
Dim res As Variant
res = Application.VLookup(WsName, RunList, 1, False)
IsInRunList = Not IsError(res)
End Function

Editing a Sub within another Sub

Having trouble figuring out how to edit a sub from within another sub. I tried this:
Sub Sub1()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1").Value = "Useless"
End Sub
Sub Sub2()
Dim test as string
test = ThisWorkbook.Worksheets("Sheet1").Range("B3").Value
If test = "here" Then
Call Sub1
With Sub1
ws.Range("A2").Value = test.Value
End With
End If
I get an expected function or variable error back, probably due to the fact that Sub1 should be a function. But even once that's changed to a function, Sub2 still doesn't work correctly though the code runs.
You were on the right track actually when you tried converting Sub1 to a function. You just need to make the function "return" the created worksheet object. Here:
Function Sub1() As Worksheet ' Don't forget to use a different name for Sub1 (and
' preferably Sub2 as well).
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1").Value = "Useless"
Set Sub1 = ws
End Function
Sub Sub2()
Dim test As String
test = ThisWorkbook.Worksheets("Sheet1").Range("B3").Value
If test = "here" Then
With Sub1
.Range("A2").Value = test
End With
End If
End Sub
Obviously, you would need to change the name of Sub1 to something else that reflects what the function does.
Also, notice that I used test instead of your test.Value because test is a string already and doesn't have a Value property.
Public ws As Worksheet
Sub Sub1()
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1") = "Useless"
End Sub
Sub Sub2()
Dim test As String
test = ThisWorkbook.Worksheets("Sheet1").Range("B3")
If test = "here" Then
Sub1
ws.Range("A2") = test
End If
End Sub
Another way to do it is by passing the variable as an argument:
Sub Sub1(ByRef ws As Worksheet) 'The variable is passed ByRef as default, but wanted to make it clear.
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1") = "Useless" 'Value is the default property of Range.
End Sub
Sub Sub2()
Dim test As String
Dim wrkSht As Worksheet
test = ThisWorkbook.Worksheets("Sheet1").Range("B3")
If test = "here" Then
Sub1 wrkSht 'Pass the variable to Sub1 to get defined.
wrkSht.Range("A2") = test
End If
End Sub
Or turn Sub1 into a function that returns a reference to the worksheet:
Function Sub1() As Worksheet
Set Sub1 = ThisWorkbook.Worksheets("Sheet2")
End Function
Sub Sub2()
Dim test As String
test = ThisWorkbook.Worksheets("Sheet1").Range("B3")
If test = "here" Then
Sub1.Range("A2") = test
End If
End Sub

Activate sheet 1 otherwise another sheet

Hi I tried to modify the following two lines of code by adding an if statement, but it didn't work. Does anyone know why?
Workbooks(wkbk_Record).Activate
Workbooks(wkbk_Record).Sheets("Tab1").Select
What's wrong with the following? Thank you
If SheetExists("Tab1", Workbooks(wkbk_Record)) Then
Workbooks(wkbk_Record).Activate
Workbooks(wkbk_Record).Sheets("Tab1").Select
Else
Workbooks(wkbk_Record).Activate
Workbooks(wkbk_Record).Sheets("Tab2").Select
Considering that you take the SheetExists from here - Test or check if sheet exists this is something that works:
Sub TestMe()
If SheetExists("Tab1") Then
Sheets("Tab1").Select
ElseIf SheetExists("Tab2") Then
Sheets("Tab2").Select
Else
MsgBox "No Sheet"
End If
End Sub
Function SheetExists(shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ThisWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
SheetExists = Not sht Is Nothing
End Function
Or if you wanna see your colleagues get crazy, write it like this:
Sub ActivateTab2OrTab1()
On Error Resume Next
Sheets("Tab2").Select
Sheets("Tab1").Select
End Sub

Refer to Function name via passed varaible

This line:
Set ws = wb.Worksheets(Module2.FirstBBSName)
will set the worksheet as the name of the return from the function, which will be the name of a sheet.
However, in this sub, this will need to change to:
Set ws = wb.Worksheets(Module2.SecondBBSName)
or
Set ws = wb.Worksheets(Module2.ThirdBBSName)
and so on. I need to do this by passing the name from a call via a variable. Lets name it SheetNameReturn.
So if I send:
Call NameOfMySub ("SecondBBSName")
It will then not work if I use
Set ws = wb.Worksheets(Module2.SheetNameReturn)
As obviously it is looking for SheetNameReturn in Module2 and not the variable.
What do I need to do to make it look at the passed variable instead?
You can run a function named by a variable with Application.Run.
See the code below - strFunction (could be SheetNameReturn) takes the name of the function (optionally with module prefix) and you then pass that string to Run to call the function.
Module1:
Option Explicit
Sub Test()
Dim wb As Workbook
Dim ws As Worksheet
Dim strFunction As String
Set wb = ThisWorkbook
strFunction = "Module2.FirstBBSName"
Set ws = wb.Worksheets(Application.Run(strFunction))
Debug.Print ws.Name
strFunction = "Module2.SecondBBSName"
Set ws = wb.Worksheets(Application.Run(strFunction))
Debug.Print ws.Name
strFunction = "Module2.ThirdBBSName"
Set ws = wb.Worksheets(Application.Run(strFunction))
Debug.Print ws.Name
End Sub
Module2:
Option Explicit
Function FirstBBSName()
FirstBBSName = "Sheet1"
End Function
Function SecondBBSName()
SecondBBSName = "Sheet2"
End Function
Function ThirdBBSName()
ThirdBBSName = "Sheet3"
End Function

Is it possible to check if the name of the sheets is around?

I was wondering if it is possible to check for a particular sheets for its availability. If it is around, it will continue on with the rest of the code. If not around then it will add in the sheet.
I have thought of it but it is giving me error. Do share some info if u know something! thanks!
sub macro1()
If sheets("Test") = False Then
Sheets.Add.Name = "Test"
End If
'Run my code
End Sub
Like this?
Sub Sample()
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets("Test")
On Error GoTo 0
If ws Is Nothing Then
Set ws = Sheets.Add
ws.Name = "Test"
End If
'~~> Run your code
End Sub
Another approach ... create a function that
- accepts a workbook object and the name of the sheet you're after and
- returns tru if the sheet is found in the workbook
Function SheetExists(oWorkbook As Workbook, sSheetname As String)
Dim oWs As Worksheet
For Each oWs In oWorkbook.Worksheets
If oWs.Name = sSheetname Then
SheetExists = True
Exit Function
End If
Next
End Function
Sub TestSheetExists()
If SheetExists(ActiveWorkbook, "Bob") Then
MsgBox "Found it"
Else
MsgBox "No joy"
End If
End Sub