Public variable value reset when called in another module, Excel VBA - vba

In Excel, I have two modules, let's say module1 and module2.
In module1, I have declared a public variable:
Public offsetNumber As Integer
Within the sub, I assign a number to the 'offsetNumber' variable.
offsetNumber = 2
Msgbox offsetNumber
This successfully displays the number 2.
Now, in module2, I try to call the variable offsetNumber.
Msgbox offsetNumber
However, the value displayed is 0, not 2.
How can I carry over the variable value from module1 to module2?
UPDTATE:
I've tried the module1.offsetNumber and checking "require variable declarations". I've also checked to make sure that the value is not being overwritten (at least in module1).
To be more in depth, this is how my module1 is currently structured:
Public offsetNumber as Integer
Sub **********
Dim .... (declare variables)
Activecell.EntireRow.Select
currentRow = ActiveCell.Row
offsetNumber = currentRow - 48
Msgbox offsetNumber (returns correct value)
........... (misc code)
Msgbox offsetNumber (returns correct value)
End Sub
This is how my module2 is structured:
Sub *********
Dim ..... (declare variables)
.............. (misc code)
Msgbox offsetNumber (returns 0)
For rowCounter = 2 to lastRow
If Sheets("****").Cells(rowCounter, 3) = ****** Then
Sheets("****").Activate
Rows(rowCounter + offsetNumber).Select
End If
Next rowCounter
End Sub
In "Immediate" window after executing module1, the following line
? offsetNumber
returns a value of 0.
SOLUTION:
This is what worked for me:
Module1:
Public globalOffsetNumber as Integer
Sub **********
Dim .... (declare variables)
Activecell.EntireRow.Select
currentRow = ActiveCell.Row
offsetNumber = currentRow - 48
globalOffsetNumber = offsetNumber (new line)
Msgbox offsetNumber (returns correct value)
........... (misc code)
Msgbox offsetNumber (returns correct value)
End Sub
Module2:
Sub *********
Dim ..... (declare variables)
.............. (misc code)
Msgbox globalOffsetNumber (now returns correct value)
For rowCounter = 2 to lastRow
If Sheets("****").Cells(rowCounter, 3) = ****** Then
Sheets("****").Activate
Rows(rowCounter + globalOffsetNumber).Select
End If
Next rowCounter
End Sub

You don't have to do anything for a public variable which is declared in one module to be accessible in another. Try this experiment:
In module 1 have:
Option Explicit
Public s As String
Sub setvar()
s = "Hi"
End Sub
In module 2 have:
Sub readvar()
Debug.Print s
End Sub
If you first run setvar and then immediately run readvar you should see "Hi" displayed in the immediate window.
My guess is that you are somehow or other resetting the project after running your first sub but before running the second.

I add the same issue,
do not put "Public s As String" in module 2.
Definition resets variable.

Related

Time Loop in VBA - Looping through Columns

There are two sheets (sheet1 and sheet2).
Need to refresh sheet1 every 4 minutes as long as the workbook is open.
Then I Need to copy values from Column C in sheet1 to column C in sheet2 every 4 minutes.
Since new values would come in every 4 mins in sheet1, I want the values to be copied to a new column in sheet2 everytime.
I'm using the following code. The problem with my code is that the variable i is getting initiated fresh everytime and I am not able to initiate it to a value outside the module using Public i as long.
Sub copyvalues()
Dim i As Long
i = 3
Sheets(2).Columns(i).Value = Sheets(1).Range("C11:C90").Value
i = i + 1
Application.OnTime Now + TimeValue("00:04:00"), "copyvalues"
End Sub
Although you mention you can't declare variable i as Public, this should work:
For example, the following works without issues:
Public i As Long
Sub test()
Debug.Print i
Application.OnTime Now + TimeValue("00:00:01"), "Module1.test"
i = i + 1
End Sub
Try the following:
Public i As Long
Public SubIsRunning As Boolean
Sub initiatesubs()
If Not SubIsRunning = True Then
i = 3
Call copyvalues
SubIsRunning = True
End If
End Sub
Sub copyvalues()
Workbooks(REF).Sheets(2).Columns(i).Value = Workbooks(REF).Sheets(1).Range("C11:C90").Value
i = i + 1
Application.OnTime Now + TimeValue("00:04:00"), "Module1.copyvalues" 'assuming the sub is in Module1
End Sub

VBA Range Function/Variable Object error

