I have been working on creating a module that has multiple subs and functions that all are applied to the same sheet. In my efforts and research to clean up my code I found that instead of declaring the "Dim" for each sub, I can declare it at the very top of the module by using either "Dim" or "Private".
Sub Sample()
Dim DataSheet As Range
'Only declared for this sub, doesn't apply to other subs
'on the other hand,
Private DataSheet As Range
Sub Sample()
'declares it for each sub in this module.
What I can't figure out is, is there a way to set the value or in this case the exact range that I want to assign to "DataSheet" that will apply to the entire module? Currently each of my subs contains,
Set DataSheet = ThisWorkbook.Sheets(1).Range("A3:FU5002")
which, since this range is constant and never changes, seems a little redundant.
Create a special sub to perform the initialization and run it first:
Dim DataSheet As Range
Sub RunMeFirst()
Set DataSheet = ThisWorkbook.Sheets(1).Range("A3:FU5002")
End Sub
add in a global variable in the ThisWorkbook module and use the workbook open event to set the value.
Public DataSheet As Range
Private Sub Workbook_Open()
Set DataSheet = ThisWorkbook.Sheets(1).Range("A3:FU5002")
End Sub
Related
I am trying to see if it's possible to click a button on a series of sheets with a function. For a single sheet, my code works fine, but I get an Runtime error 438 when I try to do the code below.
Public Sub Read_All_Data_Click()
Dim ws As Worksheet
For Each ws In Worksheets
ThisWorkbook.Sheets(ws.Name).Read_Data_Click
Next ws
End Sub
Read_Data_Click is not a built in property of a worksheet.
You have to write your Sub Read_Data_Click(MySheet as worksheet) in a module, and parse the referance to each wc from the loop. Then you only use the name of the sub like Read_Data_Click(ws)
ws is defined as worksheet, during the for loop the variable will be updated to be the current worksheet. Because of this using Sheets(ws.name) is redundant, instead your code should look like:
Public Sub Read_All_Data_Click()
Dim ws As Worksheet
For Each ws In Worksheets
ws.Read_Data_Click
Next ws
End Sub
I am trying to copy data from one worksheet to another. I have a workbook that has about 62 worksheet tabs.
The part that is especially tricky for me is that the worksheet the data needs to be copied to will not always be the same.
I have a dropdown menu that lists 62 different pieces of equipment. This is shown in G1 in the worksheet named "HOME". I want the text to copy over to the correct tab based on the selection.
I figured out how to copy over specific text, when I do this I see the word "TEXT" show up on the specified worksheet.
Sheets(Range("g1").Value).Activate
Range("a1").Value = "TEXT"
I cannot figure out how to copy over G4:G24 from my "HOME" worksheet to another worksheet based on the same drop-down menu.
This is what I tried.
Private Sub CommandButton1_Click()
Worksheets("HOME").Range("g4:g24").Copy
Sheets(Range("g1").Value).Activate
Range("a1").Value = "TEXT"
Sheets(Range("g1").Value).Activate
Range("f4").PasteSpecial
End Sub
Be explicit about workbook and worksheets - never use Range/Cells without qualifying a worksheet (though you can get away with it in a worksheet code module if you're referring to the associated worksheet).
Private Sub CommandButton1_Click()
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook 'or ActiveWorkbook?
With wb.Worksheets("HOME")
Set ws = wb.Worksheets(.Range("G1").Value) 'create a worksheet reference
ws.Range("A1").Value = "TEXT" '...and use it
.Range("g4:g24").Copy ws.Range("f4")
End With
End Sub
See for example: What is the default scope of worksheets and cells and range?
Generally speaking you have a good start there, but it can be accomplished in much fewer lines with much more speed like this:
Sub ExampleSub()
Dim SheetName As String
SheetName = Worksheets("HOME").Range("A1").Value
Worksheets("HOME").Range("G4:G24").Value = Worksheets(SheetName).Range("G4:G24").Value
End Sub
It's not even necessary to use the variable SheetName, but it can help keep things simple, it can also now be reused later in the subroutine.
An alternative to reference sheets is to make the variable a worksheet:
Sub ExampleSub()
Dim SheetName As Worksheet
Dim HomeSheet As Worksheet
Set HomeSheet = Worksheets("HOME")
Set SheetName = Worksheets(HomeSheet.Range("A1").Value)
HomeSheet.Range("G4:G24").Value = SheetName.Range("G4:G24").Value
End Sub
I was thinking if its possible to set a Master Workbook in Excel VBA and access it on all procedures and functions?
Since I am pretty new to VBA I don't understand the syntax VBA is using..
Dim MasterWB as Workbook
Set MasterWB = Workbooks.Open("Path to my Workbook")
But if I want to access it in an another Procedure or Function I'll get a Object Definition Error.
I don't want to declare the Object in every Sub or Function.
Thanks a lot!
There are two ways of doing this:
The good practice:
Option Explicit
Sub Test()
Dim MasterWB As Workbook
Set MasterWB = Workbooks.Open("Path")
UseWb MasterWB
End Sub
Sub UseWb(wb As Workbook)
wb.Close
End Sub
The you shouldn't use practice:
Option Explicit
Public MasterWB As Workbook
Sub Test()
Set MasterWB = Workbooks.Open("Path")
UseWb MasterWB
End Sub
Sub UseWb()
wb.Close
End Sub
The first one allows you to pass the Workbook Variable as parameter to other functions in this case you can't use ByVal but other variables like Integeror Long can be used as ByVal instead of (per default) ByRef.
ByVal means you are only passing the value of that variable, so you won't modify it on the function.
ByRef means you pass the reference, so the other function can modify that original variable.
The second way only allows you to use the variable as a reference so there might be changes on it without noticing.
Hope this clears out a bit your question.
I'm trying to clear all slicers on a specific worksheet but getting next error:
"object variable or with block variable not set" in this line: cache.ClearManualFilter.
My code:
Sub Clear_all_filters()
Dim cache As SlicerCache
Set mWS = Sheets("Specific_Sheet")
For Each cache In mWS.SlicerCaches
cache.ClearManualFilter
Next cache
End Sub
Just in case someone's still looking for a solution to this question, here is the code I'm using now:
Sub OnePageSlicersReset()
Dim slcrC As SlicerCache
Dim slcr As Slicer
Application.ScreenUpdating = False
For Each slcrC In ActiveWorkbook.SlicerCaches
For Each slcr In slcrC.Slicers
If slcr.Shape.Parent Is ActiveSheet Then
If slcrC.FilterCleared = False Then
slcrC.ClearManualFilter
Exit For
End If
End If
Next slcr
Next slcrC
Application.ScreenUpdating = True
End Sub
Firstly, you should go to Tools>Options and turn on Require Variable Declaration. This will add Option Explicit to the top of any new module (You'll need to add it yourself to any pre-existing module).
This will force you to declare mWS, which would need to be a Worksheet class according to the Set command. This will bring up the error 'Method or data member not found' when you try to run the code.
This is because SlicerCaches are a property in the Workbook class, not Worksheet (As described here: https://learn.microsoft.com/en-us/office/vba/api/excel.slicercache)
In this case we can remove all reference to mWS and just use ThisWorkbook. As this suggests it will loop through all slicers in the current workbook so you may need to do some extra digging if you want to limit it to those in just one sheet.
Option Explicit
Sub Clear_all_filters()
Dim cache As SlicerCache
For Each cache In ThisWorkbook.SlicerCaches
cache.ClearManualFilter
Next cache
End Sub
I have to create an Excel sheet automatically with vba.
Some cells need an Onchange Event Listener and I wanted to know if there is a way to create this Event Listener automatically by calling a macro instead of writing it down everytime in every sheet code ?
Thank you
I'm going to answer this question because I think it might have some relevance to quite a few other people too, so the code below should get you started in the right direction.
However, there is an expectation on this site that you try to help yourself at least to the same extent as we try to help you. The commenters have mentioned the VBA Object Model, Application Events and AddIns. It shouldn't be beyond the wit of most people to then research these key words (say with a google search). It's not really acceptable simply to say you "dunno where to put the code or what to do", and, in all honesty, doesn't particularly motivate people to help you - put another way, you're pretty lucky to get an answer with that post and comment.
I don't want to get into a huge comment exchange on exactly how to code your specific case. The code here is an example and I would expect you then to research it further. So here goes ...
Insert a class module (research that if you don't know how) and name it - I've called mine cApp. This will enable you to access the Application object and capture its events, like so:
Option Explicit
Private WithEvents mApp As Application
Private mSheetList As Collection
Private Sub Class_Initialize()
Dim ws As Worksheet
'Create instance of the sheet collection
Set mSheetList = New Collection
'If you wanted to add any existing sheets to be checked for changes,
'then you'd do it here.
'Just for an example, I'm using any existing sheets whose name contains "LoP".
For Each ws In ThisWorkbook.Worksheets
If InStr(ws.Name, "LoP") > 0 Then
mSheetList.Add ws
End If
Next
'Create instance of Application
Set mApp = Application
End Sub
Private Sub mApp_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim ws As Worksheet
'Test if the changed sheet is in our list.
'Check if the Sh object is a worksheet.
If TypeOf Sh Is Worksheet Then
'Loop through out list of sheets and see if the Sh object is in the list.
For Each ws In mSheetList
If Sh Is ws Then
'Check if the changed range is in the desired range of your sheet.
'In this example, we'll say it has to been in the range "A1:B2".
If Not Intersect(Target, ws.Range("A1:B2")) Is Nothing Then
MsgBox ws.Name & "!" & Target.Address(False, False) & " has changed."
End If
Exit For
End If
Next
End If
End Sub
Private Sub mApp_WorkbookNewSheet(ByVal Wb As Workbook, ByVal Sh As Object)
'A new sheet has been created so add it to our sheet list.
If Wb Is ThisWorkbook Then
If TypeOf Sh Is Worksheet Then
mSheetList.Add Sh
End If
End If
End Sub
You then want to create an instance of this class. I've done it in a standard Module:
Option Explicit
Private oApp As cApp
Public Sub RunMe()
'Create instance of your app class
Set oApp = New cApp
End Sub
You'd then call the RunMe routine somewhere within your code. You might choose to do this in your Workbook_Open() event, but it could be anywhere of your choosing.
I've commented the code pretty heavily so you can see what it's doing and you can always research each of the keywords if you're not sure what they're doing.