Editing a Sub within another Sub - vba

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

Related

Excel VBA get table range on unactive worksheet

I cannot figure out why this statement does not work.
Rng = Worksheets(sheetName).ListObjects(table).Range.Select
I have a sheet "sheetX" with a button that invokes a subprocess "export_json" in the global workspace "Thisworkbook". I want the subprocess in "Thisworkbook" to reference a table range on "sheetX" at "A2" but it gives an error "Application-defined or Object-defined error". I do not want to use Application.Goto
Why is that? I'm overlooking something basic
Public Sub CommandButton1_Click()
sheet = ActiveSheet.Name
Call ThisWorkbook.export_json(sheet)
End Sub
Public Sub export_json(sheetName)
table = ThisWorkbook.get_table(Worksheets(sheetName).Range("A2"))
Rng = Worksheets(sheetName).ListObjects(table).Range.Select
Rng = Selection.Address
table is of type string and sheet is the correct sheet name of type string so that is not the problem.
Try the code below, there's no need to use Select.
Also, it is not clear to me why you keep the code of your Function in ThisWorkbook module, instead of a regular module.
Public Sub CommandButton1_Click()
Dim TableRangeString As String
TableRangeString = ThisWorkbook.export_json(ActiveSheet.Name)
' for debug
MsgBox TableRangeString
End Sub
Public Function export_json(sheetName) As String
' use the function to return the Range.Address by changing it to return a String
Dim Rng As Range
Set Rng = Worksheets(sheetName).Range("A2").ListObject.Range
export_json = Rng.Address
End Function
Your syntaxing looks a little off, when your trying declare Rng in the function export_json() you should pass it as a string.
Public Sub CommandButton1_Click()
Dim sheetX As String
sheetX = ActiveSheet.Name
Call export_json("sheetX")
End Sub
Private Function export_json(sheetName As String)
table = ThisWorkbook.get_table(Worksheets(sheetName).Range("A2"))
Worksheets(sheetName).ListObjects(table).Range.Select
End Function

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

vba assigning sub routine to variable

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

macro that auto-executes when sheet is opened

Is it possible that my macro (update () ) auto-executes everytime the excel file is opened. The code below doesn't work well. Thanks
Private Sub Workbook_Open()
Run "update"
End Sub
Option Explicit
Sub update()
Dim rng As Range
Dim Sh As String, Cl As String
Dim ws As Worksheet
Dim i As Integer, ncol As Integer
Dim Row1 As String
ncol = Range("B1:O1").Columns.Count
For i = 1 To ncol
Set ws = ThisWorkbook.Sheets("sheet1")
With ws
Row1 = .Cells(1, i).Value
If Len(Row1) > 0 Then
Sh = Split(Row1, "'!")(0)
Cl = Split(Row1, "'!")(1)
Set rng = ThisWorkbook.Sheets(Sh).Range(Cl)
'Here you were always refering to cell A2 not moving through the values which was the main problem.
rng.Value = .Cells(2, i).Value
End If
End With
Next i
End Sub
As mentioned in the comments. Move the following:
Private Sub Workbook_Open()
Run "update"
End Sub
To here:
As mentioned by Siddharth there is another way to get a macro to run on the file open event and that is to simply to give it the following signature:
Sub Auto_Open
Also, personally I'd probably not call a sub-routine just "update" as it is quite close to lots of reserved words - I'd go for something like "updateSomething". This is just personal choice.

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