I can't figure out why I keep getting an object error in VBA when calling a function with a desired range/variable. I want to call the SumSameCells function from a sub with the B8, B9, B10 as desired/destination cells (rng As Range)
Any help would be greatly appreciated. Thanks
Sub MySums()
Call SumSameCells(B8)
Call SumSameCells(B9)
Call SumSameCells(B10)
End Sub
Function SumSameCells(rng As Range)
x = 0
For i = 2 To 3
x = x + Sheets(i).Range(" & rng.Address & ")
Next i
Sheet1.Range(" & rng.Address & ") = x
End Function
This:
Call SumSameCells(B8)
isn't passing the Range B8 but an undeclared variable named B8
Using Option Explicit would warn you about this type of error.
This would be simpler:
Sub MySums()
SumSameCells "B8"
SumSameCells "B9"
SumSameCells "B10"
End Sub
Function SumSameCells(addr As String)
x = 0
For i = 2 To 3
x = x + Sheets(i).Range(addr).Value
Next i
Sheet1.Range(addr) = x
End Function
Variation on the already given answer.
Functions return something. You are using a return value so make it a sub.
No need for a loop in this case. You can just sum direct.
Declare the appropriate type for x. Option Explicit has already been mentioned.
Use the worksheets collection to avoid trying to work with a chart sheet.
Drop the call keyword as is obsolete.
Code:
Option Explicit
Public Sub MySums()
SumSameCells "B8"
SumSameCells "B9"
SumSameCells "B10"
End Sub
Public Sub SumSameCells(ByVal addr As String)
Dim x As Double '<== Use whatever appropriate type is
x = Application.WorksheetFunction.Sum(Worksheets(2).Range(addr), Worksheets(3).Range(addr))
Worksheets("Sheet1").Range(addr) = x
End Sub

Passing Values in VBA

In the code I am posting, I am using a check box called "ACDS Test" and whenever it is checked it creates a sheet, then when it becomes unchecked it calls the upper function and deletes the sheet.
I am trying to add a message box that essentially works like a fail safe to ensure they want to delete the page. If they say they do not want to delete the page then I want the checkbox to stay checked.
For some reason I am getting this error message when I try to pass the value to make sure the checkbox stays checked and I cannot figure out why.
The error comes up on the line:
Sub ACDSTest_Click(CorrectValue As Integer)
And the specific error is: "Compile error: Procedure Declaration does not match description of event or procedure having the same name".
Any help is much appreciated! IF any more clarification is needed please feel free to ask!
Sub DeleteWorksheet(NameSheet As String)
Dim Ans As Long
Dim t As String
Dim CorrectValue As Integer
Dim i As Long, k As Long
k = Sheets.Count
Ans = MsgBox("Would you like to take this test off of the form?", vbYesNo)
Select Case Ans
Case vbYes
'Code reads through each page and finds one with corresponding name to string t
'Once it finds the correct page, it deletes it
For i = k To 1 Step -1
t = Sheets(i).Name
If t = NameSheet Then
Sheets(i).Delete
End If
Next i
CorrectValue = 0
Case vbNo
CorrectValue = 1
End Select
End Sub
Sub ACDSTest_Click(CorrectValue As Integer)
Dim NameSheet As String
Dim NameValue As String
NameSheet = "ACDS"
NameValue = "ACDS Test"
If ACDSTest.Value = True Then
CreateWorksheet (NameSheet), (NameValue)
Worksheets("Sheet1").Activate
Else
DeleteWorksheet (NameSheet)
If CorrectValue = 1 Then
ActiveSheet.Shapes("ACDS Test").ControlFormat.Value = 1
End If
End If
End Sub
The issue here is that the CorrectValue variable as you define it in DeleteWorksheet does not exist in the context of the
variable does not exist in context of the ACDSTest_Click subroutine. This is because variables defined within subroutines or functions are local to those functions. To correct this I would convert DeleteWorksheet to a function such as the below.
Further, the event that fires Private Sub ACDSTest_Click() cannot handle passing a value to that function, so changing it to Sub ACDSTest_Click(CorrectValue As Integer) causes an error.
Function DeleteWorksheet(ByVal SheetName As String) As Boolean
On Error GoTo SheetDNE
SheetName = Sheets(SheetName).Name 'Check if sheet exists w/o other objects
On Error GoTo 0
Select Case MsgBox("Would you like to take this test off of the form?", vbYesNo)
Case vbYes
Application.DisplayAlerts = False
Sheets(SheetName).Delete
Application.DisplayAlerts = True
DeleteWorksheet = True
Case Else: DeleteWorksheet = False
End Select
Exit Function 'Exit The Function w/o error
SheetDNE: 'Sheet Does Not Exist
MsgBox "The indicated sheet, " & SheetName & ", does not exist", vbOKOnly
End Function
And
Private Sub ACDSTest_Click()
Dim NameSheet As String
Dim NameValue As String
NameSheet = "ACDS"
NameValue = "ACDS Test"
If ACDSTest.Value = True Then
CreateWorksheet (NameSheet), (NameValue)
Worksheets("Sheet1").Activate
Else
If Not DeleteWorksheet(NameSheet) Then _
ActiveSheet.Shapes("ACDS Test").ControlFormat.Value = 1
End If
End Sub

Getting 424 Runtime error, object required

Please help with the code error 424 below
Public counter As String
Private Sub Workbook_WindowActivate(ByVal Wn As Window)
If ActiveSheet1.Name = Sheet2.Name Then
If counter = 0 Or counter = Null Then
Call LLP_Hide
End If
End If
End Sub
Remove 1 from ActiveSheet1.
If counter is meant to count it should be declared as Integer type instead of String.
Anyway, this part of code will also cause error: counter = 0. Replace it with counter = "0" or change the type of counter.
Public counter As Integer
Private Sub Workbook_WindowActivate(ByVal Wn As Window)
If ActiveSheet.Name = Sheet2.Name Then
If counter = 0 Then
Call LLP_Hide
End If
End If
End Sub

Type mismatch error in VBA when adding data to textbox

I have a TextBox and a ListBox with a list of various cities being populated from an Excel file
Now each city has one of two options: either within territory or outside. I want that option to be shown in textBox
I tried something like this :
Private Sub CommandButton1_Click()
TextBox2.Value = Application.VLookup(Me.ListBox1.Text,Sheets("Sheet1").Range("B:C"), 2, False)
End Sub
But am getting error stating that :
Run Time Error 2147352571 (80020005) . Could not set Value property. Type mismatch.
My excel file is something like this :
Let say your data are stored in Sheet1. You want to bind these data to ListBox1 on UserForm. I'd suggest to use custom function to load data instead of binding data via using RowSource property. In this case i'd suggest to use Dictionary to avoid duplicates.
See:
Private Sub UserForm_Initialize()
Dim d As Dictionary
Dim aKey As Variant
Set d = GetDistinctCitiesAndTerritories
For Each aKey In d.Keys
With Me.ListBox1
.AddItem ""
.Column(0, .ListCount - 1) = aKey
.Column(1, .ListCount - 1) = d.Item(aKey)
End With
Next
End Sub
'needs reference to Microsoft Scripting Runtime!
Function GetDistinctCitiesAndTerritories() As Dictionary
Dim wsh As Worksheet
Dim dict As Dictionary
Dim i As Integer
Set wsh = ThisWorkbook.Worksheets("Sheet1")
Set dict = New Dictionary
i = 2
Do While wsh.Range("A" & i) <> ""
If Not dict.Exists(wsh.Range("B" & i)) Then dict.Add wsh.Range("B" & i), wsh.Range("C" & i)
i = i + 1
Loop
Set GetDistinctCitiesAndTerritories = dict
End Function
After that, when user clicks on ListBox, city and territory are displayed in corresponding textboxes.
Private Sub ListBox1_Click()
Me.TextBoxCity = Me.ListBox1.List(Me.ListBox1.ListIndex, 0)
Me.TextBoxTerritory = Me.ListBox1.List(Me.ListBox1.ListIndex, 1)
End Sub
Note: code was written straight from the head, so it can contains errors!
The problem is likely that you aren't checking to see to see if the call to Application.VLookup succeeded. Most values returned can be successfully cast to a String - with one important exception: If the VLookup returns an error, for example it doesn't find Me.ListBox1.Text - it can't cast the Variant returned directly.
This should demonstrate:
Private Sub ReturnsOfVLookup()
Dim works As Variant, doesnt As String
works = Application.VLookup("Something not found", _
Sheets("Sheet1").Range("B:C"), 2, False)
Debug.Print works
On Error Resume Next
doesnt = Application.VLookup("Something not found", _
Sheets("Sheet1").Range("B:C"), 2, False)
If Err.Number <> 0 Then
Debug.Print Err.Description
Else
Debug.Print doesnt 'We won't be going here... ;-)
End If
End Sub